diff options
Diffstat (limited to 'modules')
37 files changed, 553 insertions, 278 deletions
diff --git a/modules/assimp/editor_scene_importer_assimp.cpp b/modules/assimp/editor_scene_importer_assimp.cpp index e5439fd132..f2f51d9dd3 100644 --- a/modules/assimp/editor_scene_importer_assimp.cpp +++ b/modules/assimp/editor_scene_importer_assimp.cpp @@ -529,7 +529,7 @@ void EditorSceneImporterAssimp::_import_animation(ImportState &state, int p_anim } // -// Mesh Generation from indicies ? why do we need so much mesh code +// Mesh Generation from indices ? why do we need so much mesh code // [debt needs looked into] Ref<Mesh> EditorSceneImporterAssimp::_generate_mesh_from_surface_indices( ImportState &state, @@ -541,6 +541,25 @@ Ref<Mesh> EditorSceneImporterAssimp::_generate_mesh_from_surface_indices( mesh.instance(); bool has_uvs = false; + Map<String, uint32_t> morph_mesh_string_lookup; + + for (int i = 0; i < p_surface_indices.size(); i++) { + const unsigned int mesh_idx = p_surface_indices[0]; + const aiMesh *ai_mesh = state.assimp_scene->mMeshes[mesh_idx]; + for (size_t j = 0; j < ai_mesh->mNumAnimMeshes; j++) { + + String ai_anim_mesh_name = AssimpUtils::get_assimp_string(ai_mesh->mAnimMeshes[j]->mName); + if (!morph_mesh_string_lookup.has(ai_anim_mesh_name)) { + morph_mesh_string_lookup.insert(ai_anim_mesh_name, j); + mesh->set_blend_shape_mode(Mesh::BLEND_SHAPE_MODE_NORMALIZED); + if (ai_anim_mesh_name.empty()) { + ai_anim_mesh_name = String("morph_") + itos(j); + } + mesh->add_blend_shape(ai_anim_mesh_name); + } + } + } + // // Process Vertex Weights // @@ -680,6 +699,25 @@ Ref<Mesh> EditorSceneImporterAssimp::_generate_mesh_from_surface_indices( mat->set_cull_mode(SpatialMaterial::CULL_BACK); // Now process materials + aiTextureType base_color = aiTextureType_BASE_COLOR; + { + String filename, path; + AssimpImageData image_data; + + if (AssimpUtils::GetAssimpTexture(state, ai_material, base_color, filename, path, image_data)) { + AssimpUtils::set_texture_mapping_mode(image_data.map_mode, image_data.texture); + + // anything transparent must be culled + if (image_data.raw_image->detect_alpha() != Image::ALPHA_NONE) { + mat->set_feature(SpatialMaterial::FEATURE_TRANSPARENT, true); + mat->set_depth_draw_mode(SpatialMaterial::DepthDrawMode::DEPTH_DRAW_ALPHA_OPAQUE_PREPASS); + mat->set_cull_mode(SpatialMaterial::CULL_DISABLED); // since you can see both sides in transparent mode + } + + mat->set_texture(SpatialMaterial::TEXTURE_ALBEDO, image_data.texture); + } + } + aiTextureType tex_diffuse = aiTextureType_DIFFUSE; { String filename, path; @@ -731,6 +769,60 @@ Ref<Mesh> EditorSceneImporterAssimp::_generate_mesh_from_surface_indices( } } + aiTextureType tex_normal_camera = aiTextureType_NORMAL_CAMERA; + { + String filename, path; + Ref<ImageTexture> texture; + AssimpImageData image_data; + + // Process texture normal map + if (AssimpUtils::GetAssimpTexture(state, ai_material, tex_normal_camera, filename, path, image_data)) { + AssimpUtils::set_texture_mapping_mode(image_data.map_mode, image_data.texture); + mat->set_feature(SpatialMaterial::Feature::FEATURE_NORMAL_MAPPING, true); + mat->set_texture(SpatialMaterial::TEXTURE_NORMAL, image_data.texture); + } + } + + aiTextureType tex_emission_color = aiTextureType_EMISSION_COLOR; + { + String filename, path; + Ref<ImageTexture> texture; + AssimpImageData image_data; + + // Process texture normal map + if (AssimpUtils::GetAssimpTexture(state, ai_material, tex_emission_color, filename, path, image_data)) { + AssimpUtils::set_texture_mapping_mode(image_data.map_mode, image_data.texture); + mat->set_feature(SpatialMaterial::Feature::FEATURE_NORMAL_MAPPING, true); + mat->set_texture(SpatialMaterial::TEXTURE_NORMAL, image_data.texture); + } + } + + aiTextureType tex_metalness = aiTextureType_METALNESS; + { + String filename, path; + Ref<ImageTexture> texture; + AssimpImageData image_data; + + // Process texture normal map + if (AssimpUtils::GetAssimpTexture(state, ai_material, tex_metalness, filename, path, image_data)) { + AssimpUtils::set_texture_mapping_mode(image_data.map_mode, image_data.texture); + mat->set_texture(SpatialMaterial::TEXTURE_METALLIC, image_data.texture); + } + } + + aiTextureType tex_roughness = aiTextureType_DIFFUSE_ROUGHNESS; + { + String filename, path; + Ref<ImageTexture> texture; + AssimpImageData image_data; + + // Process texture normal map + if (AssimpUtils::GetAssimpTexture(state, ai_material, tex_roughness, filename, path, image_data)) { + AssimpUtils::set_texture_mapping_mode(image_data.map_mode, image_data.texture); + mat->set_texture(SpatialMaterial::TEXTURE_ROUGHNESS, image_data.texture); + } + } + aiTextureType tex_emissive = aiTextureType_EMISSIVE; { String filename = ""; @@ -772,16 +864,17 @@ Ref<Mesh> EditorSceneImporterAssimp::_generate_mesh_from_surface_indices( } } - aiTextureType tex_roughness = aiTextureType_SHININESS; + aiTextureType tex_ao_map = aiTextureType_AMBIENT_OCCLUSION; { String filename, path; Ref<ImageTexture> texture; AssimpImageData image_data; // Process texture normal map - if (AssimpUtils::GetAssimpTexture(state, ai_material, tex_roughness, filename, path, image_data)) { + if (AssimpUtils::GetAssimpTexture(state, ai_material, tex_ao_map, filename, path, image_data)) { AssimpUtils::set_texture_mapping_mode(image_data.map_mode, image_data.texture); - mat->set_texture(SpatialMaterial::TEXTURE_ROUGHNESS, image_data.texture); + mat->set_feature(SpatialMaterial::FEATURE_AMBIENT_OCCLUSION, true); + mat->set_texture(SpatialMaterial::TEXTURE_AMBIENT_OCCLUSION, image_data.texture); } } @@ -789,16 +882,15 @@ Ref<Mesh> EditorSceneImporterAssimp::_generate_mesh_from_surface_indices( Array morphs; morphs.resize(ai_mesh->mNumAnimMeshes); Mesh::PrimitiveType primitive = Mesh::PRIMITIVE_TRIANGLES; - Map<uint32_t, String> morph_mesh_idx_names; + for (size_t j = 0; j < ai_mesh->mNumAnimMeshes; j++) { String ai_anim_mesh_name = AssimpUtils::get_assimp_string(ai_mesh->mAnimMeshes[j]->mName); - mesh->set_blend_shape_mode(Mesh::BLEND_SHAPE_MODE_NORMALIZED); + if (ai_anim_mesh_name.empty()) { ai_anim_mesh_name = String("morph_") + itos(j); } - mesh->add_blend_shape(ai_anim_mesh_name); - morph_mesh_idx_names.insert(j, ai_anim_mesh_name); + Array array_copy; array_copy.resize(VisualServer::ARRAY_MAX); @@ -1188,7 +1280,6 @@ void EditorSceneImporterAssimp::create_bone(ImportState &state, RecursiveState & // this transform is a bone recursive_state.skeleton->add_bone(recursive_state.node_name); - ERR_FAIL_COND(recursive_state.skeleton == NULL); // serious bug we must now exit. //ERR_FAIL_COND(recursive_state.skeleton->get_name() == ""); print_verbose("Bone added to lookup: " + AssimpUtils::get_assimp_string(recursive_state.bone->mName)); print_verbose("Skeleton attached to: " + recursive_state.skeleton->get_name()); diff --git a/modules/bmp/image_loader_bmp.cpp b/modules/bmp/image_loader_bmp.cpp index 5a32fa1c2c..8708430257 100644 --- a/modules/bmp/image_loader_bmp.cpp +++ b/modules/bmp/image_loader_bmp.cpp @@ -63,139 +63,137 @@ Error ImageLoaderBMP::convert_to_image(Ref<Image> p_image, ERR_FAIL_V(ERR_UNAVAILABLE); } - if (err == OK) { - // Image data (might be indexed) - PoolVector<uint8_t> data; - int data_len = 0; + // Image data (might be indexed) + PoolVector<uint8_t> data; + int data_len = 0; - if (bits_per_pixel <= 8) { // indexed - data_len = width * height; - } else { // color - data_len = width * height * 4; - } - ERR_FAIL_COND_V(data_len == 0, ERR_BUG); - err = data.resize(data_len); - - PoolVector<uint8_t>::Write data_w = data.write(); - uint8_t *write_buffer = data_w.ptr(); - - const uint32_t width_bytes = width * bits_per_pixel / 8; - const uint32_t line_width = (width_bytes + 3) & ~3; - - // The actual data traversal is determined by - // the data width in case of 8/4/1 bit images - const uint32_t w = bits_per_pixel >= 24 ? width : width_bytes; - const uint8_t *line = p_buffer + (line_width * (height - 1)); - - for (unsigned int i = 0; i < height; i++) { - const uint8_t *line_ptr = line; - - for (unsigned int j = 0; j < w; j++) { - switch (bits_per_pixel) { - case 1: { - uint8_t color_index = *line_ptr; - - write_buffer[index + 0] = (color_index >> 7) & 1; - write_buffer[index + 1] = (color_index >> 6) & 1; - write_buffer[index + 2] = (color_index >> 5) & 1; - write_buffer[index + 3] = (color_index >> 4) & 1; - write_buffer[index + 4] = (color_index >> 3) & 1; - write_buffer[index + 5] = (color_index >> 2) & 1; - write_buffer[index + 6] = (color_index >> 1) & 1; - write_buffer[index + 7] = (color_index >> 0) & 1; - - index += 8; - line_ptr += 1; - } break; - case 4: { - uint8_t color_index = *line_ptr; - - write_buffer[index + 0] = (color_index >> 4) & 0x0f; - write_buffer[index + 1] = color_index & 0x0f; - - index += 2; - line_ptr += 1; - } break; - case 8: { - uint8_t color_index = *line_ptr; - - write_buffer[index] = color_index; - - index += 1; - line_ptr += 1; - } break; - case 24: { - uint32_t color = *((uint32_t *)line_ptr); - - 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; - } + if (bits_per_pixel <= 8) { // indexed + data_len = width * height; + } else { // color + data_len = width * height * 4; + } + ERR_FAIL_COND_V(data_len == 0, ERR_BUG); + err = data.resize(data_len); + + PoolVector<uint8_t>::Write data_w = data.write(); + uint8_t *write_buffer = data_w.ptr(); + + const uint32_t width_bytes = width * bits_per_pixel / 8; + const uint32_t line_width = (width_bytes + 3) & ~3; + + // The actual data traversal is determined by + // the data width in case of 8/4/1 bit images + const uint32_t w = bits_per_pixel >= 24 ? width : width_bytes; + const uint8_t *line = p_buffer + (line_width * (height - 1)); + + for (uint64_t i = 0; i < height; i++) { + const uint8_t *line_ptr = line; + + for (unsigned int j = 0; j < w; j++) { + switch (bits_per_pixel) { + case 1: { + uint8_t color_index = *line_ptr; + + write_buffer[index + 0] = (color_index >> 7) & 1; + write_buffer[index + 1] = (color_index >> 6) & 1; + write_buffer[index + 2] = (color_index >> 5) & 1; + write_buffer[index + 3] = (color_index >> 4) & 1; + write_buffer[index + 4] = (color_index >> 3) & 1; + write_buffer[index + 5] = (color_index >> 2) & 1; + write_buffer[index + 6] = (color_index >> 1) & 1; + write_buffer[index + 7] = (color_index >> 0) & 1; + + index += 8; + line_ptr += 1; + } break; + case 4: { + uint8_t color_index = *line_ptr; + + write_buffer[index + 0] = (color_index >> 4) & 0x0f; + write_buffer[index + 1] = color_index & 0x0f; + + index += 2; + line_ptr += 1; + } break; + case 8: { + uint8_t color_index = *line_ptr; + + write_buffer[index] = color_index; + + index += 1; + line_ptr += 1; + } break; + case 24: { + uint32_t color = *((uint32_t *)line_ptr); + + 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; } + line -= line_width; + } - if (p_color_buffer == NULL || color_table_size == 0) { // regular pixels + if (p_color_buffer == NULL || color_table_size == 0) { // regular pixels - p_image->create(width, height, 0, Image::FORMAT_RGBA8, data); + p_image->create(width, height, 0, Image::FORMAT_RGBA8, data); - } else { // data is in indexed format, extend it + } else { // data is in indexed format, extend it - // Palette data - PoolVector<uint8_t> palette_data; - palette_data.resize(color_table_size * 4); + // Palette data + PoolVector<uint8_t> palette_data; + palette_data.resize(color_table_size * 4); - PoolVector<uint8_t>::Write palette_data_w = palette_data.write(); - uint8_t *pal = palette_data_w.ptr(); + PoolVector<uint8_t>::Write palette_data_w = palette_data.write(); + uint8_t *pal = palette_data_w.ptr(); - const uint8_t *cb = p_color_buffer; + const uint8_t *cb = p_color_buffer; - for (unsigned int i = 0; i < color_table_size; ++i) { - uint32_t color = *((uint32_t *)cb); + for (unsigned int i = 0; i < color_table_size; ++i) { + uint32_t color = *((uint32_t *)cb); - pal[i * 4 + 0] = (color >> 16) & 0xff; - pal[i * 4 + 1] = (color >> 8) & 0xff; - pal[i * 4 + 2] = (color)&0xff; - pal[i * 4 + 3] = 0xff; + pal[i * 4 + 0] = (color >> 16) & 0xff; + pal[i * 4 + 1] = (color >> 8) & 0xff; + pal[i * 4 + 2] = (color)&0xff; + pal[i * 4 + 3] = 0xff; - cb += 4; - } - // Extend palette to image - PoolVector<uint8_t> extended_data; - extended_data.resize(data.size() * 4); + cb += 4; + } + // Extend palette to image + PoolVector<uint8_t> extended_data; + extended_data.resize(data.size() * 4); - PoolVector<uint8_t>::Write ex_w = extended_data.write(); - uint8_t *dest = ex_w.ptr(); + PoolVector<uint8_t>::Write ex_w = extended_data.write(); + uint8_t *dest = ex_w.ptr(); - const int num_pixels = width * height; + const int num_pixels = width * height; - for (int i = 0; i < num_pixels; i++) { - dest[0] = pal[write_buffer[i] * 4 + 0]; - dest[1] = pal[write_buffer[i] * 4 + 1]; - dest[2] = pal[write_buffer[i] * 4 + 2]; - dest[3] = pal[write_buffer[i] * 4 + 3]; + for (int i = 0; i < num_pixels; i++) { + dest[0] = pal[write_buffer[i] * 4 + 0]; + dest[1] = pal[write_buffer[i] * 4 + 1]; + dest[2] = pal[write_buffer[i] * 4 + 2]; + dest[3] = pal[write_buffer[i] * 4 + 3]; - dest += 4; - } - p_image->create(width, height, 0, Image::FORMAT_RGBA8, extended_data); + dest += 4; } + p_image->create(width, height, 0, Image::FORMAT_RGBA8, extended_data); } } return err; diff --git a/modules/csg/csg.cpp b/modules/csg/csg.cpp index f1b3fa2ac6..5a76f32977 100644 --- a/modules/csg/csg.cpp +++ b/modules/csg/csg.cpp @@ -114,7 +114,7 @@ void CSGBrush::_regen_face_aabbs() { faces.write[i].aabb.position = faces[i].vertices[0]; faces.write[i].aabb.expand_to(faces[i].vertices[1]); faces.write[i].aabb.expand_to(faces[i].vertices[2]); - faces.write[i].aabb.grow_by(faces[i].aabb.get_longest_axis_size() * 0.001); //make it a tad bigger to avoid num precision erros + faces.write[i].aabb.grow_by(faces[i].aabb.get_longest_axis_size() * 0.001); //make it a tad bigger to avoid num precision errors } } diff --git a/modules/csg/csg_gizmos.cpp b/modules/csg/csg_gizmos.cpp index e6bfa5525d..0d26943af6 100644 --- a/modules/csg/csg_gizmos.cpp +++ b/modules/csg/csg_gizmos.cpp @@ -377,7 +377,7 @@ void CSGShapeSpatialGizmoPlugin::redraw(EditorSpatialGizmo *p_gizmo) { break; } - p_gizmo->add_mesh(mesh, false, RID(), solid_material); + p_gizmo->add_mesh(mesh, false, Ref<SkinReference>(), solid_material); } if (Object::cast_to<CSGSphere>(cs)) { diff --git a/modules/csg/csg_shape.cpp b/modules/csg/csg_shape.cpp index 23725c4960..35c75e2a8a 100644 --- a/modules/csg/csg_shape.cpp +++ b/modules/csg/csg_shape.cpp @@ -1067,6 +1067,7 @@ void CSGSphere::set_radius(const float p_radius) { radius = p_radius; _make_dirty(); update_gizmo(); + _change_notify("radius"); } float CSGSphere::get_radius() const { @@ -1251,6 +1252,7 @@ void CSGBox::set_width(const float p_width) { width = p_width; _make_dirty(); update_gizmo(); + _change_notify("width"); } float CSGBox::get_width() const { @@ -1261,6 +1263,7 @@ void CSGBox::set_height(const float p_height) { height = p_height; _make_dirty(); update_gizmo(); + _change_notify("height"); } float CSGBox::get_height() const { @@ -1271,6 +1274,7 @@ void CSGBox::set_depth(const float p_depth) { depth = p_depth; _make_dirty(); update_gizmo(); + _change_notify("depth"); } float CSGBox::get_depth() const { @@ -1465,6 +1469,7 @@ void CSGCylinder::set_radius(const float p_radius) { radius = p_radius; _make_dirty(); update_gizmo(); + _change_notify("radius"); } float CSGCylinder::get_radius() const { @@ -1475,6 +1480,7 @@ void CSGCylinder::set_height(const float p_height) { height = p_height; _make_dirty(); update_gizmo(); + _change_notify("height"); } float CSGCylinder::get_height() const { @@ -1690,6 +1696,7 @@ void CSGTorus::set_inner_radius(const float p_inner_radius) { inner_radius = p_inner_radius; _make_dirty(); update_gizmo(); + _change_notify("inner_radius"); } float CSGTorus::get_inner_radius() const { @@ -1700,6 +1707,7 @@ void CSGTorus::set_outer_radius(const float p_outer_radius) { outer_radius = p_outer_radius; _make_dirty(); update_gizmo(); + _change_notify("outer_radius"); } float CSGTorus::get_outer_radius() const { diff --git a/modules/cvtt/SCsub b/modules/cvtt/SCsub index 142af0c800..746b23ca28 100644 --- a/modules/cvtt/SCsub +++ b/modules/cvtt/SCsub @@ -6,19 +6,18 @@ Import('env_modules') env_cvtt = env_modules.Clone() # Thirdparty source files -if env['builtin_squish']: - thirdparty_dir = "#thirdparty/cvtt/" - thirdparty_sources = [ - "ConvectionKernels.cpp" - ] +thirdparty_dir = "#thirdparty/cvtt/" +thirdparty_sources = [ + "ConvectionKernels.cpp" +] - thirdparty_sources = [thirdparty_dir + file for file in thirdparty_sources] +thirdparty_sources = [thirdparty_dir + file for file in thirdparty_sources] - env_cvtt.Prepend(CPPPATH=[thirdparty_dir]) +env_cvtt.Prepend(CPPPATH=[thirdparty_dir]) - env_thirdparty = env_cvtt.Clone() - env_thirdparty.disable_warnings() - env_thirdparty.add_source_files(env.modules_sources, thirdparty_sources) +env_thirdparty = env_cvtt.Clone() +env_thirdparty.disable_warnings() +env_thirdparty.add_source_files(env.modules_sources, thirdparty_sources) # Godot source files env_cvtt.add_source_files(env.modules_sources, "*.cpp") diff --git a/modules/enet/doc_classes/NetworkedMultiplayerENet.xml b/modules/enet/doc_classes/NetworkedMultiplayerENet.xml index 84ed5fd9ee..4c10588aa6 100644 --- a/modules/enet/doc_classes/NetworkedMultiplayerENet.xml +++ b/modules/enet/doc_classes/NetworkedMultiplayerENet.xml @@ -115,9 +115,11 @@ <member name="compression_mode" type="int" setter="set_compression_mode" getter="get_compression_mode" enum="NetworkedMultiplayerENet.CompressionMode" default="0"> The compression method used for network packets. 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="refuse_new_connections" type="bool" setter="set_refuse_new_connections" getter="is_refusing_new_connections" override="true" default="false" /> <member name="transfer_channel" type="int" setter="set_transfer_channel" getter="get_transfer_channel" default="-1"> 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> + <member name="transfer_mode" type="int" setter="set_transfer_mode" getter="get_transfer_mode" override="true" enum="NetworkedMultiplayerPeer.TransferMode" default="2" /> </members> <constants> <constant name="COMPRESS_NONE" value="0" enum="CompressionMode"> diff --git a/modules/gdnative/gdnative/array.cpp b/modules/gdnative/gdnative/array.cpp index 1ef8e9f900..e97a75cca8 100644 --- a/modules/gdnative/gdnative/array.cpp +++ b/modules/gdnative/gdnative/array.cpp @@ -327,6 +327,15 @@ godot_array GDAPI godot_array_duplicate(const godot_array *p_self, const godot_b return res; } +godot_array GDAPI godot_array_slice(const godot_array *p_self, const godot_int p_begin, const godot_int p_end, const godot_int p_step, const godot_bool p_deep) { + const Array *self = (const Array *)p_self; + godot_array res; + Array *val = (Array *)&res; + memnew_placement(val, Array); + *val = self->slice(p_begin, p_end, p_step, p_deep); + return res; +} + godot_variant GDAPI godot_array_max(const godot_array *p_self) { const Array *self = (const Array *)p_self; godot_variant v; diff --git a/modules/gdnative/gdnative_api.json b/modules/gdnative/gdnative_api.json index 03258584ce..55ba4ecc1e 100644 --- a/modules/gdnative/gdnative_api.json +++ b/modules/gdnative/gdnative_api.json @@ -80,6 +80,17 @@ ["const godot_vector2 *", "p_self"], ["const godot_vector2 *", "p_to"] ] + }, + { + "name": "godot_array_slice", + "return_type": "godot_array", + "arguments": [ + ["const godot_array *", "p_self"], + ["const godot_int", "p_begin"], + ["const godot_int", "p_end"], + ["const godot_int", "p_step"], + ["const godot_bool", "p_deep"] + ] } ] }, diff --git a/modules/gdnative/include/gdnative/array.h b/modules/gdnative/include/gdnative/array.h index 10ef8a73d2..2e3ce58033 100644 --- a/modules/gdnative/include/gdnative/array.h +++ b/modules/gdnative/include/gdnative/array.h @@ -132,6 +132,8 @@ void GDAPI godot_array_destroy(godot_array *p_self); godot_array GDAPI godot_array_duplicate(const godot_array *p_self, const godot_bool p_deep); +godot_array GDAPI godot_array_slice(const godot_array *p_self, const godot_int p_begin, const godot_int p_end, const godot_int p_delta, const godot_bool p_deep); + godot_variant GDAPI godot_array_max(const godot_array *p_self); godot_variant GDAPI godot_array_min(const godot_array *p_self); diff --git a/modules/gdnative/include/nativescript/godot_nativescript.h b/modules/gdnative/include/nativescript/godot_nativescript.h index 7f52f5736c..8a05b6cfa3 100644 --- a/modules/gdnative/include/nativescript/godot_nativescript.h +++ b/modules/gdnative/include/nativescript/godot_nativescript.h @@ -64,9 +64,9 @@ typedef enum { GODOT_PROPERTY_HINT_LAYERS_3D_RENDER, GODOT_PROPERTY_HINT_LAYERS_3D_PHYSICS, GODOT_PROPERTY_HINT_FILE, ///< a file path must be passed, hint_text (optionally) is a filter "*.png,*.wav,*.doc," - GODOT_PROPERTY_HINT_DIR, ///< a directort path must be passed + GODOT_PROPERTY_HINT_DIR, ///< a directory path must be passed GODOT_PROPERTY_HINT_GLOBAL_FILE, ///< a file path must be passed, hint_text (optionally) is a filter "*.png,*.wav,*.doc," - GODOT_PROPERTY_HINT_GLOBAL_DIR, ///< a directort path must be passed + GODOT_PROPERTY_HINT_GLOBAL_DIR, ///< a directory path must be passed GODOT_PROPERTY_HINT_RESOURCE_TYPE, ///< a resource object type GODOT_PROPERTY_HINT_MULTILINE_TEXT, ///< used for string properties that can contain multiple lines GODOT_PROPERTY_HINT_PLACEHOLDER_TEXT, ///< used to set a placeholder text for string properties diff --git a/modules/gdnative/pluginscript/pluginscript_language.cpp b/modules/gdnative/pluginscript/pluginscript_language.cpp index 9de073fc8e..22898a73ce 100644 --- a/modules/gdnative/pluginscript/pluginscript_language.cpp +++ b/modules/gdnative/pluginscript/pluginscript_language.cpp @@ -200,7 +200,7 @@ void PluginScriptLanguage::get_recognized_extensions(List<String> *p_extensions) } void PluginScriptLanguage::get_public_functions(List<MethodInfo> *p_functions) const { - // TODO: provid this statically in `godot_pluginscript_language_desc` ? + // TODO: provide this statically in `godot_pluginscript_language_desc` ? if (_desc.get_public_functions) { Array functions; _desc.get_public_functions(_data, (godot_array *)&functions); @@ -212,7 +212,7 @@ void PluginScriptLanguage::get_public_functions(List<MethodInfo> *p_functions) c } void PluginScriptLanguage::get_public_constants(List<Pair<String, Variant> > *p_constants) const { - // TODO: provid this statically in `godot_pluginscript_language_desc` ? + // TODO: provide this statically in `godot_pluginscript_language_desc` ? if (_desc.get_public_constants) { Dictionary constants; _desc.get_public_constants(_data, (godot_dictionary *)&constants); diff --git a/modules/gdnative/videodecoder/video_stream_gdnative.cpp b/modules/gdnative/videodecoder/video_stream_gdnative.cpp index be131c5402..212ff51b80 100644 --- a/modules/gdnative/videodecoder/video_stream_gdnative.cpp +++ b/modules/gdnative/videodecoder/video_stream_gdnative.cpp @@ -149,7 +149,7 @@ void VideoStreamPlaybackGDNative::update(float p_delta) { if (mix_callback) { if (pcm_write_idx >= 0) { // Previous remains - int mixed = mix_callback(mix_udata, pcm, samples_decoded); + int mixed = mix_callback(mix_udata, pcm + pcm_write_idx * num_channels, samples_decoded); if (mixed == samples_decoded) { pcm_write_idx = -1; } else { diff --git a/modules/gdscript/doc_classes/@GDScript.xml b/modules/gdscript/doc_classes/@GDScript.xml index 4efa90fd86..788db7fb86 100644 --- a/modules/gdscript/doc_classes/@GDScript.xml +++ b/modules/gdscript/doc_classes/@GDScript.xml @@ -694,6 +694,14 @@ [/codeblock] </description> </method> + <method name="ord"> + <return type="int"> + </return> + <argument index="0" name="char" type="String"> + </argument> + <description> + </description> + </method> <method name="parse_json"> <return type="Variant"> </return> diff --git a/modules/gdscript/gdscript.cpp b/modules/gdscript/gdscript.cpp index 5dab063061..c8ec80c101 100644 --- a/modules/gdscript/gdscript.cpp +++ b/modules/gdscript/gdscript.cpp @@ -99,7 +99,7 @@ GDScriptInstance *GDScript::_create_instance(const Variant **p_args, int p_argco #endif instance->owner->set_script_instance(instance); - /* STEP 2, INITIALIZE AND CONSRTUCT */ + /* STEP 2, INITIALIZE AND CONSTRUCT */ #ifndef NO_THREADS GDScriptLanguage::singleton->lock->lock(); diff --git a/modules/gdscript/gdscript_compiler.cpp b/modules/gdscript/gdscript_compiler.cpp index 7166189416..dea2225e91 100644 --- a/modules/gdscript/gdscript_compiler.cpp +++ b/modules/gdscript/gdscript_compiler.cpp @@ -1520,8 +1520,16 @@ Error GDScriptCompiler::_parse_block(CodeGen &codegen, const GDScriptParser::Blo if (ret2 < 0) return ERR_PARSE_ERROR; + int message_ret = 0; + if (as->message) { + message_ret = _parse_expression(codegen, as->message, p_stack_level + 1, false); + if (message_ret < 0) + return ERR_PARSE_ERROR; + } + codegen.opcodes.push_back(GDScriptFunction::OPCODE_ASSERT); codegen.opcodes.push_back(ret2); + codegen.opcodes.push_back(message_ret); #endif } break; case GDScriptParser::Node::TYPE_BREAKPOINT: { @@ -2064,7 +2072,7 @@ Error GDScriptCompiler::_parse_class_blocks(GDScript *p_script, const GDScriptPa } instance->owner->set_script_instance(instance); - /* STEP 2, INITIALIZE AND CONSRTUCT */ + /* STEP 2, INITIALIZE AND CONSTRUCT */ Variant::CallError ce; p_script->initializer->call(instance, NULL, 0, ce); diff --git a/modules/gdscript/gdscript_function.cpp b/modules/gdscript/gdscript_function.cpp index 68f2a9473e..bdeea9cef3 100644 --- a/modules/gdscript/gdscript_function.cpp +++ b/modules/gdscript/gdscript_function.cpp @@ -1475,20 +1475,25 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a DISPATCH_OPCODE; OPCODE(OPCODE_ASSERT) { - CHECK_SPACE(2); + CHECK_SPACE(3); #ifdef DEBUG_ENABLED GET_VARIANT_PTR(test, 1); + GET_VARIANT_PTR(message, 2); bool result = test->booleanize(); if (!result) { - - err_text = "Assertion failed."; + const String &message_str = *message; + if (message_str.empty()) { + err_text = "Assertion failed."; + } else { + err_text = "Assertion failed: " + message_str; + } OPCODE_BREAK; } #endif - ip += 2; + ip += 3; } DISPATCH_OPCODE; diff --git a/modules/gdscript/gdscript_parser.cpp b/modules/gdscript/gdscript_parser.cpp index e96bf0238a..967b0c83ae 100644 --- a/modules/gdscript/gdscript_parser.cpp +++ b/modules/gdscript/gdscript_parser.cpp @@ -1207,7 +1207,7 @@ GDScriptParser::Node *GDScriptParser::_parse_expression(Node *p_parent, bool p_s if (_get_completable_identifier(COMPLETION_INDEX, identifier)) { if (identifier == StringName()) { - identifier = "@temp"; //so it parses allright + identifier = "@temp"; //so it parses alright } completion_node = op; @@ -1399,9 +1399,6 @@ GDScriptParser::Node *GDScriptParser::_parse_expression(Node *p_parent, bool p_s unary = true; break; case OperatorNode::OP_NEG: - priority = 1; - unary = true; - break; case OperatorNode::OP_POS: priority = 1; unary = true; @@ -2846,15 +2843,7 @@ void GDScriptParser::_parse_block(BlockNode *p_block, bool p_static) { assigned = subexpr; } else { - ConstantNode *c = alloc_node<ConstantNode>(); - if (lv->datatype.has_type && lv->datatype.kind == DataType::BUILTIN) { - Variant::CallError err; - c->value = Variant::construct(lv->datatype.builtin_type, NULL, 0, err); - } else { - c->value = Variant(); - } - c->line = var_line; - assigned = c; + assigned = _get_default_value_for_type(lv->datatype, var_line); } lv->assign = assigned; //must be added later, to avoid self-referencing. @@ -3280,15 +3269,36 @@ void GDScriptParser::_parse_block(BlockNode *p_block, bool p_static) { case GDScriptTokenizer::TK_PR_ASSERT: { tokenizer->advance(); - Node *condition = _parse_and_reduce_expression(p_block, p_static); - if (!condition) { - if (_recover_from_completion()) { - break; - } + + if (tokenizer->get_token() != GDScriptTokenizer::TK_PARENTHESIS_OPEN) { + _set_error("Expected '(' after assert"); + return; + } + + tokenizer->advance(); + + Vector<Node *> args; + const bool result = _parse_arguments(p_block, args, p_static); + if (!result) { + return; + } + + if (args.empty() || args.size() > 2) { + _set_error("Wrong number of arguments, expected 1 or 2"); return; } + AssertNode *an = alloc_node<AssertNode>(); - an->condition = condition; + an->condition = _reduce_expression(args[0], p_static); + + if (args.size() == 2) { + an->message = _reduce_expression(args[1], p_static); + } else { + ConstantNode *message_node = alloc_node<ConstantNode>(); + message_node->value = String(); + an->message = message_node; + } + p_block->statements.push_back(an); if (!_end_statement()) { @@ -3533,6 +3543,15 @@ void GDScriptParser::_parse_class(ClassNode *p_class) { return; } + if (p_class->classname_used && ProjectSettings::get_singleton()->has_setting("autoload/" + p_class->name)) { + const String autoload_path = ProjectSettings::get_singleton()->get_setting("autoload/" + p_class->name); + if (autoload_path.begins_with("*")) { + // It's a singleton, and not just a regular AutoLoad script. + _set_error("The class \"" + p_class->name + "\" conflicts with the AutoLoad singleton of the same name, and is therefore redundant. Remove the class_name declaration to fix this error."); + } + return; + } + tokenizer->advance(2); if (tokenizer->get_token() == GDScriptTokenizer::TK_COMMA) { @@ -4839,35 +4858,29 @@ void GDScriptParser::_parse_class(ClassNode *p_class) { return; } - Variant::Type initial_type = member.data_type.has_type ? member.data_type.builtin_type : member._export.type; + Node *expr; - if (initial_type != Variant::NIL && initial_type != Variant::OBJECT) { - IdentifierNode *id = alloc_node<IdentifierNode>(); - id->name = member.identifier; - - Node *expr; + if (member.data_type.has_type) { + expr = _get_default_value_for_type(member.data_type); + } else { + DataType exported_type; + exported_type.has_type = true; + exported_type.kind = DataType::BUILTIN; + exported_type.builtin_type = member._export.type; + expr = _get_default_value_for_type(exported_type); + } - // Make sure arrays and dictionaries are not shared - if (initial_type == Variant::ARRAY) { - expr = alloc_node<ArrayNode>(); - } else if (initial_type == Variant::DICTIONARY) { - expr = alloc_node<DictionaryNode>(); - } else { - ConstantNode *cn = alloc_node<ConstantNode>(); - Variant::CallError ce2; - cn->value = Variant::construct(initial_type, NULL, 0, ce2); - expr = cn; - } + IdentifierNode *id = alloc_node<IdentifierNode>(); + id->name = member.identifier; - OperatorNode *op = alloc_node<OperatorNode>(); - op->op = OperatorNode::OP_INIT_ASSIGN; - op->arguments.push_back(id); - op->arguments.push_back(expr); + OperatorNode *op = alloc_node<OperatorNode>(); + op->op = OperatorNode::OP_INIT_ASSIGN; + op->arguments.push_back(id); + op->arguments.push_back(expr); - p_class->initializer->statements.push_back(op); + p_class->initializer->statements.push_back(op); - member.initial_assignment = op; - } + member.initial_assignment = op; } if (autoexport && member.data_type.has_type) { @@ -5727,28 +5740,35 @@ GDScriptParser::DataType GDScriptParser::_resolve_type(const DataType &p_source, } } - // Still look for class constants in parent script + // Still look for class constants in parent scripts if (!found && (base_type.kind == DataType::GDSCRIPT || base_type.kind == DataType::SCRIPT)) { Ref<Script> scr = base_type.script_type; ERR_FAIL_COND_V(scr.is_null(), result); - Map<StringName, Variant> constants; - scr->get_constants(&constants); + while (scr.is_valid()) { + Map<StringName, Variant> constants; + scr->get_constants(&constants); - if (constants.has(id)) { - Ref<GDScript> gds = constants[id]; + if (constants.has(id)) { + Ref<GDScript> gds = constants[id]; - if (gds.is_valid()) { - result.kind = DataType::GDSCRIPT; - result.script_type = gds; - found = true; - } else { - Ref<Script> scr2 = constants[id]; - if (scr2.is_valid()) { - result.kind = DataType::SCRIPT; - result.script_type = scr2; + if (gds.is_valid()) { + result.kind = DataType::GDSCRIPT; + result.script_type = gds; found = true; + } else { + Ref<Script> scr2 = constants[id]; + if (scr2.is_valid()) { + result.kind = DataType::SCRIPT; + result.script_type = scr2; + found = true; + } } } + if (found) { + break; + } else { + scr = scr->get_base_script(); + } } } @@ -6140,6 +6160,31 @@ bool GDScriptParser::_is_type_compatible(const DataType &p_container, const Data return false; } +GDScriptParser::Node *GDScriptParser::_get_default_value_for_type(const DataType &p_type, int p_line) { + Node *result; + + if (p_type.has_type && p_type.kind == DataType::BUILTIN && p_type.builtin_type != Variant::NIL && p_type.builtin_type != Variant::OBJECT) { + if (p_type.builtin_type == Variant::ARRAY) { + result = alloc_node<ArrayNode>(); + } else if (p_type.builtin_type == Variant::DICTIONARY) { + result = alloc_node<DictionaryNode>(); + } else { + ConstantNode *c = alloc_node<ConstantNode>(); + Variant::CallError err; + c->value = Variant::construct(p_type.builtin_type, NULL, 0, err); + result = c; + } + } else { + ConstantNode *c = alloc_node<ConstantNode>(); + c->value = Variant(); + result = c; + } + + result->line = p_line; + + return result; +} + GDScriptParser::DataType GDScriptParser::_reduce_node_type(Node *p_node) { #ifdef DEBUG_ENABLED if (p_node->get_datatype().has_type && p_node->type != Node::TYPE_ARRAY && p_node->type != Node::TYPE_DICTIONARY) { diff --git a/modules/gdscript/gdscript_parser.h b/modules/gdscript/gdscript_parser.h index 72aa819a8c..04ce9cf4c6 100644 --- a/modules/gdscript/gdscript_parser.h +++ b/modules/gdscript/gdscript_parser.h @@ -481,7 +481,12 @@ public: struct AssertNode : public Node { Node *condition; - AssertNode() { type = TYPE_ASSERT; } + Node *message; + AssertNode() : + condition(0), + message(0) { + type = TYPE_ASSERT; + } }; struct BreakpointNode : public Node { @@ -610,6 +615,7 @@ private: bool _get_function_signature(DataType &p_base_type, const StringName &p_function, DataType &r_return_type, List<DataType> &r_arg_types, int &r_default_arg_count, bool &r_static, bool &r_vararg) const; bool _get_member_type(const DataType &p_base_type, const StringName &p_member, DataType &r_member_type) const; bool _is_type_compatible(const DataType &p_container, const DataType &p_expression, bool p_allow_implicit_conversion = false) const; + Node *_get_default_value_for_type(const DataType &p_type, int p_line = -1); DataType _reduce_node_type(Node *p_node); DataType _reduce_function_call_type(const OperatorNode *p_call); diff --git a/modules/gdscript/language_server/gdscript_extend_parser.cpp b/modules/gdscript/language_server/gdscript_extend_parser.cpp index 45f9ec9c6a..6db8cb2c88 100644 --- a/modules/gdscript/language_server/gdscript_extend_parser.cpp +++ b/modules/gdscript/language_server/gdscript_extend_parser.cpp @@ -189,6 +189,7 @@ void ExtendGDScriptParser::parse_class_symbol(const GDScriptParser::ClassNode *p lsp::DocumentSymbol symbol; const GDScriptParser::ClassNode::Constant &c = E->value(); const GDScriptParser::ConstantNode *node = dynamic_cast<const GDScriptParser::ConstantNode *>(c.expression); + ERR_FAIL_COND(!node); symbol.name = E->key(); symbol.kind = lsp::SymbolKind::Constant; symbol.deprecated = false; @@ -344,15 +345,13 @@ String ExtendGDScriptParser::marked_documentation(const String &p_bbcode) { if (block_start != -1) { code_block_indent = block_start; in_code_block = true; - line = "'''gdscript"; - line = "\n"; + line = "'''gdscript\n"; } else if (in_code_block) { line = "\t" + line.substr(code_block_indent, line.length()); } if (in_code_block && line.find("[/codeblock]") != -1) { - line = "'''\n"; - line = "\n"; + line = "'''\n\n"; in_code_block = false; } @@ -674,6 +673,7 @@ Dictionary ExtendGDScriptParser::dump_class_api(const GDScriptParser::ClassNode const GDScriptParser::ClassNode::Constant &c = E->value(); const GDScriptParser::ConstantNode *node = dynamic_cast<const GDScriptParser::ConstantNode *>(c.expression); + ERR_FAIL_COND_V(!node, class_api); Dictionary api; api["name"] = E->key(); diff --git a/modules/gdscript/language_server/gdscript_language_protocol.cpp b/modules/gdscript/language_server/gdscript_language_protocol.cpp index afe461b68e..ce3de9bc3b 100644 --- a/modules/gdscript/language_server/gdscript_language_protocol.cpp +++ b/modules/gdscript/language_server/gdscript_language_protocol.cpp @@ -100,9 +100,10 @@ Dictionary GDScriptLanguageProtocol::initialize(const Dictionary &p_params) { String root_uri = p_params["rootUri"]; String root = p_params["rootPath"]; - bool is_same_workspace = root == workspace->root; + bool is_same_workspace; +#ifndef WINDOWS_ENABLED is_same_workspace = root.to_lower() == workspace->root.to_lower(); -#ifdef WINDOWS_ENABLED +#else is_same_workspace = root.replace("\\", "/").to_lower() == workspace->root.to_lower(); #endif @@ -142,6 +143,7 @@ void GDScriptLanguageProtocol::poll() { Error GDScriptLanguageProtocol::start(int p_port) { if (server == NULL) { server = dynamic_cast<WebSocketServer *>(ClassDB::instance("WebSocketServer")); + ERR_FAIL_COND_V(!server, FAILED); server->set_buffers(8192, 1024, 8192, 1024); // 8mb should be way more than enough server->connect("data_received", this, "on_data_received"); server->connect("client_connected", this, "on_client_connected"); diff --git a/modules/gdscript/language_server/gdscript_language_server.cpp b/modules/gdscript/language_server/gdscript_language_server.cpp index 9bea4557ac..62c212a2bd 100644 --- a/modules/gdscript/language_server/gdscript_language_server.cpp +++ b/modules/gdscript/language_server/gdscript_language_server.cpp @@ -64,7 +64,7 @@ void GDScriptLanguageServer::thread_main(void *p_userdata) { void GDScriptLanguageServer::start() { int port = (int)_EDITOR_GET("network/language_server/remote_port"); if (protocol.start(port) == OK) { - EditorNode::get_log()->add_message("** GDScript Language Server Started **"); + EditorNode::get_log()->add_message("--- GDScript language server started ---", EditorLog::MSG_TYPE_EDITOR); ERR_FAIL_COND(thread != NULL || thread_exit); thread_exit = false; thread = Thread::create(GDScriptLanguageServer::thread_main, this); @@ -78,7 +78,7 @@ void GDScriptLanguageServer::stop() { memdelete(thread); thread = NULL; protocol.stop(); - EditorNode::get_log()->add_message("** GDScript Language Server Stopped **"); + EditorNode::get_log()->add_message("--- GDScript language server stopped ---", EditorLog::MSG_TYPE_EDITOR); } void register_lsp_types() { diff --git a/modules/gdscript/language_server/gdscript_text_document.cpp b/modules/gdscript/language_server/gdscript_text_document.cpp index f211fae526..7c58c7aa15 100644 --- a/modules/gdscript/language_server/gdscript_text_document.cpp +++ b/modules/gdscript/language_server/gdscript_text_document.cpp @@ -380,8 +380,8 @@ GDScriptTextDocument::~GDScriptTextDocument() { memdelete(file_checker); } -void GDScriptTextDocument::sync_script_content(const String &p_uri, const String &p_content) { - String path = GDScriptLanguageProtocol::get_singleton()->get_workspace()->get_file_path(p_uri); +void GDScriptTextDocument::sync_script_content(const String &p_path, const String &p_content) { + String path = GDScriptLanguageProtocol::get_singleton()->get_workspace()->get_file_path(p_path); GDScriptLanguageProtocol::get_singleton()->get_workspace()->parse_script(path, p_content); } diff --git a/modules/gridmap/grid_map_editor_plugin.cpp b/modules/gridmap/grid_map_editor_plugin.cpp index 07b4f7f596..c97524a54d 100644 --- a/modules/gridmap/grid_map_editor_plugin.cpp +++ b/modules/gridmap/grid_map_editor_plugin.cpp @@ -385,8 +385,8 @@ bool GridMapEditor::do_input_action(Camera *p_camera, const Point2 &p_point, boo if (!p.intersects_segment(from, from + normal * settings_pick_distance->get_value(), &inters)) return false; - //make sure the intersection is inside the frustum planes, to avoid - //painting on invisible regions + // Make sure the intersection is inside the frustum planes, to avoid + // Painting on invisible regions. for (int i = 0; i < planes.size(); i++) { Plane fp = local_xform.xform(planes[i]); @@ -397,8 +397,6 @@ bool GridMapEditor::do_input_action(Camera *p_camera, const Point2 &p_point, boo int cell[3]; float cell_size[3] = { node->get_cell_size().x, node->get_cell_size().y, node->get_cell_size().z }; - last_mouseover = Vector3(-1, -1, -1); - for (int i = 0; i < 3; i++) { if (i == edit_axis) @@ -407,19 +405,11 @@ bool GridMapEditor::do_input_action(Camera *p_camera, const Point2 &p_point, boo cell[i] = inters[i] / node->get_cell_size()[i]; if (inters[i] < 0) - cell[i] -= 1; //compensate negative + cell[i] -= 1; // Compensate negative. grid_ofs[i] = cell[i] * cell_size[i]; } - - /*if (cell[i]<0 || cell[i]>=grid_size[i]) { - - cursor_visible=false; - _update_cursor_transform(); - return false; - }*/ } - last_mouseover = Vector3(cell[0], cell[1], cell[2]); VS::get_singleton()->instance_set_transform(grid_instance[edit_axis], node->get_global_transform() * edit_grid_xform); if (cursor_instance.is_valid()) { @@ -656,7 +646,7 @@ bool GridMapEditor::forward_spatial_input_event(Camera *p_camera, const Ref<Inpu if (mb->is_pressed()) floor->set_value(floor->get_value() + mb->get_factor()); - return true; //eaten + return true; // Eaten. } else if (mb->get_button_index() == BUTTON_WHEEL_DOWN && (mb->get_command() || mb->get_shift())) { if (mb->is_pressed()) floor->set_value(floor->get_value() - mb->get_factor()); @@ -702,9 +692,7 @@ bool GridMapEditor::forward_spatial_input_event(Camera *p_camera, const Ref<Inpu return do_input_action(p_camera, Point2(mb->get_position().x, mb->get_position().y), true); } else { - if ( - (mb->get_button_index() == BUTTON_RIGHT && input_action == INPUT_ERASE) || - (mb->get_button_index() == BUTTON_LEFT && input_action == INPUT_PAINT)) { + if ((mb->get_button_index() == BUTTON_RIGHT && input_action == INPUT_ERASE) || (mb->get_button_index() == BUTTON_LEFT && input_action == INPUT_PAINT)) { if (set_items.size()) { undo_redo->create_action(TTR("GridMap Paint")); @@ -884,9 +872,15 @@ void GridMapEditor::update_palette() { if (mesh_library.is_null()) { last_mesh_library = NULL; + search_box->set_text(""); + search_box->set_editable(false); + info_message->show(); return; } + search_box->set_editable(true); + info_message->hide(); + Vector<int> ids; ids = mesh_library->get_item_list(); @@ -927,7 +921,7 @@ void GridMapEditor::update_palette() { item++; } - if (selected != -1) { + if (selected != -1 && mesh_library_palette->get_item_count() > 0) { mesh_library_palette->select(selected); } @@ -939,7 +933,6 @@ void GridMapEditor::edit(GridMap *p_gridmap) { node = p_gridmap; VS *vs = VS::get_singleton(); - last_mouseover = Vector3(-1, -1, -1); input_action = INPUT_NONE; selection.active = false; _update_selection_transform(); @@ -975,7 +968,7 @@ void GridMapEditor::edit(GridMap *p_gridmap) { { - //update grids + // Update grids. indicator_mat.instance(); indicator_mat->set_flag(SpatialMaterial::FLAG_UNSHADED, true); indicator_mat->set_feature(SpatialMaterial::FEATURE_TRANSPARENT, true); @@ -1046,9 +1039,7 @@ void GridMapEditor::_update_clip() { void GridMapEditor::update_grid() { - grid_xform.origin.x -= 1; //force update in hackish way.. what do i care - - //VS *vs = VS::get_singleton(); + grid_xform.origin.x -= 1; // Force update in hackish way. grid_ofs[edit_axis] = edit_floor[edit_axis] * node->get_cell_size()[edit_axis]; @@ -1069,6 +1060,7 @@ void GridMapEditor::_notification(int p_what) { switch (p_what) { case NOTIFICATION_ENTER_TREE: { + get_tree()->connect("node_removed", this, "_node_removed"); mesh_library_palette->connect("item_selected", this, "_item_selected_cbk"); for (int i = 0; i < 3; i++) { @@ -1085,6 +1077,7 @@ void GridMapEditor::_notification(int p_what) { } break; case NOTIFICATION_EXIT_TREE: { + get_tree()->disconnect("node_removed", this, "_node_removed"); _clear_clipboard_data(); for (int i = 0; i < 3; i++) { @@ -1132,7 +1125,6 @@ void GridMapEditor::_notification(int p_what) { SpatialEditorPlugin *sep = Object::cast_to<SpatialEditorPlugin>(editor->get_editor_plugin_screen()); if (sep) sep->snap_cursor_to_plane(p); - //editor->get_editor_plugin_screen()->call("snap_cursor_to_plane",p); } } break; @@ -1198,6 +1190,7 @@ void GridMapEditor::_bind_methods() { ClassDB::bind_method("_floor_changed", &GridMapEditor::_floor_changed); ClassDB::bind_method("_floor_mouse_exited", &GridMapEditor::_floor_mouse_exited); ClassDB::bind_method("_set_selection", &GridMapEditor::_set_selection); + ClassDB::bind_method("_node_removed", &GridMapEditor::_node_removed); ClassDB::bind_method(D_METHOD("_set_display_mode", "mode"), &GridMapEditor::_set_display_mode); } @@ -1296,6 +1289,7 @@ GridMapEditor::GridMapEditor(EditorNode *p_editor) { search_box = memnew(LineEdit); search_box->set_h_size_flags(SIZE_EXPAND_FILL); + search_box->set_placeholder(TTR("Filter meshes")); hb->add_child(search_box); search_box->connect("text_changed", this, "_text_changed"); search_box->connect("gui_input", this, "_sbox_input"); @@ -1331,6 +1325,14 @@ GridMapEditor::GridMapEditor(EditorNode *p_editor) { add_child(mesh_library_palette); mesh_library_palette->set_v_size_flags(SIZE_EXPAND_FILL); + info_message = memnew(Label); + info_message->set_text(TTR("Give a MeshLibrary resource to this GridMap to use its meshes.")); + info_message->set_valign(Label::VALIGN_CENTER); + info_message->set_align(Label::ALIGN_CENTER); + info_message->set_autowrap(true); + info_message->set_anchors_and_margins_preset(PRESET_WIDE, PRESET_MODE_KEEP_SIZE, 8 * EDSCALE); + mesh_library_palette->add_child(info_message); + edit_axis = Vector3::AXIS_Y; edit_floor[0] = -1; edit_floor[1] = -1; @@ -1340,13 +1342,12 @@ GridMapEditor::GridMapEditor(EditorNode *p_editor) { selected_palette = -1; lock_view = false; cursor_rot = 0; - last_mouseover = Vector3(-1, -1, -1); selection_mesh = VisualServer::get_singleton()->mesh_create(); paste_mesh = VisualServer::get_singleton()->mesh_create(); { - //selection mesh create + // Selection mesh create. PoolVector<Vector3> lines; PoolVector<Vector3> triangles; @@ -1424,7 +1425,6 @@ GridMapEditor::GridMapEditor(EditorNode *p_editor) { inner_mat.instance(); inner_mat->set_albedo(Color(0.7, 0.7, 1.0, 0.2)); - //inner_mat->set_flag(SpatialMaterial::FLAG_ONTOP, true); inner_mat->set_flag(SpatialMaterial::FLAG_UNSHADED, true); inner_mat->set_feature(SpatialMaterial::FEATURE_TRANSPARENT, true); @@ -1444,7 +1444,6 @@ GridMapEditor::GridMapEditor(EditorNode *p_editor) { selection_floor_mat->set_on_top_of_alpha(); selection_floor_mat->set_flag(SpatialMaterial::FLAG_UNSHADED, true); selection_floor_mat->set_line_width(3.0); - //selection_floor_mat->set_feature(SpatialMaterial::FEATURE_TRANSPARENT, true); d[VS::ARRAY_VERTEX] = lines; VisualServer::get_singleton()->mesh_add_surface_from_arrays(selection_mesh, VS::PRIMITIVE_LINES, d); diff --git a/modules/gridmap/grid_map_editor_plugin.h b/modules/gridmap/grid_map_editor_plugin.h index d174ac1035..48a07e9c7f 100644 --- a/modules/gridmap/grid_map_editor_plugin.h +++ b/modules/gridmap/grid_map_editor_plugin.h @@ -156,7 +156,6 @@ class GridMapEditor : public VBoxContainer { Transform cursor_transform; Vector3 cursor_origin; - Vector3 last_mouseover; int display_mode; int selected_palette; @@ -197,12 +196,16 @@ class GridMapEditor : public VBoxContainer { RID instance; }; + ItemList *mesh_library_palette; + Label *info_message; + + EditorNode *editor; + void update_grid(); void _configure(); void _menu_option(int); void update_palette(); void _set_display_mode(int p_mode); - ItemList *mesh_library_palette; void _item_selected_cbk(int idx); void _update_cursor_transform(); void _update_cursor_instance(); @@ -227,7 +230,6 @@ class GridMapEditor : public VBoxContainer { void _delete_selection(); void _fill_selection(); - EditorNode *editor; bool do_input_action(Camera *p_camera, const Point2 &p_point, bool p_click); friend class GridMapEditorPlugin; diff --git a/modules/mono/build_scripts/mono_configure.py b/modules/mono/build_scripts/mono_configure.py index f751719531..4c1ebd8d74 100644 --- a/modules/mono/build_scripts/mono_configure.py +++ b/modules/mono/build_scripts/mono_configure.py @@ -18,7 +18,7 @@ android_arch_dirs = { def get_android_out_dir(env): - return os.path.join(Dir('#platform/android/java/libs').abspath, + return os.path.join(Dir('#platform/android/java/lib/libs').abspath, 'release' if env['target'] == 'release' else 'debug', android_arch_dirs[env['android_arch']]) diff --git a/modules/mono/editor/bindings_generator.cpp b/modules/mono/editor/bindings_generator.cpp index 1888bb3cb9..22bfa14d5d 100644 --- a/modules/mono/editor/bindings_generator.cpp +++ b/modules/mono/editor/bindings_generator.cpp @@ -863,6 +863,8 @@ void BindingsGenerator::_generate_global_constants(StringBuilder &p_output) { Error BindingsGenerator::generate_cs_core_project(const String &p_proj_dir, Vector<String> &r_compile_items) { + ERR_FAIL_COND_V(!initialized, ERR_UNCONFIGURED); + DirAccessRef da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); ERR_FAIL_COND_V(!da, ERR_CANT_CREATE); @@ -984,6 +986,8 @@ Error BindingsGenerator::generate_cs_core_project(const String &p_proj_dir, Vect Error BindingsGenerator::generate_cs_editor_project(const String &p_proj_dir, Vector<String> &r_compile_items) { + ERR_FAIL_COND_V(!initialized, ERR_UNCONFIGURED); + DirAccessRef da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); ERR_FAIL_COND_V(!da, ERR_CANT_CREATE); @@ -1064,6 +1068,8 @@ Error BindingsGenerator::generate_cs_editor_project(const String &p_proj_dir, Ve Error BindingsGenerator::generate_cs_api(const String &p_output_dir) { + ERR_FAIL_COND_V(!initialized, ERR_UNCONFIGURED); + String output_dir = path::abspath(path::realpath(p_output_dir)); DirAccessRef da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); @@ -1703,6 +1709,8 @@ Error BindingsGenerator::_generate_cs_method(const BindingsGenerator::TypeInterf Error BindingsGenerator::generate_glue(const String &p_output_dir) { + ERR_FAIL_COND_V(!initialized, ERR_UNCONFIGURED); + bool dir_exists = DirAccess::exists(p_output_dir); ERR_FAIL_COND_V_MSG(!dir_exists, ERR_FILE_BAD_PATH, "The output directory does not exist."); @@ -1785,6 +1793,9 @@ Error BindingsGenerator::generate_glue(const String &p_output_dir) { output.append("uint32_t get_bindings_version() { return "); output.append(String::num_uint64(BINDINGS_GENERATOR_VERSION) + "; }\n"); + output.append("uint32_t get_cs_glue_version() { return "); + output.append(String::num_uint64(CS_GLUE_VERSION) + "; }\n"); + output.append("\nvoid register_generated_icalls() " OPEN_BLOCK); output.append("\tgodot_register_glue_header_icalls();\n"); @@ -2148,7 +2159,7 @@ StringName BindingsGenerator::_get_float_type_name_from_meta(GodotTypeInfo::Meta } } -void BindingsGenerator::_populate_object_type_interfaces() { +bool BindingsGenerator::_populate_object_type_interfaces() { obj_types.clear(); @@ -2226,7 +2237,7 @@ void BindingsGenerator::_populate_object_type_interfaces() { bool valid = false; iprop.index = ClassDB::get_property_index(type_cname, iprop.cname, &valid); - ERR_FAIL_COND(!valid); + ERR_FAIL_COND_V(!valid, false); iprop.proxy_name = escape_csharp_keyword(snake_to_pascal_case(iprop.cname)); @@ -2290,7 +2301,7 @@ void BindingsGenerator::_populate_object_type_interfaces() { imethod.is_vararg = m && m->is_vararg(); if (!m && !imethod.is_virtual) { - ERR_FAIL_COND_MSG(!virtual_method_list.find(method_info), + ERR_FAIL_COND_V_MSG(!virtual_method_list.find(method_info), false, "Missing MethodBind for non-virtual method: '" + itype.name + "." + imethod.name + "'."); // A virtual method without the virtual flag. This is a special case. @@ -2307,9 +2318,9 @@ void BindingsGenerator::_populate_object_type_interfaces() { // which could actually will return something different. // Let's put this to notify us if that ever happens. if (itype.cname != name_cache.type_Object || imethod.name != "free") { - ERR_PRINTS("Notification: New unexpected virtual non-overridable method found." - " We only expected Object.free, but found '" + - itype.name + "." + imethod.name + "'."); + WARN_PRINTS("Notification: New unexpected virtual non-overridable method found." + " We only expected Object.free, but found '" + + itype.name + "." + imethod.name + "'."); } } else if (return_info.type == Variant::INT && return_info.usage & PROPERTY_USAGE_CLASS_IS_ENUM) { imethod.return_type.cname = return_info.class_name; @@ -2321,7 +2332,7 @@ void BindingsGenerator::_populate_object_type_interfaces() { ERR_PRINTS("Return type is reference but hint is not '" _STR(PROPERTY_HINT_RESOURCE_TYPE) "'." " Are you returning a reference type by pointer? Method: '" + itype.name + "." + imethod.name + "'."); /* clang-format on */ - ERR_FAIL(); + ERR_FAIL_V(false); } } else if (return_info.hint == PROPERTY_HINT_RESOURCE_TYPE) { imethod.return_type.cname = return_info.hint_string; @@ -2342,8 +2353,10 @@ void BindingsGenerator::_populate_object_type_interfaces() { for (int i = 0; i < argc; i++) { PropertyInfo arginfo = method_info.arguments[i]; + String orig_arg_name = arginfo.name; + ArgumentInterface iarg; - iarg.name = arginfo.name; + iarg.name = orig_arg_name; if (arginfo.type == Variant::INT && arginfo.usage & PROPERTY_USAGE_CLASS_IS_ENUM) { iarg.type.cname = arginfo.class_name; @@ -2367,7 +2380,9 @@ void BindingsGenerator::_populate_object_type_interfaces() { iarg.name = escape_csharp_keyword(snake_to_camel_case(iarg.name)); if (m && m->has_default_argument(i)) { - _default_argument_from_variant(m->get_default_argument(i), iarg); + bool defval_ok = _arg_default_value_from_variant(m->get_default_argument(i), iarg); + ERR_FAIL_COND_V_MSG(!defval_ok, false, + "Cannot determine default value for argument '" + orig_arg_name + "' of method '" + itype.name + "." + imethod.name + "'."); } imethod.add_argument(iarg); @@ -2447,7 +2462,7 @@ void BindingsGenerator::_populate_object_type_interfaces() { const StringName &constant_cname = E->get(); String constant_name = constant_cname.operator String(); int *value = class_info->constant_map.getptr(constant_cname); - ERR_FAIL_NULL(value); + ERR_FAIL_NULL_V(value, false); constants.erase(constant_name); ConstantInterface iconstant(constant_name, snake_to_pascal_case(constant_name, true), *value); @@ -2483,7 +2498,7 @@ void BindingsGenerator::_populate_object_type_interfaces() { for (const List<String>::Element *E = constants.front(); E; E = E->next()) { const String &constant_name = E->get(); int *value = class_info->constant_map.getptr(StringName(E->get())); - ERR_FAIL_NULL(value); + ERR_FAIL_NULL_V(value, false); ConstantInterface iconstant(constant_name, snake_to_pascal_case(constant_name, true), *value); @@ -2504,9 +2519,11 @@ void BindingsGenerator::_populate_object_type_interfaces() { class_list.pop_front(); } + + return true; } -void BindingsGenerator::_default_argument_from_variant(const Variant &p_val, ArgumentInterface &r_iarg) { +bool BindingsGenerator::_arg_default_value_from_variant(const Variant &p_val, ArgumentInterface &r_iarg) { r_iarg.default_argument = p_val; @@ -2552,16 +2569,24 @@ void BindingsGenerator::_default_argument_from_variant(const Variant &p_val, Arg r_iarg.def_param_mode = ArgumentInterface::NULLABLE_VAL; break; case Variant::OBJECT: - if (p_val.is_zero()) { - r_iarg.default_argument = "null"; - break; - } - FALLTHROUGH; + ERR_FAIL_COND_V_MSG(!p_val.is_zero(), false, + "Parameter of type '" + String(r_iarg.type.cname) + "' can only have null/zero as the default value."); + + r_iarg.default_argument = "null"; + break; case Variant::DICTIONARY: - case Variant::_RID: r_iarg.default_argument = "new %s()"; r_iarg.def_param_mode = ArgumentInterface::NULLABLE_REF; break; + case Variant::_RID: + ERR_FAIL_COND_V_MSG(r_iarg.type.cname != name_cache.type_RID, false, + "Parameter of type '" + String(r_iarg.type.cname) + "' cannot have a default value of type '" + String(name_cache.type_RID) + "'."); + + ERR_FAIL_COND_V_MSG(!p_val.is_zero(), false, + "Parameter of type '" + String(r_iarg.type.cname) + "' can only have null/zero as the default value."); + + r_iarg.default_argument = "null"; + break; case Variant::ARRAY: case Variant::POOL_BYTE_ARRAY: case Variant::POOL_INT_ARRAY: @@ -2585,6 +2610,8 @@ void BindingsGenerator::_default_argument_from_variant(const Variant &p_val, Arg if (r_iarg.def_param_mode == ArgumentInterface::CONSTANT && r_iarg.type.cname == name_cache.type_Variant && r_iarg.default_argument != "null") r_iarg.def_param_mode = ArgumentInterface::NULLABLE_REF; + + return true; } void BindingsGenerator::_populate_builtin_type_interfaces() { @@ -2970,13 +2997,17 @@ void BindingsGenerator::_log(const char *p_format, ...) { void BindingsGenerator::_initialize() { + initialized = false; + EditorHelp::generate_doc(); enum_types.clear(); _initialize_blacklisted_methods(); - _populate_object_type_interfaces(); + bool obj_type_ok = _populate_object_type_interfaces(); + ERR_FAIL_COND_MSG(!obj_type_ok, "Failed to generate object type interfaces"); + _populate_builtin_type_interfaces(); _populate_global_constants(); @@ -2988,6 +3019,8 @@ void BindingsGenerator::_initialize() { for (OrderedHashMap<StringName, TypeInterface>::Element E = obj_types.front(); E; E = E.next()) _generate_method_icalls(E.get()); + + initialized = true; } void BindingsGenerator::handle_cmdline_args(const List<String> &p_cmdline_args) { @@ -3048,6 +3081,11 @@ void BindingsGenerator::handle_cmdline_args(const List<String> &p_cmdline_args) BindingsGenerator bindings_generator; bindings_generator.set_log_print_enabled(true); + if (!bindings_generator.initialized) { + ERR_PRINTS("Failed to initialize the bindings generator"); + ::exit(0); + } + if (glue_dir_path.length()) { if (bindings_generator.generate_glue(glue_dir_path) != OK) ERR_PRINTS(generate_all_glue_option + ": Failed to generate the C++ glue."); diff --git a/modules/mono/editor/bindings_generator.h b/modules/mono/editor/bindings_generator.h index 6f0c297575..26718f1d11 100644 --- a/modules/mono/editor/bindings_generator.h +++ b/modules/mono/editor/bindings_generator.h @@ -472,6 +472,7 @@ class BindingsGenerator { }; bool log_print_enabled; + bool initialized; OrderedHashMap<StringName, TypeInterface> obj_types; @@ -502,6 +503,7 @@ class BindingsGenerator { StringName type_VarArg; StringName type_Object; StringName type_Reference; + StringName type_RID; StringName type_String; StringName type_at_GlobalScope; StringName enum_Error; @@ -525,6 +527,7 @@ class BindingsGenerator { type_VarArg = StaticCString::create("VarArg"); type_Object = StaticCString::create("Object"); type_Reference = StaticCString::create("Reference"); + type_RID = StaticCString::create("RID"); type_String = StaticCString::create("String"); type_at_GlobalScope = StaticCString::create("@GlobalScope"); enum_Error = StaticCString::create("Error"); @@ -590,9 +593,9 @@ class BindingsGenerator { StringName _get_int_type_name_from_meta(GodotTypeInfo::Metadata p_meta); StringName _get_float_type_name_from_meta(GodotTypeInfo::Metadata p_meta); - void _default_argument_from_variant(const Variant &p_val, ArgumentInterface &r_iarg); + bool _arg_default_value_from_variant(const Variant &p_val, ArgumentInterface &r_iarg); - void _populate_object_type_interfaces(); + bool _populate_object_type_interfaces(); void _populate_builtin_type_interfaces(); void _populate_global_constants(); @@ -621,12 +624,15 @@ public: _FORCE_INLINE_ bool is_log_print_enabled() { return log_print_enabled; } _FORCE_INLINE_ void set_log_print_enabled(bool p_enabled) { log_print_enabled = p_enabled; } + _FORCE_INLINE_ bool is_initialized() { return initialized; } + static uint32_t get_version(); static void handle_cmdline_args(const List<String> &p_cmdline_args); BindingsGenerator() : - log_print_enabled(true) { + log_print_enabled(true), + initialized(false) { _initialize(); } }; diff --git a/modules/mono/mono_gd/gd_mono.cpp b/modules/mono/mono_gd/gd_mono.cpp index cd111abd4d..915a01af7e 100644 --- a/modules/mono/mono_gd/gd_mono.cpp +++ b/modules/mono/mono_gd/gd_mono.cpp @@ -44,7 +44,6 @@ #include "core/project_settings.h" #include "../csharp_script.h" -#include "../glue/cs_glue_version.gen.h" #include "../godotsharp_dirs.h" #include "../utils/path_utils.h" #include "gd_mono_class.h" @@ -395,23 +394,24 @@ uint64_t get_core_api_hash(); uint64_t get_editor_api_hash(); #endif uint32_t get_bindings_version(); +uint32_t get_cs_glue_version(); void register_generated_icalls(); #else uint64_t get_core_api_hash() { - CRASH_NOW(); GD_UNREACHABLE(); } #ifdef TOOLS_ENABLED uint64_t get_editor_api_hash() { - CRASH_NOW(); GD_UNREACHABLE(); } #endif uint32_t get_bindings_version() { - CRASH_NOW(); + GD_UNREACHABLE(); +} +uint32_t get_cs_glue_version() { GD_UNREACHABLE(); } @@ -687,7 +687,7 @@ bool GDMono::_load_core_api_assembly() { APIAssembly::Version api_assembly_ver = APIAssembly::Version::get_from_loaded_assembly(core_api_assembly, APIAssembly::API_CORE); core_api_assembly_out_of_sync = GodotSharpBindings::get_core_api_hash() != api_assembly_ver.godot_api_hash || GodotSharpBindings::get_bindings_version() != api_assembly_ver.bindings_version || - CS_GLUE_VERSION != api_assembly_ver.cs_glue_version; + GodotSharpBindings::get_cs_glue_version() != api_assembly_ver.cs_glue_version; if (!core_api_assembly_out_of_sync) { GDMonoUtils::update_godot_api_cache(); @@ -722,7 +722,7 @@ bool GDMono::_load_editor_api_assembly() { APIAssembly::Version api_assembly_ver = APIAssembly::Version::get_from_loaded_assembly(editor_api_assembly, APIAssembly::API_EDITOR); editor_api_assembly_out_of_sync = GodotSharpBindings::get_editor_api_hash() != api_assembly_ver.godot_api_hash || GodotSharpBindings::get_bindings_version() != api_assembly_ver.bindings_version || - CS_GLUE_VERSION != api_assembly_ver.cs_glue_version; + GodotSharpBindings::get_cs_glue_version() != api_assembly_ver.cs_glue_version; } else { editor_api_assembly_out_of_sync = false; } diff --git a/modules/opensimplex/doc_classes/NoiseTexture.xml b/modules/opensimplex/doc_classes/NoiseTexture.xml index 4b59a380f5..07d5eb27d6 100644 --- a/modules/opensimplex/doc_classes/NoiseTexture.xml +++ b/modules/opensimplex/doc_classes/NoiseTexture.xml @@ -17,6 +17,7 @@ </member> <member name="bump_strength" type="float" setter="set_bump_strength" getter="get_bump_strength" default="8.0"> </member> + <member name="flags" type="int" setter="set_flags" getter="get_flags" override="true" default="7" /> <member name="height" type="int" setter="set_height" getter="get_height" default="512"> Height of the generated texture. </member> diff --git a/modules/visual_script/doc_classes/VisualScriptBuiltinFunc.xml b/modules/visual_script/doc_classes/VisualScriptBuiltinFunc.xml index 9e3670ec35..b5b452ee47 100644 --- a/modules/visual_script/doc_classes/VisualScriptBuiltinFunc.xml +++ b/modules/visual_script/doc_classes/VisualScriptBuiltinFunc.xml @@ -217,7 +217,9 @@ </constant> <constant name="MATH_LERP_ANGLE" value="66" enum="BuiltinFunc"> </constant> - <constant name="FUNC_MAX" value="67" enum="BuiltinFunc"> + <constant name="TEXT_ORD" value="67" enum="BuiltinFunc"> + </constant> + <constant name="FUNC_MAX" value="68" enum="BuiltinFunc"> Represents the size of the [enum BuiltinFunc] enum. </constant> </constants> diff --git a/modules/visual_script/visual_script.cpp b/modules/visual_script/visual_script.cpp index 70389b6729..6bed1742eb 100644 --- a/modules/visual_script/visual_script.cpp +++ b/modules/visual_script/visual_script.cpp @@ -578,6 +578,10 @@ void VisualScript::get_data_connection_list(const StringName &p_func, List<DataC } } +void VisualScript::set_tool_enabled(bool p_enabled) { + is_tool_script = p_enabled; +} + void VisualScript::add_variable(const StringName &p_name, const Variant &p_default_value, bool p_export) { ERR_FAIL_COND(instances.size()); @@ -894,7 +898,7 @@ ScriptInstance *VisualScript::instance_create(Object *p_this) { #ifdef TOOLS_ENABLED - if (!ScriptServer::is_scripting_enabled()) { + if (!ScriptServer::is_scripting_enabled() && !is_tool_script) { PlaceHolderScriptInstance *sins = memnew(PlaceHolderScriptInstance(VisualScriptLanguage::singleton, Ref<Script>((Script *)this), p_this)); placeholders.insert(sins); @@ -958,7 +962,7 @@ Error VisualScript::reload(bool p_keep_state) { bool VisualScript::is_tool() const { - return false; + return is_tool_script; } bool VisualScript::is_valid() const { @@ -1164,6 +1168,11 @@ void VisualScript::_set_data(const Dictionary &p_data) { data_connect(name, data_connections[j + 0], data_connections[j + 1], data_connections[j + 2], data_connections[j + 3]); } } + + if (d.has("is_tool_script")) + is_tool_script = d["is_tool_script"]; + else + is_tool_script = false; } Dictionary VisualScript::_get_data() const { @@ -1246,6 +1255,8 @@ Dictionary VisualScript::_get_data() const { d["functions"] = funcs; + d["is_tool_script"] = is_tool_script; + return d; } diff --git a/modules/visual_script/visual_script.h b/modules/visual_script/visual_script.h index 098c28370d..14927c4363 100644 --- a/modules/visual_script/visual_script.h +++ b/modules/visual_script/visual_script.h @@ -247,6 +247,8 @@ private: Map<Object *, VisualScriptInstance *> instances; + bool is_tool_script; + #ifdef TOOLS_ENABLED Set<PlaceHolderScriptInstance *> placeholders; //void _update_placeholder(PlaceHolderScriptInstance *p_placeholder); @@ -273,6 +275,7 @@ public: Vector2 get_function_scroll(const StringName &p_name) const; void get_function_list(List<StringName> *r_functions) const; int get_function_node_id(const StringName &p_name) const; + void set_tool_enabled(bool p_enabled); void add_node(const StringName &p_func, int p_id, const Ref<VisualScriptNode> &p_node, const Point2 &p_pos = Point2()); void remove_node(const StringName &p_func, int p_id); diff --git a/modules/visual_script/visual_script_editor.cpp b/modules/visual_script/visual_script_editor.cpp index 8faa342bbe..7262dde359 100644 --- a/modules/visual_script/visual_script_editor.cpp +++ b/modules/visual_script/visual_script_editor.cpp @@ -2227,6 +2227,10 @@ void VisualScriptEditor::_change_base_type() { select_base_type->popup_create(true, true); } +void VisualScriptEditor::_toggle_tool_script() { + script->set_tool_enabled(!script->is_tool()); +} + void VisualScriptEditor::clear_edit_menu() { memdelete(edit_menu); memdelete(left_vsplit); @@ -3448,6 +3452,7 @@ void VisualScriptEditor::_bind_methods() { ClassDB::bind_method("_update_members", &VisualScriptEditor::_update_members); ClassDB::bind_method("_change_base_type", &VisualScriptEditor::_change_base_type); ClassDB::bind_method("_change_base_type_callback", &VisualScriptEditor::_change_base_type_callback); + ClassDB::bind_method("_toggle_tool_script", &VisualScriptEditor::_toggle_tool_script); ClassDB::bind_method("_node_selected", &VisualScriptEditor::_node_selected); ClassDB::bind_method("_node_moved", &VisualScriptEditor::_node_moved); ClassDB::bind_method("_move_node", &VisualScriptEditor::_move_node); @@ -3533,6 +3538,11 @@ VisualScriptEditor::VisualScriptEditor() { left_vb->set_v_size_flags(SIZE_EXPAND_FILL); //left_vb->set_custom_minimum_size(Size2(230, 1) * EDSCALE); + CheckButton *tool_script_check = memnew(CheckButton); + tool_script_check->set_text(TTR("Make Tool:")); + left_vb->add_child(tool_script_check); + tool_script_check->connect("pressed", this, "_toggle_tool_script"); + base_type_select = memnew(Button); left_vb->add_margin_child(TTR("Base Type:"), base_type_select); base_type_select->connect("pressed", this, "_change_base_type"); diff --git a/modules/visual_script/visual_script_editor.h b/modules/visual_script/visual_script_editor.h index 4f302d1d72..5df9b1a004 100644 --- a/modules/visual_script/visual_script_editor.h +++ b/modules/visual_script/visual_script_editor.h @@ -186,6 +186,7 @@ class VisualScriptEditor : public ScriptEditorBase { void _node_filter_changed(const String &p_text); void _change_base_type_callback(); void _change_base_type(); + void _toggle_tool_script(); void _member_selected(); void _member_edited(); diff --git a/modules/webrtc/doc_classes/WebRTCMultiplayer.xml b/modules/webrtc/doc_classes/WebRTCMultiplayer.xml index 2b0622fffa..605b1ef082 100644 --- a/modules/webrtc/doc_classes/WebRTCMultiplayer.xml +++ b/modules/webrtc/doc_classes/WebRTCMultiplayer.xml @@ -80,6 +80,10 @@ </description> </method> </methods> + <members> + <member name="refuse_new_connections" type="bool" setter="set_refuse_new_connections" getter="is_refusing_new_connections" override="true" default="false" /> + <member name="transfer_mode" type="int" setter="set_transfer_mode" getter="get_transfer_mode" override="true" enum="NetworkedMultiplayerPeer.TransferMode" default="2" /> + </members> <constants> </constants> </class> diff --git a/modules/websocket/doc_classes/WebSocketMultiplayerPeer.xml b/modules/websocket/doc_classes/WebSocketMultiplayerPeer.xml index b80a28e648..7070cfbdab 100644 --- a/modules/websocket/doc_classes/WebSocketMultiplayerPeer.xml +++ b/modules/websocket/doc_classes/WebSocketMultiplayerPeer.xml @@ -37,6 +37,10 @@ </description> </method> </methods> + <members> + <member name="refuse_new_connections" type="bool" setter="set_refuse_new_connections" getter="is_refusing_new_connections" override="true" default="false" /> + <member name="transfer_mode" type="int" setter="set_transfer_mode" getter="get_transfer_mode" override="true" enum="NetworkedMultiplayerPeer.TransferMode" default="2" /> + </members> <signals> <signal name="peer_packet"> <argument index="0" name="peer_source" type="int"> |