diff options
Diffstat (limited to 'modules')
137 files changed, 3004 insertions, 734 deletions
diff --git a/modules/bmp/SCsub b/modules/bmp/SCsub new file mode 100644 index 0000000000..e7da7cf108 --- /dev/null +++ b/modules/bmp/SCsub @@ -0,0 +1,9 @@ +#!/usr/bin/env python + +Import('env') +Import('env_modules') + +env_bmp = env_modules.Clone() + +# Godot's own source files +env_bmp.add_source_files(env.modules_sources, "*.cpp") diff --git a/modules/bmp/config.py b/modules/bmp/config.py new file mode 100644 index 0000000000..1c8cd12a2d --- /dev/null +++ b/modules/bmp/config.py @@ -0,0 +1,5 @@ +def can_build(env, platform): + return True + +def configure(env): + pass diff --git a/modules/bmp/image_loader_bmp.cpp b/modules/bmp/image_loader_bmp.cpp new file mode 100644 index 0000000000..769119a0dc --- /dev/null +++ b/modules/bmp/image_loader_bmp.cpp @@ -0,0 +1,194 @@ +/*************************************************************************/ +/* image_loader_bmp.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 "image_loader_bmp.h" + +Error ImageLoaderBMP::convert_to_image(Ref<Image> p_image, + const uint8_t *p_buffer, + const uint8_t *p_color_buffer, + const bmp_header_s &p_header) { + + Error err = OK; + + if (p_buffer == NULL) + err = FAILED; + + if (err == OK) { + size_t index = 0; + size_t width = + static_cast<size_t>(p_header.bmp_info_header.bmp_width < 0 ? -p_header.bmp_info_header.bmp_width : p_header.bmp_info_header.bmp_width); + size_t height = + static_cast<size_t>(p_header.bmp_info_header.bmp_height < 0 ? -p_header.bmp_info_header.bmp_height : p_header.bmp_info_header.bmp_height); + size_t bits_per_pixel = + static_cast<size_t>(p_header.bmp_info_header.bmp_bit_count); + + if (p_header.bmp_info_header.bmp_compression != 0) { + err = FAILED; + } + + if (bits_per_pixel != 24 || bits_per_pixel != 32) { + err = FAILED; + } + + 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; + + PoolVector<uint8_t> image_data; + err = image_data.resize(width * height * 4); + + PoolVector<uint8_t>::Write image_data_w = image_data.write(); + uint8_t *write_buffer = image_data_w.ptr(); + + 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++) { + switch (bits_per_pixel) { + case 24: { + uint32_t color = *((uint32_t *)line_ptr); + + write_buffer[index + 2] = color & 0xff; + 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; + case 32: { + uint32_t color = *((uint32_t *)line_ptr); + + write_buffer[index + 2] = color & 0xff; + 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; + } + } + line -= line_width; + } + p_image->create(width, height, 0, Image::FORMAT_RGBA8, image_data); + } + } + return err; +} + +Error ImageLoaderBMP::load_image(Ref<Image> p_image, FileAccess *f, + bool p_force_linear, float p_scale) { + + bmp_header_s bmp_header; + Error err = ERR_INVALID_DATA; + + if (f->get_len() > sizeof(bmp_header)) { + // File Header + bmp_header.bmp_file_header.bmp_signature = f->get_16(); + if (bmp_header.bmp_file_header.bmp_signature == BITMAP_SIGNATURE) { + bmp_header.bmp_file_header.bmp_file_size = f->get_32(); + bmp_header.bmp_file_header.bmp_file_padding = f->get_32(); + bmp_header.bmp_file_header.bmp_file_offset = f->get_32(); + + // Info Header + bmp_header.bmp_info_header.bmp_header_size = f->get_32(); + 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(); + 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(); + bmp_header.bmp_info_header.bmp_pixels_per_meter_x = f->get_32(); + bmp_header.bmp_info_header.bmp_pixels_per_meter_y = f->get_32(); + 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); + + 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; + + PoolVector<uint8_t> bmp_color_table; + if (color_table_size > 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->seek(bmp_header.bmp_file_header.bmp_file_offset); + + uint32_t bmp_buffer_size = (bmp_header.bmp_file_header.bmp_file_size - + bmp_header.bmp_file_header.bmp_file_offset); + + PoolVector<uint8_t> bmp_buffer; + err = bmp_buffer.resize(bmp_buffer_size); + if (err == OK) { + PoolVector<uint8_t>::Write bmp_buffer_w = bmp_buffer.write(); + f->get_buffer(bmp_buffer_w.ptr(), bmp_buffer_size); + + 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); + } + f->close(); + } + } + return err; +} + +void ImageLoaderBMP::get_recognized_extensions( + List<String> *p_extensions) const { + + p_extensions->push_back("bmp"); +} + +ImageLoaderBMP::ImageLoaderBMP() {} diff --git a/modules/bmp/image_loader_bmp.h b/modules/bmp/image_loader_bmp.h new file mode 100644 index 0000000000..3fa7481287 --- /dev/null +++ b/modules/bmp/image_loader_bmp.h @@ -0,0 +1,84 @@ +/*************************************************************************/ +/* image_loader_bmp.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 IMAGE_LOADER_BMP_H +#define IMAGE_LOADER_BMP_H + +#include "io/image_loader.h" + +class ImageLoaderBMP : public ImageFormatLoader { +protected: + static const unsigned BITMAP_SIGNATURE = 0x4d42; + + struct bmp_header_s { + struct bmp_file_header_s { + uint16_t bmp_signature; + uint32_t bmp_file_size; + uint32_t bmp_file_padding; + uint32_t bmp_file_offset; + } bmp_file_header; + + struct bmp_info_header_s { + uint32_t bmp_header_size; + uint32_t bmp_width; + uint32_t bmp_height; + uint16_t bmp_planes; + uint16_t bmp_bit_count; + uint32_t bmp_compression; + uint32_t bmp_size_image; + uint32_t bmp_pixels_per_meter_x; + 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 bmp_header_s &p_header); + +public: + virtual Error load_image(Ref<Image> p_image, FileAccess *f, + bool p_force_linear, float p_scale); + virtual void get_recognized_extensions(List<String> *p_extensions) const; + ImageLoaderBMP(); +}; + +#endif // IMAGE_LOADER_BMP_H diff --git a/modules/bmp/register_types.cpp b/modules/bmp/register_types.cpp new file mode 100644 index 0000000000..1f68a03e85 --- /dev/null +++ b/modules/bmp/register_types.cpp @@ -0,0 +1,44 @@ +/*************************************************************************/ +/* register_types.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 "register_types.h" + +#include "image_loader_bmp.h" + +static ImageLoaderBMP *image_loader_bmp = NULL; + +void register_bmp_types() { + image_loader_bmp = memnew(ImageLoaderBMP); + ImageLoader::add_image_format_loader(image_loader_bmp); +} + +void unregister_bmp_types() { + memdelete(image_loader_bmp); +} diff --git a/modules/bmp/register_types.h b/modules/bmp/register_types.h new file mode 100644 index 0000000000..d8755db397 --- /dev/null +++ b/modules/bmp/register_types.h @@ -0,0 +1,32 @@ +/*************************************************************************/ +/* register_types.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. */ +/*************************************************************************/ + +void register_bmp_types(); +void unregister_bmp_types(); diff --git a/modules/bullet/config.py b/modules/bullet/config.py index 0a31c2e503..92dbcf5cb0 100644 --- a/modules/bullet/config.py +++ b/modules/bullet/config.py @@ -1,4 +1,4 @@ -def can_build(platform): +def can_build(env, platform): return True def configure(env): diff --git a/modules/bullet/space_bullet.cpp b/modules/bullet/space_bullet.cpp index 3a1f5d78dd..971fd39509 100644 --- a/modules/bullet/space_bullet.cpp +++ b/modules/bullet/space_bullet.cpp @@ -841,20 +841,19 @@ bool SpaceBullet::test_body_motion(RigidBodyBullet *p_body, const Transform &p_f } #endif - btTransform body_safe_position; - G_TO_B(p_from, body_safe_position); - UNSCALE_BT_BASIS(body_safe_position); + btTransform body_transform; + G_TO_B(p_from, body_transform); + UNSCALE_BT_BASIS(body_transform); - btVector3 recover_initial_position(0, 0, 0); + btVector3 initial_recover_motion(0, 0, 0); { /// Phase one - multi shapes depenetration using margin for (int t(RECOVERING_MOVEMENT_CYCLES); 0 < t; --t) { - if (!recover_from_penetration(p_body, body_safe_position, RECOVERING_MOVEMENT_SCALE, p_infinite_inertia, recover_initial_position)) { + if (!recover_from_penetration(p_body, body_transform, RECOVERING_MOVEMENT_SCALE, p_infinite_inertia, initial_recover_motion)) { break; } } - // Add recover movement in order to make it safe - body_safe_position.getOrigin() += recover_initial_position; + body_transform.getOrigin() += initial_recover_motion; } btVector3 motion; @@ -885,7 +884,7 @@ bool SpaceBullet::test_body_motion(RigidBodyBullet *p_body, const Transform &p_f } btConvexShape *convex_shape_test(static_cast<btConvexShape *>(p_body->get_bt_shape(shIndex))); - btTransform shape_world_from = body_safe_position * p_body->get_kinematic_utilities()->shapes[shIndex].transform; + btTransform shape_world_from = body_transform * p_body->get_kinematic_utilities()->shapes[shIndex].transform; btTransform shape_world_to(shape_world_from); shape_world_to.getOrigin() += motion; @@ -903,62 +902,49 @@ bool SpaceBullet::test_body_motion(RigidBodyBullet *p_body, const Transform &p_f } } - body_safe_position.getOrigin() += motion; + body_transform.getOrigin() += motion; } bool has_penetration = false; - { /// Phase three - Recover + contact test with margin + { /// Phase three - contact test with margin - btVector3 delta_recover_movement(0, 0, 0); + btVector3 __rec(0, 0, 0); RecoverResult r_recover_result; - bool l_has_penetration; - real_t l_penetration_distance = 1e20; - for (int t(RECOVERING_MOVEMENT_CYCLES); 0 < t; --t) { - l_has_penetration = recover_from_penetration(p_body, body_safe_position, RECOVERING_MOVEMENT_SCALE, p_infinite_inertia, delta_recover_movement, &r_recover_result); + has_penetration = recover_from_penetration(p_body, body_transform, 0, p_infinite_inertia, __rec, &r_recover_result); - if (r_result) { - B_TO_G(motion + delta_recover_movement + recover_initial_position, r_result->motion); + // Parse results + if (r_result) { + B_TO_G(motion + initial_recover_motion, r_result->motion); - if (l_has_penetration) { - has_penetration = true; - if (l_penetration_distance <= r_recover_result.penetration_distance) { - continue; - } + if (has_penetration) { - l_penetration_distance = r_recover_result.penetration_distance; + const btRigidBody *btRigid = static_cast<const btRigidBody *>(r_recover_result.other_collision_object); + CollisionObjectBullet *collisionObject = static_cast<CollisionObjectBullet *>(btRigid->getUserPointer()); - const btRigidBody *btRigid = static_cast<const btRigidBody *>(r_recover_result.other_collision_object); - CollisionObjectBullet *collisionObject = static_cast<CollisionObjectBullet *>(btRigid->getUserPointer()); + B_TO_G(motion, r_result->remainder); // is the remaining movements + r_result->remainder = p_motion - r_result->remainder; - B_TO_G(motion, r_result->remainder); // is the remaining movements - r_result->remainder = p_motion - r_result->remainder; - B_TO_G(r_recover_result.pointWorld, r_result->collision_point); - B_TO_G(r_recover_result.normal, r_result->collision_normal); - B_TO_G(btRigid->getVelocityInLocalPoint(r_recover_result.pointWorld - btRigid->getWorldTransform().getOrigin()), r_result->collider_velocity); // It calculates velocity at point and assign it using special function Bullet_to_Godot - r_result->collider = collisionObject->get_self(); - r_result->collider_id = collisionObject->get_instance_id(); - r_result->collider_shape = r_recover_result.other_compound_shape_index; - r_result->collision_local_shape = r_recover_result.local_shape_most_recovered; + B_TO_G(r_recover_result.pointWorld, r_result->collision_point); + B_TO_G(r_recover_result.normal, r_result->collision_normal); + B_TO_G(btRigid->getVelocityInLocalPoint(r_recover_result.pointWorld - btRigid->getWorldTransform().getOrigin()), r_result->collider_velocity); // It calculates velocity at point and assign it using special function Bullet_to_Godot + r_result->collider = collisionObject->get_self(); + r_result->collider_id = collisionObject->get_instance_id(); + r_result->collider_shape = r_recover_result.other_compound_shape_index; + r_result->collision_local_shape = r_recover_result.local_shape_most_recovered; #if debug_test_motion - Vector3 sup_line2; - B_TO_G(motion, sup_line2); - normalLine->clear(); - normalLine->begin(Mesh::PRIMITIVE_LINES, NULL); - normalLine->add_vertex(r_result->collision_point); - normalLine->add_vertex(r_result->collision_point + r_result->collision_normal * 10); - normalLine->end(); + Vector3 sup_line2; + B_TO_G(motion, sup_line2); + normalLine->clear(); + normalLine->begin(Mesh::PRIMITIVE_LINES, NULL); + normalLine->add_vertex(r_result->collision_point); + normalLine->add_vertex(r_result->collision_point + r_result->collision_normal * 10); + normalLine->end(); #endif - } else { - r_result->remainder = Vector3(); - } } else { - if (!l_has_penetration) - break; - else - has_penetration = true; + r_result->remainder = Vector3(); } } } diff --git a/modules/csg/config.py b/modules/csg/config.py index 5f133eba90..38ccc66d91 100644 --- a/modules/csg/config.py +++ b/modules/csg/config.py @@ -1,5 +1,21 @@ -def can_build(platform): +def can_build(env, platform): return True def configure(env): pass + +def get_doc_classes(): + return [ + "CSGBox", + "CSGCombiner", + "CSGCylinder", + "CSGMesh", + "CSGPolygon", + "CSGPrimitive", + "CSGShape", + "CSGSphere", + "CSGTorus", + ] + +def get_doc_path(): + return "doc_classes" diff --git a/modules/csg/csg.cpp b/modules/csg/csg.cpp index c1fe11d6aa..4e6e701bfd 100644 --- a/modules/csg/csg.cpp +++ b/modules/csg/csg.cpp @@ -1,3 +1,33 @@ +/*************************************************************************/ +/* csg.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 "csg.h" #include "face3.h" #include "geometry.h" diff --git a/modules/csg/csg.h b/modules/csg/csg.h index bb67e1fb36..53303a6533 100644 --- a/modules/csg/csg.h +++ b/modules/csg/csg.h @@ -1,3 +1,33 @@ +/*************************************************************************/ +/* csg.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 CSG_H #define CSG_H diff --git a/modules/csg/csg_gizmos.cpp b/modules/csg/csg_gizmos.cpp index 06cbaab3b0..2150320c4a 100644 --- a/modules/csg/csg_gizmos.cpp +++ b/modules/csg/csg_gizmos.cpp @@ -1,3 +1,33 @@ +/*************************************************************************/ +/* csg_gizmos.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 "csg_gizmos.h" /////////// diff --git a/modules/csg/csg_gizmos.h b/modules/csg/csg_gizmos.h index b5e394ecad..68e916823b 100644 --- a/modules/csg/csg_gizmos.h +++ b/modules/csg/csg_gizmos.h @@ -1,3 +1,33 @@ +/*************************************************************************/ +/* csg_gizmos.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 CSG_GIZMOS_H #define CSG_GIZMOS_H diff --git a/modules/csg/csg_shape.cpp b/modules/csg/csg_shape.cpp index 1f2f12f54d..82db1871da 100644 --- a/modules/csg/csg_shape.cpp +++ b/modules/csg/csg_shape.cpp @@ -1,3 +1,33 @@ +/*************************************************************************/ +/* csg_shape.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 "csg_shape.h" #include "scene/3d/path.h" @@ -389,9 +419,9 @@ void CSGShape::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_collision"), "set_use_collision", "is_using_collision"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "snap", PROPERTY_HINT_RANGE, "0.0001,1,0.001"), "set_snap", "get_snap"); - BIND_CONSTANT(OPERATION_UNION); - BIND_CONSTANT(OPERATION_INTERSECTION); - BIND_CONSTANT(OPERATION_SUBTRACTION); + BIND_ENUM_CONSTANT(OPERATION_UNION); + BIND_ENUM_CONSTANT(OPERATION_INTERSECTION); + BIND_ENUM_CONSTANT(OPERATION_SUBTRACTION); } CSGShape::CSGShape() { @@ -966,9 +996,9 @@ void CSGBox::_bind_methods() { ClassDB::bind_method(D_METHOD("set_material", "material"), &CSGBox::set_material); ClassDB::bind_method(D_METHOD("get_material"), &CSGBox::get_material); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "width", PROPERTY_HINT_RANGE, "0.001,1000.0,0.001"), "set_width", "get_width"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "height", PROPERTY_HINT_RANGE, "0.001,1000.0,0.001"), "set_height", "get_height"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "depth", PROPERTY_HINT_RANGE, "0.001,1000.0,0.001"), "set_depth", "get_depth"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "width", PROPERTY_HINT_EXP_RANGE, "0.001,1000.0,0.001,or_greater"), "set_width", "get_width"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "height", PROPERTY_HINT_EXP_RANGE, "0.001,1000.0,0.001,or_greater"), "set_height", "get_height"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "depth", PROPERTY_HINT_EXP_RANGE, "0.001,1000.0,0.001,or_greater"), "set_depth", "get_depth"); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "material", PROPERTY_HINT_RESOURCE_TYPE, "SpatialMaterial,ShaderMaterial"), "set_material", "get_material"); } @@ -1178,8 +1208,8 @@ void CSGCylinder::_bind_methods() { ClassDB::bind_method(D_METHOD("set_smooth_faces", "smooth_faces"), &CSGCylinder::set_smooth_faces); ClassDB::bind_method(D_METHOD("get_smooth_faces"), &CSGCylinder::get_smooth_faces); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "radius", PROPERTY_HINT_RANGE, "0.001,1000.0,0.001"), "set_radius", "get_radius"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "height", PROPERTY_HINT_RANGE, "0.001,1000.0,0.001"), "set_height", "get_height"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "radius", PROPERTY_HINT_EXP_RANGE, "0.001,1000.0,0.001,or_greater"), "set_radius", "get_radius"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "height", PROPERTY_HINT_EXP_RANGE, "0.001,1000.0,0.001,or_greater"), "set_height", "get_height"); ADD_PROPERTY(PropertyInfo(Variant::INT, "sides", PROPERTY_HINT_RANGE, "3,64,1"), "set_sides", "get_sides"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "cone"), "set_cone", "is_cone"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "smooth_faces"), "set_smooth_faces", "get_smooth_faces"); @@ -1403,8 +1433,8 @@ void CSGTorus::_bind_methods() { ClassDB::bind_method(D_METHOD("set_smooth_faces", "smooth_faces"), &CSGTorus::set_smooth_faces); ClassDB::bind_method(D_METHOD("get_smooth_faces"), &CSGTorus::get_smooth_faces); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "inner_radius", PROPERTY_HINT_RANGE, "0.001,1000.0,0.001"), "set_inner_radius", "get_inner_radius"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "outer_radius", PROPERTY_HINT_RANGE, "0.001,1000.0,0.001"), "set_outer_radius", "get_outer_radius"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "inner_radius", PROPERTY_HINT_EXP_RANGE, "0.001,1000.0,0.001,or_greater"), "set_inner_radius", "get_inner_radius"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "outer_radius", PROPERTY_HINT_EXP_RANGE, "0.001,1000.0,0.001,or_greater"), "set_outer_radius", "get_outer_radius"); ADD_PROPERTY(PropertyInfo(Variant::INT, "sides", PROPERTY_HINT_RANGE, "3,64,1"), "set_sides", "get_sides"); ADD_PROPERTY(PropertyInfo(Variant::INT, "ring_sides", PROPERTY_HINT_RANGE, "3,64,1"), "set_ring_sides", "get_ring_sides"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "smooth_faces"), "set_smooth_faces", "get_smooth_faces"); @@ -1978,11 +2008,11 @@ void CSGPolygon::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::POOL_VECTOR2_ARRAY, "polygon"), "set_polygon", "get_polygon"); ADD_PROPERTY(PropertyInfo(Variant::INT, "mode", PROPERTY_HINT_ENUM, "Depth,Spin,Path"), "set_mode", "get_mode"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "depth", PROPERTY_HINT_RANGE, "0.001,1000.0,0.001"), "set_depth", "get_depth"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "depth", PROPERTY_HINT_EXP_RANGE, "0.001,1000.0,0.001,or_greater"), "set_depth", "get_depth"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "spin_degrees", PROPERTY_HINT_RANGE, "1,360,0.1"), "set_spin_degrees", "get_spin_degrees"); ADD_PROPERTY(PropertyInfo(Variant::INT, "spin_sides", PROPERTY_HINT_RANGE, "3,64,1"), "set_spin_sides", "get_spin_sides"); ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "path_node"), "set_path_node", "get_path_node"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "path_interval", PROPERTY_HINT_RANGE, "0.001,1000.0,0.001"), "set_path_interval", "get_path_interval"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "path_interval", PROPERTY_HINT_EXP_RANGE, "0.001,1000.0,0.001,or_greater"), "set_path_interval", "get_path_interval"); ADD_PROPERTY(PropertyInfo(Variant::INT, "path_rotation", PROPERTY_HINT_ENUM, "Polygon,Path,PathFollow"), "set_path_rotation", "get_path_rotation"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "smooth_faces"), "set_smooth_faces", "get_smooth_faces"); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "material", PROPERTY_HINT_RESOURCE_TYPE, "SpatialMaterial,ShaderMaterial"), "set_material", "get_material"); diff --git a/modules/csg/csg_shape.h b/modules/csg/csg_shape.h index c1d2cce606..cbb5c7e041 100644 --- a/modules/csg/csg_shape.h +++ b/modules/csg/csg_shape.h @@ -1,3 +1,33 @@ +/*************************************************************************/ +/* csg_shape.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 CSG_SHAPE_H #define CSG_SHAPE_H diff --git a/modules/csg/doc_classes/CSGBox.xml b/modules/csg/doc_classes/CSGBox.xml new file mode 100644 index 0000000000..80455fda80 --- /dev/null +++ b/modules/csg/doc_classes/CSGBox.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<class name="CSGBox" inherits="CSGPrimitive" category="Core" version="3.1"> + <brief_description> + </brief_description> + <description> + </description> + <tutorials> + </tutorials> + <demos> + </demos> + <methods> + </methods> + <members> + <member name="depth" type="float" setter="set_depth" getter="get_depth"> + </member> + <member name="height" type="float" setter="set_height" getter="get_height"> + </member> + <member name="material" type="Material" setter="set_material" getter="get_material"> + </member> + <member name="width" type="float" setter="set_width" getter="get_width"> + </member> + </members> + <constants> + </constants> +</class> diff --git a/modules/csg/doc_classes/CSGCombiner.xml b/modules/csg/doc_classes/CSGCombiner.xml new file mode 100644 index 0000000000..b2265d7703 --- /dev/null +++ b/modules/csg/doc_classes/CSGCombiner.xml @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<class name="CSGCombiner" inherits="CSGShape" category="Core" version="3.1"> + <brief_description> + </brief_description> + <description> + </description> + <tutorials> + </tutorials> + <demos> + </demos> + <methods> + </methods> + <constants> + </constants> +</class> diff --git a/modules/csg/doc_classes/CSGCylinder.xml b/modules/csg/doc_classes/CSGCylinder.xml new file mode 100644 index 0000000000..0cab26ad3d --- /dev/null +++ b/modules/csg/doc_classes/CSGCylinder.xml @@ -0,0 +1,29 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<class name="CSGCylinder" inherits="CSGPrimitive" category="Core" version="3.1"> + <brief_description> + </brief_description> + <description> + </description> + <tutorials> + </tutorials> + <demos> + </demos> + <methods> + </methods> + <members> + <member name="cone" type="bool" setter="set_cone" getter="is_cone"> + </member> + <member name="height" type="float" setter="set_height" getter="get_height"> + </member> + <member name="material" type="Material" setter="set_material" getter="get_material"> + </member> + <member name="radius" type="float" setter="set_radius" getter="get_radius"> + </member> + <member name="sides" type="int" setter="set_sides" getter="get_sides"> + </member> + <member name="smooth_faces" type="bool" setter="set_smooth_faces" getter="get_smooth_faces"> + </member> + </members> + <constants> + </constants> +</class> diff --git a/modules/csg/doc_classes/CSGMesh.xml b/modules/csg/doc_classes/CSGMesh.xml new file mode 100644 index 0000000000..e5c3e5ccf3 --- /dev/null +++ b/modules/csg/doc_classes/CSGMesh.xml @@ -0,0 +1,19 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<class name="CSGMesh" inherits="CSGPrimitive" category="Core" version="3.1"> + <brief_description> + </brief_description> + <description> + </description> + <tutorials> + </tutorials> + <demos> + </demos> + <methods> + </methods> + <members> + <member name="mesh" type="Mesh" setter="set_mesh" getter="get_mesh"> + </member> + </members> + <constants> + </constants> +</class> diff --git a/modules/csg/doc_classes/CSGPolygon.xml b/modules/csg/doc_classes/CSGPolygon.xml new file mode 100644 index 0000000000..379c512d6a --- /dev/null +++ b/modules/csg/doc_classes/CSGPolygon.xml @@ -0,0 +1,49 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<class name="CSGPolygon" inherits="CSGPrimitive" category="Core" version="3.1"> + <brief_description> + </brief_description> + <description> + </description> + <tutorials> + </tutorials> + <demos> + </demos> + <methods> + </methods> + <members> + <member name="depth" type="float" setter="set_depth" getter="get_depth"> + </member> + <member name="material" type="Material" setter="set_material" getter="get_material"> + </member> + <member name="mode" type="int" setter="set_mode" getter="get_mode" enum="CSGPolygon.Mode"> + </member> + <member name="path_interval" type="float" setter="set_path_interval" getter="get_path_interval"> + </member> + <member name="path_node" type="NodePath" setter="set_path_node" getter="get_path_node"> + </member> + <member name="path_rotation" type="int" setter="set_path_rotation" getter="get_path_rotation" enum="CSGPolygon.PathRotation"> + </member> + <member name="polygon" type="PoolVector2Array" setter="set_polygon" getter="get_polygon"> + </member> + <member name="smooth_faces" type="bool" setter="set_smooth_faces" getter="get_smooth_faces"> + </member> + <member name="spin_degrees" type="float" setter="set_spin_degrees" getter="get_spin_degrees"> + </member> + <member name="spin_sides" type="int" setter="set_spin_sides" getter="get_spin_sides"> + </member> + </members> + <constants> + <constant name="MODE_DEPTH" value="0" enum="Mode"> + </constant> + <constant name="MODE_SPIN" value="1" enum="Mode"> + </constant> + <constant name="MODE_PATH" value="2" enum="Mode"> + </constant> + <constant name="PATH_ROTATION_POLYGON" value="0" enum="PathRotation"> + </constant> + <constant name="PATH_ROTATION_PATH" value="1" enum="PathRotation"> + </constant> + <constant name="PATH_ROTATION_PATH_FOLLOW" value="2" enum="PathRotation"> + </constant> + </constants> +</class> diff --git a/modules/csg/doc_classes/CSGPrimitive.xml b/modules/csg/doc_classes/CSGPrimitive.xml new file mode 100644 index 0000000000..bf41c40f22 --- /dev/null +++ b/modules/csg/doc_classes/CSGPrimitive.xml @@ -0,0 +1,19 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<class name="CSGPrimitive" inherits="CSGShape" category="Core" version="3.1"> + <brief_description> + </brief_description> + <description> + </description> + <tutorials> + </tutorials> + <demos> + </demos> + <methods> + </methods> + <members> + <member name="invert_faces" type="bool" setter="set_invert_faces" getter="is_inverting_faces"> + </member> + </members> + <constants> + </constants> +</class> diff --git a/modules/csg/doc_classes/CSGShape.xml b/modules/csg/doc_classes/CSGShape.xml new file mode 100644 index 0000000000..cf236a4207 --- /dev/null +++ b/modules/csg/doc_classes/CSGShape.xml @@ -0,0 +1,35 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<class name="CSGShape" inherits="VisualInstance" category="Core" version="3.1"> + <brief_description> + </brief_description> + <description> + </description> + <tutorials> + </tutorials> + <demos> + </demos> + <methods> + <method name="is_root_shape" qualifiers="const"> + <return type="bool"> + </return> + <description> + </description> + </method> + </methods> + <members> + <member name="operation" type="int" setter="set_operation" getter="get_operation" enum="CSGShape.Operation"> + </member> + <member name="snap" type="float" setter="set_snap" getter="get_snap"> + </member> + <member name="use_collision" type="bool" setter="set_use_collision" getter="is_using_collision"> + </member> + </members> + <constants> + <constant name="OPERATION_UNION" value="0" enum="Operation"> + </constant> + <constant name="OPERATION_INTERSECTION" value="1" enum="Operation"> + </constant> + <constant name="OPERATION_SUBTRACTION" value="2" enum="Operation"> + </constant> + </constants> +</class> diff --git a/modules/csg/doc_classes/CSGSphere.xml b/modules/csg/doc_classes/CSGSphere.xml new file mode 100644 index 0000000000..520368506e --- /dev/null +++ b/modules/csg/doc_classes/CSGSphere.xml @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<class name="CSGSphere" inherits="CSGPrimitive" category="Core" version="3.1"> + <brief_description> + </brief_description> + <description> + </description> + <tutorials> + </tutorials> + <demos> + </demos> + <methods> + </methods> + <members> + <member name="material" type="Material" setter="set_material" getter="get_material"> + </member> + <member name="radial_segments" type="int" setter="set_radial_segments" getter="get_radial_segments"> + </member> + <member name="radius" type="float" setter="set_radius" getter="get_radius"> + </member> + <member name="rings" type="int" setter="set_rings" getter="get_rings"> + </member> + <member name="smooth_faces" type="bool" setter="set_smooth_faces" getter="get_smooth_faces"> + </member> + </members> + <constants> + </constants> +</class> diff --git a/modules/csg/doc_classes/CSGTorus.xml b/modules/csg/doc_classes/CSGTorus.xml new file mode 100644 index 0000000000..58bbef2600 --- /dev/null +++ b/modules/csg/doc_classes/CSGTorus.xml @@ -0,0 +1,29 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<class name="CSGTorus" inherits="CSGPrimitive" category="Core" version="3.1"> + <brief_description> + </brief_description> + <description> + </description> + <tutorials> + </tutorials> + <demos> + </demos> + <methods> + </methods> + <members> + <member name="inner_radius" type="float" setter="set_inner_radius" getter="get_inner_radius"> + </member> + <member name="material" type="Material" setter="set_material" getter="get_material"> + </member> + <member name="outer_radius" type="float" setter="set_outer_radius" getter="get_outer_radius"> + </member> + <member name="ring_sides" type="int" setter="set_ring_sides" getter="get_ring_sides"> + </member> + <member name="sides" type="int" setter="set_sides" getter="get_sides"> + </member> + <member name="smooth_faces" type="bool" setter="set_smooth_faces" getter="get_smooth_faces"> + </member> + </members> + <constants> + </constants> +</class> diff --git a/modules/csg/register_types.cpp b/modules/csg/register_types.cpp index 020724ee59..0dea09808a 100644 --- a/modules/csg/register_types.cpp +++ b/modules/csg/register_types.cpp @@ -30,8 +30,8 @@ #include "register_types.h" -#include "csg_shape.h" #include "csg_gizmos.h" +#include "csg_shape.h" void register_csg_types() { @@ -51,9 +51,7 @@ void register_csg_types() { EditorPlugins::add_by_type<EditorPluginCSG>(); #endif #endif - } void unregister_csg_types() { - } diff --git a/modules/dds/config.py b/modules/dds/config.py index 5f133eba90..1c8cd12a2d 100644 --- a/modules/dds/config.py +++ b/modules/dds/config.py @@ -1,4 +1,4 @@ -def can_build(platform): +def can_build(env, platform): return True def configure(env): diff --git a/modules/enet/config.py b/modules/enet/config.py index 8031fbb4b6..3e30bbe778 100644 --- a/modules/enet/config.py +++ b/modules/enet/config.py @@ -1,4 +1,4 @@ -def can_build(platform): +def can_build(env, platform): return True def configure(env): diff --git a/modules/enet/doc_classes/NetworkedMultiplayerENet.xml b/modules/enet/doc_classes/NetworkedMultiplayerENet.xml index 7bee63019b..d5fd4bff09 100644 --- a/modules/enet/doc_classes/NetworkedMultiplayerENet.xml +++ b/modules/enet/doc_classes/NetworkedMultiplayerENet.xml @@ -16,6 +16,8 @@ <method name="close_connection"> <return type="void"> </return> + <argument index="0" name="wait_usec" type="int" default="100"> + </argument> <description> Closes the connection. Ignored if no connection is currently established. If this is a server it tries to notify all clients before forcibly disconnecting them. If this is a client it simply closes the connection to the server. </description> @@ -23,7 +25,7 @@ <method name="create_client"> <return type="int" enum="Error"> </return> - <argument index="0" name="ip" type="String"> + <argument index="0" name="address" type="String"> </argument> <argument index="1" name="port" type="int"> </argument> @@ -31,8 +33,10 @@ </argument> <argument index="3" name="out_bandwidth" type="int" default="0"> </argument> + <argument index="4" name="client_port" type="int" default="0"> + </argument> <description> - Create client that connects to a server at address [code]ip[/code] using specified [code]port[/code]. The given IP needs to be in IPv4 or IPv6 address format, for example: [code]192.168.1.1[/code]. The [code]port[/code] is the port the server is listening on. The [code]in_bandwidth[/code] and [code]out_bandwidth[/code] parameters can be used to limit the incoming and outgoing bandwidth to the given number of bytes per second. The default of 0 means unlimited bandwidth. Note that ENet will strategically drop packets on specific sides of a connection between peers to ensure the peer's bandwidth is not overwhelmed. The bandwidth parameters also determine the window size of a connection which limits the amount of reliable packets that may be in transit at any given time. Returns [code]OK[/code] if a client was created, [code]ERR_ALREADY_IN_USE[/code] if this NetworkedMultiplayerEnet instance already has an open connection (in which case you need to call [method close_connection] first) or [code]ERR_CANT_CREATE[/code] if the client could not be created. + 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. </description> </method> <method name="create_server"> @@ -50,6 +54,49 @@ Create server that listens to connections via [code]port[/code]. The port needs to be an available, unused port between 0 and 65535. Note that ports below 1024 are privileged and may require elevated permissions depending on the platform. To change the interface the server listens on, use [method set_bind_ip]. The default IP is the wildcard [code]*[/code], which listens on all available interfaces. [code]max_clients[/code] is the maximum number of clients that are allowed at once, any number up to 4096 may be used, although the achievable number of simultaneous clients may be far lower and depends on the application. For additional details on the bandwidth parameters, see [method create_client]. Returns [code]OK[/code] if a server was created, [code]ERR_ALREADY_IN_USE[/code] if this NetworkedMultiplayerEnet instance already has an open connection (in which case you need to call [method close_connection] first) or [code]ERR_CANT_CREATE[/code] if the server could not be created. </description> </method> + <method name="disconnect_peer"> + <return type="void"> + </return> + <argument index="0" name="id" type="int"> + </argument> + <argument index="1" name="now" type="bool" default="false"> + </argument> + <description> + Disconnect the given peer. If "now" is set to true, the connection will be closed immediately without flushing queued messages. + </description> + </method> + <method name="get_last_packet_channel" qualifiers="const"> + <return type="int"> + </return> + <description> + Returns the channel of the last packet fetched via [method PacketPeer.get_packet] + </description> + </method> + <method name="get_packet_channel" qualifiers="const"> + <return type="int"> + </return> + <description> + Returns the channel of the next packet that will be retrieved via [method PacketPeer.get_packet_peer] + </description> + </method> + <method name="get_peer_address" qualifiers="const"> + <return type="String"> + </return> + <argument index="0" name="id" type="int"> + </argument> + <description> + Returns the IP address of the given peer. + </description> + </method> + <method name="get_peer_port" qualifiers="const"> + <return type="int"> + </return> + <argument index="0" name="id" type="int"> + </argument> + <description> + Returns the remote port of the given peer. + </description> + </method> <method name="set_bind_ip"> <return type="void"> </return> @@ -61,9 +108,18 @@ </method> </methods> <members> + <member name="always_ordered" type="bool" setter="set_always_ordered" getter="is_always_ordered"> + Always use [code]TRANSFER_MODE_ORDERED[/code] in place of [code]TRANSFER_MODE_UNRELIABLE[/code]. This is the only way to use ordering with the RPC system. + </member> + <member name="channel_count" type="int" setter="set_channel_count" getter="get_channel_count"> + The number of channels to be used by ENet. Default: [code]3[/code]. Channels are used to separate different kinds of data. In realiable or ordered mode, for example, the packet delivery order is ensured on a per channel basis. + </member> <member name="compression_mode" type="int" setter="set_compression_mode" getter="get_compression_mode" enum="NetworkedMultiplayerENet.CompressionMode"> The compression method used for network packets. Default is no compression. These have different tradeoffs of compression speed versus bandwidth, you may need to test which one works best for your use case if you use compression at all. </member> + <member name="transfer_channel" type="int" setter="set_transfer_channel" getter="get_transfer_channel"> + Set the default channel to be used to transfer data. By default this value is [code]-1[/code] which means that ENet will only use 2 channels, one for reliable and one for unreliable packets. Channel [code]0[/code] is reserved, and cannot be used. Setting this member to any value between [code]0[/code] and [member channel_count] (excluded) will force ENet to use that channel for sending data. + </member> </members> <constants> <constant name="COMPRESS_NONE" value="0" enum="CompressionMode"> diff --git a/modules/enet/networked_multiplayer_enet.cpp b/modules/enet/networked_multiplayer_enet.cpp index bd76c766a0..88768829d7 100644 --- a/modules/enet/networked_multiplayer_enet.cpp +++ b/modules/enet/networked_multiplayer_enet.cpp @@ -55,6 +55,22 @@ int NetworkedMultiplayerENet::get_packet_peer() const { return incoming_packets.front()->get().from; } +int NetworkedMultiplayerENet::get_packet_channel() const { + + ERR_FAIL_COND_V(!active, -1); + ERR_FAIL_COND_V(incoming_packets.size() == 0, -1); + + return incoming_packets.front()->get().channel; +} + +int NetworkedMultiplayerENet::get_last_packet_channel() const { + + ERR_FAIL_COND_V(!active, -1); + ERR_FAIL_COND_V(!current_packet.packet, -1); + + return current_packet.channel; +} + Error NetworkedMultiplayerENet::create_server(int p_port, int p_max_clients, int p_in_bandwidth, int p_out_bandwidth) { ERR_FAIL_COND_V(active, ERR_ALREADY_IN_USE); @@ -83,7 +99,7 @@ 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 */, - SYSCH_MAX /* allow up to SYSCH_MAX channels to be used */, + 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 */); @@ -127,13 +143,13 @@ 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 */, - SYSCH_MAX /* allow up to SYSCH_MAX channels to be used */, + 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 */); } else { host = enet_host_create(NULL /* create a client host */, 1 /* only allow 1 outgoing connection */, - SYSCH_MAX /* allow up to SYSCH_MAX channels to be used */, + 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 */); } @@ -167,7 +183,7 @@ Error NetworkedMultiplayerENet::create_client(const String &p_address, int p_por unique_id = _gen_unique_id(); // Initiate connection, allocating enough channels - ENetPeer *peer = enet_host_connect(host, &address, SYSCH_MAX, unique_id); + ENetPeer *peer = enet_host_connect(host, &address, channel_count, unique_id); if (peer == NULL) { enet_host_destroy(host); @@ -316,7 +332,7 @@ void NetworkedMultiplayerENet::poll() { } enet_packet_destroy(event.packet); - } else if (event.channelID < SYSCH_MAX) { + } else if (event.channelID < channel_count) { Packet packet; packet.packet = event.packet; @@ -330,6 +346,7 @@ void NetworkedMultiplayerENet::poll() { uint32_t flags = decode_uint32(&event.packet->data[8]); packet.from = source; + packet.channel = event.channelID; if (server) { // Someone is cheating and trying to fake the source! @@ -496,7 +513,10 @@ Error NetworkedMultiplayerENet::put_packet(const uint8_t *p_buffer, int p_buffer switch (transfer_mode) { case TRANSFER_MODE_UNRELIABLE: { - packet_flags = ENET_PACKET_FLAG_UNSEQUENCED; + if (always_ordered) + packet_flags = 0; + else + packet_flags = ENET_PACKET_FLAG_UNSEQUENCED; channel = SYSCH_UNRELIABLE; } break; case TRANSFER_MODE_UNRELIABLE_ORDERED: { @@ -509,6 +529,9 @@ Error NetworkedMultiplayerENet::put_packet(const uint8_t *p_buffer, int p_buffer } break; } + if (transfer_channel > SYSCH_CONFIG) + channel = transfer_channel; + Map<int, ENetPeer *>::Element *E = NULL; if (target_peer != 0) { @@ -572,6 +595,7 @@ void NetworkedMultiplayerENet::_pop_current_packet() { enet_packet_destroy(current_packet.packet); current_packet.packet = NULL; current_packet.from = 0; + current_packet.channel = -1; } } @@ -759,6 +783,40 @@ int NetworkedMultiplayerENet::get_peer_port(int p_peer_id) const { #endif } +void NetworkedMultiplayerENet::set_transfer_channel(int p_channel) { + + ERR_FAIL_COND(p_channel < -1 || p_channel >= channel_count); + + if (p_channel == SYSCH_CONFIG) { + ERR_EXPLAIN("Channel " + itos(SYSCH_CONFIG) + " is reserved"); + ERR_FAIL(); + } + transfer_channel = p_channel; +} + +int NetworkedMultiplayerENet::get_transfer_channel() const { + return transfer_channel; +} + +void NetworkedMultiplayerENet::set_channel_count(int p_channel) { + + ERR_FAIL_COND(active); + ERR_FAIL_COND(p_channel < SYSCH_MAX); + channel_count = p_channel; +} + +int NetworkedMultiplayerENet::get_channel_count() const { + return channel_count; +} + +void NetworkedMultiplayerENet::set_always_ordered(bool p_ordered) { + always_ordered = p_ordered; +} + +bool NetworkedMultiplayerENet::is_always_ordered() const { + return always_ordered; +} + void NetworkedMultiplayerENet::_bind_methods() { ClassDB::bind_method(D_METHOD("create_server", "port", "max_clients", "in_bandwidth", "out_bandwidth"), &NetworkedMultiplayerENet::create_server, DEFVAL(32), DEFVAL(0), DEFVAL(0)); @@ -768,10 +826,22 @@ void NetworkedMultiplayerENet::_bind_methods() { ClassDB::bind_method(D_METHOD("set_compression_mode", "mode"), &NetworkedMultiplayerENet::set_compression_mode); ClassDB::bind_method(D_METHOD("get_compression_mode"), &NetworkedMultiplayerENet::get_compression_mode); ClassDB::bind_method(D_METHOD("set_bind_ip", "ip"), &NetworkedMultiplayerENet::set_bind_ip); - ClassDB::bind_method(D_METHOD("get_peer_address"), &NetworkedMultiplayerENet::get_peer_address); - ClassDB::bind_method(D_METHOD("get_peer_port"), &NetworkedMultiplayerENet::get_peer_port); + ClassDB::bind_method(D_METHOD("get_peer_address", "id"), &NetworkedMultiplayerENet::get_peer_address); + ClassDB::bind_method(D_METHOD("get_peer_port", "id"), &NetworkedMultiplayerENet::get_peer_port); + + ClassDB::bind_method(D_METHOD("get_packet_channel"), &NetworkedMultiplayerENet::get_packet_channel); + ClassDB::bind_method(D_METHOD("get_last_packet_channel"), &NetworkedMultiplayerENet::get_last_packet_channel); + ClassDB::bind_method(D_METHOD("set_transfer_channel", "channel"), &NetworkedMultiplayerENet::set_transfer_channel); + ClassDB::bind_method(D_METHOD("get_transfer_channel"), &NetworkedMultiplayerENet::get_transfer_channel); + ClassDB::bind_method(D_METHOD("set_channel_count", "channels"), &NetworkedMultiplayerENet::set_channel_count); + ClassDB::bind_method(D_METHOD("get_channel_count"), &NetworkedMultiplayerENet::get_channel_count); + ClassDB::bind_method(D_METHOD("set_always_ordered", "ordered"), &NetworkedMultiplayerENet::set_always_ordered); + ClassDB::bind_method(D_METHOD("is_always_ordered"), &NetworkedMultiplayerENet::is_always_ordered); ADD_PROPERTY(PropertyInfo(Variant::INT, "compression_mode", PROPERTY_HINT_ENUM, "None,Range Coder,FastLZ,ZLib,ZStd"), "set_compression_mode", "get_compression_mode"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "transfer_channel"), "set_transfer_channel", "get_transfer_channel"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "channel_count"), "set_channel_count", "get_channel_count"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "always_ordered"), "set_always_ordered", "is_always_ordered"); BIND_ENUM_CONSTANT(COMPRESS_NONE); BIND_ENUM_CONSTANT(COMPRESS_RANGE_CODER); @@ -789,6 +859,9 @@ NetworkedMultiplayerENet::NetworkedMultiplayerENet() { target_peer = 0; current_packet.packet = NULL; transfer_mode = TRANSFER_MODE_RELIABLE; + channel_count = SYSCH_MAX; + transfer_channel = -1; + always_ordered = false; connection_status = CONNECTION_DISCONNECTED; compression_mode = COMPRESS_NONE; enet_compressor.context = this; diff --git a/modules/enet/networked_multiplayer_enet.h b/modules/enet/networked_multiplayer_enet.h index d481f5d496..705807d429 100644 --- a/modules/enet/networked_multiplayer_enet.h +++ b/modules/enet/networked_multiplayer_enet.h @@ -68,6 +68,9 @@ private: int target_peer; TransferMode transfer_mode; + int transfer_channel; + int channel_count; + bool always_ordered; ENetEvent event; ENetPeer *peer; @@ -83,6 +86,7 @@ private: ENetPacket *packet; int from; + int channel; }; CompressionMode compression_mode; @@ -145,6 +149,15 @@ public: void set_compression_mode(CompressionMode p_mode); CompressionMode get_compression_mode() const; + int get_packet_channel() const; + int get_last_packet_channel() const; + void set_transfer_channel(int p_channel); + int get_transfer_channel() const; + void set_channel_count(int p_channel); + int get_channel_count() const; + void set_always_ordered(bool p_ordered); + bool is_always_ordered() const; + NetworkedMultiplayerENet(); ~NetworkedMultiplayerENet(); diff --git a/modules/etc/config.py b/modules/etc/config.py index 395fc1bb02..098f1eafa9 100644 --- a/modules/etc/config.py +++ b/modules/etc/config.py @@ -1,9 +1,5 @@ -def can_build(platform): - return True +def can_build(env, platform): + return env['tools'] def configure(env): - # Tools only, disabled for non-tools - # TODO: Find a cleaner way to achieve that - if not env['tools']: - env['module_etc_enabled'] = False - env.disabled_modules.append("etc") + pass diff --git a/modules/freetype/SCsub b/modules/freetype/SCsub index 8a7c2a773a..301f218361 100644 --- a/modules/freetype/SCsub +++ b/modules/freetype/SCsub @@ -17,18 +17,15 @@ if env['builtin_freetype']: "src/base/ftbitmap.c", "src/base/ftcid.c", "src/base/ftdebug.c", - "src/base/ftfntfmt.c", "src/base/ftfstype.c", "src/base/ftgasp.c", "src/base/ftglyph.c", "src/base/ftgxval.c", "src/base/ftinit.c", - "src/base/ftlcdfil.c", "src/base/ftmm.c", "src/base/ftotval.c", "src/base/ftpatent.c", "src/base/ftpfr.c", - "src/base/ftpic.c", "src/base/ftstroke.c", "src/base/ftsynth.c", "src/base/ftsystem.c", diff --git a/modules/freetype/config.py b/modules/freetype/config.py index 5f133eba90..1c8cd12a2d 100644 --- a/modules/freetype/config.py +++ b/modules/freetype/config.py @@ -1,4 +1,4 @@ -def can_build(platform): +def can_build(env, platform): return True def configure(env): diff --git a/modules/gdnative/SCsub b/modules/gdnative/SCsub index 8654ef3d82..6d2f8ce8ad 100644 --- a/modules/gdnative/SCsub +++ b/modules/gdnative/SCsub @@ -23,7 +23,8 @@ def _build_gdnative_api_struct_header(api): '\textern const godot_gdnative_core_api_struct *_gdnative_wrapper_api_struct;' ] - for name in api['extensions']: + for ext in api['extensions']: + name = ext['name'] gdnative_api_init_macro.append( '\textern const godot_gdnative_ext_{0}_api_struct *_gdnative_wrapper_{0}_api_struct;'.format(name)) @@ -31,9 +32,10 @@ def _build_gdnative_api_struct_header(api): gdnative_api_init_macro.append('\tfor (unsigned int i = 0; i < _gdnative_wrapper_api_struct->num_extensions; i++) { ') gdnative_api_init_macro.append('\t\tswitch (_gdnative_wrapper_api_struct->extensions[i]->type) {') - for name in api['extensions']: + for ext in api['extensions']: + name = ext['name'] gdnative_api_init_macro.append( - '\t\t\tcase GDNATIVE_EXT_%s:' % api['extensions'][name]['type']) + '\t\t\tcase GDNATIVE_EXT_%s:' % ext['type']) gdnative_api_init_macro.append( '\t\t\t\t_gdnative_wrapper_{0}_api_struct = (godot_gdnative_ext_{0}_api_struct *)' ' _gdnative_wrapper_api_struct->extensions[i];'.format(name)) @@ -61,8 +63,8 @@ def _build_gdnative_api_struct_header(api): '\tGDNATIVE_' + api['core']['type'] + ',' ] - for name in api['extensions']: - out += ['\tGDNATIVE_EXT_' + api['extensions'][name]['type'] + ','] + for ext in api['extensions']: + out += ['\tGDNATIVE_EXT_' + ext['type'] + ','] out += ['};', ''] @@ -88,8 +90,9 @@ def _build_gdnative_api_struct_header(api): return ret_val - for name in api['extensions']: - out += generate_extension_struct(name, api['extensions'][name], False) + for ext in api['extensions']: + name = ext['name'] + out += generate_extension_struct(name, ext, False) out += [ 'typedef struct godot_gdnative_core_api_struct {', @@ -151,12 +154,14 @@ def _build_gdnative_api_struct_source(api): return ret_val - for name in api['extensions']: - out += get_extension_struct_definition(name, api['extensions'][name], False) + for ext in api['extensions']: + name = ext['name'] + out += get_extension_struct_definition(name, ext, False) out += ['', 'const godot_gdnative_api_struct *gdnative_extensions_pointers[] = {'] - for name in api['extensions']: + for ext in api['extensions']: + name = ext['name'] out += ['\t(godot_gdnative_api_struct *)&api_extension_' + name + '_struct,'] out += ['};\n'] @@ -214,7 +219,8 @@ def _build_gdnative_wrapper_code(api): 'godot_gdnative_core_api_struct *_gdnative_wrapper_api_struct = 0;', ] - for name in api['extensions']: + for ext in api['extensions']: + name = ext['name'] out.append('godot_gdnative_ext_' + name + '_api_struct *_gdnative_wrapper_' + name + '_api_struct = 0;') out += [''] @@ -232,8 +238,9 @@ def _build_gdnative_wrapper_code(api): out.append('}') out.append('') - for name in api['extensions']: - for funcdef in api['extensions'][name]['api']: + for ext in api['extensions']: + name = ext['name'] + for funcdef in ext['api']: args = ', '.join(['%s%s' % (_spaced(t), n) for t, n in funcdef['arguments']]) out.append('%s%s(%s) {' % (_spaced(funcdef['return_type']), funcdef['name'], args)) @@ -267,7 +274,7 @@ def build_gdnative_wrapper_code(target, source, env): if ARGUMENTS.get('gdnative_wrapper', False): - #build wrapper code +#build wrapper code gensource, = gdn_env.Command('gdnative_wrapper_code.gen.cpp', 'gdnative_api.json', build_gdnative_wrapper_code) gd_wrapper_env = env.Clone() diff --git a/modules/gdnative/arvr/arvr_interface_gdnative.cpp b/modules/gdnative/arvr/arvr_interface_gdnative.cpp index 49e0a19d9e..385c020a78 100644 --- a/modules/gdnative/arvr/arvr_interface_gdnative.cpp +++ b/modules/gdnative/arvr/arvr_interface_gdnative.cpp @@ -217,6 +217,10 @@ void ARVRInterfaceGDNative::process() { extern "C" { void GDAPI godot_arvr_register_interface(const godot_arvr_interface_gdnative *p_interface) { + // If our major version is 0 or bigger then 10, we're likely looking at our constructor pointer from an older plugin + ERR_EXPLAINC("GDNative ARVR interfaces build for Godot 3.0 are not supported"); + ERR_FAIL_COND((p_interface->version.major == 0) || (p_interface->version.major > 10)); + Ref<ARVRInterfaceGDNative> new_interface; new_interface.instance(); new_interface->set_interface((godot_arvr_interface_gdnative *const)p_interface); diff --git a/modules/gdnative/config.py b/modules/gdnative/config.py index 68148c4d87..626e9239f8 100644 --- a/modules/gdnative/config.py +++ b/modules/gdnative/config.py @@ -1,4 +1,4 @@ -def can_build(platform): +def can_build(env, platform): return True def configure(env): diff --git a/modules/gdnative/gdnative.cpp b/modules/gdnative/gdnative.cpp index 897588385a..e7ebcc73af 100644 --- a/modules/gdnative/gdnative.cpp +++ b/modules/gdnative/gdnative.cpp @@ -469,7 +469,9 @@ Variant GDNative::call_native(StringName p_native_call_type, StringName p_proced godot_variant result = E->get()(procedure_handle, (godot_array *)&p_arguments); - return *(Variant *)&result; + Variant res = *(Variant *)&result; + godot_variant_destroy(&result); + return res; } Error GDNative::get_symbol(StringName p_procedure_name, void *&r_handle, bool p_optional) { diff --git a/modules/gdnative/gdnative_api.json b/modules/gdnative/gdnative_api.json index f41c3859bd..c16f2d3b40 100644 --- a/modules/gdnative/gdnative_api.json +++ b/modules/gdnative/gdnative_api.json @@ -5756,8 +5756,9 @@ } ] }, - "extensions": { - "nativescript": { + "extensions": [ + { + "name": "nativescript", "type": "NATIVESCRIPT", "version": { "major": 1, @@ -5942,7 +5943,8 @@ } ] }, - "pluginscript": { + { + "name": "pluginscript", "type": "PLUGINSCRIPT", "version": { "major": 1, @@ -5959,11 +5961,12 @@ } ] }, - "arvr": { + { + "name": "arvr", "type": "ARVR", "version": { "major": 1, - "minor": 0 + "minor": 1 }, "next": null, "api": [ @@ -6055,5 +6058,5 @@ } ] } - } + ] } diff --git a/modules/gdnative/include/arvr/godot_arvr.h b/modules/gdnative/include/arvr/godot_arvr.h index b9aedc0bef..63de62b507 100644 --- a/modules/gdnative/include/arvr/godot_arvr.h +++ b/modules/gdnative/include/arvr/godot_arvr.h @@ -37,7 +37,15 @@ extern "C" { #endif +// For future versions of the API we should only add new functions at the end of the structure and use the +// version info to detect whether a call is available + +// Use these to populate version in your plugin +#define GODOTVR_API_MAJOR 1 +#define GODOTVR_API_MINOR 0 + typedef struct { + godot_gdnative_api_version version; /* version of our API */ void *(*constructor)(godot_object *); void (*destructor)(void *); godot_string (*get_name)(const void *); diff --git a/modules/gdnative/include/nativescript/godot_nativescript.h b/modules/gdnative/include/nativescript/godot_nativescript.h index cfbe16fa7d..f28ba352ab 100644 --- a/modules/gdnative/include/nativescript/godot_nativescript.h +++ b/modules/gdnative/include/nativescript/godot_nativescript.h @@ -43,6 +43,9 @@ typedef enum { GODOT_METHOD_RPC_MODE_SYNC, GODOT_METHOD_RPC_MODE_MASTER, GODOT_METHOD_RPC_MODE_SLAVE, + GODOT_METHOD_RPC_MODE_REMOTESYNC, + GODOT_METHOD_RPC_MODE_MASTERSYNC, + GODOT_METHOD_RPC_MODE_SLAVESYNC, } godot_method_rpc_mode; typedef enum { diff --git a/modules/gdnative/nativescript/nativescript.cpp b/modules/gdnative/nativescript/nativescript.cpp index cf8977f3ea..d6abbc1bcf 100644 --- a/modules/gdnative/nativescript/nativescript.cpp +++ b/modules/gdnative/nativescript/nativescript.cpp @@ -747,7 +747,7 @@ Ref<Script> NativeScriptInstance::get_script() const { return script; } -NativeScriptInstance::RPCMode NativeScriptInstance::get_rpc_mode(const StringName &p_method) const { +MultiplayerAPI::RPCMode NativeScriptInstance::get_rpc_mode(const StringName &p_method) const { NativeScriptDesc *script_data = GET_SCRIPT_DESC(); @@ -757,27 +757,33 @@ NativeScriptInstance::RPCMode NativeScriptInstance::get_rpc_mode(const StringNam if (E) { switch (E->get().rpc_mode) { case GODOT_METHOD_RPC_MODE_DISABLED: - return RPC_MODE_DISABLED; + return MultiplayerAPI::RPC_MODE_DISABLED; case GODOT_METHOD_RPC_MODE_REMOTE: - return RPC_MODE_REMOTE; + return MultiplayerAPI::RPC_MODE_REMOTE; case GODOT_METHOD_RPC_MODE_SYNC: - return RPC_MODE_SYNC; + return MultiplayerAPI::RPC_MODE_SYNC; case GODOT_METHOD_RPC_MODE_MASTER: - return RPC_MODE_MASTER; + return MultiplayerAPI::RPC_MODE_MASTER; case GODOT_METHOD_RPC_MODE_SLAVE: - return RPC_MODE_SLAVE; + return MultiplayerAPI::RPC_MODE_SLAVE; + case GODOT_METHOD_RPC_MODE_REMOTESYNC: + return MultiplayerAPI::RPC_MODE_REMOTESYNC; + case GODOT_METHOD_RPC_MODE_MASTERSYNC: + return MultiplayerAPI::RPC_MODE_MASTERSYNC; + case GODOT_METHOD_RPC_MODE_SLAVESYNC: + return MultiplayerAPI::RPC_MODE_SLAVESYNC; default: - return RPC_MODE_DISABLED; + return MultiplayerAPI::RPC_MODE_DISABLED; } } script_data = script_data->base_data; } - return RPC_MODE_DISABLED; + return MultiplayerAPI::RPC_MODE_DISABLED; } -NativeScriptInstance::RPCMode NativeScriptInstance::get_rset_mode(const StringName &p_variable) const { +MultiplayerAPI::RPCMode NativeScriptInstance::get_rset_mode(const StringName &p_variable) const { NativeScriptDesc *script_data = GET_SCRIPT_DESC(); @@ -787,24 +793,24 @@ NativeScriptInstance::RPCMode NativeScriptInstance::get_rset_mode(const StringNa if (E) { switch (E.get().rset_mode) { case GODOT_METHOD_RPC_MODE_DISABLED: - return RPC_MODE_DISABLED; + return MultiplayerAPI::RPC_MODE_DISABLED; case GODOT_METHOD_RPC_MODE_REMOTE: - return RPC_MODE_REMOTE; + return MultiplayerAPI::RPC_MODE_REMOTE; case GODOT_METHOD_RPC_MODE_SYNC: - return RPC_MODE_SYNC; + return MultiplayerAPI::RPC_MODE_SYNC; case GODOT_METHOD_RPC_MODE_MASTER: - return RPC_MODE_MASTER; + return MultiplayerAPI::RPC_MODE_MASTER; case GODOT_METHOD_RPC_MODE_SLAVE: - return RPC_MODE_SLAVE; + return MultiplayerAPI::RPC_MODE_SLAVE; default: - return RPC_MODE_DISABLED; + return MultiplayerAPI::RPC_MODE_DISABLED; } } script_data = script_data->base_data; } - return RPC_MODE_DISABLED; + return MultiplayerAPI::RPC_MODE_DISABLED; } ScriptLanguage *NativeScriptInstance::get_language() { diff --git a/modules/gdnative/nativescript/nativescript.h b/modules/gdnative/nativescript/nativescript.h index 68a8126a32..b47962dc37 100644 --- a/modules/gdnative/nativescript/nativescript.h +++ b/modules/gdnative/nativescript/nativescript.h @@ -196,8 +196,8 @@ public: virtual Variant call(const StringName &p_method, const Variant **p_args, int p_argcount, Variant::CallError &r_error); virtual void notification(int p_notification); virtual Ref<Script> get_script() const; - virtual RPCMode get_rpc_mode(const StringName &p_method) const; - virtual RPCMode get_rset_mode(const StringName &p_variable) const; + virtual MultiplayerAPI::RPCMode get_rpc_mode(const StringName &p_method) const; + virtual MultiplayerAPI::RPCMode get_rset_mode(const StringName &p_variable) const; virtual ScriptLanguage *get_language(); virtual void call_multilevel(const StringName &p_method, const Variant **p_args, int p_argcount); diff --git a/modules/gdnative/pluginscript/pluginscript_instance.cpp b/modules/gdnative/pluginscript/pluginscript_instance.cpp index 931ab0bfe4..13026e8e7a 100644 --- a/modules/gdnative/pluginscript/pluginscript_instance.cpp +++ b/modules/gdnative/pluginscript/pluginscript_instance.cpp @@ -138,11 +138,11 @@ void PluginScriptInstance::notification(int p_notification) { _desc->notification(_data, p_notification); } -ScriptInstance::RPCMode PluginScriptInstance::get_rpc_mode(const StringName &p_method) const { +MultiplayerAPI::RPCMode PluginScriptInstance::get_rpc_mode(const StringName &p_method) const { return _script->get_rpc_mode(p_method); } -ScriptInstance::RPCMode PluginScriptInstance::get_rset_mode(const StringName &p_variable) const { +MultiplayerAPI::RPCMode PluginScriptInstance::get_rset_mode(const StringName &p_variable) const { return _script->get_rset_mode(p_variable); } diff --git a/modules/gdnative/pluginscript/pluginscript_instance.h b/modules/gdnative/pluginscript/pluginscript_instance.h index 3c7b360ad9..8be6a4ccaa 100644 --- a/modules/gdnative/pluginscript/pluginscript_instance.h +++ b/modules/gdnative/pluginscript/pluginscript_instance.h @@ -76,8 +76,8 @@ public: void set_path(const String &p_path); - virtual RPCMode get_rpc_mode(const StringName &p_method) const; - virtual RPCMode get_rset_mode(const StringName &p_variable) const; + virtual MultiplayerAPI::RPCMode get_rpc_mode(const StringName &p_method) const; + virtual MultiplayerAPI::RPCMode get_rset_mode(const StringName &p_variable) const; virtual void refcount_incremented(); virtual bool refcount_decremented(); diff --git a/modules/gdnative/pluginscript/pluginscript_script.cpp b/modules/gdnative/pluginscript/pluginscript_script.cpp index 5ae7926f1b..eb2e7903e5 100644 --- a/modules/gdnative/pluginscript/pluginscript_script.cpp +++ b/modules/gdnative/pluginscript/pluginscript_script.cpp @@ -245,9 +245,9 @@ Error PluginScript::reload(bool p_keep_state) { // rpc_mode is passed as an optional field and is not part of MethodInfo Variant var = v["rpc_mode"]; if (var == Variant()) { - _methods_rpc_mode[mi.name] = ScriptInstance::RPC_MODE_DISABLED; + _methods_rpc_mode[mi.name] = MultiplayerAPI::RPC_MODE_DISABLED; } else { - _methods_rpc_mode[mi.name] = ScriptInstance::RPCMode(int(var)); + _methods_rpc_mode[mi.name] = MultiplayerAPI::RPCMode(int(var)); } } Array *signals = (Array *)&manifest.signals; @@ -265,9 +265,9 @@ Error PluginScript::reload(bool p_keep_state) { // rset_mode is passed as an optional field and is not part of PropertyInfo Variant var = v["rset_mode"]; if (var == Variant()) { - _methods_rpc_mode[pi.name] = ScriptInstance::RPC_MODE_DISABLED; + _methods_rpc_mode[pi.name] = MultiplayerAPI::RPC_MODE_DISABLED; } else { - _methods_rpc_mode[pi.name] = ScriptInstance::RPCMode(int(var)); + _methods_rpc_mode[pi.name] = MultiplayerAPI::RPCMode(int(var)); } } // Manifest's attributes must be explicitly freed @@ -402,23 +402,23 @@ int PluginScript::get_member_line(const StringName &p_member) const { return -1; } -ScriptInstance::RPCMode PluginScript::get_rpc_mode(const StringName &p_method) const { - ASSERT_SCRIPT_VALID_V(ScriptInstance::RPC_MODE_DISABLED); - const Map<StringName, ScriptInstance::RPCMode>::Element *e = _methods_rpc_mode.find(p_method); +MultiplayerAPI::RPCMode PluginScript::get_rpc_mode(const StringName &p_method) const { + ASSERT_SCRIPT_VALID_V(MultiplayerAPI::RPC_MODE_DISABLED); + const Map<StringName, MultiplayerAPI::RPCMode>::Element *e = _methods_rpc_mode.find(p_method); if (e != NULL) { return e->get(); } else { - return ScriptInstance::RPC_MODE_DISABLED; + return MultiplayerAPI::RPC_MODE_DISABLED; } } -ScriptInstance::RPCMode PluginScript::get_rset_mode(const StringName &p_variable) const { - ASSERT_SCRIPT_VALID_V(ScriptInstance::RPC_MODE_DISABLED); - const Map<StringName, ScriptInstance::RPCMode>::Element *e = _variables_rset_mode.find(p_variable); +MultiplayerAPI::RPCMode PluginScript::get_rset_mode(const StringName &p_variable) const { + ASSERT_SCRIPT_VALID_V(MultiplayerAPI::RPC_MODE_DISABLED); + const Map<StringName, MultiplayerAPI::RPCMode>::Element *e = _variables_rset_mode.find(p_variable); if (e != NULL) { return e->get(); } else { - return ScriptInstance::RPC_MODE_DISABLED; + return MultiplayerAPI::RPC_MODE_DISABLED; } } diff --git a/modules/gdnative/pluginscript/pluginscript_script.h b/modules/gdnative/pluginscript/pluginscript_script.h index 1be9e907c2..31c6c4d67f 100644 --- a/modules/gdnative/pluginscript/pluginscript_script.h +++ b/modules/gdnative/pluginscript/pluginscript_script.h @@ -62,8 +62,8 @@ private: Map<StringName, PropertyInfo> _properties_info; Map<StringName, MethodInfo> _signals_info; Map<StringName, MethodInfo> _methods_info; - Map<StringName, ScriptInstance::RPCMode> _variables_rset_mode; - Map<StringName, ScriptInstance::RPCMode> _methods_rpc_mode; + Map<StringName, MultiplayerAPI::RPCMode> _variables_rset_mode; + Map<StringName, MultiplayerAPI::RPCMode> _methods_rpc_mode; Set<Object *> _instances; //exported members @@ -116,8 +116,8 @@ public: virtual int get_member_line(const StringName &p_member) const; - ScriptInstance::RPCMode get_rpc_mode(const StringName &p_method) const; - ScriptInstance::RPCMode get_rset_mode(const StringName &p_variable) const; + MultiplayerAPI::RPCMode get_rpc_mode(const StringName &p_method) const; + MultiplayerAPI::RPCMode get_rset_mode(const StringName &p_variable) const; PluginScript(); void init(PluginScriptLanguage *language); diff --git a/modules/gdscript/SCsub b/modules/gdscript/SCsub index 13870170a5..73f09f1659 100644 --- a/modules/gdscript/SCsub +++ b/modules/gdscript/SCsub @@ -7,4 +7,7 @@ env_gdscript = env_modules.Clone() env_gdscript.add_source_files(env.modules_sources, "*.cpp") +if env['tools']: + env_gdscript.add_source_files(env.modules_sources, "./editor/*.cpp") + Export('env') diff --git a/modules/gdscript/config.py b/modules/gdscript/config.py index 6496b59d75..95b40d90af 100644 --- a/modules/gdscript/config.py +++ b/modules/gdscript/config.py @@ -1,4 +1,4 @@ -def can_build(platform): +def can_build(env, platform): return True def configure(env): diff --git a/modules/gdscript/gdscript_highlighter.cpp b/modules/gdscript/editor/gdscript_highlighter.cpp index 4e89851bf2..ea3efff9cf 100644 --- a/modules/gdscript/gdscript_highlighter.cpp +++ b/modules/gdscript/editor/gdscript_highlighter.cpp @@ -29,6 +29,8 @@ /*************************************************************************/ #include "gdscript_highlighter.h" +#include "../gdscript_tokenizer.h" +#include "editor/editor_settings.h" #include "scene/gui/text_edit.h" inline bool _is_symbol(CharType c) { @@ -61,12 +63,20 @@ static bool _is_hex_symbol(CharType c) { Map<int, TextEdit::HighlighterInfo> GDScriptSyntaxHighlighter::_get_line_syntax_highlighting(int p_line) { Map<int, TextEdit::HighlighterInfo> color_map; + Type next_type = NONE; + Type current_type = NONE; + Type previous_type = NONE; + + String previous_text = ""; + int previous_column = 0; + bool prev_is_char = false; bool prev_is_number = false; bool in_keyword = false; bool in_word = false; bool in_function_name = false; bool in_member_variable = false; + bool in_node_path = false; bool is_hex_notation = false; Color keyword_color; Color color; @@ -214,18 +224,64 @@ Map<int, TextEdit::HighlighterInfo> GDScriptSyntaxHighlighter::_get_line_syntax_ in_member_variable = false; } - if (in_region >= 0) + if (!in_node_path && in_region == -1 && str[j] == '$') { + in_node_path = true; + } else if (in_region != -1 || (is_symbol && str[j] != '/')) { + in_node_path = false; + } + + if (in_region >= 0) { + next_type = REGION; color = text_editor->_get_color_region(in_region).color; - else if (in_keyword) + } else if (in_node_path) { + next_type = NODE_PATH; + color = node_path_color; + } else if (in_keyword) { + next_type = KEYWORD; color = keyword_color; - else if (in_member_variable) + } else if (in_member_variable) { + next_type = MEMBER; color = member_color; - else if (in_function_name) - color = function_color; - else if (is_symbol) + } else if (in_function_name) { + next_type = FUNCTION; + + if (previous_text == GDScriptTokenizer::get_token_name(GDScriptTokenizer::TK_PR_FUNCTION)) { + color = function_definition_color; + } else { + color = function_color; + } + } else if (is_symbol) { + next_type = SYMBOL; color = symbol_color; - else if (is_number) + } else if (is_number) { + next_type = NUMBER; color = number_color; + } else { + next_type = IDENTIFIER; + } + + if (next_type != current_type) { + if (current_type == NONE) { + current_type = next_type; + } else { + previous_type = current_type; + current_type = next_type; + + // no need to store regions... + if (previous_type == REGION) { + previous_text = ""; + previous_column = j; + } else { + String text = str.substr(previous_column, j - previous_column).strip_edges(); + previous_column = j; + + // ignore if just whitespace + if (text != "") { + previous_text = text; + } + } + } + } prev_is_char = is_char; prev_is_number = is_number; @@ -255,6 +311,9 @@ void GDScriptSyntaxHighlighter::_update_cache() { function_color = text_editor->get_color("function_color"); number_color = text_editor->get_color("number_color"); member_color = text_editor->get_color("member_variable_color"); + + function_definition_color = EDITOR_DEF("text_editor/highlighting/gdscript/function_definition_color", Color::html("#01e1ff")); + node_path_color = EDITOR_DEF("text_editor/highlighting/gdscript/node_path_color", Color::html("#64c15a")); } SyntaxHighlighter *GDScriptSyntaxHighlighter::create() { diff --git a/modules/gdscript/gdscript_highlighter.h b/modules/gdscript/editor/gdscript_highlighter.h index ef1bdd4103..0296ab7652 100644 --- a/modules/gdscript/gdscript_highlighter.h +++ b/modules/gdscript/editor/gdscript_highlighter.h @@ -35,13 +35,27 @@ class GDScriptSyntaxHighlighter : public SyntaxHighlighter { private: + enum Type { + NONE, + REGION, + NODE_PATH, + SYMBOL, + NUMBER, + FUNCTION, + KEYWORD, + MEMBER, + IDENTIFIER + }; + // colours Color font_color; Color symbol_color; Color function_color; + Color function_definition_color; Color built_in_type_color; Color number_color; Color member_color; + Color node_path_color; public: static SyntaxHighlighter *create(); diff --git a/modules/gdscript/gdscript.cpp b/modules/gdscript/gdscript.cpp index 4e3ee4d22c..f23e7854a5 100644 --- a/modules/gdscript/gdscript.cpp +++ b/modules/gdscript/gdscript.cpp @@ -1220,7 +1220,7 @@ ScriptLanguage *GDScriptInstance::get_language() { return GDScriptLanguage::get_singleton(); } -GDScriptInstance::RPCMode GDScriptInstance::get_rpc_mode(const StringName &p_method) const { +MultiplayerAPI::RPCMode GDScriptInstance::get_rpc_mode(const StringName &p_method) const { const GDScript *cscript = script.ptr(); @@ -1228,17 +1228,17 @@ GDScriptInstance::RPCMode GDScriptInstance::get_rpc_mode(const StringName &p_met const Map<StringName, GDScriptFunction *>::Element *E = cscript->member_functions.find(p_method); if (E) { - if (E->get()->get_rpc_mode() != RPC_MODE_DISABLED) { + if (E->get()->get_rpc_mode() != MultiplayerAPI::RPC_MODE_DISABLED) { return E->get()->get_rpc_mode(); } } cscript = cscript->_base; } - return RPC_MODE_DISABLED; + return MultiplayerAPI::RPC_MODE_DISABLED; } -GDScriptInstance::RPCMode GDScriptInstance::get_rset_mode(const StringName &p_variable) const { +MultiplayerAPI::RPCMode GDScriptInstance::get_rset_mode(const StringName &p_variable) const { const GDScript *cscript = script.ptr(); @@ -1253,7 +1253,7 @@ GDScriptInstance::RPCMode GDScriptInstance::get_rset_mode(const StringName &p_va cscript = cscript->_base; } - return RPC_MODE_DISABLED; + return MultiplayerAPI::RPC_MODE_DISABLED; } void GDScriptInstance::reload_members() { @@ -1333,6 +1333,15 @@ void GDScriptLanguage::add_global_constant(const StringName &p_variable, const V _add_global(p_variable, p_value); } +void GDScriptLanguage::add_named_global_constant(const StringName &p_name, const Variant &p_value) { + named_globals[p_name] = p_value; +} + +void GDScriptLanguage::remove_named_global_constant(const StringName &p_name) { + ERR_FAIL_COND(!named_globals.has(p_name)); + named_globals.erase(p_name); +} + void GDScriptLanguage::init() { //populate global constants @@ -1760,6 +1769,9 @@ void GDScriptLanguage::get_reserved_words(List<String> *p_words) const { "sync", "master", "slave", + "remotesync", + "mastersync", + "slavesync", 0 }; diff --git a/modules/gdscript/gdscript.h b/modules/gdscript/gdscript.h index 9566e3b32e..a35b0a10d5 100644 --- a/modules/gdscript/gdscript.h +++ b/modules/gdscript/gdscript.h @@ -63,7 +63,7 @@ class GDScript : public Script { int index; StringName setter; StringName getter; - ScriptInstance::RPCMode rpc_mode; + MultiplayerAPI::RPCMode rpc_mode; }; friend class GDScriptInstance; @@ -248,8 +248,8 @@ public: void reload_members(); - virtual RPCMode get_rpc_mode(const StringName &p_method) const; - virtual RPCMode get_rset_mode(const StringName &p_variable) const; + virtual MultiplayerAPI::RPCMode get_rpc_mode(const StringName &p_method) const; + virtual MultiplayerAPI::RPCMode get_rset_mode(const StringName &p_variable) const; GDScriptInstance(); ~GDScriptInstance(); @@ -262,6 +262,7 @@ class GDScriptLanguage : public ScriptLanguage { Variant *_global_array; Vector<Variant> global_array; Map<StringName, int> globals; + Map<StringName, Variant> named_globals; struct CallLevel { @@ -369,7 +370,8 @@ public: _FORCE_INLINE_ int get_global_array_size() const { return global_array.size(); } _FORCE_INLINE_ Variant *get_global_array() { return _global_array; } - _FORCE_INLINE_ const Map<StringName, int> &get_global_map() { return globals; } + _FORCE_INLINE_ const Map<StringName, int> &get_global_map() const { return globals; } + _FORCE_INLINE_ const Map<StringName, Variant> &get_named_globals_map() const { return named_globals; } _FORCE_INLINE_ static GDScriptLanguage *get_singleton() { return singleton; } @@ -403,6 +405,8 @@ public: virtual String _get_indentation() const; virtual void auto_indent_code(String &p_code, int p_from_line, int p_to_line) const; virtual void add_global_constant(const StringName &p_variable, const Variant &p_value); + virtual void add_named_global_constant(const StringName &p_name, const Variant &p_value); + virtual void remove_named_global_constant(const StringName &p_name); /* DEBUGGER FUNCTIONS */ diff --git a/modules/gdscript/gdscript_compiler.cpp b/modules/gdscript/gdscript_compiler.cpp index 048948dada..5c834966c5 100644 --- a/modules/gdscript/gdscript_compiler.cpp +++ b/modules/gdscript/gdscript_compiler.cpp @@ -278,6 +278,18 @@ int GDScriptCompiler::_parse_expression(CodeGen &codegen, const GDScriptParser:: return idx | (GDScriptFunction::ADDR_TYPE_GLOBAL << GDScriptFunction::ADDR_BITS); //argument (stack root) } +#ifdef TOOLS_ENABLED + if (GDScriptLanguage::get_singleton()->get_named_globals_map().has(identifier)) { + + int idx = codegen.named_globals.find(identifier); + if (idx == -1) { + idx = codegen.named_globals.size(); + codegen.named_globals.push_back(identifier); + } + return idx | (GDScriptFunction::ADDR_TYPE_NAMED_GLOBAL << GDScriptFunction::ADDR_BITS); + } +#endif + //not found, error _set_error("Identifier not found: " + String(identifier), p_expression); @@ -726,6 +738,9 @@ int GDScriptCompiler::_parse_expression(CodeGen &codegen, const GDScriptParser:: case GDScriptParser::OperatorNode::OP_NEG: { if (!_create_unary_operator(codegen, on, Variant::OP_NEGATE, p_stack_level)) return -1; } break; + case GDScriptParser::OperatorNode::OP_POS: { + if (!_create_unary_operator(codegen, on, Variant::OP_POSITIVE, p_stack_level)) return -1; + } break; case GDScriptParser::OperatorNode::OP_NOT: { if (!_create_unary_operator(codegen, on, Variant::OP_NOT, p_stack_level)) return -1; } break; @@ -1511,6 +1526,18 @@ Error GDScriptCompiler::_parse_function(GDScript *p_script, const GDScriptParser gdfunc->_global_names_count = 0; } +#ifdef TOOLS_ENABLED + // Named globals + if (codegen.named_globals.size()) { + gdfunc->named_globals.resize(codegen.named_globals.size()); + gdfunc->_named_globals_ptr = gdfunc->named_globals.ptr(); + for (int i = 0; i < codegen.named_globals.size(); i++) { + gdfunc->named_globals[i] = codegen.named_globals[i]; + } + gdfunc->_named_globals_count = gdfunc->named_globals.size(); + } +#endif + if (codegen.opcodes.size()) { gdfunc->code = codegen.opcodes; diff --git a/modules/gdscript/gdscript_compiler.h b/modules/gdscript/gdscript_compiler.h index 62aafdbe01..237b0de9e7 100644 --- a/modules/gdscript/gdscript_compiler.h +++ b/modules/gdscript/gdscript_compiler.h @@ -94,6 +94,9 @@ class GDScriptCompiler { HashMap<Variant, int, VariantHasher, VariantComparator> constant_map; Map<StringName, int> name_map; +#ifdef TOOLS_ENABLED + Vector<StringName> named_globals; +#endif int get_name_map_pos(const StringName &p_identifier) { int ret; diff --git a/modules/gdscript/gdscript_editor.cpp b/modules/gdscript/gdscript_editor.cpp index 87e1276492..4286412c14 100644 --- a/modules/gdscript/gdscript_editor.cpp +++ b/modules/gdscript/gdscript_editor.cpp @@ -416,7 +416,7 @@ String GDScriptLanguage::make_function(const String &p_class, const String &p_na s += p_args[i].get_slice(":", 0); } } - s += "):\n" + _get_indentation() + "pass # replace with function body\n"; + s += "):\n" + _get_indentation() + "pass # Replace with function body.\n"; return s; } @@ -2636,6 +2636,13 @@ Error GDScriptLanguage::lookup_code(const String &p_code, const String &p_symbol } } + if ("PI" == p_symbol || "TAU" == p_symbol || "INF" == p_symbol || "NAN" == p_symbol) { + r_result.type = ScriptLanguage::LookupResult::RESULT_CLASS_CONSTANT; + r_result.class_name = "@GDScript"; + r_result.class_member = p_symbol; + return OK; + } + GDScriptParser p; p.parse(p_code, p_base_path, false, "", true); diff --git a/modules/gdscript/gdscript_function.cpp b/modules/gdscript/gdscript_function.cpp index 1c5b8187ca..61130cb58f 100644 --- a/modules/gdscript/gdscript_function.cpp +++ b/modules/gdscript/gdscript_function.cpp @@ -108,6 +108,21 @@ Variant *GDScriptFunction::_get_variant(int p_address, GDScriptInstance *p_insta #endif return &GDScriptLanguage::get_singleton()->get_global_array()[address]; } break; +#ifdef TOOLS_ENABLED + case ADDR_TYPE_NAMED_GLOBAL: { +#ifdef DEBUG_ENABLED + ERR_FAIL_INDEX_V(address, _named_globals_count, NULL); +#endif + StringName id = _named_globals_ptr[address]; + + if (GDScriptLanguage::get_singleton()->get_named_globals_map().has(id)) { + return (Variant *)&GDScriptLanguage::get_singleton()->get_named_globals_map()[id]; + } else { + r_error = "Autoload singleton '" + String(id) + "' has been removed."; + return NULL; + } + } break; +#endif case ADDR_TYPE_NIL: { return &nil; } break; @@ -1440,7 +1455,7 @@ GDScriptFunction::GDScriptFunction() : _stack_size = 0; _call_size = 0; - rpc_mode = ScriptInstance::RPC_MODE_DISABLED; + rpc_mode = MultiplayerAPI::RPC_MODE_DISABLED; name = "<anonymous>"; #ifdef DEBUG_ENABLED _func_cname = NULL; diff --git a/modules/gdscript/gdscript_function.h b/modules/gdscript/gdscript_function.h index dff4bdfaf2..836325f0fe 100644 --- a/modules/gdscript/gdscript_function.h +++ b/modules/gdscript/gdscript_function.h @@ -92,15 +92,8 @@ public: ADDR_TYPE_STACK = 5, ADDR_TYPE_STACK_VARIABLE = 6, ADDR_TYPE_GLOBAL = 7, - ADDR_TYPE_NIL = 8 - }; - - enum RPCMode { - RPC_DISABLED, - RPC_ENABLED, - RPC_SYNC, - RPC_SYNC_MASTER, - RPC_SYNC_SLAVE + ADDR_TYPE_NAMED_GLOBAL = 8, + ADDR_TYPE_NIL = 9 }; struct StackDebug { @@ -121,6 +114,10 @@ private: int _constant_count; const StringName *_global_names_ptr; int _global_names_count; +#ifdef TOOLS_ENABLED + const StringName *_named_globals_ptr; + int _named_globals_count; +#endif const int *_default_arg_ptr; int _default_arg_count; const int *_code_ptr; @@ -130,13 +127,16 @@ private: int _call_size; int _initial_line; bool _static; - ScriptInstance::RPCMode rpc_mode; + MultiplayerAPI::RPCMode rpc_mode; GDScript *_script; StringName name; Vector<Variant> constants; Vector<StringName> global_names; +#ifdef TOOLS_ENABLED + Vector<StringName> named_globals; +#endif Vector<int> default_arguments; Vector<int> code; @@ -222,7 +222,7 @@ public: Variant call(GDScriptInstance *p_instance, const Variant **p_args, int p_argcount, Variant::CallError &r_err, CallState *p_state = NULL); - _FORCE_INLINE_ ScriptInstance::RPCMode get_rpc_mode() const { return rpc_mode; } + _FORCE_INLINE_ MultiplayerAPI::RPCMode get_rpc_mode() const { return rpc_mode; } GDScriptFunction(); ~GDScriptFunction(); }; diff --git a/modules/gdscript/gdscript_parser.cpp b/modules/gdscript/gdscript_parser.cpp index e7b0700e76..fdb92a68a9 100644 --- a/modules/gdscript/gdscript_parser.cpp +++ b/modules/gdscript/gdscript_parser.cpp @@ -716,6 +716,14 @@ GDScriptParser::Node *GDScriptParser::_parse_expression(Node *p_parent, bool p_s expr = constant; bfn = true; } + + if (!bfn && GDScriptLanguage::get_singleton()->get_named_globals_map().has(identifier)) { + //check from singletons + ConstantNode *constant = alloc_node<ConstantNode>(); + constant->value = GDScriptLanguage::get_singleton()->get_named_globals_map()[identifier]; + expr = constant; + bfn = true; + } } if (!bfn) { @@ -3365,7 +3373,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) { function->line = fnline; function->rpc_mode = rpc_mode; - rpc_mode = ScriptInstance::RPC_MODE_DISABLED; + rpc_mode = MultiplayerAPI::RPC_MODE_DISABLED; if (_static) p_class->static_functions.push_back(function); @@ -3923,10 +3931,10 @@ void GDScriptParser::_parse_class(ClassNode *p_class) { tokenizer->advance(); } - if (tokenizer->get_token() != GDScriptTokenizer::TK_PR_VAR && tokenizer->get_token() != GDScriptTokenizer::TK_PR_ONREADY && tokenizer->get_token() != GDScriptTokenizer::TK_PR_REMOTE && tokenizer->get_token() != GDScriptTokenizer::TK_PR_MASTER && tokenizer->get_token() != GDScriptTokenizer::TK_PR_SLAVE && tokenizer->get_token() != GDScriptTokenizer::TK_PR_SYNC) { + if (tokenizer->get_token() != GDScriptTokenizer::TK_PR_VAR && tokenizer->get_token() != GDScriptTokenizer::TK_PR_ONREADY && tokenizer->get_token() != GDScriptTokenizer::TK_PR_REMOTE && tokenizer->get_token() != GDScriptTokenizer::TK_PR_MASTER && tokenizer->get_token() != GDScriptTokenizer::TK_PR_SLAVE && tokenizer->get_token() != GDScriptTokenizer::TK_PR_SYNC && tokenizer->get_token() != GDScriptTokenizer::TK_PR_REMOTESYNC && tokenizer->get_token() != GDScriptTokenizer::TK_PR_MASTERSYNC && tokenizer->get_token() != GDScriptTokenizer::TK_PR_SLAVESYNC) { current_export = PropertyInfo(); - _set_error("Expected 'var', 'onready', 'remote', 'master', 'slave' or 'sync'."); + _set_error("Expected 'var', 'onready', 'remote', 'master', 'slave', 'sync', 'remotesync', 'mastersync', 'slavesync'."); return; } @@ -3959,7 +3967,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) { return; } } - rpc_mode = ScriptInstance::RPC_MODE_REMOTE; + rpc_mode = MultiplayerAPI::RPC_MODE_REMOTE; continue; } break; @@ -3980,7 +3988,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) { } } - rpc_mode = ScriptInstance::RPC_MODE_MASTER; + rpc_mode = MultiplayerAPI::RPC_MODE_MASTER; continue; } break; case GDScriptTokenizer::TK_PR_SLAVE: { @@ -4000,9 +4008,10 @@ void GDScriptParser::_parse_class(ClassNode *p_class) { } } - rpc_mode = ScriptInstance::RPC_MODE_SLAVE; + rpc_mode = MultiplayerAPI::RPC_MODE_SLAVE; continue; } break; + case GDScriptTokenizer::TK_PR_REMOTESYNC: case GDScriptTokenizer::TK_PR_SYNC: { //may be fallthrough from export, ignore if so @@ -4015,7 +4024,37 @@ void GDScriptParser::_parse_class(ClassNode *p_class) { return; } - rpc_mode = ScriptInstance::RPC_MODE_SYNC; + rpc_mode = MultiplayerAPI::RPC_MODE_SYNC; + continue; + } break; + case GDScriptTokenizer::TK_PR_MASTERSYNC: { + + //may be fallthrough from export, ignore if so + tokenizer->advance(); + if (tokenizer->get_token() != GDScriptTokenizer::TK_PR_VAR && tokenizer->get_token() != GDScriptTokenizer::TK_PR_FUNCTION) { + if (current_export.type) + _set_error("Expected 'var'."); + else + _set_error("Expected 'var' or 'func'."); + return; + } + + rpc_mode = MultiplayerAPI::RPC_MODE_MASTERSYNC; + continue; + } break; + case GDScriptTokenizer::TK_PR_SLAVESYNC: { + + //may be fallthrough from export, ignore if so + tokenizer->advance(); + if (tokenizer->get_token() != GDScriptTokenizer::TK_PR_VAR && tokenizer->get_token() != GDScriptTokenizer::TK_PR_FUNCTION) { + if (current_export.type) + _set_error("Expected 'var'."); + else + _set_error("Expected 'var' or 'func'."); + return; + } + + rpc_mode = MultiplayerAPI::RPC_MODE_SLAVESYNC; continue; } break; case GDScriptTokenizer::TK_PR_VAR: { @@ -4045,7 +4084,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) { tokenizer->advance(); - rpc_mode = ScriptInstance::RPC_MODE_DISABLED; + rpc_mode = MultiplayerAPI::RPC_MODE_DISABLED; if (tokenizer->get_token() == GDScriptTokenizer::TK_OP_ASSIGN) { @@ -4470,7 +4509,7 @@ void GDScriptParser::clear() { current_class = NULL; completion_found = false; - rpc_mode = ScriptInstance::RPC_MODE_DISABLED; + rpc_mode = MultiplayerAPI::RPC_MODE_DISABLED; current_function = NULL; diff --git a/modules/gdscript/gdscript_parser.h b/modules/gdscript/gdscript_parser.h index 485ba1263d..b88a59537c 100644 --- a/modules/gdscript/gdscript_parser.h +++ b/modules/gdscript/gdscript_parser.h @@ -89,7 +89,7 @@ public: StringName getter; int line; Node *expression; - ScriptInstance::RPCMode rpc_mode; + MultiplayerAPI::RPCMode rpc_mode; }; struct Constant { StringName identifier; @@ -125,7 +125,7 @@ public: struct FunctionNode : public Node { bool _static; - ScriptInstance::RPCMode rpc_mode; + MultiplayerAPI::RPCMode rpc_mode; StringName name; Vector<StringName> arguments; Vector<Node *> default_values; @@ -134,7 +134,7 @@ public: FunctionNode() { type = TYPE_FUNCTION; _static = false; - rpc_mode = ScriptInstance::RPC_MODE_DISABLED; + rpc_mode = MultiplayerAPI::RPC_MODE_DISABLED; } }; @@ -493,7 +493,7 @@ private: PropertyInfo current_export; - ScriptInstance::RPCMode rpc_mode; + MultiplayerAPI::RPCMode rpc_mode; void _set_error(const String &p_error, int p_line = -1, int p_column = -1); bool _recover_from_completion(); diff --git a/modules/gdscript/gdscript_tokenizer.cpp b/modules/gdscript/gdscript_tokenizer.cpp index 6a844cd651..3c8e1ddbe4 100644 --- a/modules/gdscript/gdscript_tokenizer.cpp +++ b/modules/gdscript/gdscript_tokenizer.cpp @@ -110,6 +110,9 @@ const char *GDScriptTokenizer::token_names[TK_MAX] = { "sync", "master", "slave", + "remotesync", + "mastersync", + "slavesync", "'['", "']'", "'{'", @@ -201,6 +204,9 @@ static const _kws _keyword_list[] = { { GDScriptTokenizer::TK_PR_MASTER, "master" }, { GDScriptTokenizer::TK_PR_SLAVE, "slave" }, { GDScriptTokenizer::TK_PR_SYNC, "sync" }, + { GDScriptTokenizer::TK_PR_REMOTESYNC, "remotesync" }, + { GDScriptTokenizer::TK_PR_MASTERSYNC, "mastersync" }, + { GDScriptTokenizer::TK_PR_SLAVESYNC, "slavesync" }, { GDScriptTokenizer::TK_PR_CONST, "const" }, { GDScriptTokenizer::TK_PR_ENUM, "enum" }, //controlflow @@ -247,6 +253,9 @@ bool GDScriptTokenizer::is_token_literal(int p_offset, bool variable_safe) const case TK_PR_MASTER: case TK_PR_SLAVE: case TK_PR_SYNC: + case TK_PR_REMOTESYNC: + case TK_PR_MASTERSYNC: + case TK_PR_SLAVESYNC: return true; // Literal for non-variables only: diff --git a/modules/gdscript/gdscript_tokenizer.h b/modules/gdscript/gdscript_tokenizer.h index b020c85199..c4f1f9fd94 100644 --- a/modules/gdscript/gdscript_tokenizer.h +++ b/modules/gdscript/gdscript_tokenizer.h @@ -115,6 +115,9 @@ public: TK_PR_SYNC, TK_PR_MASTER, TK_PR_SLAVE, + TK_PR_REMOTESYNC, + TK_PR_MASTERSYNC, + TK_PR_SLAVESYNC, TK_BRACKET_OPEN, TK_BRACKET_CLOSE, TK_CURLY_BRACKET_OPEN, diff --git a/modules/gdscript/register_types.cpp b/modules/gdscript/register_types.cpp index 85c94c3596..422223370b 100644 --- a/modules/gdscript/register_types.cpp +++ b/modules/gdscript/register_types.cpp @@ -30,8 +30,8 @@ #include "register_types.h" +#include "editor/gdscript_highlighter.h" #include "gdscript.h" -#include "gdscript_highlighter.h" #include "gdscript_tokenizer.h" #include "io/file_access_encrypted.h" #include "io/resource_loader.h" diff --git a/modules/gridmap/config.py b/modules/gridmap/config.py index a93f4edb81..5022116c9b 100644 --- a/modules/gridmap/config.py +++ b/modules/gridmap/config.py @@ -1,4 +1,4 @@ -def can_build(platform): +def can_build(env, platform): return True def configure(env): diff --git a/modules/hdr/config.py b/modules/hdr/config.py index 5f133eba90..1c8cd12a2d 100644 --- a/modules/hdr/config.py +++ b/modules/hdr/config.py @@ -1,4 +1,4 @@ -def can_build(platform): +def can_build(env, platform): return True def configure(env): diff --git a/modules/jpg/config.py b/modules/jpg/config.py index 5f133eba90..1c8cd12a2d 100644 --- a/modules/jpg/config.py +++ b/modules/jpg/config.py @@ -1,4 +1,4 @@ -def can_build(platform): +def can_build(env, platform): return True def configure(env): diff --git a/modules/mbedtls/config.py b/modules/mbedtls/config.py index 5f133eba90..1c8cd12a2d 100755 --- a/modules/mbedtls/config.py +++ b/modules/mbedtls/config.py @@ -1,4 +1,4 @@ -def can_build(platform): +def can_build(env, platform): return True def configure(env): diff --git a/modules/mobile_vr/config.py b/modules/mobile_vr/config.py index aa8ef111d3..4912457e2b 100644 --- a/modules/mobile_vr/config.py +++ b/modules/mobile_vr/config.py @@ -1,4 +1,4 @@ -def can_build(platform): +def can_build(env, platform): # should probably change this to only be true on iOS and Android return False diff --git a/modules/mono/config.py b/modules/mono/config.py index 18d9c67795..8b52d77f80 100644 --- a/modules/mono/config.py +++ b/modules/mono/config.py @@ -19,7 +19,7 @@ def find_file_in_dir(directory, files, prefix='', extension=''): return '' -def can_build(platform): +def can_build(env, platform): if platform in ["javascript"]: return False # Not yet supported return True @@ -80,7 +80,11 @@ def configure(env): if mono_static: lib_suffix = Environment()['LIBSUFFIX'] - mono_static_lib_name = 'libmono-static-sgen' + + if env.msvc: + mono_static_lib_name = 'libmono-static-sgen' + else: + mono_static_lib_name = 'libmonosgen-2.0' if not os.path.isfile(os.path.join(mono_lib_path, mono_static_lib_name + lib_suffix)): raise RuntimeError('Could not find static mono library in: ' + mono_lib_path) @@ -93,7 +97,10 @@ def configure(env): env.Append(LINKFLAGS='LIBCMT' + lib_suffix) env.Append(LINKFLAGS='Psapi' + lib_suffix) else: - env.Append(LIBS=mono_static_lib_name) + env.Append(LINKFLAGS=os.path.join(mono_lib_path, mono_static_lib_name + lib_suffix)) + + env.Append(LIBS='psapi') + env.Append(LIBS='version') else: mono_lib_name = find_file_in_dir(mono_lib_path, mono_lib_names, extension='.lib') diff --git a/modules/mono/csharp_script.cpp b/modules/mono/csharp_script.cpp index bbe245951e..46c40b2690 100644 --- a/modules/mono/csharp_script.cpp +++ b/modules/mono/csharp_script.cpp @@ -446,7 +446,7 @@ String CSharpLanguage::make_function(const String &p_class, const String &p_name s += variant_type_to_managed_name(arg.get_slice(":", 1)) + " " + escape_csharp_keyword(arg.get_slice(":", 0)); } - s += ")\n{\n // Replace with function body\n}\n"; + s += ")\n{\n // Replace with function body.\n}\n"; return s; #else @@ -782,7 +782,7 @@ void CSharpLanguage::reload_assemblies_if_needed(bool p_soft_reload) { } if (Engine::get_singleton()->is_editor_hint()) { - EditorNode::get_singleton()->get_property_editor()->update_tree(); + EditorNode::get_singleton()->get_inspector()->update_tree(); NodeDock::singleton->update_lists(); } } @@ -1310,21 +1310,27 @@ bool CSharpInstance::refcount_decremented() { return ref_dying; } -ScriptInstance::RPCMode CSharpInstance::_member_get_rpc_mode(GDMonoClassMember *p_member) const { +MultiplayerAPI::RPCMode CSharpInstance::_member_get_rpc_mode(GDMonoClassMember *p_member) const { if (p_member->has_attribute(CACHED_CLASS(RemoteAttribute))) - return RPC_MODE_REMOTE; + return MultiplayerAPI::RPC_MODE_REMOTE; if (p_member->has_attribute(CACHED_CLASS(SyncAttribute))) - return RPC_MODE_SYNC; + return MultiplayerAPI::RPC_MODE_SYNC; if (p_member->has_attribute(CACHED_CLASS(MasterAttribute))) - return RPC_MODE_MASTER; + return MultiplayerAPI::RPC_MODE_MASTER; if (p_member->has_attribute(CACHED_CLASS(SlaveAttribute))) - return RPC_MODE_SLAVE; + return MultiplayerAPI::RPC_MODE_SLAVE; + if (p_member->has_attribute(CACHED_CLASS(RemoteSyncAttribute))) + return MultiplayerAPI::RPC_MODE_REMOTESYNC; + if (p_member->has_attribute(CACHED_CLASS(MasterSyncAttribute))) + return MultiplayerAPI::RPC_MODE_MASTERSYNC; + if (p_member->has_attribute(CACHED_CLASS(SlaveSyncAttribute))) + return MultiplayerAPI::RPC_MODE_SLAVESYNC; - return RPC_MODE_DISABLED; + return MultiplayerAPI::RPC_MODE_DISABLED; } -ScriptInstance::RPCMode CSharpInstance::get_rpc_mode(const StringName &p_method) const { +MultiplayerAPI::RPCMode CSharpInstance::get_rpc_mode(const StringName &p_method) const { GDMonoClass *top = script->script_class; @@ -1337,10 +1343,10 @@ ScriptInstance::RPCMode CSharpInstance::get_rpc_mode(const StringName &p_method) top = top->get_parent_class(); } - return RPC_MODE_DISABLED; + return MultiplayerAPI::RPC_MODE_DISABLED; } -ScriptInstance::RPCMode CSharpInstance::get_rset_mode(const StringName &p_variable) const { +MultiplayerAPI::RPCMode CSharpInstance::get_rset_mode(const StringName &p_variable) const { GDMonoClass *top = script->script_class; @@ -1358,7 +1364,7 @@ ScriptInstance::RPCMode CSharpInstance::get_rset_mode(const StringName &p_variab top = top->get_parent_class(); } - return RPC_MODE_DISABLED; + return MultiplayerAPI::RPC_MODE_DISABLED; } void CSharpInstance::notification(int p_notification) { @@ -1726,6 +1732,12 @@ void CSharpScript::_clear() { Variant CSharpScript::call(const StringName &p_method, const Variant **p_args, int p_argcount, Variant::CallError &r_error) { + if (unlikely(GDMono::get_singleton() == NULL)) { + // Probably not the best error but eh. + r_error.error = Variant::CallError::CALL_ERROR_INSTANCE_IS_NULL; + return Variant(); + } + GDMonoClass *top = script_class; while (top && top != native) { @@ -1954,11 +1966,6 @@ Variant CSharpScript::_new(const Variant **p_args, int p_argcount, Variant::Call ScriptInstance *CSharpScript::instance_create(Object *p_this) { - if (!script_class) { - ERR_EXPLAIN("Cannot find class " + name + " for script " + get_path()); - ERR_FAIL_V(NULL); - } - ERR_FAIL_COND_V(!valid, NULL); if (!tool && !ScriptServer::is_scripting_enabled()) { @@ -1973,6 +1980,18 @@ ScriptInstance *CSharpScript::instance_create(Object *p_this) { #endif } + if (!script_class) { + if (GDMono::get_singleton()->get_project_assembly() == NULL) { + // The project assembly is not loaded + ERR_EXPLAIN("Cannot instance script because the project assembly is not loaded. Script: " + get_path()); + ERR_FAIL_V(NULL); + } + + // The project assembly is loaded, but the class could not found + ERR_EXPLAIN("Cannot instance script because the class '" + name + "' could not be found. Script: " + get_path()); + ERR_FAIL_V(NULL); + } + update_signals(); if (native) { diff --git a/modules/mono/csharp_script.h b/modules/mono/csharp_script.h index 8666149111..cae2bbf40a 100644 --- a/modules/mono/csharp_script.h +++ b/modules/mono/csharp_script.h @@ -192,7 +192,7 @@ class CSharpInstance : public ScriptInstance { void _call_multilevel(MonoObject *p_mono_object, const StringName &p_method, const Variant **p_args, int p_argcount); - RPCMode _member_get_rpc_mode(GDMonoClassMember *p_member) const; + MultiplayerAPI::RPCMode _member_get_rpc_mode(GDMonoClassMember *p_member) const; public: MonoObject *get_mono_object() const; @@ -213,8 +213,8 @@ public: virtual void refcount_incremented(); virtual bool refcount_decremented(); - virtual RPCMode get_rpc_mode(const StringName &p_method) const; - virtual RPCMode get_rset_mode(const StringName &p_variable) const; + virtual MultiplayerAPI::RPCMode get_rpc_mode(const StringName &p_method) const; + 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); diff --git a/modules/mono/editor/GodotSharpTools/Build/BuildSystem.cs b/modules/mono/editor/GodotSharpTools/Build/BuildSystem.cs index 04da0600cc..16beacb45c 100644 --- a/modules/mono/editor/GodotSharpTools/Build/BuildSystem.cs +++ b/modules/mono/editor/GodotSharpTools/Build/BuildSystem.cs @@ -16,24 +16,48 @@ namespace GodotSharpTools.Build private extern static void godot_icall_BuildInstance_ExitCallback(string solution, string config, int exitCode); [MethodImpl(MethodImplOptions.InternalCall)] - private extern static void godot_icall_BuildInstance_get_MSBuildInfo(ref string msbuildPath, ref string frameworkPath); + private extern static string godot_icall_BuildInstance_get_MSBuildPath(); + [MethodImpl(MethodImplOptions.InternalCall)] + private extern static string godot_icall_BuildInstance_get_FrameworkPath(); + [MethodImpl(MethodImplOptions.InternalCall)] + private extern static string godot_icall_BuildInstance_get_MonoWindowsBinDir(); + [MethodImpl(MethodImplOptions.InternalCall)] + private extern static bool godot_icall_BuildInstance_get_UsingMonoMSBuildOnWindows(); - private struct MSBuildInfo + private static string GetMSBuildPath() { - public string path; - public string frameworkPathOverride; + string msbuildPath = godot_icall_BuildInstance_get_MSBuildPath(); + + if (msbuildPath == null) + throw new FileNotFoundException("Cannot find the MSBuild executable."); + + return msbuildPath; } - private static MSBuildInfo GetMSBuildInfo() + private static string GetFrameworkPath() { - MSBuildInfo msbuildInfo = new MSBuildInfo(); + return godot_icall_BuildInstance_get_FrameworkPath(); + } - godot_icall_BuildInstance_get_MSBuildInfo(ref msbuildInfo.path, ref msbuildInfo.frameworkPathOverride); + private static string MonoWindowsBinDir + { + get + { + string monoWinBinDir = godot_icall_BuildInstance_get_MonoWindowsBinDir(); - if (msbuildInfo.path == null) - throw new FileNotFoundException("Cannot find the MSBuild executable."); + if (monoWinBinDir == null) + throw new FileNotFoundException("Cannot find the Windows Mono binaries directory."); - return msbuildInfo; + return monoWinBinDir; + } + } + + private static bool UsingMonoMSBuildOnWindows + { + get + { + return godot_icall_BuildInstance_get_UsingMonoMSBuildOnWindows(); + } } private string solution; @@ -54,25 +78,38 @@ namespace GodotSharpTools.Build public bool Build(string loggerAssemblyPath, string loggerOutputDir, string[] customProperties = null) { - MSBuildInfo msbuildInfo = GetMSBuildInfo(); + bool debugMSBuild = IsDebugMSBuildRequested(); List<string> customPropertiesList = new List<string>(); if (customProperties != null) customPropertiesList.AddRange(customProperties); - if (msbuildInfo.frameworkPathOverride != null) - customPropertiesList.Add("FrameworkPathOverride=" + msbuildInfo.frameworkPathOverride); + string frameworkPath = GetFrameworkPath(); + + if (!string.IsNullOrEmpty(frameworkPath)) + customPropertiesList.Add("FrameworkPathOverride=" + frameworkPath); string compilerArgs = BuildArguments(loggerAssemblyPath, loggerOutputDir, customPropertiesList); - ProcessStartInfo startInfo = new ProcessStartInfo(msbuildInfo.path, compilerArgs); + ProcessStartInfo startInfo = new ProcessStartInfo(GetMSBuildPath(), compilerArgs); + + bool redirectOutput = !debugMSBuild; - // No console output, thanks - startInfo.RedirectStandardOutput = true; - startInfo.RedirectStandardError = true; + startInfo.RedirectStandardOutput = redirectOutput; + startInfo.RedirectStandardError = redirectOutput; startInfo.UseShellExecute = false; + if (UsingMonoMSBuildOnWindows) + { + // These environment variables are required for Mono's MSBuild to find the compilers. + // We use the batch files in Mono's bin directory to make sure the compilers are executed with mono. + string monoWinBinDir = MonoWindowsBinDir; + startInfo.EnvironmentVariables.Add("CscToolExe", Path.Combine(monoWinBinDir, "csc.bat")); + startInfo.EnvironmentVariables.Add("VbcToolExe", Path.Combine(monoWinBinDir, "vbc.bat")); + startInfo.EnvironmentVariables.Add("FscToolExe", Path.Combine(monoWinBinDir, "fsharpc.bat")); + } + // Needed when running from Developer Command Prompt for VS RemovePlatformVariable(startInfo.EnvironmentVariables); @@ -82,8 +119,11 @@ namespace GodotSharpTools.Build process.Start(); - process.BeginOutputReadLine(); - process.BeginErrorReadLine(); + if (redirectOutput) + { + process.BeginOutputReadLine(); + process.BeginErrorReadLine(); + } process.WaitForExit(); @@ -95,28 +135,41 @@ namespace GodotSharpTools.Build public bool BuildAsync(string loggerAssemblyPath, string loggerOutputDir, string[] customProperties = null) { + bool debugMSBuild = IsDebugMSBuildRequested(); + if (process != null) throw new InvalidOperationException("Already in use"); - MSBuildInfo msbuildInfo = GetMSBuildInfo(); - List<string> customPropertiesList = new List<string>(); if (customProperties != null) customPropertiesList.AddRange(customProperties); - if (msbuildInfo.frameworkPathOverride.Length > 0) - customPropertiesList.Add("FrameworkPathOverride=" + msbuildInfo.frameworkPathOverride); + string frameworkPath = GetFrameworkPath(); + + if (!string.IsNullOrEmpty(frameworkPath)) + customPropertiesList.Add("FrameworkPathOverride=" + frameworkPath); string compilerArgs = BuildArguments(loggerAssemblyPath, loggerOutputDir, customPropertiesList); - ProcessStartInfo startInfo = new ProcessStartInfo(msbuildInfo.path, compilerArgs); + ProcessStartInfo startInfo = new ProcessStartInfo(GetMSBuildPath(), compilerArgs); - // No console output, thanks - startInfo.RedirectStandardOutput = true; - startInfo.RedirectStandardError = true; + bool redirectOutput = !debugMSBuild; + + startInfo.RedirectStandardOutput = redirectOutput; + startInfo.RedirectStandardError = redirectOutput; startInfo.UseShellExecute = false; + if (UsingMonoMSBuildOnWindows) + { + // These environment variables are required for Mono's MSBuild to find the compilers. + // We use the batch files in Mono's bin directory to make sure the compilers are executed with mono. + string monoWinBinDir = MonoWindowsBinDir; + startInfo.EnvironmentVariables.Add("CscToolExe", Path.Combine(monoWinBinDir, "csc.bat")); + startInfo.EnvironmentVariables.Add("VbcToolExe", Path.Combine(monoWinBinDir, "vbc.bat")); + startInfo.EnvironmentVariables.Add("FscToolExe", Path.Combine(monoWinBinDir, "fsharpc.bat")); + } + // Needed when running from Developer Command Prompt for VS RemovePlatformVariable(startInfo.EnvironmentVariables); @@ -127,8 +180,11 @@ namespace GodotSharpTools.Build process.Start(); - process.BeginOutputReadLine(); - process.BeginErrorReadLine(); + if (redirectOutput) + { + process.BeginOutputReadLine(); + process.BeginErrorReadLine(); + } return true; } @@ -176,6 +232,11 @@ namespace GodotSharpTools.Build Dispose(); } + private static bool IsDebugMSBuildRequested() + { + return Environment.GetEnvironmentVariable("GODOT_DEBUG_MSBUILD")?.Trim() == "1"; + } + public void Dispose() { if (process != null) diff --git a/modules/mono/editor/GodotSharpTools/GodotSharpTools.csproj b/modules/mono/editor/GodotSharpTools/GodotSharpTools.csproj index 981083a3c2..1c8714e31d 100644 --- a/modules/mono/editor/GodotSharpTools/GodotSharpTools.csproj +++ b/modules/mono/editor/GodotSharpTools/GodotSharpTools.csproj @@ -11,7 +11,7 @@ </PropertyGroup> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> <DebugSymbols>true</DebugSymbols> - <DebugType>full</DebugType> + <DebugType>portable</DebugType> <Optimize>false</Optimize> <OutputPath>bin\Debug</OutputPath> <DefineConstants>DEBUG;</DefineConstants> @@ -20,7 +20,7 @@ <ConsolePause>false</ConsolePause> </PropertyGroup> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> - <DebugType>full</DebugType> + <DebugType>portable</DebugType> <Optimize>true</Optimize> <OutputPath>bin\Release</OutputPath> <ErrorReport>prompt</ErrorReport> diff --git a/modules/mono/editor/GodotSharpTools/Project/ProjectGenerator.cs b/modules/mono/editor/GodotSharpTools/Project/ProjectGenerator.cs index 6bf54a0156..1d863e6f61 100644 --- a/modules/mono/editor/GodotSharpTools/Project/ProjectGenerator.cs +++ b/modules/mono/editor/GodotSharpTools/Project/ProjectGenerator.cs @@ -70,7 +70,7 @@ namespace GodotSharpTools.Project var toolsGroup = root.AddPropertyGroup(); toolsGroup.Condition = " '$(Configuration)|$(Platform)' == 'Tools|AnyCPU' "; toolsGroup.AddProperty("DebugSymbols", "true"); - toolsGroup.AddProperty("DebugType", "full"); + toolsGroup.AddProperty("DebugType", "portable"); toolsGroup.AddProperty("Optimize", "false"); toolsGroup.AddProperty("DefineConstants", "DEBUG;TOOLS;"); toolsGroup.AddProperty("ErrorReport", "prompt"); @@ -148,7 +148,7 @@ namespace GodotSharpTools.Project var debugGroup = root.AddPropertyGroup(); debugGroup.Condition = " '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "; debugGroup.AddProperty("DebugSymbols", "true"); - debugGroup.AddProperty("DebugType", "full"); + debugGroup.AddProperty("DebugType", "portable"); debugGroup.AddProperty("Optimize", "false"); debugGroup.AddProperty("DefineConstants", "DEBUG;"); debugGroup.AddProperty("ErrorReport", "prompt"); @@ -157,7 +157,7 @@ namespace GodotSharpTools.Project var releaseGroup = root.AddPropertyGroup(); releaseGroup.Condition = " '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "; - releaseGroup.AddProperty("DebugType", "full"); + releaseGroup.AddProperty("DebugType", "portable"); releaseGroup.AddProperty("Optimize", "true"); releaseGroup.AddProperty("ErrorReport", "prompt"); releaseGroup.AddProperty("WarningLevel", "4"); diff --git a/modules/mono/editor/godotsharp_builds.cpp b/modules/mono/editor/godotsharp_builds.cpp index 2f2b5768db..43d58caad2 100644 --- a/modules/mono/editor/godotsharp_builds.cpp +++ b/modules/mono/editor/godotsharp_builds.cpp @@ -39,6 +39,10 @@ #include "bindings_generator.h" #include "godotsharp_editor.h" +#define PROP_NAME_MSBUILD_MONO "MSBuild (Mono)" +#define PROP_NAME_MSBUILD_VS "MSBuild (VS Build Tools)" +#define PROP_NAME_XBUILD "xbuild (Deprecated)" + void godot_icall_BuildInstance_ExitCallback(MonoString *p_solution, MonoString *p_config, int p_exit_code) { String solution = GDMonoMarshal::mono_string_to_godot(p_solution); @@ -76,46 +80,42 @@ String _find_build_engine_on_unix(const String &p_name) { } #endif -void godot_icall_BuildInstance_get_MSBuildInfo(MonoString **r_msbuild_path, MonoString **r_framework_path) { +MonoString *godot_icall_BuildInstance_get_MSBuildPath() { GodotSharpBuilds::BuildTool build_tool = GodotSharpBuilds::BuildTool(int(EditorSettings::get_singleton()->get("mono/builds/build_tool"))); #if defined(WINDOWS_ENABLED) switch (build_tool) { - case GodotSharpBuilds::MSBUILD: { + case GodotSharpBuilds::MSBUILD_VS: { static String msbuild_tools_path = MonoRegUtils::find_msbuild_tools_path(); if (msbuild_tools_path.length()) { if (!msbuild_tools_path.ends_with("\\")) msbuild_tools_path += "\\"; - // FrameworkPathOverride - const MonoRegInfo &mono_reg_info = GDMono::get_singleton()->get_mono_reg_info(); - if (mono_reg_info.assembly_dir.length()) { - *r_msbuild_path = GDMonoMarshal::mono_string_from_godot(msbuild_tools_path + "MSBuild.exe"); - - String framework_path = path_join(mono_reg_info.assembly_dir, "mono", "4.5"); - *r_framework_path = GDMonoMarshal::mono_string_from_godot(framework_path); - } else { - ERR_PRINT("Cannot find Mono's assemblies directory in the registry"); - } - - return; + return GDMonoMarshal::mono_string_from_godot(msbuild_tools_path + "MSBuild.exe"); } if (OS::get_singleton()->is_stdout_verbose()) - OS::get_singleton()->print("Cannot find System's MSBuild. Trying with Mono's...\n"); - } // fall through + OS::get_singleton()->print("Cannot find executable for '" PROP_NAME_MSBUILD_VS "'. Trying with '" PROP_NAME_MSBUILD_MONO "'...\n"); + } // FALL THROUGH case GodotSharpBuilds::MSBUILD_MONO: { String msbuild_path = GDMono::get_singleton()->get_mono_reg_info().bin_dir.plus_file("msbuild.bat"); if (!FileAccess::exists(msbuild_path)) { - WARN_PRINTS("Cannot find msbuild ('mono/builds/build_tool'). Tried with path: " + msbuild_path); + WARN_PRINTS("Cannot find executable for '" PROP_NAME_MSBUILD_MONO "'. Tried with path: " + msbuild_path); } - *r_msbuild_path = GDMonoMarshal::mono_string_from_godot(msbuild_path); + return GDMonoMarshal::mono_string_from_godot(msbuild_path); + } break; + case GodotSharpBuilds::XBUILD: { + String xbuild_path = GDMono::get_singleton()->get_mono_reg_info().bin_dir.plus_file("xbuild.bat"); - return; + if (!FileAccess::exists(xbuild_path)) { + WARN_PRINTS("Cannot find executable for '" PROP_NAME_XBUILD "'. Tried with path: " + xbuild_path); + } + + return GDMonoMarshal::mono_string_from_godot(xbuild_path); } break; default: ERR_EXPLAIN("You don't deserve to live"); @@ -125,31 +125,74 @@ void godot_icall_BuildInstance_get_MSBuildInfo(MonoString **r_msbuild_path, Mono static String msbuild_path = _find_build_engine_on_unix("msbuild"); static String xbuild_path = _find_build_engine_on_unix("xbuild"); - if (build_tool != GodotSharpBuilds::XBUILD) { - if (msbuild_path.empty()) { - WARN_PRINT("Cannot find msbuild ('mono/builds/build_tool')."); - return; + if (build_tool == GodotSharpBuilds::XBUILD) { + if (xbuild_path.empty()) { + WARN_PRINT("Cannot find binary for '" PROP_NAME_XBUILD "'"); + return NULL; } } else { - if (xbuild_path.empty()) { - WARN_PRINT("Cannot find xbuild ('mono/builds/build_tool')."); - return; + if (msbuild_path.empty()) { + WARN_PRINT("Cannot find binary for '" PROP_NAME_MSBUILD_MONO "'"); + return NULL; } } - *r_msbuild_path = GDMonoMarshal::mono_string_from_godot(build_tool != GodotSharpBuilds::XBUILD ? msbuild_path : xbuild_path); + return GDMonoMarshal::mono_string_from_godot(build_tool != GodotSharpBuilds::XBUILD ? msbuild_path : xbuild_path); +#else + (void)build_tool; // UNUSED + + ERR_EXPLAIN("Not implemented on this platform"); + ERR_FAIL_V(NULL); +#endif +} + +MonoString *godot_icall_BuildInstance_get_FrameworkPath() { + +#if defined(WINDOWS_ENABLED) + const MonoRegInfo &mono_reg_info = GDMono::get_singleton()->get_mono_reg_info(); + if (mono_reg_info.assembly_dir.length()) { + String framework_path = path_join(mono_reg_info.assembly_dir, "mono", "4.5"); + return GDMonoMarshal::mono_string_from_godot(framework_path); + } + + ERR_EXPLAIN("Cannot find Mono's assemblies directory in the registry"); + ERR_FAIL_V(NULL); +#else + return NULL; +#endif +} + +MonoString *godot_icall_BuildInstance_get_MonoWindowsBinDir() { + +#if defined(WINDOWS_ENABLED) + const MonoRegInfo &mono_reg_info = GDMono::get_singleton()->get_mono_reg_info(); + if (mono_reg_info.bin_dir.length()) { + return GDMonoMarshal::mono_string_from_godot(mono_reg_info.bin_dir); + } + + ERR_EXPLAIN("Cannot find Mono's binaries directory in the registry"); + ERR_FAIL_V(NULL); +#else + return NULL; +#endif +} - return; +MonoBoolean godot_icall_BuildInstance_get_UsingMonoMSBuildOnWindows() { + +#if defined(WINDOWS_ENABLED) + return GodotSharpBuilds::BuildTool(int(EditorSettings::get_singleton()->get("mono/builds/build_tool"))) == GodotSharpBuilds::MSBUILD_MONO; #else - ERR_PRINT("Not implemented on this platform"); - return; + return false; #endif } void GodotSharpBuilds::_register_internal_calls() { mono_add_internal_call("GodotSharpTools.Build.BuildSystem::godot_icall_BuildInstance_ExitCallback", (void *)godot_icall_BuildInstance_ExitCallback); - mono_add_internal_call("GodotSharpTools.Build.BuildInstance::godot_icall_BuildInstance_get_MSBuildInfo", (void *)godot_icall_BuildInstance_get_MSBuildInfo); + mono_add_internal_call("GodotSharpTools.Build.BuildInstance::godot_icall_BuildInstance_get_MSBuildPath", (void *)godot_icall_BuildInstance_get_MSBuildPath); + mono_add_internal_call("GodotSharpTools.Build.BuildInstance::godot_icall_BuildInstance_get_FrameworkPath", (void *)godot_icall_BuildInstance_get_FrameworkPath); + mono_add_internal_call("GodotSharpTools.Build.BuildInstance::godot_icall_BuildInstance_get_MonoWindowsBinDir", (void *)godot_icall_BuildInstance_get_MonoWindowsBinDir); + mono_add_internal_call("GodotSharpTools.Build.BuildInstance::godot_icall_BuildInstance_get_UsingMonoMSBuildOnWindows", (void *)godot_icall_BuildInstance_get_UsingMonoMSBuildOnWindows); } void GodotSharpBuilds::show_build_error_dialog(const String &p_message) { @@ -386,20 +429,14 @@ GodotSharpBuilds::GodotSharpBuilds() { // Build tool settings EditorSettings *ed_settings = EditorSettings::get_singleton(); -#ifdef WINDOWS_ENABLED - // TODO: Default to MSBUILD_MONO if its csc.exe issue is fixed in the installed mono version - EDITOR_DEF("mono/builds/build_tool", MSBUILD); -#else EDITOR_DEF("mono/builds/build_tool", MSBUILD_MONO); -#endif ed_settings->add_property_hint(PropertyInfo(Variant::INT, "mono/builds/build_tool", PROPERTY_HINT_ENUM, + PROP_NAME_MSBUILD_MONO #ifdef WINDOWS_ENABLED - "MSBuild (Mono),MSBuild (System)" -#else - "MSBuild (Mono),xbuild (Deprecated)" + "," PROP_NAME_MSBUILD_VS #endif - )); + "," PROP_NAME_XBUILD)); } GodotSharpBuilds::~GodotSharpBuilds() { @@ -424,12 +461,12 @@ void GodotSharpBuilds::BuildProcess::start(bool p_blocking) { exit_code = -1; - String logs_dir = GodotSharpDirs::get_build_logs_dir().plus_file(build_info.solution.md5_text() + "_" + build_info.configuration); + String log_dirpath = build_info.get_log_dirpath(); if (build_tab) { build_tab->on_build_start(); } else { - build_tab = memnew(MonoBuildTab(build_info, logs_dir)); + build_tab = memnew(MonoBuildTab(build_info, log_dirpath)); MonoBottomPanel::get_singleton()->add_build_tab(build_tab); } @@ -451,12 +488,12 @@ void GodotSharpBuilds::BuildProcess::start(bool p_blocking) { // Remove old issues file String issues_file = "msbuild_issues.csv"; - DirAccessRef d = DirAccess::create_for_path(logs_dir); + DirAccessRef d = DirAccess::create_for_path(log_dirpath); if (d->file_exists(issues_file)) { Error err = d->remove(issues_file); if (err != OK) { exited = true; - String file_path = ProjectSettings::get_singleton()->localize_path(logs_dir).plus_file(issues_file); + String file_path = ProjectSettings::get_singleton()->localize_path(log_dirpath).plus_file(issues_file); String message = "Cannot remove issues file: " + file_path; build_tab->on_build_exec_failed(message); ERR_EXPLAIN(message); @@ -490,8 +527,9 @@ void GodotSharpBuilds::BuildProcess::start(bool p_blocking) { // Call Build - Variant logger_assembly = OS::get_singleton()->get_executable_path().get_base_dir().plus_file(EDITOR_TOOLS_ASSEMBLY_NAME) + ".dll"; - Variant logger_output_dir = logs_dir; + String logger_assembly_path = GDMono::get_singleton()->get_editor_tools_assembly()->get_path(); + Variant logger_assembly = ProjectSettings::get_singleton()->globalize_path(logger_assembly_path); + Variant logger_output_dir = log_dirpath; Variant custom_props = build_info.custom_props; const Variant *args[3] = { &logger_assembly, &logger_output_dir, &custom_props }; diff --git a/modules/mono/editor/godotsharp_builds.h b/modules/mono/editor/godotsharp_builds.h index 27b771e324..4afc284d45 100644 --- a/modules/mono/editor/godotsharp_builds.h +++ b/modules/mono/editor/godotsharp_builds.h @@ -68,10 +68,9 @@ public: enum BuildTool { MSBUILD_MONO, #ifdef WINDOWS_ENABLED - MSBUILD -#else - XBUILD // Deprecated + MSBUILD_VS, #endif + XBUILD // Deprecated }; _FORCE_INLINE_ static GodotSharpBuilds *get_singleton() { return singleton; } diff --git a/modules/mono/editor/mono_bottom_panel.cpp b/modules/mono/editor/mono_bottom_panel.cpp index 1b5a303835..9317550d28 100644 --- a/modules/mono/editor/mono_bottom_panel.cpp +++ b/modules/mono/editor/mono_bottom_panel.cpp @@ -73,7 +73,7 @@ void MonoBottomPanel::_update_build_tabs_list() { if (no_current_tab || current_tab == i) { build_tabs_list->select(i); - _build_tab_item_selected(i); + _build_tabs_item_selected(i); } } } @@ -105,21 +105,27 @@ void MonoBottomPanel::show_build_tab() { ERR_PRINT("Builds tab not found"); } -void MonoBottomPanel::_build_tab_item_selected(int p_idx) { +void MonoBottomPanel::_build_tabs_item_selected(int p_idx) { ERR_FAIL_INDEX(p_idx, build_tabs->get_tab_count()); + build_tabs->set_current_tab(p_idx); + if (!build_tabs->is_visible()) + build_tabs->set_visible(true); + + warnings_btn->set_visible(true); + errors_btn->set_visible(true); + view_log_btn->set_visible(true); } -void MonoBottomPanel::_build_tab_changed(int p_idx) { +void MonoBottomPanel::_build_tabs_nothing_selected() { - if (p_idx < 0 || p_idx >= build_tabs->get_tab_count()) { - warnings_btn->set_visible(false); - errors_btn->set_visible(false); - } else { - warnings_btn->set_visible(true); - errors_btn->set_visible(true); - } + if (build_tabs->get_tab_count() != 0) // just in case + build_tabs->set_visible(false); + + warnings_btn->set_visible(false); + errors_btn->set_visible(false); + view_log_btn->set_visible(false); } void MonoBottomPanel::_warnings_toggled(bool p_pressed) { @@ -148,6 +154,22 @@ void MonoBottomPanel::_build_project_pressed() { CSharpLanguage::get_singleton()->reload_assemblies_if_needed(true); } +void MonoBottomPanel::_view_log_pressed() { + + if (build_tabs_list->is_anything_selected()) { + Vector<int> selected_items = build_tabs_list->get_selected_items(); + CRASH_COND(selected_items.size() != 1); + int selected_item = selected_items[0]; + + MonoBuildTab *build_tab = Object::cast_to<MonoBuildTab>(build_tabs->get_tab_control(selected_item)); + ERR_FAIL_NULL(build_tab); + + String log_dirpath = build_tab->get_build_info().get_log_dirpath(); + + OS::get_singleton()->shell_open(log_dirpath.plus_file("msbuild_log.txt")); + } +} + void MonoBottomPanel::_notification(int p_what) { switch (p_what) { @@ -163,10 +185,11 @@ void MonoBottomPanel::_notification(int p_what) { void MonoBottomPanel::_bind_methods() { ClassDB::bind_method(D_METHOD("_build_project_pressed"), &MonoBottomPanel::_build_project_pressed); + ClassDB::bind_method(D_METHOD("_view_log_pressed"), &MonoBottomPanel::_view_log_pressed); ClassDB::bind_method(D_METHOD("_warnings_toggled", "pressed"), &MonoBottomPanel::_warnings_toggled); ClassDB::bind_method(D_METHOD("_errors_toggled", "pressed"), &MonoBottomPanel::_errors_toggled); - ClassDB::bind_method(D_METHOD("_build_tab_item_selected", "idx"), &MonoBottomPanel::_build_tab_item_selected); - ClassDB::bind_method(D_METHOD("_build_tab_changed", "idx"), &MonoBottomPanel::_build_tab_changed); + ClassDB::bind_method(D_METHOD("_build_tabs_item_selected", "idx"), &MonoBottomPanel::_build_tabs_item_selected); + ClassDB::bind_method(D_METHOD("_build_tabs_nothing_selected"), &MonoBottomPanel::_build_tabs_nothing_selected); } MonoBottomPanel::MonoBottomPanel(EditorNode *p_editor) { @@ -223,6 +246,15 @@ MonoBottomPanel::MonoBottomPanel(EditorNode *p_editor) { errors_btn->connect("toggled", this, "_errors_toggled"); toolbar_hbc->add_child(errors_btn); + toolbar_hbc->add_spacer(); + + view_log_btn = memnew(Button); + view_log_btn->set_text(TTR("View log")); + view_log_btn->set_focus_mode(FOCUS_NONE); + view_log_btn->set_visible(false); + view_log_btn->connect("pressed", this, "_view_log_pressed"); + toolbar_hbc->add_child(view_log_btn); + HSplitContainer *hsc = memnew(HSplitContainer); hsc->set_h_size_flags(SIZE_EXPAND_FILL); hsc->set_v_size_flags(SIZE_EXPAND_FILL); @@ -230,14 +262,14 @@ MonoBottomPanel::MonoBottomPanel(EditorNode *p_editor) { build_tabs_list = memnew(ItemList); build_tabs_list->set_h_size_flags(SIZE_EXPAND_FILL); - build_tabs_list->connect("item_selected", this, "_build_tab_item_selected"); + build_tabs_list->connect("item_selected", this, "_build_tabs_item_selected"); + build_tabs_list->connect("nothing_selected", this, "_build_tabs_nothing_selected"); hsc->add_child(build_tabs_list); build_tabs = memnew(TabContainer); build_tabs->set_tab_align(TabContainer::ALIGN_LEFT); build_tabs->set_h_size_flags(SIZE_EXPAND_FILL); build_tabs->set_tabs_visible(false); - build_tabs->connect("tab_changed", this, "_build_tab_changed"); hsc->add_child(build_tabs); } } diff --git a/modules/mono/editor/mono_bottom_panel.h b/modules/mono/editor/mono_bottom_panel.h index a44d3a9af8..03240e9a13 100644 --- a/modules/mono/editor/mono_bottom_panel.h +++ b/modules/mono/editor/mono_bottom_panel.h @@ -53,16 +53,18 @@ class MonoBottomPanel : public VBoxContainer { Button *warnings_btn; Button *errors_btn; + Button *view_log_btn; void _update_build_tabs_list(); - void _build_tab_item_selected(int p_idx); - void _build_tab_changed(int p_idx); + void _build_tabs_item_selected(int p_idx); + void _build_tabs_nothing_selected(); void _warnings_toggled(bool p_pressed); void _errors_toggled(bool p_pressed); void _build_project_pressed(); + void _view_log_pressed(); static MonoBottomPanel *singleton; diff --git a/modules/mono/editor/mono_build_info.cpp b/modules/mono/editor/mono_build_info.cpp new file mode 100644 index 0000000000..e4af2aac4f --- /dev/null +++ b/modules/mono/editor/mono_build_info.cpp @@ -0,0 +1,62 @@ +/*************************************************************************/ +/* mono_build_info.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 "mono_build_info.h" + +#include "../godotsharp_dirs.h" +#include "../mono_gd/gd_mono_utils.h" + +uint32_t MonoBuildInfo::Hasher::hash(const MonoBuildInfo &p_key) { + + uint32_t hash = 0; + + GDMonoUtils::hash_combine(hash, p_key.solution.hash()); + GDMonoUtils::hash_combine(hash, p_key.configuration.hash()); + + return hash; +} + +bool MonoBuildInfo::operator==(const MonoBuildInfo &p_b) const { + + return p_b.solution == solution && p_b.configuration == configuration; +} + +String MonoBuildInfo::get_log_dirpath() { + + return GodotSharpDirs::get_build_logs_dir().plus_file(solution.md5_text() + "_" + configuration); +} + +MonoBuildInfo::MonoBuildInfo() {} + +MonoBuildInfo::MonoBuildInfo(const String &p_solution, const String &p_config) { + + solution = p_solution; + configuration = p_config; +} diff --git a/modules/mono/editor/mono_build_info.h b/modules/mono/editor/mono_build_info.h index 4806764a61..64ba0f4037 100644 --- a/modules/mono/editor/mono_build_info.h +++ b/modules/mono/editor/mono_build_info.h @@ -31,35 +31,25 @@ #ifndef MONO_BUILD_INFO_H #define MONO_BUILD_INFO_H -#include "../mono_gd/gd_mono_utils.h" +#include "core/ustring.h" +#include "core/vector.h" struct MonoBuildInfo { struct Hasher { - static _FORCE_INLINE_ uint32_t hash(const MonoBuildInfo &p_key) { - uint32_t hash = 0; - - GDMonoUtils::hash_combine(hash, p_key.solution.hash()); - GDMonoUtils::hash_combine(hash, p_key.configuration.hash()); - - return hash; - } + static uint32_t hash(const MonoBuildInfo &p_key); }; String solution; String configuration; Vector<String> custom_props; - MonoBuildInfo() {} + bool operator==(const MonoBuildInfo &p_b) const; - MonoBuildInfo(const String &p_solution, const String &p_config) { - solution = p_solution; - configuration = p_config; - } + String get_log_dirpath(); - bool operator==(const MonoBuildInfo &p_b) const { - return p_b.solution == solution && p_b.configuration == configuration; - } + MonoBuildInfo(); + MonoBuildInfo(const String &p_solution, const String &p_config); }; #endif // MONO_BUILD_INFO_H diff --git a/modules/mono/glue/builtin_types_glue.h b/modules/mono/glue/builtin_types_glue.h index 460de84b65..ef9f152682 100644 --- a/modules/mono/glue/builtin_types_glue.h +++ b/modules/mono/glue/builtin_types_glue.h @@ -1,3 +1,33 @@ +/*************************************************************************/ +/* builtin_types_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 BUILTIN_TYPES_GLUE_H #define BUILTIN_TYPES_GLUE_H diff --git a/modules/mono/glue/cs_files/Basis.cs b/modules/mono/glue/cs_files/Basis.cs index 929b13d70c..aa49a5e04f 100644 --- a/modules/mono/glue/cs_files/Basis.cs +++ b/modules/mono/glue/cs_files/Basis.cs @@ -446,6 +446,26 @@ namespace Godot _z = new Vector3(xz - wy, yz + wx, 1.0f - (xx + yy)); } + public Basis(Vector3 euler) + { + real_t c; + real_t s; + + c = Mathf.Cos(euler.x); + s = Mathf.Sin(euler.x); + var xmat = new Basis(1, 0, 0, 0, c, -s, 0, s, c); + + c = Mathf.Cos(euler.y); + s = Mathf.Sin(euler.y); + var ymat = new Basis(c, 0, s, 0, 1, 0, -s, 0, c); + + c = Mathf.Cos(euler.z); + s = Mathf.Sin(euler.z); + var zmat = new Basis(c, -s, 0, s, c, 0, 0, 0, 1); + + this = ymat * xmat * zmat; + } + public Basis(Vector3 axis, real_t phi) { var axis_sq = new Vector3(axis.x * axis.x, axis.y * axis.y, axis.z * axis.z); diff --git a/modules/mono/glue/cs_files/Color.cs b/modules/mono/glue/cs_files/Color.cs index af94bb616e..e0d6d27840 100644 --- a/modules/mono/glue/cs_files/Color.cs +++ b/modules/mono/glue/cs_files/Color.cs @@ -249,6 +249,15 @@ namespace Godot ); } + public Color Darkened(float amount) + { + Color res = this; + res.r = res.r * (1.0f - amount); + res.g = res.g * (1.0f - amount); + res.b = res.b * (1.0f - amount); + return res; + } + public float Gray() { return (r + g + b) / 3.0f; @@ -263,6 +272,15 @@ namespace Godot ); } + public Color Lightened(float amount) + { + Color res = this; + res.r = res.r + (1.0f - res.r) * amount; + res.g = res.g + (1.0f - res.g) * amount; + res.b = res.b + (1.0f - res.b) * amount; + return res; + } + public Color LinearInterpolate(Color c, float t) { var res = this; @@ -275,15 +293,15 @@ namespace Godot return res; } - public int To32() + public int ToRgba32() { - int c = (byte)(a * 255); - c <<= 8; - c |= (byte)(r * 255); + int c = (byte)(r * 255); c <<= 8; c |= (byte)(g * 255); c <<= 8; c |= (byte)(b * 255); + c <<= 8; + c |= (byte)(a * 255); return c; } diff --git a/modules/mono/glue/cs_files/GodotTaskScheduler.cs b/modules/mono/glue/cs_files/GodotTaskScheduler.cs index 6bf25a89d2..3d23ec10f1 100644 --- a/modules/mono/glue/cs_files/GodotTaskScheduler.cs +++ b/modules/mono/glue/cs_files/GodotTaskScheduler.cs @@ -14,6 +14,7 @@ namespace Godot public GodotTaskScheduler() { Context = new GodotSynchronizationContext(); + SynchronizationContext.SetSynchronizationContext(Context); } protected sealed override void QueueTask(Task task) @@ -57,7 +58,6 @@ namespace Godot public void Activate() { - SynchronizationContext.SetSynchronizationContext(Context); ExecuteQueuedTasks(); Context.ExecutePendingContinuations(); } diff --git a/modules/mono/glue/cs_files/Plane.cs b/modules/mono/glue/cs_files/Plane.cs index 8b92522029..1020f06bf5 100644 --- a/modules/mono/glue/cs_files/Plane.cs +++ b/modules/mono/glue/cs_files/Plane.cs @@ -9,17 +9,23 @@ namespace Godot { public struct Plane : IEquatable<Plane> { - Vector3 normal; + private Vector3 _normal; + + public Vector3 Normal + { + get { return _normal; } + set { _normal = value; } + } public real_t x { get { - return normal.x; + return _normal.x; } set { - normal.x = value; + _normal.x = value; } } @@ -27,11 +33,11 @@ namespace Godot { get { - return normal.y; + return _normal.y; } set { - normal.y = value; + _normal.y = value; } } @@ -39,62 +45,62 @@ namespace Godot { get { - return normal.z; + return _normal.z; } set { - normal.z = value; + _normal.z = value; } } - real_t d; + public real_t D { get; set; } public Vector3 Center { get { - return normal * d; + return _normal * D; } } public real_t DistanceTo(Vector3 point) { - return normal.Dot(point) - d; + return _normal.Dot(point) - D; } public Vector3 GetAnyPoint() { - return normal * d; + return _normal * D; } public bool HasPoint(Vector3 point, real_t epsilon = Mathf.Epsilon) { - real_t dist = normal.Dot(point) - d; + real_t dist = _normal.Dot(point) - D; return Mathf.Abs(dist) <= epsilon; } public Vector3 Intersect3(Plane b, Plane c) { - real_t denom = normal.Cross(b.normal).Dot(c.normal); + real_t denom = _normal.Cross(b._normal).Dot(c._normal); if (Mathf.Abs(denom) <= Mathf.Epsilon) return new Vector3(); - Vector3 result = b.normal.Cross(c.normal) * d + - c.normal.Cross(normal) * b.d + - normal.Cross(b.normal) * c.d; + Vector3 result = b._normal.Cross(c._normal) * D + + c._normal.Cross(_normal) * b.D + + _normal.Cross(b._normal) * c.D; return result / denom; } public Vector3 IntersectRay(Vector3 from, Vector3 dir) { - real_t den = normal.Dot(dir); + real_t den = _normal.Dot(dir); if (Mathf.Abs(den) <= Mathf.Epsilon) return new Vector3(); - real_t dist = (normal.Dot(from) - d) / den; + real_t dist = (_normal.Dot(from) - D) / den; // This is a ray, before the emitting pos (from) does not exist if (dist > Mathf.Epsilon) @@ -106,12 +112,12 @@ namespace Godot public Vector3 IntersectSegment(Vector3 begin, Vector3 end) { Vector3 segment = begin - end; - real_t den = normal.Dot(segment); + real_t den = _normal.Dot(segment); if (Mathf.Abs(den) <= Mathf.Epsilon) return new Vector3(); - real_t dist = (normal.Dot(begin) - d) / den; + real_t dist = (_normal.Dot(begin) - D) / den; if (dist < -Mathf.Epsilon || dist > 1.0f + Mathf.Epsilon) return new Vector3(); @@ -121,46 +127,46 @@ namespace Godot public bool IsPointOver(Vector3 point) { - return normal.Dot(point) > d; + return _normal.Dot(point) > D; } public Plane Normalized() { - real_t len = normal.Length(); + real_t len = _normal.Length(); if (len == 0) return new Plane(0, 0, 0, 0); - return new Plane(normal / len, d / len); + return new Plane(_normal / len, D / len); } public Vector3 Project(Vector3 point) { - return point - normal * DistanceTo(point); + return point - _normal * DistanceTo(point); } // Constructors public Plane(real_t a, real_t b, real_t c, real_t d) { - normal = new Vector3(a, b, c); - this.d = d; + _normal = new Vector3(a, b, c); + this.D = d; } public Plane(Vector3 normal, real_t d) { - this.normal = normal; - this.d = d; + this._normal = normal; + this.D = d; } public Plane(Vector3 v1, Vector3 v2, Vector3 v3) { - normal = (v1 - v3).Cross(v1 - v2); - normal.Normalize(); - d = normal.Dot(v1); + _normal = (v1 - v3).Cross(v1 - v2); + _normal.Normalize(); + D = _normal.Dot(v1); } public static Plane operator -(Plane plane) { - return new Plane(-plane.normal, -plane.d); + return new Plane(-plane._normal, -plane.D); } public static bool operator ==(Plane left, Plane right) @@ -185,20 +191,20 @@ namespace Godot public bool Equals(Plane other) { - return normal == other.normal && d == other.d; + return _normal == other._normal && D == other.D; } public override int GetHashCode() { - return normal.GetHashCode() ^ d.GetHashCode(); + return _normal.GetHashCode() ^ D.GetHashCode(); } public override string ToString() { return String.Format("({0}, {1})", new object[] { - normal.ToString(), - d.ToString() + _normal.ToString(), + D.ToString() }); } @@ -206,8 +212,8 @@ namespace Godot { return String.Format("({0}, {1})", new object[] { - normal.ToString(format), - d.ToString(format) + _normal.ToString(format), + D.ToString(format) }); } } diff --git a/modules/mono/glue/cs_files/RPCAttributes.cs b/modules/mono/glue/cs_files/RPCAttributes.cs index 08841ffd76..6bf9560bfa 100644 --- a/modules/mono/glue/cs_files/RPCAttributes.cs +++ b/modules/mono/glue/cs_files/RPCAttributes.cs @@ -13,4 +13,13 @@ namespace Godot [AttributeUsage(AttributeTargets.Method | AttributeTargets.Field)] public class SlaveAttribute : Attribute {} + + [AttributeUsage(AttributeTargets.Method | AttributeTargets.Field)] + public class RemoteSyncAttribute : Attribute {} + + [AttributeUsage(AttributeTargets.Method | AttributeTargets.Field)] + public class MasterSyncAttribute : Attribute {} + + [AttributeUsage(AttributeTargets.Method | AttributeTargets.Field)] + public class SlaveSyncAttribute : Attribute {} } diff --git a/modules/mono/glue/cs_files/StringExtensions.cs b/modules/mono/glue/cs_files/StringExtensions.cs index 21090fb68d..eaeed7b37b 100644 --- a/modules/mono/glue/cs_files/StringExtensions.cs +++ b/modules/mono/glue/cs_files/StringExtensions.cs @@ -225,7 +225,7 @@ namespace Godot if (pos < 0) return instance; - return instance.Substring(pos + 1, instance.Length); + return instance.Substring(pos + 1); } // <summary> diff --git a/modules/mono/glue/cs_files/VERSION.txt b/modules/mono/glue/cs_files/VERSION.txt index 0cfbf08886..00750edc07 100755 --- a/modules/mono/glue/cs_files/VERSION.txt +++ b/modules/mono/glue/cs_files/VERSION.txt @@ -1 +1 @@ -2 +3 diff --git a/modules/mono/glue/cs_files/Vector2.cs b/modules/mono/glue/cs_files/Vector2.cs index 9bc40cf8df..c274364895 100644 --- a/modules/mono/glue/cs_files/Vector2.cs +++ b/modules/mono/glue/cs_files/Vector2.cs @@ -62,7 +62,7 @@ namespace Godot } } - private real_t Cross(Vector2 b) + public real_t Cross(Vector2 b) { return x * b.y - y * b.x; } @@ -210,6 +210,12 @@ namespace Godot x = v.x; y = v.y; } + + public Vector2 Slerp(Vector2 b, real_t t) + { + real_t theta = AngleTo(b); + return Rotated(theta * t); + } public Vector2 Slide(Vector2 n) { diff --git a/modules/mono/glue/cs_files/Vector3.cs b/modules/mono/glue/cs_files/Vector3.cs index 57e4494f7e..085a4f0043 100644 --- a/modules/mono/glue/cs_files/Vector3.cs +++ b/modules/mono/glue/cs_files/Vector3.cs @@ -242,6 +242,12 @@ namespace Godot z = v.z; } + public Vector3 Slerp(Vector3 b, real_t t) + { + real_t theta = AngleTo(b); + return Rotated(Cross(b), theta * t); + } + public Vector3 Slide(Vector3 n) { return this - n * Dot(n); diff --git a/modules/mono/mono_gd/gd_mono_assembly.cpp b/modules/mono/mono_gd/gd_mono_assembly.cpp index d062d56dcf..9d3bee2176 100644 --- a/modules/mono/mono_gd/gd_mono_assembly.cpp +++ b/modules/mono/mono_gd/gd_mono_assembly.cpp @@ -33,9 +33,10 @@ #include <mono/metadata/mono-debug.h> #include <mono/metadata/tokentype.h> -#include "list.h" -#include "os/file_access.h" -#include "os/os.h" +#include "core/list.h" +#include "core/os/file_access.h" +#include "core/os/os.h" +#include "core/project_settings.h" #include "../godotsharp_dirs.h" #include "gd_mono_class.h" @@ -210,7 +211,7 @@ Error GDMonoAssembly::load(bool p_refonly) { Vector<uint8_t> data = FileAccess::get_file_as_array(path); ERR_FAIL_COND_V(data.empty(), ERR_FILE_CANT_READ); - String image_filename(path); + String image_filename = ProjectSettings::get_singleton()->globalize_path(path); MonoImageOpenStatus status = MONO_IMAGE_OK; diff --git a/modules/mono/mono_gd/gd_mono_marshal.cpp b/modules/mono/mono_gd/gd_mono_marshal.cpp index aa1a8e39c7..c04fcca962 100644 --- a/modules/mono/mono_gd/gd_mono_marshal.cpp +++ b/modules/mono/mono_gd/gd_mono_marshal.cpp @@ -606,11 +606,14 @@ MonoArray *Array_to_mono_array(const Array &p_array) { Array mono_array_to_Array(MonoArray *p_array) { Array ret; + if (!p_array) + return ret; int length = mono_array_length(p_array); + ret.resize(length); for (int i = 0; i < length; i++) { MonoObject *elem = mono_array_get(p_array, MonoObject *, i); - ret.push_back(mono_object_to_variant(elem)); + ret[i] = mono_object_to_variant(elem); } return ret; @@ -630,11 +633,13 @@ MonoArray *PoolIntArray_to_mono_array(const PoolIntArray &p_array) { PoolIntArray mono_array_to_PoolIntArray(MonoArray *p_array) { PoolIntArray ret; + if (!p_array) + return ret; int length = mono_array_length(p_array); - + ret.resize(length); for (int i = 0; i < length; i++) { int32_t elem = mono_array_get(p_array, int32_t, i); - ret.push_back(elem); + ret.set(i, elem); } return ret; @@ -652,11 +657,14 @@ MonoArray *PoolByteArray_to_mono_array(const PoolByteArray &p_array) { PoolByteArray mono_array_to_PoolByteArray(MonoArray *p_array) { PoolByteArray ret; + if (!p_array) + return ret; int length = mono_array_length(p_array); + ret.resize(length); for (int i = 0; i < length; i++) { uint8_t elem = mono_array_get(p_array, uint8_t, i); - ret.push_back(elem); + ret.set(i, elem); } return ret; @@ -674,11 +682,14 @@ MonoArray *PoolRealArray_to_mono_array(const PoolRealArray &p_array) { PoolRealArray mono_array_to_PoolRealArray(MonoArray *p_array) { PoolRealArray ret; + if (!p_array) + return ret; int length = mono_array_length(p_array); + ret.resize(length); for (int i = 0; i < length; i++) { real_t elem = mono_array_get(p_array, real_t, i); - ret.push_back(elem); + ret.set(i, elem); } return ret; @@ -697,11 +708,14 @@ MonoArray *PoolStringArray_to_mono_array(const PoolStringArray &p_array) { PoolStringArray mono_array_to_PoolStringArray(MonoArray *p_array) { PoolStringArray ret; + if (!p_array) + return ret; int length = mono_array_length(p_array); + ret.resize(length); for (int i = 0; i < length; i++) { MonoString *elem = mono_array_get(p_array, MonoString *, i); - ret.push_back(mono_string_to_godot(elem)); + ret.set(i, mono_string_to_godot(elem)); } return ret; @@ -728,12 +742,15 @@ MonoArray *PoolColorArray_to_mono_array(const PoolColorArray &p_array) { PoolColorArray mono_array_to_PoolColorArray(MonoArray *p_array) { PoolColorArray ret; + if (!p_array) + return ret; int length = mono_array_length(p_array); + ret.resize(length); for (int i = 0; i < length; i++) { real_t *raw_elem = (real_t *)mono_array_addr_with_size(p_array, sizeof(real_t) * 4, i); MARSHALLED_IN(Color, raw_elem, elem); - ret.push_back(elem); + ret.set(i, elem); } return ret; @@ -758,12 +775,15 @@ MonoArray *PoolVector2Array_to_mono_array(const PoolVector2Array &p_array) { PoolVector2Array mono_array_to_PoolVector2Array(MonoArray *p_array) { PoolVector2Array ret; + if (!p_array) + return ret; int length = mono_array_length(p_array); + ret.resize(length); for (int i = 0; i < length; i++) { real_t *raw_elem = (real_t *)mono_array_addr_with_size(p_array, sizeof(real_t) * 2, i); MARSHALLED_IN(Vector2, raw_elem, elem); - ret.push_back(elem); + ret.set(i, elem); } return ret; @@ -789,12 +809,15 @@ MonoArray *PoolVector3Array_to_mono_array(const PoolVector3Array &p_array) { PoolVector3Array mono_array_to_PoolVector3Array(MonoArray *p_array) { PoolVector3Array ret; + if (!p_array) + return ret; int length = mono_array_length(p_array); + ret.resize(length); for (int i = 0; i < length; i++) { real_t *raw_elem = (real_t *)mono_array_addr_with_size(p_array, sizeof(real_t) * 3, i); MARSHALLED_IN(Vector3, raw_elem, elem); - ret.push_back(elem); + ret.set(i, elem); } return ret; @@ -828,6 +851,9 @@ MonoObject *Dictionary_to_mono_object(const Dictionary &p_dict) { Dictionary mono_object_to_Dictionary(MonoObject *p_dict) { Dictionary ret; + if (!p_dict) + return ret; + GDMonoUtils::MarshalUtils_DictToArrays dict_to_arrays = CACHED_METHOD_THUNK(MarshalUtils, DictionaryToArrays); MonoArray *keys = NULL; diff --git a/modules/mono/mono_gd/gd_mono_utils.cpp b/modules/mono/mono_gd/gd_mono_utils.cpp index db136a1313..fbdbeaa3f7 100644 --- a/modules/mono/mono_gd/gd_mono_utils.cpp +++ b/modules/mono/mono_gd/gd_mono_utils.cpp @@ -120,6 +120,9 @@ void MonoCache::clear_members() { class_SyncAttribute = NULL; class_MasterAttribute = NULL; class_SlaveAttribute = NULL; + class_RemoteSyncAttribute = NULL; + class_MasterSyncAttribute = NULL; + class_SlaveSyncAttribute = NULL; class_GodotMethodAttribute = NULL; field_GodotMethodAttribute_methodName = NULL; @@ -208,6 +211,9 @@ void update_godot_api_cache() { CACHE_CLASS_AND_CHECK(SyncAttribute, GODOT_API_CLASS(SyncAttribute)); CACHE_CLASS_AND_CHECK(MasterAttribute, GODOT_API_CLASS(MasterAttribute)); CACHE_CLASS_AND_CHECK(SlaveAttribute, GODOT_API_CLASS(SlaveAttribute)); + CACHE_CLASS_AND_CHECK(RemoteSyncAttribute, GODOT_API_CLASS(RemoteSyncAttribute)); + CACHE_CLASS_AND_CHECK(MasterSyncAttribute, GODOT_API_CLASS(MasterSyncAttribute)); + CACHE_CLASS_AND_CHECK(SlaveSyncAttribute, GODOT_API_CLASS(SlaveSyncAttribute)); CACHE_CLASS_AND_CHECK(GodotMethodAttribute, GODOT_API_CLASS(GodotMethodAttribute)); CACHE_FIELD_AND_CHECK(GodotMethodAttribute, methodName, CACHED_CLASS(GodotMethodAttribute)->get_field("methodName")); diff --git a/modules/mono/mono_gd/gd_mono_utils.h b/modules/mono/mono_gd/gd_mono_utils.h index 1a34180d15..fc13a00e85 100644 --- a/modules/mono/mono_gd/gd_mono_utils.h +++ b/modules/mono/mono_gd/gd_mono_utils.h @@ -112,6 +112,9 @@ struct MonoCache { GDMonoClass *class_ToolAttribute; GDMonoClass *class_RemoteAttribute; GDMonoClass *class_SyncAttribute; + GDMonoClass *class_RemoteSyncAttribute; + GDMonoClass *class_MasterSyncAttribute; + GDMonoClass *class_SlaveSyncAttribute; GDMonoClass *class_MasterAttribute; GDMonoClass *class_SlaveAttribute; GDMonoClass *class_GodotMethodAttribute; diff --git a/modules/ogg/config.py b/modules/ogg/config.py index 5f133eba90..1c8cd12a2d 100644 --- a/modules/ogg/config.py +++ b/modules/ogg/config.py @@ -1,4 +1,4 @@ -def can_build(platform): +def can_build(env, platform): return True def configure(env): diff --git a/modules/opus/config.py b/modules/opus/config.py index 60f8d838d6..a1cde10ea0 100644 --- a/modules/opus/config.py +++ b/modules/opus/config.py @@ -1,4 +1,4 @@ -def can_build(platform): +def can_build(env, platform): return True def configure(env): diff --git a/modules/pvr/config.py b/modules/pvr/config.py index 5f133eba90..1c8cd12a2d 100644 --- a/modules/pvr/config.py +++ b/modules/pvr/config.py @@ -1,4 +1,4 @@ -def can_build(platform): +def can_build(env, platform): return True def configure(env): diff --git a/modules/recast/SCsub b/modules/recast/SCsub index 530df9a37c..f56be72b24 100644 --- a/modules/recast/SCsub +++ b/modules/recast/SCsub @@ -1,8 +1,9 @@ #!/usr/bin/env python Import('env') +Import('env_modules') -# Not building in a separate env as core needs it +env_recast = env_modules.Clone() # Thirdparty source files if env['builtin_recast']: @@ -22,13 +23,10 @@ if env['builtin_recast']: ] thirdparty_sources = [thirdparty_dir + file for file in thirdparty_sources] - env.Append(CPPPATH=[thirdparty_dir, thirdparty_dir + "/Include"]) - - lib = env.add_library("recast_builtin", thirdparty_sources) - env.Append(LIBS=[lib]) + env_recast.add_source_files(env.modules_sources, thirdparty_sources) + env_recast.Append(CPPPATH=[thirdparty_dir + "/Include"]) # Godot source files -env.add_source_files(env.modules_sources, "*.cpp") -env.Append(CCFLAGS=['-DRECAST_ENABLED']) +env_recast.add_source_files(env.modules_sources, "*.cpp") Export('env') diff --git a/modules/recast/config.py b/modules/recast/config.py index fc074cf661..098f1eafa9 100644 --- a/modules/recast/config.py +++ b/modules/recast/config.py @@ -1,5 +1,5 @@ -def can_build(platform): - return platform != "android" +def can_build(env, platform): + return env['tools'] def configure(env): pass diff --git a/modules/recast/navigation_mesh_editor_plugin.cpp b/modules/recast/navigation_mesh_editor_plugin.cpp new file mode 100644 index 0000000000..8556b7aa0a --- /dev/null +++ b/modules/recast/navigation_mesh_editor_plugin.cpp @@ -0,0 +1,163 @@ +/*************************************************************************/ +/* navigation_mesh_editor_plugin.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 "navigation_mesh_editor_plugin.h" + +#include "io/marshalls.h" +#include "io/resource_saver.h" +#include "scene/3d/mesh_instance.h" +#include "scene/gui/box_container.h" + +void NavigationMeshEditor::_node_removed(Node *p_node) { + + if (p_node == node) { + node = NULL; + + hide(); + } +} + +void NavigationMeshEditor::_notification(int p_option) { + + if (p_option == NOTIFICATION_ENTER_TREE) { + + button_bake->set_icon(get_icon("Bake", "EditorIcons")); + button_reset->set_icon(get_icon("Reload", "EditorIcons")); + } +} + +void NavigationMeshEditor::_bake_pressed() { + + ERR_FAIL_COND(!node); + const String conf_warning = node->get_configuration_warning(); + if (!conf_warning.empty()) { + err_dialog->set_text(conf_warning); + err_dialog->popup_centered_minsize(); + button_bake->set_pressed(false); + return; + } + + NavigationMeshGenerator::clear(node->get_navigation_mesh()); + NavigationMeshGenerator::bake(node->get_navigation_mesh(), node); + + if (node) { + node->update_gizmo(); + } +} + +void NavigationMeshEditor::_clear_pressed() { + + if (node) + NavigationMeshGenerator::clear(node->get_navigation_mesh()); + + button_bake->set_pressed(false); + bake_info->set_text(""); + + if (node) { + node->update_gizmo(); + } +} + +void NavigationMeshEditor::edit(NavigationMeshInstance *p_nav_mesh_instance) { + + if (p_nav_mesh_instance == NULL || node == p_nav_mesh_instance) { + return; + } + + node = p_nav_mesh_instance; +} + +void NavigationMeshEditor::_bind_methods() { + + ClassDB::bind_method("_bake_pressed", &NavigationMeshEditor::_bake_pressed); + ClassDB::bind_method("_clear_pressed", &NavigationMeshEditor::_clear_pressed); +} + +NavigationMeshEditor::NavigationMeshEditor() { + + bake_hbox = memnew(HBoxContainer); + button_bake = memnew(ToolButton); + button_bake->set_text(TTR("Bake!")); + button_bake->set_toggle_mode(true); + button_reset = memnew(Button); + button_bake->set_tooltip(TTR("Bake the navigation mesh.") + "\n"); + + bake_info = memnew(Label); + bake_hbox->add_child(button_bake); + bake_hbox->add_child(button_reset); + bake_hbox->add_child(bake_info); + + err_dialog = memnew(AcceptDialog); + add_child(err_dialog); + node = NULL; + + button_bake->connect("pressed", this, "_bake_pressed"); + button_reset->connect("pressed", this, "_clear_pressed"); + button_reset->set_tooltip(TTR("Clear the navigation mesh.")); +} + +NavigationMeshEditor::~NavigationMeshEditor() { +} + +void NavigationMeshEditorPlugin::edit(Object *p_object) { + + navigation_mesh_editor->edit(Object::cast_to<NavigationMeshInstance>(p_object)); +} + +bool NavigationMeshEditorPlugin::handles(Object *p_object) const { + + return p_object->is_class("NavigationMeshInstance"); +} + +void NavigationMeshEditorPlugin::make_visible(bool p_visible) { + + if (p_visible) { + navigation_mesh_editor->show(); + navigation_mesh_editor->bake_hbox->show(); + } else { + + navigation_mesh_editor->hide(); + navigation_mesh_editor->bake_hbox->hide(); + navigation_mesh_editor->edit(NULL); + } +} + +NavigationMeshEditorPlugin::NavigationMeshEditorPlugin(EditorNode *p_node) { + + editor = p_node; + navigation_mesh_editor = memnew(NavigationMeshEditor); + editor->get_viewport()->add_child(navigation_mesh_editor); + add_control_to_container(CONTAINER_SPATIAL_EDITOR_MENU, navigation_mesh_editor->bake_hbox); + navigation_mesh_editor->hide(); + navigation_mesh_editor->bake_hbox->hide(); +} + +NavigationMeshEditorPlugin::~NavigationMeshEditorPlugin() { +} diff --git a/modules/recast/navigation_mesh_editor_plugin.h b/modules/recast/navigation_mesh_editor_plugin.h new file mode 100644 index 0000000000..4f3e222002 --- /dev/null +++ b/modules/recast/navigation_mesh_editor_plugin.h @@ -0,0 +1,84 @@ +/*************************************************************************/ +/* navigation_mesh_editor_plugin.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 NAVIGATION_MESH_GENERATOR_PLUGIN_H +#define NAVIGATION_MESH_GENERATOR_PLUGIN_H + +#include "editor/editor_node.h" +#include "editor/editor_plugin.h" +#include "navigation_mesh_generator.h" + +class NavigationMeshEditor : public Control { + friend class NavigationMeshEditorPlugin; + + GDCLASS(NavigationMeshEditor, Control); + + AcceptDialog *err_dialog; + + HBoxContainer *bake_hbox; + Button *button_bake; + Button *button_reset; + Label *bake_info; + + NavigationMeshInstance *node; + + void _bake_pressed(); + void _clear_pressed(); + +protected: + void _node_removed(Node *p_node); + static void _bind_methods(); + void _notification(int p_option); + +public: + void edit(NavigationMeshInstance *p_nav_mesh_instance); + NavigationMeshEditor(); + ~NavigationMeshEditor(); +}; + +class NavigationMeshEditorPlugin : public EditorPlugin { + + GDCLASS(NavigationMeshEditorPlugin, EditorPlugin); + + NavigationMeshEditor *navigation_mesh_editor; + EditorNode *editor; + +public: + virtual String get_name() const { return "NavigationMesh"; } + bool has_main_screen() const { return false; } + virtual void edit(Object *p_object); + virtual bool handles(Object *p_object) const; + virtual void make_visible(bool p_visible); + + NavigationMeshEditorPlugin(EditorNode *p_node); + ~NavigationMeshEditorPlugin(); +}; + +#endif // NAVIGATION_MESH_GENERATOR_PLUGIN_H diff --git a/modules/recast/navigation_mesh_generator.cpp b/modules/recast/navigation_mesh_generator.cpp new file mode 100644 index 0000000000..64c4b85269 --- /dev/null +++ b/modules/recast/navigation_mesh_generator.cpp @@ -0,0 +1,304 @@ +/*************************************************************************/ +/* navigation_mesh_generator.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 "navigation_mesh_generator.h" + +void NavigationMeshGenerator::_add_vertex(const Vector3 &p_vec3, Vector<float> &p_verticies) { + p_verticies.push_back(p_vec3.x); + p_verticies.push_back(p_vec3.y); + p_verticies.push_back(p_vec3.z); +} + +void NavigationMeshGenerator::_add_mesh(const Ref<Mesh> &p_mesh, const Transform &p_xform, Vector<float> &p_verticies, Vector<int> &p_indices) { + int current_vertex_count = 0; + + for (int i = 0; i < p_mesh->get_surface_count(); i++) { + current_vertex_count = p_verticies.size() / 3; + + if (p_mesh->surface_get_primitive_type(i) != Mesh::PRIMITIVE_TRIANGLES) + continue; + + int index_count = 0; + if (p_mesh->surface_get_format(i) & Mesh::ARRAY_FORMAT_INDEX) { + index_count = p_mesh->surface_get_array_index_len(i); + } else { + index_count = p_mesh->surface_get_array_len(i); + } + + ERR_CONTINUE((index_count == 0 || (index_count % 3) != 0)); + + int face_count = index_count / 3; + + Array a = p_mesh->surface_get_arrays(i); + + PoolVector<Vector3> mesh_vertices = a[Mesh::ARRAY_VERTEX]; + PoolVector<Vector3>::Read vr = mesh_vertices.read(); + + if (p_mesh->surface_get_format(i) & Mesh::ARRAY_FORMAT_INDEX) { + + PoolVector<int> mesh_indices = a[Mesh::ARRAY_INDEX]; + PoolVector<int>::Read ir = mesh_indices.read(); + + for (int i = 0; i < mesh_vertices.size(); i++) { + _add_vertex(p_xform.xform(vr[i]), p_verticies); + } + + for (int i = 0; i < face_count; i++) { + // CCW + p_indices.push_back(current_vertex_count + (ir[i * 3 + 0])); + p_indices.push_back(current_vertex_count + (ir[i * 3 + 2])); + p_indices.push_back(current_vertex_count + (ir[i * 3 + 1])); + } + } else { + face_count = mesh_vertices.size() / 3; + for (int i = 0; i < face_count; i++) { + _add_vertex(p_xform.xform(vr[i * 3 + 0]), p_verticies); + _add_vertex(p_xform.xform(vr[i * 3 + 2]), p_verticies); + _add_vertex(p_xform.xform(vr[i * 3 + 1]), p_verticies); + + p_indices.push_back(current_vertex_count + (i * 3 + 0)); + p_indices.push_back(current_vertex_count + (i * 3 + 1)); + p_indices.push_back(current_vertex_count + (i * 3 + 2)); + } + } + } +} + +void NavigationMeshGenerator::_parse_geometry(const Transform &p_base_inverse, Node *p_node, Vector<float> &p_verticies, Vector<int> &p_indices) { + + if (Object::cast_to<MeshInstance>(p_node)) { + + MeshInstance *mesh_instance = Object::cast_to<MeshInstance>(p_node); + Ref<Mesh> mesh = mesh_instance->get_mesh(); + if (mesh.is_valid()) { + _add_mesh(mesh, p_base_inverse * mesh_instance->get_global_transform(), p_verticies, p_indices); + } + } + + for (int i = 0; i < p_node->get_child_count(); i++) { + _parse_geometry(p_base_inverse, p_node->get_child(i), p_verticies, p_indices); + } +} + +void NavigationMeshGenerator::_convert_detail_mesh_to_native_navigation_mesh(const rcPolyMeshDetail *p_detail_mesh, Ref<NavigationMesh> p_nav_mesh) { + + PoolVector<Vector3> nav_vertices; + + for (int i = 0; i < p_detail_mesh->nverts; i++) { + const float *v = &p_detail_mesh->verts[i * 3]; + nav_vertices.append(Vector3(v[0], v[1], v[2])); + } + p_nav_mesh->set_vertices(nav_vertices); + + for (int i = 0; i < p_detail_mesh->nmeshes; i++) { + const unsigned int *m = &p_detail_mesh->meshes[i * 4]; + const unsigned int bverts = m[0]; + const unsigned int btris = m[2]; + const unsigned int ntris = m[3]; + const unsigned char *tris = &p_detail_mesh->tris[btris * 4]; + for (unsigned int j = 0; j < ntris; j++) { + Vector<int> nav_indices; + nav_indices.resize(3); + nav_indices[0] = ((int)(bverts + tris[j * 4 + 0])); + nav_indices[1] = ((int)(bverts + tris[j * 4 + 1])); + nav_indices[2] = ((int)(bverts + tris[j * 4 + 2])); + p_nav_mesh->add_polygon(nav_indices); + } + } +} + +void NavigationMeshGenerator::_build_recast_navigation_mesh(Ref<NavigationMesh> p_nav_mesh, EditorProgress *ep, + rcHeightfield *hf, rcCompactHeightfield *chf, rcContourSet *cset, rcPolyMesh *poly_mesh, rcPolyMeshDetail *detail_mesh, + Vector<float> &vertices, Vector<int> &indices) { + rcContext ctx; + ep->step(TTR("Setting up Configuration..."), 1); + + const float *verts = vertices.ptr(); + const int nverts = vertices.size() / 3; + const int *tris = indices.ptr(); + const int ntris = indices.size() / 3; + + float bmin[3], bmax[3]; + rcCalcBounds(verts, nverts, bmin, bmax); + + rcConfig cfg; + memset(&cfg, 0, sizeof(cfg)); + + cfg.cs = p_nav_mesh->get_cell_size(); + cfg.ch = p_nav_mesh->get_cell_height(); + cfg.walkableSlopeAngle = p_nav_mesh->get_agent_max_slope(); + cfg.walkableHeight = (int)Math::ceil(p_nav_mesh->get_agent_height() / cfg.ch); + cfg.walkableClimb = (int)Math::floor(p_nav_mesh->get_agent_max_climb() / cfg.ch); + cfg.walkableRadius = (int)Math::ceil(p_nav_mesh->get_agent_radius() / cfg.cs); + cfg.maxEdgeLen = (int)(p_nav_mesh->get_edge_max_length() / p_nav_mesh->get_cell_size()); + cfg.maxSimplificationError = p_nav_mesh->get_edge_max_error(); + cfg.minRegionArea = (int)(p_nav_mesh->get_region_min_size() * p_nav_mesh->get_region_min_size()); + cfg.mergeRegionArea = (int)(p_nav_mesh->get_region_merge_size() * p_nav_mesh->get_region_merge_size()); + cfg.maxVertsPerPoly = (int)p_nav_mesh->get_verts_per_poly(); + cfg.detailSampleDist = p_nav_mesh->get_detail_sample_distance() < 0.9f ? 0 : p_nav_mesh->get_cell_size() * p_nav_mesh->get_detail_sample_distance(); + cfg.detailSampleMaxError = p_nav_mesh->get_cell_height() * p_nav_mesh->get_detail_sample_max_error(); + + cfg.bmin[0] = bmin[0]; + cfg.bmin[1] = bmin[1]; + cfg.bmin[2] = bmin[2]; + cfg.bmax[0] = bmax[0]; + cfg.bmax[1] = bmax[1]; + cfg.bmax[2] = bmax[2]; + + ep->step(TTR("Calculating grid size..."), 2); + rcCalcGridSize(cfg.bmin, cfg.bmax, cfg.cs, &cfg.width, &cfg.height); + + ep->step(TTR("Creating heightfield..."), 3); + hf = rcAllocHeightfield(); + + ERR_FAIL_COND(!hf); + ERR_FAIL_COND(!rcCreateHeightfield(&ctx, *hf, cfg.width, cfg.height, cfg.bmin, cfg.bmax, cfg.cs, cfg.ch)); + + ep->step(TTR("Marking walkable triangles..."), 4); + { + Vector<unsigned char> tri_areas; + tri_areas.resize(ntris); + + ERR_FAIL_COND(tri_areas.size() == 0); + + memset(tri_areas.ptrw(), 0, ntris * sizeof(unsigned char)); + rcMarkWalkableTriangles(&ctx, cfg.walkableSlopeAngle, verts, nverts, tris, ntris, tri_areas.ptrw()); + + ERR_FAIL_COND(!rcRasterizeTriangles(&ctx, verts, nverts, tris, tri_areas.ptr(), ntris, *hf, cfg.walkableClimb)); + } + + if (p_nav_mesh->get_filter_low_hanging_obstacles()) + rcFilterLowHangingWalkableObstacles(&ctx, cfg.walkableClimb, *hf); + if (p_nav_mesh->get_filter_ledge_spans()) + rcFilterLedgeSpans(&ctx, cfg.walkableHeight, cfg.walkableClimb, *hf); + if (p_nav_mesh->get_filter_walkable_low_height_spans()) + rcFilterWalkableLowHeightSpans(&ctx, cfg.walkableHeight, *hf); + + ep->step(TTR("Constructing compact heightfield..."), 5); + + chf = rcAllocCompactHeightfield(); + + ERR_FAIL_COND(!chf); + ERR_FAIL_COND(!rcBuildCompactHeightfield(&ctx, cfg.walkableHeight, cfg.walkableClimb, *hf, *chf)); + + rcFreeHeightField(hf); + hf = 0; + + ep->step(TTR("Eroding walkable area..."), 6); + ERR_FAIL_COND(!rcErodeWalkableArea(&ctx, cfg.walkableRadius, *chf)); + + ep->step(TTR("Partitioning..."), 7); + if (p_nav_mesh->get_sample_partition_type() == NavigationMesh::SAMPLE_PARTITION_WATERSHED) { + ERR_FAIL_COND(!rcBuildDistanceField(&ctx, *chf)); + ERR_FAIL_COND(!rcBuildRegions(&ctx, *chf, 0, cfg.minRegionArea, cfg.mergeRegionArea)); + } else if (p_nav_mesh->get_sample_partition_type() == NavigationMesh::SAMPLE_PARTITION_MONOTONE) { + ERR_FAIL_COND(!rcBuildRegionsMonotone(&ctx, *chf, 0, cfg.minRegionArea, cfg.mergeRegionArea)); + } else { + ERR_FAIL_COND(!rcBuildLayerRegions(&ctx, *chf, 0, cfg.minRegionArea)); + } + + ep->step(TTR("Creating contours..."), 8); + + cset = rcAllocContourSet(); + + ERR_FAIL_COND(!cset); + ERR_FAIL_COND(!rcBuildContours(&ctx, *chf, cfg.maxSimplificationError, cfg.maxEdgeLen, *cset)); + + ep->step(TTR("Creating polymesh..."), 9); + + poly_mesh = rcAllocPolyMesh(); + ERR_FAIL_COND(!poly_mesh); + ERR_FAIL_COND(!rcBuildPolyMesh(&ctx, *cset, cfg.maxVertsPerPoly, *poly_mesh)); + + detail_mesh = rcAllocPolyMeshDetail(); + ERR_FAIL_COND(!detail_mesh); + ERR_FAIL_COND(!rcBuildPolyMeshDetail(&ctx, *poly_mesh, *chf, cfg.detailSampleDist, cfg.detailSampleMaxError, *detail_mesh)); + + rcFreeCompactHeightfield(chf); + chf = 0; + rcFreeContourSet(cset); + cset = 0; + + ep->step(TTR("Converting to native navigation mesh..."), 10); + + _convert_detail_mesh_to_native_navigation_mesh(detail_mesh, p_nav_mesh); + + rcFreePolyMesh(poly_mesh); + poly_mesh = 0; + rcFreePolyMeshDetail(detail_mesh); + detail_mesh = 0; +} + +void NavigationMeshGenerator::bake(Ref<NavigationMesh> p_nav_mesh, Node *p_node) { + + ERR_FAIL_COND(!p_nav_mesh.is_valid()); + + EditorProgress ep("bake", TTR("Navigation Mesh Generator Setup:"), 11); + ep.step(TTR("Parsing Geometry..."), 0); + + Vector<float> vertices; + Vector<int> indices; + + _parse_geometry(Object::cast_to<Spatial>(p_node)->get_global_transform().affine_inverse(), p_node, vertices, indices); + + if (vertices.size() > 0 && indices.size() > 0) { + + rcHeightfield *hf = NULL; + rcCompactHeightfield *chf = NULL; + rcContourSet *cset = NULL; + rcPolyMesh *poly_mesh = NULL; + rcPolyMeshDetail *detail_mesh = NULL; + + _build_recast_navigation_mesh(p_nav_mesh, &ep, hf, chf, cset, poly_mesh, detail_mesh, vertices, indices); + + rcFreeHeightField(hf); + hf = 0; + + rcFreeCompactHeightfield(chf); + chf = 0; + + rcFreeContourSet(cset); + cset = 0; + + rcFreePolyMesh(poly_mesh); + poly_mesh = 0; + + rcFreePolyMeshDetail(detail_mesh); + detail_mesh = 0; + } + ep.step(TTR("Done!"), 11); +} + +void NavigationMeshGenerator::clear(Ref<NavigationMesh> p_nav_mesh) { + if (p_nav_mesh.is_valid()) { + p_nav_mesh->clear_polygons(); + p_nav_mesh->set_vertices(PoolVector<Vector3>()); + } +} diff --git a/modules/recast/navigation_mesh_generator.h b/modules/recast/navigation_mesh_generator.h new file mode 100644 index 0000000000..3588539ef1 --- /dev/null +++ b/modules/recast/navigation_mesh_generator.h @@ -0,0 +1,59 @@ +/*************************************************************************/ +/* navigation_mesh_generator.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 NAVIGATION_MESH_GENERATOR_H +#define NAVIGATION_MESH_GENERATOR_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" + +#include <Recast.h> + +class NavigationMeshGenerator { +protected: + static void _add_vertex(const Vector3 &p_vec3, Vector<float> &p_verticies); + static void _add_mesh(const Ref<Mesh> &p_mesh, const Transform &p_xform, Vector<float> &p_verticies, Vector<int> &p_indices); + static void _parse_geometry(const Transform &p_base_inverse, Node *p_node, Vector<float> &p_verticies, Vector<int> &p_indices); + + static void _convert_detail_mesh_to_native_navigation_mesh(const rcPolyMeshDetail *p_detail_mesh, Ref<NavigationMesh> p_nav_mesh); + static void _build_recast_navigation_mesh(Ref<NavigationMesh> p_nav_mesh, EditorProgress *ep, + rcHeightfield *hf, rcCompactHeightfield *chf, rcContourSet *cset, rcPolyMesh *poly_mesh, + rcPolyMeshDetail *detail_mesh, Vector<float> &vertices, Vector<int> &indices); + +public: + static void bake(Ref<NavigationMesh> p_nav_mesh, Node *p_node); + static void clear(Ref<NavigationMesh> p_nav_mesh); +}; + +#endif // NAVIGATION_MESH_GENERATOR_H diff --git a/modules/recast/register_types.cpp b/modules/recast/register_types.cpp index 913857c591..f2f18fc86f 100644 --- a/modules/recast/register_types.cpp +++ b/modules/recast/register_types.cpp @@ -30,5 +30,10 @@ #include "register_types.h" -void register_recast_types() {} +#include "navigation_mesh_editor_plugin.h" + +void register_recast_types() { + EditorPlugins::add_by_type<NavigationMeshEditorPlugin>(); +} + void unregister_recast_types() {} diff --git a/modules/regex/config.py b/modules/regex/config.py index cb2da26738..42cfe3b43c 100644 --- a/modules/regex/config.py +++ b/modules/regex/config.py @@ -1,4 +1,4 @@ -def can_build(platform): +def can_build(env, platform): return True def configure(env): diff --git a/modules/squish/config.py b/modules/squish/config.py index 97c95999c8..098f1eafa9 100644 --- a/modules/squish/config.py +++ b/modules/squish/config.py @@ -1,9 +1,5 @@ -def can_build(platform): - return True +def can_build(env, platform): + return env['tools'] def configure(env): - # Tools only, disabled for non-tools - # TODO: Find a cleaner way to achieve that - if not env['tools']: - env['module_squish_enabled'] = False - env.disabled_modules.append("squish") + pass diff --git a/modules/stb_vorbis/audio_stream_ogg_vorbis.cpp b/modules/stb_vorbis/audio_stream_ogg_vorbis.cpp index 18ab616826..c95a8ac2dd 100644 --- a/modules/stb_vorbis/audio_stream_ogg_vorbis.cpp +++ b/modules/stb_vorbis/audio_stream_ogg_vorbis.cpp @@ -263,8 +263,8 @@ float AudioStreamOGGVorbis::get_length() const { void AudioStreamOGGVorbis::_bind_methods() { - ClassDB::bind_method(D_METHOD("_set_data", "data"), &AudioStreamOGGVorbis::set_data); - ClassDB::bind_method(D_METHOD("_get_data"), &AudioStreamOGGVorbis::get_data); + ClassDB::bind_method(D_METHOD("set_data", "data"), &AudioStreamOGGVorbis::set_data); + ClassDB::bind_method(D_METHOD("get_data"), &AudioStreamOGGVorbis::get_data); ClassDB::bind_method(D_METHOD("set_loop", "enable"), &AudioStreamOGGVorbis::set_loop); ClassDB::bind_method(D_METHOD("has_loop"), &AudioStreamOGGVorbis::has_loop); @@ -272,7 +272,7 @@ void AudioStreamOGGVorbis::_bind_methods() { ClassDB::bind_method(D_METHOD("set_loop_offset", "seconds"), &AudioStreamOGGVorbis::set_loop_offset); ClassDB::bind_method(D_METHOD("get_loop_offset"), &AudioStreamOGGVorbis::get_loop_offset); - ADD_PROPERTY(PropertyInfo(Variant::POOL_BYTE_ARRAY, "data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "_set_data", "_get_data"); + ADD_PROPERTY(PropertyInfo(Variant::POOL_BYTE_ARRAY, "data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_data", "get_data"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "loop", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_loop", "has_loop"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "loop_offset", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_loop_offset", "get_loop_offset"); } diff --git a/modules/stb_vorbis/config.py b/modules/stb_vorbis/config.py index defe8d0c94..d75e41797a 100644 --- a/modules/stb_vorbis/config.py +++ b/modules/stb_vorbis/config.py @@ -1,4 +1,4 @@ -def can_build(platform): +def can_build(env, platform): return True def configure(env): diff --git a/modules/stb_vorbis/doc_classes/AudioStreamOGGVorbis.xml b/modules/stb_vorbis/doc_classes/AudioStreamOGGVorbis.xml index ac95a7197f..e2281babf7 100644 --- a/modules/stb_vorbis/doc_classes/AudioStreamOGGVorbis.xml +++ b/modules/stb_vorbis/doc_classes/AudioStreamOGGVorbis.xml @@ -13,6 +13,9 @@ <methods> </methods> <members> + <member name="data" type="PoolByteArray" setter="set_data" getter="get_data"> + Contains the audio data in bytes. + </member> <member name="loop" type="bool" setter="set_loop" getter="has_loop"> </member> <member name="loop_offset" type="float" setter="set_loop_offset" getter="get_loop_offset"> diff --git a/modules/svg/SCsub b/modules/svg/SCsub index e12abac8c1..a41e0703bd 100644 --- a/modules/svg/SCsub +++ b/modules/svg/SCsub @@ -1,7 +1,6 @@ #!/usr/bin/env python Import('env') -from compat import isbasestring # Thirdparty source files thirdparty_dir = "#thirdparty/nanosvg/" @@ -10,23 +9,7 @@ thirdparty_sources = [ ] thirdparty_sources = [thirdparty_dir + file for file in thirdparty_sources] -# env.add_source_files(env.modules_sources, thirdparty_sources) - -lib = env.add_library("svg_builtin", thirdparty_sources) - -# Needs to be appended to arrive after libscene in the linker call, -# but we don't want it to arrive *after* system libs, so manual hack -# LIBS contains first SCons Library objects ("SCons.Node.FS.File object") -# and then plain strings for system library. We insert between the two. -inserted = False -for idx, linklib in enumerate(env["LIBS"]): - if isbasestring(linklib): # first system lib such as "X11", otherwise SCons lib object - env["LIBS"].insert(idx, lib) - inserted = True - break -if not inserted: - env.Append(LIBS=[lib]) - +env.add_source_files(env.modules_sources, thirdparty_sources) env.Append(CPPPATH=[thirdparty_dir]) env.Append(CCFLAGS=["-DSVG_ENABLED"]) diff --git a/modules/svg/config.py b/modules/svg/config.py index 5f133eba90..1c8cd12a2d 100644 --- a/modules/svg/config.py +++ b/modules/svg/config.py @@ -1,4 +1,4 @@ -def can_build(platform): +def can_build(env, platform): return True def configure(env): diff --git a/modules/tga/config.py b/modules/tga/config.py index 5f133eba90..1c8cd12a2d 100644 --- a/modules/tga/config.py +++ b/modules/tga/config.py @@ -1,4 +1,4 @@ -def can_build(platform): +def can_build(env, platform): return True def configure(env): diff --git a/modules/thekla_unwrap/config.py b/modules/thekla_unwrap/config.py index b1ce7d4b91..bd092bdc16 100644 --- a/modules/thekla_unwrap/config.py +++ b/modules/thekla_unwrap/config.py @@ -1,7 +1,5 @@ -def can_build(platform): - return platform != "android" and platform != "ios" +def can_build(env, platform): + return (env['tools'] and platform not in ["android", "ios"]) def configure(env): - if not env['tools']: - env['builtin_thekla_atlas'] = False - env.disabled_modules.append("thekla_unwrap") + pass diff --git a/modules/theora/config.py b/modules/theora/config.py index 34d34f8be2..7504166237 100644 --- a/modules/theora/config.py +++ b/modules/theora/config.py @@ -1,4 +1,4 @@ -def can_build(platform): +def can_build(env, platform): return True def configure(env): diff --git a/modules/tinyexr/config.py b/modules/tinyexr/config.py index e12bb398ce..098f1eafa9 100644 --- a/modules/tinyexr/config.py +++ b/modules/tinyexr/config.py @@ -1,9 +1,5 @@ -def can_build(platform): - return True +def can_build(env, platform): + return env['tools'] def configure(env): - # Tools only, disabled for non-tools - # TODO: Find a cleaner way to achieve that - if not env['tools']: - env['module_tinyexr_enabled'] = False - env.disabled_modules.append("tinyexr") + pass diff --git a/modules/visual_script/config.py b/modules/visual_script/config.py index 6b1ce41014..07a0450734 100644 --- a/modules/visual_script/config.py +++ b/modules/visual_script/config.py @@ -1,4 +1,4 @@ -def can_build(platform): +def can_build(env, platform): return True def configure(env): diff --git a/modules/visual_script/visual_script.cpp b/modules/visual_script/visual_script.cpp index 03bc4c114a..9331092171 100644 --- a/modules/visual_script/visual_script.cpp +++ b/modules/visual_script/visual_script.cpp @@ -121,6 +121,10 @@ Array VisualScriptNode::_get_default_input_values() const { return default_input_values; } +String VisualScriptNode::get_text() const { + return ""; +} + void VisualScriptNode::_bind_methods() { ClassDB::bind_method(D_METHOD("get_visual_script"), &VisualScriptNode::get_visual_script); @@ -1967,11 +1971,11 @@ Ref<Script> VisualScriptInstance::get_script() const { return script; } -ScriptInstance::RPCMode VisualScriptInstance::get_rpc_mode(const StringName &p_method) const { +MultiplayerAPI::RPCMode VisualScriptInstance::get_rpc_mode(const StringName &p_method) const { const Map<StringName, VisualScript::Function>::Element *E = script->functions.find(p_method); if (!E) { - return RPC_MODE_DISABLED; + return MultiplayerAPI::RPC_MODE_DISABLED; } if (E->get().function_id >= 0 && E->get().nodes.has(E->get().function_id)) { @@ -1983,12 +1987,12 @@ ScriptInstance::RPCMode VisualScriptInstance::get_rpc_mode(const StringName &p_m } } - return RPC_MODE_DISABLED; + return MultiplayerAPI::RPC_MODE_DISABLED; } -ScriptInstance::RPCMode VisualScriptInstance::get_rset_mode(const StringName &p_variable) const { +MultiplayerAPI::RPCMode VisualScriptInstance::get_rset_mode(const StringName &p_variable) const { - return RPC_MODE_DISABLED; + return MultiplayerAPI::RPC_MODE_DISABLED; } void VisualScriptInstance::create(const Ref<VisualScript> &p_script, Object *p_owner) { diff --git a/modules/visual_script/visual_script.h b/modules/visual_script/visual_script.h index dad9c68312..aaa6dfea11 100644 --- a/modules/visual_script/visual_script.h +++ b/modules/visual_script/visual_script.h @@ -78,7 +78,7 @@ public: Variant get_default_input_value(int p_port) const; virtual String get_caption() const = 0; - virtual String get_text() const = 0; + virtual String get_text() const; virtual String get_category() const = 0; //used by editor, this is not really saved @@ -433,8 +433,8 @@ public: virtual ScriptLanguage *get_language(); - virtual RPCMode get_rpc_mode(const StringName &p_method) const; - virtual RPCMode get_rset_mode(const StringName &p_variable) const; + virtual MultiplayerAPI::RPCMode get_rpc_mode(const StringName &p_method) const; + virtual MultiplayerAPI::RPCMode get_rset_mode(const StringName &p_variable) const; VisualScriptInstance(); ~VisualScriptInstance(); diff --git a/modules/visual_script/visual_script_builtin_funcs.cpp b/modules/visual_script/visual_script_builtin_funcs.cpp index 7f0a42da82..73b6d702c1 100644 --- a/modules/visual_script/visual_script_builtin_funcs.cpp +++ b/modules/visual_script/visual_script_builtin_funcs.cpp @@ -666,12 +666,14 @@ PropertyInfo VisualScriptBuiltinFunc::get_output_value_port_info(int p_idx) cons return PropertyInfo(t, ""); } +/* String VisualScriptBuiltinFunc::get_caption() const { return "BuiltinFunc"; } +*/ -String VisualScriptBuiltinFunc::get_text() const { +String VisualScriptBuiltinFunc::get_caption() const { return func_name[func]; } diff --git a/modules/visual_script/visual_script_builtin_funcs.h b/modules/visual_script/visual_script_builtin_funcs.h index f862d5c26f..3345762b9f 100644 --- a/modules/visual_script/visual_script_builtin_funcs.h +++ b/modules/visual_script/visual_script_builtin_funcs.h @@ -129,7 +129,7 @@ public: virtual PropertyInfo get_output_value_port_info(int p_idx) const; virtual String get_caption() const; - virtual String get_text() const; + //virtual String get_text() const; virtual String get_category() const { return "functions"; } void set_func(BuiltinFunc p_which); diff --git a/modules/visual_script/visual_script_editor.cpp b/modules/visual_script/visual_script_editor.cpp index eb10c5e99f..0618064ea6 100644 --- a/modules/visual_script/visual_script_editor.cpp +++ b/modules/visual_script/visual_script_editor.cpp @@ -268,7 +268,7 @@ protected: if (String(p_name) == "export") { script->set_variable_export(var, p_value); - EditorNode::get_singleton()->get_property_editor()->update_tree(); + EditorNode::get_singleton()->get_inspector()->update_tree(); return true; } @@ -527,6 +527,7 @@ void VisualScriptEditor::_update_graph(int p_only_id) { GraphNode *gnode = memnew(GraphNode); gnode->set_title(node->get_caption()); + gnode->set_offset(pos * EDSCALE); if (error_line == E->get()) { gnode->set_overlay(GraphNode::OVERLAY_POSITION); } else if (node->is_breakpoint()) { @@ -543,8 +544,10 @@ void VisualScriptEditor::_update_graph(int p_only_id) { gnode->set_show_close_button(true); } - if (Object::cast_to<VisualScriptExpression>(node.ptr())) { + bool has_gnode_text = false; + if (Object::cast_to<VisualScriptExpression>(node.ptr())) { + has_gnode_text = true; LineEdit *line_edit = memnew(LineEdit); line_edit->set_text(node->get_text()); line_edit->set_expand_to_text_length(true); @@ -552,9 +555,13 @@ void VisualScriptEditor::_update_graph(int p_only_id) { gnode->add_child(line_edit); line_edit->connect("text_changed", this, "_expression_text_changed", varray(E->get())); } else { - Label *text = memnew(Label); - text->set_text(node->get_text()); - gnode->add_child(text); + String text = node->get_text(); + if (!text.empty()) { + has_gnode_text = true; + Label *label = memnew(Label); + label->set_text(text); + gnode->add_child(label); + } } if (Object::cast_to<VisualScriptComment>(node.ptr())) { @@ -589,9 +596,21 @@ void VisualScriptEditor::_update_graph(int p_only_id) { int slot_idx = 0; bool single_seq_output = node->get_output_sequence_port_count() == 1 && node->get_output_sequence_port_text(0) == String(); - gnode->set_slot(0, node->has_input_sequence_port(), TYPE_SEQUENCE, mono_color, single_seq_output, TYPE_SEQUENCE, mono_color, seq_port, seq_port); - gnode->set_offset(pos * EDSCALE); - slot_idx++; + if ((node->has_input_sequence_port() || single_seq_output) || has_gnode_text) { + // IF has_gnode_text is true BUT we have no sequence ports to draw (in here), + // we still draw the disabled default ones to shift up the slots by one, + // so the slots DON'T start with the content text. + + // IF has_gnode_text is false, but we DO want to draw default sequence ports, + // we draw a dummy text to take up the position of the sequence nodes, so all the other ports are still aligned correctly. + if (!has_gnode_text) { + Label *dummy = memnew(Label); + dummy->set_text(" "); + gnode->add_child(dummy); + } + gnode->set_slot(0, node->has_input_sequence_port(), TYPE_SEQUENCE, mono_color, single_seq_output, TYPE_SEQUENCE, mono_color, seq_port, seq_port); + slot_idx++; + } int mixed_seq_ports = 0; diff --git a/modules/visual_script/visual_script_flow_control.cpp b/modules/visual_script/visual_script_flow_control.cpp index 5c097dfa76..ea23ab1b2a 100644 --- a/modules/visual_script/visual_script_flow_control.cpp +++ b/modules/visual_script/visual_script_flow_control.cpp @@ -772,7 +772,7 @@ PropertyInfo VisualScriptTypeCast::get_output_value_port_info(int p_idx) const { String VisualScriptTypeCast::get_caption() const { - return "TypeCast"; + return "Type Cast"; } String VisualScriptTypeCast::get_text() const { diff --git a/modules/visual_script/visual_script_func_nodes.cpp b/modules/visual_script/visual_script_func_nodes.cpp index 187c9b0b9e..bdf5705ecd 100644 --- a/modules/visual_script/visual_script_func_nodes.cpp +++ b/modules/visual_script/visual_script_func_nodes.cpp @@ -262,26 +262,6 @@ PropertyInfo VisualScriptFunctionCall::get_output_value_port_info(int p_idx) con } String VisualScriptFunctionCall::get_caption() const { - - static const char *cname[5] = { - "CallSelf", - "CallNode", - "CallInstance", - "CallBasic", - "CallSingleton" - }; - - String caption = cname[call_mode]; - - if (rpc_call_mode) { - caption += " (RPC)"; - } - - return caption; -} - -String VisualScriptFunctionCall::get_text() const { - if (call_mode == CALL_MODE_SELF) return " " + String(function) + "()"; if (call_mode == CALL_MODE_SINGLETON) @@ -294,6 +274,14 @@ String VisualScriptFunctionCall::get_text() const { return " " + base_type + "." + String(function) + "()"; } +String VisualScriptFunctionCall::get_text() const { + + if (rpc_call_mode) { + return "RPC"; + } + return ""; +} + void VisualScriptFunctionCall::set_basic_type(Variant::Type p_type) { if (basic_type == p_type) @@ -1075,36 +1063,31 @@ PropertyInfo VisualScriptPropertySet::get_output_value_port_info(int p_idx) cons String VisualScriptPropertySet::get_caption() const { - static const char *cname[4] = { - "Self", - "Node", - "Instance", - "Basic" - }; - static const char *opname[ASSIGN_OP_MAX] = { - "Set", "Add", "Sub", "Mul", "Div", "Mod", "ShiftLeft", "ShiftRight", "BitAnd", "BitOr", "BitXor" + "Set", "Add", "Subtract", "Multiply", "Divide", "Mod", "ShiftLeft", "ShiftRight", "BitAnd", "BitOr", "BitXor" }; - return String(cname[call_mode]) + opname[assign_op]; + + String prop = String(opname[assign_op]) + " " + property; + if (index != StringName()) { + prop += "." + String(index); + } + + return prop; } String VisualScriptPropertySet::get_text() const { - String prop; + if (call_mode == CALL_MODE_BASIC_TYPE) { + return String("On ") + Variant::get_type_name(basic_type); + } - if (call_mode == CALL_MODE_BASIC_TYPE) - prop = Variant::get_type_name(basic_type) + "." + property; - else if (call_mode == CALL_MODE_NODE_PATH) - prop = String(base_path) + ":" + property; - else if (call_mode == CALL_MODE_SELF) - prop = property; - else if (call_mode == CALL_MODE_INSTANCE) - prop = String(base_type) + ":" + property; + static const char *cname[3] = { + "Self", + "Scene Node", + "Instance" + }; - if (index != StringName()) { - prop += "." + String(index); - } - return prop; + return String("On ") + cname[call_mode]; } void VisualScriptPropertySet::_update_base_type() { @@ -1838,30 +1821,22 @@ PropertyInfo VisualScriptPropertyGet::get_output_value_port_info(int p_idx) cons String VisualScriptPropertyGet::get_caption() const { - static const char *cname[4] = { - "SelfGet", - "NodeGet", - "InstanceGet", - "BasicGet" - }; - - return cname[call_mode]; + return String("Get ") + property; } String VisualScriptPropertyGet::get_text() const { - String prop; + if (call_mode == CALL_MODE_BASIC_TYPE) { + return String("On ") + Variant::get_type_name(basic_type); + } - if (call_mode == CALL_MODE_BASIC_TYPE) - prop = Variant::get_type_name(basic_type) + "." + property; - else if (call_mode == CALL_MODE_NODE_PATH) - prop = String(base_path) + ":" + property; - else if (call_mode == CALL_MODE_SELF) - prop = property; - else if (call_mode == CALL_MODE_INSTANCE) - prop = String(base_type) + ":" + property; + static const char *cname[3] = { + "Self", + "Scene Node", + "Instance" + }; - return prop; + return String("On ") + cname[call_mode]; } void VisualScriptPropertyGet::set_base_type(const StringName &p_type) { @@ -2399,12 +2374,7 @@ PropertyInfo VisualScriptEmitSignal::get_output_value_port_info(int p_idx) const String VisualScriptEmitSignal::get_caption() const { - return "EmitSignal"; -} - -String VisualScriptEmitSignal::get_text() const { - - return "emit " + String(name); + return "Emit " + String(name); } void VisualScriptEmitSignal::set_signal(const StringName &p_type) { diff --git a/modules/visual_script/visual_script_func_nodes.h b/modules/visual_script/visual_script_func_nodes.h index 0b30eae65a..3b522564d4 100644 --- a/modules/visual_script/visual_script_func_nodes.h +++ b/modules/visual_script/visual_script_func_nodes.h @@ -346,7 +346,7 @@ public: virtual PropertyInfo get_output_value_port_info(int p_idx) const; virtual String get_caption() const; - virtual String get_text() const; + //virtual String get_text() const; virtual String get_category() const { return "functions"; } void set_signal(const StringName &p_type); diff --git a/modules/visual_script/visual_script_nodes.cpp b/modules/visual_script/visual_script_nodes.cpp index c5654a5a20..8b7b809ec0 100644 --- a/modules/visual_script/visual_script_nodes.cpp +++ b/modules/visual_script/visual_script_nodes.cpp @@ -93,7 +93,7 @@ bool VisualScriptFunction::_set(const StringName &p_name, const Variant &p_value } if (p_name == "rpc/mode") { - rpc_mode = ScriptInstance::RPCMode(int(p_value)); + rpc_mode = MultiplayerAPI::RPCMode(int(p_value)); return true; } @@ -267,11 +267,11 @@ int VisualScriptFunction::get_argument_count() const { return arguments.size(); } -void VisualScriptFunction::set_rpc_mode(ScriptInstance::RPCMode p_mode) { +void VisualScriptFunction::set_rpc_mode(MultiplayerAPI::RPCMode p_mode) { rpc_mode = p_mode; } -ScriptInstance::RPCMode VisualScriptFunction::get_rpc_mode() const { +MultiplayerAPI::RPCMode VisualScriptFunction::get_rpc_mode() const { return rpc_mode; } @@ -319,7 +319,7 @@ VisualScriptFunction::VisualScriptFunction() { stack_size = 256; stack_less = false; sequenced = true; - rpc_mode = ScriptInstance::RPC_MODE_DISABLED; + rpc_mode = MultiplayerAPI::RPC_MODE_DISABLED; } void VisualScriptFunction::set_stack_less(bool p_enable) { @@ -467,12 +467,12 @@ PropertyInfo VisualScriptOperator::get_output_value_port_info(int p_idx) const { static const char *op_names[] = { //comparison - "Equal", //OP_EQUAL, - "NotEqual", //OP_NOT_EQUAL, - "Less", //OP_LESS, - "LessEqual", //OP_LESS_EQUAL, - "Greater", //OP_GREATER, - "GreaterEq", //OP_GREATER_EQUAL, + "Are Equal", //OP_EQUAL, + "Are Not Equal", //OP_NOT_EQUAL, + "Less Than", //OP_LESS, + "Less Than or Equal", //OP_LESS_EQUAL, + "Greater Than", //OP_GREATER, + "Greater Than or Equal", //OP_GREATER_EQUAL, //mathematic "Add", //OP_ADD, "Subtract", //OP_SUBTRACT, @@ -481,14 +481,14 @@ static const char *op_names[] = { "Negate", //OP_NEGATE, "Positive", //OP_POSITIVE, "Remainder", //OP_MODULE, - "Concat", //OP_STRING_CONCAT, + "Concatenate", //OP_STRING_CONCAT, //bitwise - "ShiftLeft", //OP_SHIFT_LEFT, - "ShiftRight", //OP_SHIFT_RIGHT, - "BitAnd", //OP_BIT_AND, - "BitOr", //OP_BIT_OR, - "BitXor", //OP_BIT_XOR, - "BitNeg", //OP_BIT_NEGATE, + "Bit Shift Left", //OP_SHIFT_LEFT, + "Bit Shift Right", //OP_SHIFT_RIGHT, + "Bit And", //OP_BIT_AND, + "Bit Or", //OP_BIT_OR, + "Bit Xor", //OP_BIT_XOR, + "Bit Negate", //OP_BIT_NEGATE, //logic "And", //OP_AND, "Or", //OP_OR, @@ -500,11 +500,6 @@ static const char *op_names[] = { String VisualScriptOperator::get_caption() const { - return op_names[op]; -} - -String VisualScriptOperator::get_text() const { - static const wchar_t *op_names[] = { //comparison L"A = B", //OP_EQUAL, @@ -803,14 +798,8 @@ PropertyInfo VisualScriptVariableGet::get_output_value_port_info(int p_idx) cons String VisualScriptVariableGet::get_caption() const { - return "Variable"; + return "Get " + variable; } - -String VisualScriptVariableGet::get_text() const { - - return variable; -} - void VisualScriptVariableGet::set_variable(StringName p_variable) { if (variable == p_variable) @@ -928,12 +917,7 @@ PropertyInfo VisualScriptVariableSet::get_output_value_port_info(int p_idx) cons String VisualScriptVariableSet::get_caption() const { - return "VariableSet"; -} - -String VisualScriptVariableSet::get_text() const { - - return variable; + return "Set " + variable; } void VisualScriptVariableSet::set_variable(StringName p_variable) { @@ -1044,7 +1028,7 @@ PropertyInfo VisualScriptConstant::get_input_value_port_info(int p_idx) const { PropertyInfo VisualScriptConstant::get_output_value_port_info(int p_idx) const { PropertyInfo pinfo; - pinfo.name = "get"; + pinfo.name = String(value); pinfo.type = type; return pinfo; } @@ -1054,11 +1038,6 @@ String VisualScriptConstant::get_caption() const { return "Constant"; } -String VisualScriptConstant::get_text() const { - - return String(value); -} - void VisualScriptConstant::set_constant_type(Variant::Type p_type) { if (type == p_type) @@ -1174,10 +1153,20 @@ PropertyInfo VisualScriptPreload::get_input_value_port_info(int p_idx) const { PropertyInfo VisualScriptPreload::get_output_value_port_info(int p_idx) const { - PropertyInfo pinfo = PropertyInfo(Variant::OBJECT, "res"); + PropertyInfo pinfo; + pinfo.type = Variant::OBJECT; if (preload.is_valid()) { pinfo.hint = PROPERTY_HINT_RESOURCE_TYPE; pinfo.hint_string = preload->get_class(); + if (preload->get_path().is_resource_file()) { + pinfo.name = preload->get_path(); + } else if (preload->get_name() != String()) { + pinfo.name = preload->get_name(); + } else { + pinfo.name = preload->get_class(); + } + } else { + pinfo.name = "<empty>"; } return pinfo; @@ -1188,21 +1177,6 @@ String VisualScriptPreload::get_caption() const { return "Preload"; } -String VisualScriptPreload::get_text() const { - - if (preload.is_valid()) { - if (preload->get_path().is_resource_file()) { - return preload->get_path(); - } else if (preload->get_name() != String()) { - return preload->get_name(); - } else { - return preload->get_class(); - } - } else { - return "<empty>"; - } -} - void VisualScriptPreload::set_preload(const Ref<Resource> &p_preload) { if (preload == p_preload) @@ -1291,12 +1265,7 @@ PropertyInfo VisualScriptIndexGet::get_output_value_port_info(int p_idx) const { String VisualScriptIndexGet::get_caption() const { - return "IndexGet"; -} - -String VisualScriptIndexGet::get_text() const { - - return String("get"); + return "Get Index"; } class VisualScriptNodeInstanceIndexGet : public VisualScriptNodeInstance { @@ -1371,12 +1340,7 @@ PropertyInfo VisualScriptIndexSet::get_output_value_port_info(int p_idx) const { String VisualScriptIndexSet::get_caption() const { - return "IndexSet"; -} - -String VisualScriptIndexSet::get_text() const { - - return String("set"); + return "Set Index"; } class VisualScriptNodeInstanceIndexSet : public VisualScriptNodeInstance { @@ -1439,18 +1403,13 @@ PropertyInfo VisualScriptGlobalConstant::get_input_value_port_info(int p_idx) co } PropertyInfo VisualScriptGlobalConstant::get_output_value_port_info(int p_idx) const { - - return PropertyInfo(Variant::REAL, "value"); + String name = GlobalConstants::get_global_constant_name(index); + return PropertyInfo(Variant::REAL, name); } String VisualScriptGlobalConstant::get_caption() const { - return "GlobalConst"; -} - -String VisualScriptGlobalConstant::get_text() const { - - return GlobalConstants::get_global_constant_name(index); + return "Global Constant"; } void VisualScriptGlobalConstant::set_global_constant(int p_which) { @@ -1539,17 +1498,12 @@ PropertyInfo VisualScriptClassConstant::get_input_value_port_info(int p_idx) con PropertyInfo VisualScriptClassConstant::get_output_value_port_info(int p_idx) const { - return PropertyInfo(Variant::INT, "value"); + return PropertyInfo(Variant::INT, String(base_type) + "." + String(name)); } String VisualScriptClassConstant::get_caption() const { - return "ClassConst"; -} - -String VisualScriptClassConstant::get_text() const { - - return String(base_type) + "." + String(name); + return "Class Constant"; } void VisualScriptClassConstant::set_class_constant(const StringName &p_which) { @@ -1673,7 +1627,7 @@ PropertyInfo VisualScriptBasicTypeConstant::get_output_value_port_info(int p_idx String VisualScriptBasicTypeConstant::get_caption() const { - return "BasicConst"; + return "Basic Constant"; } String VisualScriptBasicTypeConstant::get_text() const { @@ -1828,17 +1782,12 @@ PropertyInfo VisualScriptMathConstant::get_input_value_port_info(int p_idx) cons PropertyInfo VisualScriptMathConstant::get_output_value_port_info(int p_idx) const { - return PropertyInfo(Variant::REAL, "value"); + return PropertyInfo(Variant::REAL, const_name[constant]); } String VisualScriptMathConstant::get_caption() const { - return "MathConst"; -} - -String VisualScriptMathConstant::get_text() const { - - return const_name[constant]; + return "Math Constant"; } void VisualScriptMathConstant::set_math_constant(MathConstant p_which) { @@ -1903,7 +1852,7 @@ VisualScriptMathConstant::VisualScriptMathConstant() { } ////////////////////////////////////////// -////////////////GLOBALSINGLETON/////////// +////////////////ENGINESINGLETON/////////// ////////////////////////////////////////// int VisualScriptEngineSingleton::get_output_sequence_port_count() const { @@ -1937,17 +1886,12 @@ PropertyInfo VisualScriptEngineSingleton::get_input_value_port_info(int p_idx) c PropertyInfo VisualScriptEngineSingleton::get_output_value_port_info(int p_idx) const { - return PropertyInfo(Variant::OBJECT, "instance"); + return PropertyInfo(Variant::OBJECT, singleton); } String VisualScriptEngineSingleton::get_caption() const { - return "EngineSingleton"; -} - -String VisualScriptEngineSingleton::get_text() const { - - return singleton; + return "Get Engine Singleton"; } void VisualScriptEngineSingleton::set_singleton(const String &p_string) { @@ -2058,17 +2002,12 @@ PropertyInfo VisualScriptSceneNode::get_input_value_port_info(int p_idx) const { PropertyInfo VisualScriptSceneNode::get_output_value_port_info(int p_idx) const { - return PropertyInfo(Variant::OBJECT, "node"); + return PropertyInfo(Variant::OBJECT, path.simplified()); } String VisualScriptSceneNode::get_caption() const { - return "SceneNode"; -} - -String VisualScriptSceneNode::get_text() const { - - return path.simplified(); + return "Get Scene Node"; } void VisualScriptSceneNode::set_node_path(const NodePath &p_path) { @@ -2259,17 +2198,12 @@ PropertyInfo VisualScriptSceneTree::get_input_value_port_info(int p_idx) const { PropertyInfo VisualScriptSceneTree::get_output_value_port_info(int p_idx) const { - return PropertyInfo(Variant::OBJECT, "instance"); + return PropertyInfo(Variant::OBJECT, "Scene Tree"); } String VisualScriptSceneTree::get_caption() const { - return "SceneTree"; -} - -String VisualScriptSceneTree::get_text() const { - - return ""; + return "Get Scene Tree"; } class VisualScriptNodeInstanceSceneTree : public VisualScriptNodeInstance { @@ -2361,17 +2295,12 @@ PropertyInfo VisualScriptResourcePath::get_input_value_port_info(int p_idx) cons PropertyInfo VisualScriptResourcePath::get_output_value_port_info(int p_idx) const { - return PropertyInfo(Variant::STRING, "path"); + return PropertyInfo(Variant::STRING, path); } String VisualScriptResourcePath::get_caption() const { - return "ResourcePath"; -} - -String VisualScriptResourcePath::get_text() const { - - return path; + return "Resource Path"; } void VisualScriptResourcePath::set_resource_path(const String &p_path) { @@ -2453,20 +2382,18 @@ PropertyInfo VisualScriptSelf::get_input_value_port_info(int p_idx) const { PropertyInfo VisualScriptSelf::get_output_value_port_info(int p_idx) const { - return PropertyInfo(Variant::OBJECT, "instance"); -} - -String VisualScriptSelf::get_caption() const { + String type_name; + if (get_visual_script().is_valid()) + type_name = get_visual_script()->get_instance_base_type(); + else + type_name = "instance"; - return "Self"; + return PropertyInfo(Variant::OBJECT, type_name); } -String VisualScriptSelf::get_text() const { +String VisualScriptSelf::get_caption() const { - if (get_visual_script().is_valid()) - return get_visual_script()->get_instance_base_type(); - else - return ""; + return "Get Self"; } class VisualScriptNodeInstanceSelf : public VisualScriptNodeInstance { @@ -3032,12 +2959,7 @@ PropertyInfo VisualScriptConstructor::get_output_value_port_info(int p_idx) cons String VisualScriptConstructor::get_caption() const { - return "Construct"; -} - -String VisualScriptConstructor::get_text() const { - - return "new " + Variant::get_type_name(type) + "()"; + return "Construct " + Variant::get_type_name(type); } String VisualScriptConstructor::get_category() const { @@ -3163,17 +3085,12 @@ PropertyInfo VisualScriptLocalVar::get_input_value_port_info(int p_idx) const { } PropertyInfo VisualScriptLocalVar::get_output_value_port_info(int p_idx) const { - return PropertyInfo(type, "get"); + return PropertyInfo(type, name); } String VisualScriptLocalVar::get_caption() const { - return "LocalVarGet"; -} - -String VisualScriptLocalVar::get_text() const { - - return name; + return "Get Local Var"; } String VisualScriptLocalVar::get_category() const { @@ -3289,7 +3206,7 @@ PropertyInfo VisualScriptLocalVarSet::get_output_value_port_info(int p_idx) cons String VisualScriptLocalVarSet::get_caption() const { - return "LocalVarSet"; + return "Set Local Var"; } String VisualScriptLocalVarSet::get_text() const { @@ -3427,12 +3344,7 @@ PropertyInfo VisualScriptInputAction::get_output_value_port_info(int p_idx) cons String VisualScriptInputAction::get_caption() const { - return "Action"; -} - -String VisualScriptInputAction::get_text() const { - - return name; + return "Action " + name; } String VisualScriptInputAction::get_category() const { @@ -3600,12 +3512,7 @@ PropertyInfo VisualScriptDeconstruct::get_output_value_port_info(int p_idx) cons String VisualScriptDeconstruct::get_caption() const { - return "Deconstruct"; -} - -String VisualScriptDeconstruct::get_text() const { - - return "from " + Variant::get_type_name(type) + ":"; + return "Deconstruct " + Variant::get_type_name(type); } String VisualScriptDeconstruct::get_category() const { diff --git a/modules/visual_script/visual_script_nodes.h b/modules/visual_script/visual_script_nodes.h index a581e81c8c..9bfbd46e47 100644 --- a/modules/visual_script/visual_script_nodes.h +++ b/modules/visual_script/visual_script_nodes.h @@ -46,7 +46,7 @@ class VisualScriptFunction : public VisualScriptNode { bool stack_less; int stack_size; - ScriptInstance::RPCMode rpc_mode; + MultiplayerAPI::RPCMode rpc_mode; bool sequenced; protected: @@ -93,8 +93,8 @@ public: void set_return_type(Variant::Type p_type); Variant::Type get_return_type() const; - void set_rpc_mode(ScriptInstance::RPCMode p_mode); - ScriptInstance::RPCMode get_rpc_mode() const; + void set_rpc_mode(MultiplayerAPI::RPCMode p_mode); + MultiplayerAPI::RPCMode get_rpc_mode() const; virtual VisualScriptNodeInstance *instance(VisualScriptInstance *p_instance); @@ -124,7 +124,6 @@ public: virtual PropertyInfo get_output_value_port_info(int p_idx) const; virtual String get_caption() const; - virtual String get_text() const; virtual String get_category() const { return "operators"; } void set_operator(Variant::Operator p_op); @@ -194,7 +193,6 @@ public: virtual PropertyInfo get_output_value_port_info(int p_idx) const; virtual String get_caption() const; - virtual String get_text() const; virtual String get_category() const { return "data"; } void set_variable(StringName p_variable); @@ -228,7 +226,6 @@ public: virtual PropertyInfo get_output_value_port_info(int p_idx) const; virtual String get_caption() const; - virtual String get_text() const; virtual String get_category() const { return "data"; } void set_variable(StringName p_variable); @@ -263,7 +260,6 @@ public: virtual PropertyInfo get_output_value_port_info(int p_idx) const; virtual String get_caption() const; - virtual String get_text() const; virtual String get_category() const { return "constants"; } void set_constant_type(Variant::Type p_type); @@ -299,7 +295,6 @@ public: virtual PropertyInfo get_output_value_port_info(int p_idx) const; virtual String get_caption() const; - virtual String get_text() const; virtual String get_category() const { return "data"; } void set_preload(const Ref<Resource> &p_preload); @@ -327,7 +322,6 @@ public: virtual PropertyInfo get_output_value_port_info(int p_idx) const; virtual String get_caption() const; - virtual String get_text() const; virtual String get_category() const { return "operators"; } virtual VisualScriptNodeInstance *instance(VisualScriptInstance *p_instance); @@ -352,7 +346,6 @@ public: virtual PropertyInfo get_output_value_port_info(int p_idx) const; virtual String get_caption() const; - virtual String get_text() const; virtual String get_category() const { return "operators"; } virtual VisualScriptNodeInstance *instance(VisualScriptInstance *p_instance); @@ -381,7 +374,6 @@ public: virtual PropertyInfo get_output_value_port_info(int p_idx) const; virtual String get_caption() const; - virtual String get_text() const; virtual String get_category() const { return "constants"; } void set_global_constant(int p_which); @@ -416,7 +408,6 @@ public: virtual PropertyInfo get_output_value_port_info(int p_idx) const; virtual String get_caption() const; - virtual String get_text() const; virtual String get_category() const { return "constants"; } void set_class_constant(const StringName &p_which); @@ -505,7 +496,6 @@ public: virtual PropertyInfo get_output_value_port_info(int p_idx) const; virtual String get_caption() const; - virtual String get_text() const; virtual String get_category() const { return "constants"; } void set_math_constant(MathConstant p_which); @@ -539,7 +529,6 @@ public: virtual PropertyInfo get_output_value_port_info(int p_idx) const; virtual String get_caption() const; - virtual String get_text() const; virtual String get_category() const { return "data"; } void set_singleton(const String &p_string); @@ -575,7 +564,6 @@ public: virtual PropertyInfo get_output_value_port_info(int p_idx) const; virtual String get_caption() const; - virtual String get_text() const; virtual String get_category() const { return "data"; } void set_node_path(const NodePath &p_path); @@ -609,7 +597,6 @@ public: virtual PropertyInfo get_output_value_port_info(int p_idx) const; virtual String get_caption() const; - virtual String get_text() const; virtual String get_category() const { return "data"; } virtual VisualScriptNodeInstance *instance(VisualScriptInstance *p_instance); @@ -641,7 +628,6 @@ public: virtual PropertyInfo get_output_value_port_info(int p_idx) const; virtual String get_caption() const; - virtual String get_text() const; virtual String get_category() const { return "data"; } void set_resource_path(const String &p_path); @@ -672,7 +658,6 @@ public: virtual PropertyInfo get_output_value_port_info(int p_idx) const; virtual String get_caption() const; - virtual String get_text() const; virtual String get_category() const { return "data"; } virtual VisualScriptNodeInstance *instance(VisualScriptInstance *p_instance); @@ -822,7 +807,6 @@ public: virtual PropertyInfo get_output_value_port_info(int p_idx) const; virtual String get_caption() const; - virtual String get_text() const; virtual String get_category() const; void set_constructor_type(Variant::Type p_type); @@ -859,7 +843,6 @@ public: virtual PropertyInfo get_output_value_port_info(int p_idx) const; virtual String get_caption() const; - virtual String get_text() const; virtual String get_category() const; void set_var_name(const StringName &p_name); @@ -942,7 +925,6 @@ public: virtual PropertyInfo get_output_value_port_info(int p_idx) const; virtual String get_caption() const; - virtual String get_text() const; virtual String get_category() const; void set_action_name(const StringName &p_name); @@ -993,7 +975,6 @@ public: virtual PropertyInfo get_output_value_port_info(int p_idx) const; virtual String get_caption() const; - virtual String get_text() const; virtual String get_category() const; void set_deconstruct_type(Variant::Type p_type); diff --git a/modules/vorbis/config.py b/modules/vorbis/config.py index 5f133eba90..1c8cd12a2d 100644 --- a/modules/vorbis/config.py +++ b/modules/vorbis/config.py @@ -1,4 +1,4 @@ -def can_build(platform): +def can_build(env, platform): return True def configure(env): diff --git a/modules/webm/config.py b/modules/webm/config.py index dcae4447d5..72a4073423 100644 --- a/modules/webm/config.py +++ b/modules/webm/config.py @@ -1,5 +1,5 @@ -def can_build(platform): - return platform != 'iphone' +def can_build(env, platform): + return platform not in ['iphone'] def configure(env): pass diff --git a/modules/webm/libvpx/SCsub b/modules/webm/libvpx/SCsub index b09c232b3c..c681e2b34f 100644 --- a/modules/webm/libvpx/SCsub +++ b/modules/webm/libvpx/SCsub @@ -263,7 +263,7 @@ if env["platform"] == 'uwp': webm_cpu_x86 = True else: import platform - is_x11_or_server_arm = ((env["platform"] == 'x11' or env["platform"] == 'server') and platform.machine().startswith('arm')) + is_x11_or_server_arm = ((env["platform"] == 'x11' or env["platform"] == 'server') and (platform.machine().startswith('arm') or platform.machine().startswith('aarch'))) is_ios_x86 = (env["platform"] == 'iphone' and env["ios_sim"]) is_android_x86 = (env["platform"] == 'android' and env["android_arch"] == 'x86') if is_android_x86: @@ -337,7 +337,6 @@ if webm_cpu_arm: if webm_simd_optimizations == False: print("WebM SIMD optimizations are disabled. Check if your CPU architecture, CPU bits or platform are supported!") - env_libvpx.add_source_files(env.modules_sources, libvpx_sources) if webm_cpu_x86: is_clang_or_gcc = ('gcc' in env["CC"]) or ('clang' in env["CC"]) or ("OSXCROSS_ROOT" in os.environ) @@ -379,5 +378,5 @@ elif webm_cpu_arm: env_libvpx.add_source_files(env.modules_sources, libvpx_sources_arm_neon_armasm_ms) elif env["platform"] == 'iphone': env_libvpx.add_source_files(env.modules_sources, libvpx_sources_arm_neon_gas_apple) - elif not env["android_arch"] == 'arm64v8': + elif (is_x11_or_server_arm and cpu_bits == '32') or (env["platform"] == 'android' and not env["android_arch"] == 'arm64v8'): env_libvpx.add_source_files(env.modules_sources, libvpx_sources_arm_neon_gas) diff --git a/modules/webp/SCsub b/modules/webp/SCsub index ea7af1bf9e..21ae0ce7c2 100644 --- a/modules/webp/SCsub +++ b/modules/webp/SCsub @@ -78,10 +78,12 @@ if env['builtin_libwebp']: "dsp/upsampling_msa.c", "dsp/upsampling_neon.c", "dsp/upsampling_sse2.c", + "dsp/upsampling_sse41.c", "dsp/yuv.c", "dsp/yuv_mips32.c", "dsp/yuv_mips_dsp_r2.c", "dsp/yuv_sse2.c", + "dsp/yuv_sse41.c", "enc/alpha_enc.c", "enc/analysis_enc.c", "enc/backward_references_cost_enc.c", diff --git a/modules/webp/config.py b/modules/webp/config.py index 5f133eba90..1c8cd12a2d 100644 --- a/modules/webp/config.py +++ b/modules/webp/config.py @@ -1,4 +1,4 @@ -def can_build(platform): +def can_build(env, platform): return True def configure(env): diff --git a/modules/websocket/config.py b/modules/websocket/config.py index fb920482f5..f59ef432b4 100644 --- a/modules/websocket/config.py +++ b/modules/websocket/config.py @@ -1,7 +1,16 @@ - -def can_build(platform): +def can_build(env, platform): return True - def configure(env): pass + +def get_doc_classes(): + return [ + "WebSocketClient", + "WebSocketMultiplayerPeer", + "WebSocketPeer", + "WebSocketServer" + ] + +def get_doc_path(): + return "doc_classes" diff --git a/modules/websocket/doc_classes/WebSocketClient.xml b/modules/websocket/doc_classes/WebSocketClient.xml new file mode 100644 index 0000000000..2e11e1a44c --- /dev/null +++ b/modules/websocket/doc_classes/WebSocketClient.xml @@ -0,0 +1,70 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<class name="WebSocketClient" inherits="WebSocketMultiplayerPeer" category="Core" version="3.1"> + <brief_description> + A WebSocket client implementation + </brief_description> + <description> + This class implements a WebSocket client compatible with any RFC 6455 complaint WebSocket server. + This client can be optionally used as a network peer for the [MultiplayerAPI]. + After starting the client ([method connect_to_url]), you will need to [method NetworkedMultiplayerPeer.poll] it at regular intervals (e.g. inside [method Node._process]). + You will received appropriate signals when connecting, disconnecting, or when new data is available. + </description> + <tutorials> + </tutorials> + <demos> + </demos> + <methods> + <method name="connect_to_url"> + <return type="int" enum="Error"> + </return> + <argument index="0" name="url" type="String"> + </argument> + <argument index="1" name="protocols" type="PoolStringArray" default="PoolStringArray( )"> + </argument> + <argument index="2" name="gd_mp_api" type="bool" default="false"> + </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. + </description> + </method> + <method name="disconnect_from_host"> + <return type="void"> + </return> + <description> + Disconnect from the server if currently connected. + </description> + </method> + </methods> + <members> + <member name="verify_ssl" type="bool" setter="set_verify_ssl_enabled" getter="is_verify_ssl_enabled"> + Enable or disable SSL certificate verification. Note: You must specify the certificates to be used in the project settings for it to work when exported. + </member> + </members> + <signals> + <signal name="connection_closed"> + <description> + Emitted when the connection to the server is closed. + </description> + </signal> + <signal name="connection_error"> + <description> + Emitted when the connection to the server fails. + </description> + </signal> + <signal name="connection_established"> + <argument index="0" name="protocol" type="String"> + </argument> + <description> + Emitted when a connection with the server is established, [code]protocol[/code] will contain the sub-protocol agreed with the server. + </description> + </signal> + <signal name="data_received"> + <description> + Emitted when a WebSocket message is received. Note: This signal is NOT emitted when used as high level multiplayer peer. + </description> + </signal> + </signals> + <constants> + </constants> +</class> diff --git a/modules/websocket/doc_classes/WebSocketMultiplayerPeer.xml b/modules/websocket/doc_classes/WebSocketMultiplayerPeer.xml new file mode 100644 index 0000000000..1a841f85ed --- /dev/null +++ b/modules/websocket/doc_classes/WebSocketMultiplayerPeer.xml @@ -0,0 +1,35 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<class name="WebSocketMultiplayerPeer" inherits="NetworkedMultiplayerPeer" category="Core" version="3.1"> + <brief_description> + Base class for WebSocket server and client. + </brief_description> + <description> + Base class for WebSocket server and client, allowing them to be used as network peer for the [MultiplayerAPI]. + </description> + <tutorials> + </tutorials> + <demos> + </demos> + <methods> + <method name="get_peer" qualifiers="const"> + <return type="WebSocketPeer"> + </return> + <argument index="0" name="peer_id" type="int"> + </argument> + <description> + Returns the [WebSocketPeer] associated to the given [code]peer_id[/code]. + </description> + </method> + </methods> + <signals> + <signal name="peer_packet"> + <argument index="0" name="peer_source" type="int"> + </argument> + <description> + Emitted when a packet is received from a peer. Note: this signal is only emitted when the client or server is configured to use Godot multiplayer API. + </description> + </signal> + </signals> + <constants> + </constants> +</class> diff --git a/modules/websocket/doc_classes/WebSocketPeer.xml b/modules/websocket/doc_classes/WebSocketPeer.xml new file mode 100644 index 0000000000..85a08e0c0b --- /dev/null +++ b/modules/websocket/doc_classes/WebSocketPeer.xml @@ -0,0 +1,75 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<class name="WebSocketPeer" inherits="PacketPeer" category="Core" version="3.1"> + <brief_description> + A class representing a specific WebSocket connection. + </brief_description> + <description> + This class represent a specific WebSocket connection, you can do lower level operations with it. + You can choose to write to the socket in binary or text mode, and you can recognize the mode used for writing by the other peer. + </description> + <tutorials> + </tutorials> + <demos> + </demos> + <methods> + <method name="close"> + <return type="void"> + </return> + <description> + Close this WebSocket connection, actively disconnecting the peer. + </description> + </method> + <method name="get_connected_host" qualifiers="const"> + <return type="String"> + </return> + <description> + Returns the IP Address of the connected peer. (Not available in HTML5 export) + </description> + </method> + <method name="get_connected_port" qualifiers="const"> + <return type="int"> + </return> + <description> + Returns the remote port of the connected peer. (Not available in HTML5 export) + </description> + </method> + <method name="get_write_mode" qualifiers="const"> + <return type="int" enum="WebSocketPeer.WriteMode"> + </return> + <description> + Get the current selected write mode. See [enum WriteMode]. + </description> + </method> + <method name="is_connected_to_host" qualifiers="const"> + <return type="bool"> + </return> + <description> + Returns [code]true[/code] if this peer is currently connected. + </description> + </method> + <method name="set_write_mode"> + <return type="void"> + </return> + <argument index="0" name="mode" type="int" enum="WebSocketPeer.WriteMode"> + </argument> + <description> + Sets the socket to use the given [enum WriteMode]. + </description> + </method> + <method name="was_string_packet" qualifiers="const"> + <return type="bool"> + </return> + <description> + Returns [code]true[/code] if the last received packet was sent as a text payload. See [enum WriteMode] + </description> + </method> + </methods> + <constants> + <constant name="WRITE_MODE_TEXT" value="0" enum="WriteMode"> + Specify that WebSockets messages should be transferred as text payload (only valid UTF-8 is allowed). + </constant> + <constant name="WRITE_MODE_BINARY" value="1" enum="WriteMode"> + Specify that WebSockets messages should be transferred as binary payload (any byte combination is allowed). + </constant> + </constants> +</class> diff --git a/modules/websocket/doc_classes/WebSocketServer.xml b/modules/websocket/doc_classes/WebSocketServer.xml new file mode 100644 index 0000000000..a1061e446b --- /dev/null +++ b/modules/websocket/doc_classes/WebSocketServer.xml @@ -0,0 +1,109 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<class name="WebSocketServer" inherits="WebSocketMultiplayerPeer" category="Core" version="3.1"> + <brief_description> + A WebSocket server implementation + </brief_description> + <description> + This class implements a WebSocket server that can also support the high level multiplayer API. + After starting the server ([method listen]), you will need to [method NetworkedMultiplayerPeer.poll] it at regular intervals (e.g. inside [method Node._process]). When clients connect, disconnect, or send data, you will receive the appropriate signal. + Note: This class will not work in HTML5 exports due to browser restrictions. + </description> + <tutorials> + </tutorials> + <demos> + </demos> + <methods> + <method name="disconnect_peer"> + <return type="void"> + </return> + <argument index="0" name="id" type="int"> + </argument> + <description> + Disconnects the given peer. + </description> + </method> + <method name="get_peer_address" qualifiers="const"> + <return type="String"> + </return> + <argument index="0" name="id" type="int"> + </argument> + <description> + Returns the IP address of the given peer. + </description> + </method> + <method name="get_peer_port" qualifiers="const"> + <return type="int"> + </return> + <argument index="0" name="id" type="int"> + </argument> + <description> + Returns the remote port of the given peer. + </description> + </method> + <method name="has_peer" qualifiers="const"> + <return type="bool"> + </return> + <argument index="0" name="id" type="int"> + </argument> + <description> + Returns [code]true[/code] if a peer with the given ID is connected. + </description> + </method> + <method name="is_listening" qualifiers="const"> + <return type="bool"> + </return> + <description> + Returns [code]true[/code] if the server is actively listening on a port. + </description> + </method> + <method name="listen"> + <return type="int" enum="Error"> + </return> + <argument index="0" name="port" type="int"> + </argument> + <argument index="1" name="protocols" type="PoolStringArray" default="PoolStringArray( )"> + </argument> + <argument index="2" name="gd_mp_api" type="bool" default="false"> + </argument> + <description> + Start listening on the given port. + You can specify the desired subprotocols via the "protocols" array. If the list empty (default), "binary" will be used. + You can use this server as a network peer for [MultiplayerAPI] by passing true as "gd_mp_api". Note: [signal data_received] will not be fired and clients other than Godot will not work in this case. + </description> + </method> + <method name="stop"> + <return type="void"> + </return> + <description> + Stop the server and clear its state. + </description> + </method> + </methods> + <signals> + <signal name="client_connected"> + <argument index="0" name="id" type="int"> + </argument> + <argument index="1" name="protocol" type="String"> + </argument> + <description> + Emitted when a new client connects. "protocol" will be the sub-protocol agreed with the client. + </description> + </signal> + <signal name="client_disconnected"> + <argument index="0" name="id" type="int"> + </argument> + <description> + Emitted when a client disconnects. + </description> + </signal> + <signal name="data_received"> + <argument index="0" name="id" type="int"> + </argument> + <description> + Emitted when a new message is received. Note: This signal is NOT emitted when used as high level multiplayer peer. + </description> + </signal> + </signals> + <constants> + </constants> +</class> diff --git a/modules/websocket/lws_peer.cpp b/modules/websocket/lws_peer.cpp index 3855a39aef..96acb99cc4 100644 --- a/modules/websocket/lws_peer.cpp +++ b/modules/websocket/lws_peer.cpp @@ -191,8 +191,8 @@ IP_Address LWSPeer::get_connected_host() const { IP_Address ip; int port = 0; - socklen_t len = 0; struct sockaddr_storage addr; + socklen_t len = sizeof(addr); int fd = lws_get_socket_fd(wsi); ERR_FAIL_COND_V(fd == -1, IP_Address()); @@ -212,8 +212,8 @@ uint16_t LWSPeer::get_connected_port() const { IP_Address ip; int port = 0; - socklen_t len = 0; struct sockaddr_storage addr; + socklen_t len = sizeof(addr); int fd = lws_get_socket_fd(wsi); ERR_FAIL_COND_V(fd == -1, 0); diff --git a/modules/websocket/websocket_server.cpp b/modules/websocket/websocket_server.cpp index 2693b26e47..53dd7b51b7 100644 --- a/modules/websocket/websocket_server.cpp +++ b/modules/websocket/websocket_server.cpp @@ -44,9 +44,9 @@ void WebSocketServer::_bind_methods() { ClassDB::bind_method(D_METHOD("listen", "port", "protocols", "gd_mp_api"), &WebSocketServer::listen, DEFVAL(PoolVector<String>()), DEFVAL(false)); ClassDB::bind_method(D_METHOD("stop"), &WebSocketServer::stop); ClassDB::bind_method(D_METHOD("has_peer", "id"), &WebSocketServer::has_peer); - ClassDB::bind_method(D_METHOD("get_peer_address"), &WebSocketServer::get_peer_address); - ClassDB::bind_method(D_METHOD("get_peer_port"), &WebSocketServer::get_peer_port); - ClassDB::bind_method(D_METHOD("disconnect_peer"), &WebSocketServer::disconnect_peer); + ClassDB::bind_method(D_METHOD("get_peer_address", "id"), &WebSocketServer::get_peer_address); + ClassDB::bind_method(D_METHOD("get_peer_port", "id"), &WebSocketServer::get_peer_port); + ClassDB::bind_method(D_METHOD("disconnect_peer", "id"), &WebSocketServer::disconnect_peer); ADD_SIGNAL(MethodInfo("client_disconnected", PropertyInfo(Variant::INT, "id"))); ADD_SIGNAL(MethodInfo("client_connected", PropertyInfo(Variant::INT, "id"), PropertyInfo(Variant::STRING, "protocol"))); |