diff options
35 files changed, 209 insertions, 56 deletions
diff --git a/core/bind/core_bind.cpp b/core/bind/core_bind.cpp index cd28081f76..0032c43179 100644 --- a/core/bind/core_bind.cpp +++ b/core/bind/core_bind.cpp @@ -1754,9 +1754,9 @@ String _File::get_line() const { return f->get_line(); } -Vector<String> _File::get_csv_line(String delim) const { +Vector<String> _File::get_csv_line(const String &p_delim) const { ERR_FAIL_COND_V(!f, Vector<String>()); - return f->get_csv_line(delim); + return f->get_csv_line(p_delim); } /**< use this for files WRITTEN in _big_ endian machines (ie, amiga/mac) @@ -1853,6 +1853,11 @@ void _File::store_line(const String &p_string) { f->store_line(p_string); } +void _File::store_csv_line(const Vector<String> &p_values, const String &p_delim) { + ERR_FAIL_COND(!f); + f->store_csv_line(p_values, p_delim); +} + void _File::store_buffer(const PoolVector<uint8_t> &p_buffer) { ERR_FAIL_COND(!f); @@ -1936,6 +1941,7 @@ void _File::_bind_methods() { ClassDB::bind_method(D_METHOD("get_real"), &_File::get_real); ClassDB::bind_method(D_METHOD("get_buffer", "len"), &_File::get_buffer); ClassDB::bind_method(D_METHOD("get_line"), &_File::get_line); + ClassDB::bind_method(D_METHOD("get_csv_line", "delim"), &_File::get_csv_line, DEFVAL(",")); ClassDB::bind_method(D_METHOD("get_as_text"), &_File::get_as_text); ClassDB::bind_method(D_METHOD("get_md5", "path"), &_File::get_md5); ClassDB::bind_method(D_METHOD("get_sha256", "path"), &_File::get_sha256); @@ -1943,7 +1949,6 @@ void _File::_bind_methods() { ClassDB::bind_method(D_METHOD("set_endian_swap", "enable"), &_File::set_endian_swap); ClassDB::bind_method(D_METHOD("get_error"), &_File::get_error); ClassDB::bind_method(D_METHOD("get_var"), &_File::get_var); - ClassDB::bind_method(D_METHOD("get_csv_line", "delim"), &_File::get_csv_line, DEFVAL(",")); ClassDB::bind_method(D_METHOD("store_8", "value"), &_File::store_8); ClassDB::bind_method(D_METHOD("store_16", "value"), &_File::store_16); @@ -1954,6 +1959,7 @@ void _File::_bind_methods() { ClassDB::bind_method(D_METHOD("store_real", "value"), &_File::store_real); ClassDB::bind_method(D_METHOD("store_buffer", "buffer"), &_File::store_buffer); ClassDB::bind_method(D_METHOD("store_line", "line"), &_File::store_line); + ClassDB::bind_method(D_METHOD("store_csv_line", "values", "delim"), &_File::store_csv_line, DEFVAL(",")); ClassDB::bind_method(D_METHOD("store_string", "string"), &_File::store_string); ClassDB::bind_method(D_METHOD("store_var", "value"), &_File::store_var); diff --git a/core/bind/core_bind.h b/core/bind/core_bind.h index 437d7515c6..720b14bf56 100644 --- a/core/bind/core_bind.h +++ b/core/bind/core_bind.h @@ -455,6 +455,7 @@ public: PoolVector<uint8_t> get_buffer(int p_length) const; ///< get an array of bytes String get_line() const; + Vector<String> get_csv_line(const String &p_delim = ",") const; String get_as_text() const; String get_md5(const String &p_path) const; String get_sha256(const String &p_path) const; @@ -480,12 +481,11 @@ public: void store_string(const String &p_string); void store_line(const String &p_string); + void store_csv_line(const Vector<String> &p_values, const String &p_delim = ","); virtual void store_pascal_string(const String &p_string); virtual String get_pascal_string(); - Vector<String> get_csv_line(String delim = ",") const; - void store_buffer(const PoolVector<uint8_t> &p_buffer); ///< store an array of bytes void store_var(const Variant &p_var); diff --git a/core/image.cpp b/core/image.cpp index 172f5e517a..698a0b0b98 100644 --- a/core/image.cpp +++ b/core/image.cpp @@ -1766,6 +1766,15 @@ int Image::get_image_required_mipmaps(int p_width, int p_height, Format p_format return mm; } +int Image::get_image_mipmap_offset(int p_width, int p_height, Format p_format, int p_mipmap) { + + if (p_mipmap <= 0) { + return 0; + } + int mm; + return _get_dst_image_size(p_width, p_height, p_format, mm, p_mipmap - 1); +} + bool Image::is_compressed() const { return format > FORMAT_RGBE9995; } diff --git a/core/image.h b/core/image.h index 11f9380c3c..0770eb953e 100644 --- a/core/image.h +++ b/core/image.h @@ -286,6 +286,7 @@ public: static int get_image_data_size(int p_width, int p_height, Format p_format, bool p_mipmaps = false); static int get_image_required_mipmaps(int p_width, int p_height, Format p_format); + static int get_image_mipmap_offset(int p_width, int p_height, Format p_format, int p_mipmap); enum CompressMode { COMPRESS_S3TC, diff --git a/core/object.cpp b/core/object.cpp index 6a6749f3b8..1eff56f026 100644 --- a/core/object.cpp +++ b/core/object.cpp @@ -1715,6 +1715,8 @@ void Object::_bind_methods() { ClassDB::bind_vararg_method(METHOD_FLAGS_DEFAULT, "call_deferred", &Object::_call_deferred_bind, mi); } + ClassDB::bind_method(D_METHOD("set_deferred", "property", "value"), &Object::set_deferred); + ClassDB::bind_method(D_METHOD("callv", "method", "arg_array"), &Object::callv); ClassDB::bind_method(D_METHOD("has_method", "method"), &Object::has_method); @@ -1771,6 +1773,10 @@ void Object::call_deferred(const StringName &p_method, VARIANT_ARG_DECLARE) { MessageQueue::get_singleton()->push_call(this, p_method, VARIANT_ARG_PASS); } +void Object::set_deferred(const StringName &p_property, const Variant &p_value) { + MessageQueue::get_singleton()->push_set(this, p_property, p_value); +} + void Object::set_block_signals(bool p_block) { _block_signals = p_block; diff --git a/core/object.h b/core/object.h index 25d41140aa..88a98dacbe 100644 --- a/core/object.h +++ b/core/object.h @@ -698,6 +698,7 @@ public: bool is_connected(const StringName &p_signal, Object *p_to_object, const StringName &p_to_method) const; void call_deferred(const StringName &p_method, VARIANT_ARG_LIST); + void set_deferred(const StringName &p_property, const Variant &p_value); void set_block_signals(bool p_block); bool is_blocking_signals() const; diff --git a/core/os/file_access.cpp b/core/os/file_access.cpp index e09e5e16ad..8f4fae9eb1 100644 --- a/core/os/file_access.cpp +++ b/core/os/file_access.cpp @@ -346,9 +346,9 @@ String FileAccess::get_line() const { return String::utf8(line.get_data()); } -Vector<String> FileAccess::get_csv_line(String delim) const { +Vector<String> FileAccess::get_csv_line(const String &p_delim) const { - ERR_FAIL_COND_V(delim.length() != 1, Vector<String>()); + ERR_FAIL_COND_V(p_delim.length() != 1, Vector<String>()); String l; int qc = 0; @@ -376,7 +376,7 @@ Vector<String> FileAccess::get_csv_line(String delim) const { CharType c = l[i]; CharType s[2] = { 0, 0 }; - if (!in_quote && c == delim[0]) { + if (!in_quote && c == p_delim[0]) { strings.push_back(current); current = String(); } else if (c == '"') { @@ -525,6 +525,28 @@ void FileAccess::store_line(const String &p_line) { store_8('\n'); } +void FileAccess::store_csv_line(const Vector<String> &p_values, const String &p_delim) { + + ERR_FAIL_COND(p_delim.length() != 1); + + String line = ""; + int size = p_values.size(); + for (int i = 0; i < size; ++i) { + String value = p_values[i]; + + if (value.find("\"") != -1 || value.find(p_delim) != -1 || value.find("\n")) { + value = "\"" + value.replace("\"", "\"\"") + "\""; + } + if (i < size - 1) { + value += p_delim; + } + + line += value; + } + + store_line(line); +} + void FileAccess::store_buffer(const uint8_t *p_src, int p_length) { for (int i = 0; i < p_length; i++) diff --git a/core/os/file_access.h b/core/os/file_access.h index b7d93e9f5d..f1f3005dd9 100644 --- a/core/os/file_access.h +++ b/core/os/file_access.h @@ -112,7 +112,7 @@ public: virtual int get_buffer(uint8_t *p_dst, int p_length) const; ///< get an array of bytes virtual String get_line() const; virtual String get_token() const; - virtual Vector<String> get_csv_line(String delim = ",") const; + virtual Vector<String> get_csv_line(const String &p_delim = ",") const; /**< use this for files WRITTEN in _big_ endian machines (ie, amiga/mac) * It's not about the current CPU type but file formats. @@ -136,6 +136,7 @@ public: virtual void store_string(const String &p_string); virtual void store_line(const String &p_line); + virtual void store_csv_line(const Vector<String> &p_values, const String &p_delim = ","); virtual void store_pascal_string(const String &p_string); virtual String get_pascal_string(); diff --git a/core/undo_redo.cpp b/core/undo_redo.cpp index 7d67076df5..6f7c8ea08a 100644 --- a/core/undo_redo.cpp +++ b/core/undo_redo.cpp @@ -333,7 +333,7 @@ void UndoRedo::clear_history() { while (actions.size()) _pop_history_tail(); - //version++; + version++; } String UndoRedo::get_current_action_name() const { diff --git a/doc/classes/AudioEffectReverb.xml b/doc/classes/AudioEffectReverb.xml index fb2009105d..87c622e3bb 100644 --- a/doc/classes/AudioEffectReverb.xml +++ b/doc/classes/AudioEffectReverb.xml @@ -15,7 +15,7 @@ </methods> <members> <member name="damping" type="float" setter="set_damping" getter="get_damping"> - Widens or narrows the stereo image of the reverb tail. 1 means fully widens. Value can range from 0 to 1. Default value: [code]1[/code]. + Defines how reflective the imaginary room's walls are. Value can range from 0 to 1. Default value: [code]1[/code]. </member> <member name="dry" type="float" setter="set_dry" getter="get_dry"> Output percent of original sound. At 0, only modified sound is outputted. Value can range from 0 to 1. Default value: [code]1[/code]. @@ -33,7 +33,7 @@ Dimensions of simulated room. Bigger means more echoes. Value can range from 0 to 1. Default value: [code]0.8[/code]. </member> <member name="spread" type="float" setter="set_spread" getter="get_spread"> - Defines how reflective the imaginary room's walls are. Value can range from 0 to 1. Default value: [code]1[/code]. + Widens or narrows the stereo image of the reverb tail. 1 means fully widens. Value can range from 0 to 1. Default value: [code]1[/code]. </member> <member name="wet" type="float" setter="set_wet" getter="get_wet"> Output percent of modified sound. At 0, only original sound is outputted. Value can range from 0 to 1. Default value: [code]0.5[/code]. diff --git a/doc/classes/File.xml b/doc/classes/File.xml index 6c900385f7..1745389833 100644 --- a/doc/classes/File.xml +++ b/doc/classes/File.xml @@ -100,7 +100,7 @@ <argument index="0" name="delim" type="String" default="",""> </argument> <description> - Returns the next value of the file in CSV (Comma Separated Values) format. You can pass a different delimiter to use other than the default "," (comma). + Returns the next value of the file in CSV (Comma Separated Values) format. You can pass a different delimiter to use other than the default "," (comma), it should be one character long. </description> </method> <method name="get_double" qualifiers="const"> @@ -327,6 +327,17 @@ Stores the given array of bytes in the file. </description> </method> + <method name="store_csv_line"> + <return type="void"> + </return> + <argument index="0" name="values" type="PoolStringArray" default="",""> + </argument> + <argument index="1" name="delim" type="String" default="",""> + </argument> + <description> + Store the given [PoolStringArray] in the file as a line formatted in the CSV (Comma Separated Values) format. You can pass a different delimiter to use other than the default "," (comma), it should be one character long. + </description> + </method> <method name="store_double"> <return type="void"> </return> diff --git a/drivers/gles2/rasterizer_scene_gles2.cpp b/drivers/gles2/rasterizer_scene_gles2.cpp index 64fe385889..0c0bf56793 100644 --- a/drivers/gles2/rasterizer_scene_gles2.cpp +++ b/drivers/gles2/rasterizer_scene_gles2.cpp @@ -2339,7 +2339,6 @@ void RasterizerSceneGLES2::_render_render_list(RenderList::Element **p_elements, state.scene_shader.set_uniform(SceneShaderGLES2::TIME, storage->frame.time[0]); state.scene_shader.set_uniform(SceneShaderGLES2::SCREEN_PIXEL_SIZE, screen_pixel_size); - state.scene_shader.set_uniform(SceneShaderGLES2::NORMAL_MULT, 1.0); // TODO mirror? } if (rebind_light && light) { @@ -2498,6 +2497,7 @@ void RasterizerSceneGLES2::render_scene(const Transform &p_cam_transform, const Environment *env = NULL; int viewport_width, viewport_height; + bool probe_interior = false; if (p_reflection_probe.is_valid()) { ReflectionProbeInstance *probe = reflection_probe_instance_owner.getornull(p_reflection_probe); @@ -2515,6 +2515,8 @@ void RasterizerSceneGLES2::render_scene(const Transform &p_cam_transform, const viewport_width = probe->probe_ptr->resolution; viewport_height = probe->probe_ptr->resolution; + probe_interior = probe->probe_ptr->interior; + } else { state.render_no_shadows = false; current_fb = storage->frame.current_rt->fbo; @@ -2625,6 +2627,10 @@ void RasterizerSceneGLES2::render_scene(const Transform &p_cam_transform, const } } + if (probe_interior) { + env_radiance_tex = 0; //do not use radiance texture on interiors + } + // render opaque things first render_list.sort_by_key(false); _render_render_list(render_list.elements, render_list.element_count, p_cam_transform, p_cam_projection, p_shadow_atlas, env, env_radiance_tex, 0.0, 0.0, false, false, false); diff --git a/drivers/gles2/shaders/scene.glsl b/drivers/gles2/shaders/scene.glsl index 4c652cd9e9..bc83b69b49 100644 --- a/drivers/gles2/shaders/scene.glsl +++ b/drivers/gles2/shaders/scene.glsl @@ -84,7 +84,7 @@ uniform highp mat4 world_transform; uniform highp float time; -uniform float normal_mult; + #ifdef RENDER_DEPTH uniform float light_bias; @@ -330,11 +330,10 @@ void main() { #endif - vec3 normal = normal_attrib * normal_mult; + vec3 normal = normal_attrib; #if defined(ENABLE_TANGENT_INTERP) || defined(ENABLE_NORMALMAP) vec3 tangent = tangent_attrib.xyz; - tangent *= normal_mult; float binormalf = tangent_attrib.a; vec3 binormal = normalize(cross(normal, tangent) * binormalf); #endif diff --git a/drivers/gles3/rasterizer_canvas_gles3.cpp b/drivers/gles3/rasterizer_canvas_gles3.cpp index 6e7ecee007..c76db83c0c 100644 --- a/drivers/gles3/rasterizer_canvas_gles3.cpp +++ b/drivers/gles3/rasterizer_canvas_gles3.cpp @@ -213,12 +213,12 @@ RasterizerStorageGLES3::Texture *RasterizerCanvasGLES3::_bind_canvas_texture(con } else { + texture = texture->get_ptr(); + if (texture->redraw_if_visible) { //check before proxy, because this is usually used with proxies VisualServerRaster::redraw_request(); } - texture = texture->get_ptr(); - if (texture->render_target) texture->render_target->used_in_frame = true; @@ -254,11 +254,12 @@ RasterizerStorageGLES3::Texture *RasterizerCanvasGLES3::_bind_canvas_texture(con } else { + normal_map = normal_map->get_ptr(); + if (normal_map->redraw_if_visible) { //check before proxy, because this is usually used with proxies VisualServerRaster::redraw_request(); } - normal_map = normal_map->get_ptr(); glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D, normal_map->tex_id); state.current_normal = p_normal_map; @@ -1385,12 +1386,12 @@ void RasterizerCanvasGLES3::canvas_render_items(Item *p_item_list, int p_z, cons continue; } + t = t->get_ptr(); + if (t->redraw_if_visible) { //check before proxy, because this is usually used with proxies VisualServerRaster::redraw_request(); } - t = t->get_ptr(); - if (storage->config.srgb_decode_supported && t->using_srgb) { //no srgb in 2D glTexParameteri(t->target, _TEXTURE_SRGB_DECODE_EXT, _SKIP_DECODE_EXT); diff --git a/drivers/gles3/rasterizer_scene_gles3.cpp b/drivers/gles3/rasterizer_scene_gles3.cpp index 8d0e438ec5..0951b8f798 100644 --- a/drivers/gles3/rasterizer_scene_gles3.cpp +++ b/drivers/gles3/rasterizer_scene_gles3.cpp @@ -1190,11 +1190,12 @@ bool RasterizerSceneGLES3::_setup_material(RasterizerStorageGLES3::Material *p_m if (t) { + t = t->get_ptr(); //resolve for proxies + if (t->redraw_if_visible) { //must check before proxy because this is often used with proxies VisualServerRaster::redraw_request(); } - t = t->get_ptr(); //resolve for proxies #ifdef TOOLS_ENABLED if (t->detect_3d) { t->detect_3d(t->detect_3d_ud); @@ -2222,7 +2223,6 @@ void RasterizerSceneGLES3::_render_list(RenderList::Element **p_elements, int p_ _set_cull(e->sort_key & RenderList::SORT_KEY_MIRROR_FLAG, e->sort_key & RenderList::SORT_KEY_CULL_DISABLED_FLAG, p_reverse_cull); - state.scene_shader.set_uniform(SceneShaderGLES3::NORMAL_MULT, e->instance->mirror ? -1.0 : 1.0); state.scene_shader.set_uniform(SceneShaderGLES3::WORLD_TRANSFORM, e->instance->transform); _render_geometry(e); @@ -4341,6 +4341,10 @@ void RasterizerSceneGLES3::render_scene(const Transform &p_cam_transform, const } } + if (probe && probe->probe_ptr->interior) { + env_radiance_tex = 0; //for rendering probe interiors, radiance must not be used. + } + state.texscreen_copied = false; glBlendEquation(GL_FUNC_ADD); diff --git a/drivers/gles3/shaders/scene.glsl b/drivers/gles3/shaders/scene.glsl index 2288c17334..d4079c4b4f 100644 --- a/drivers/gles3/shaders/scene.glsl +++ b/drivers/gles3/shaders/scene.glsl @@ -42,8 +42,6 @@ layout(location = 4) in vec2 uv_attrib; layout(location = 5) in vec2 uv2_attrib; #endif -uniform float normal_mult; - #ifdef USE_SKELETON layout(location = 6) in uvec4 bone_indices; // attrib:6 layout(location = 7) in vec4 bone_weights; // attrib:7 @@ -280,11 +278,10 @@ void main() { } #endif - vec3 normal = normal_attrib * normal_mult; + vec3 normal = normal_attrib; #if defined(ENABLE_TANGENT_INTERP) || defined(ENABLE_NORMALMAP) || defined(LIGHT_USE_ANISOTROPY) vec3 tangent = tangent_attrib.xyz; - tangent *= normal_mult; float binormalf = tangent_attrib.a; #endif @@ -1106,9 +1103,9 @@ LIGHT_SHADER_CODE float Fr = mix(.04, 1.0, cLdotH5); float Gr = G_GGX_2cos(cNdotL, .25) * G_GGX_2cos(cNdotV, .25); - float specular_brdf_NL = 0.25 * clearcoat * Gr * Fr * Dr * cNdotL; + float clearcoat_specular_brdf_NL = 0.25 * clearcoat * Gr * Fr * Dr * cNdotL; - specular_light += specular_brdf_NL * light_color * specular_blob_intensity * attenuation; + specular_light += clearcoat_specular_brdf_NL * light_color * specular_blob_intensity * attenuation; #endif } diff --git a/editor/editor_data.cpp b/editor/editor_data.cpp index 9420452da1..bd6ce797b5 100644 --- a/editor/editor_data.cpp +++ b/editor/editor_data.cpp @@ -946,16 +946,18 @@ void EditorData::script_class_save_icon_paths() { void EditorData::script_class_load_icon_paths() { script_class_clear_icon_paths(); - Dictionary d = ProjectSettings::get_singleton()->get("_global_script_class_icons"); - List<Variant> keys; - d.get_key_list(&keys); + if (ProjectSettings::get_singleton()->has_setting("_global_script_class_icons")) { + Dictionary d = ProjectSettings::get_singleton()->get("_global_script_class_icons"); + List<Variant> keys; + d.get_key_list(&keys); - for (List<Variant>::Element *E = keys.front(); E; E = E->next()) { - String name = E->get().operator String(); - _script_class_icon_paths[name] = d[name]; + for (List<Variant>::Element *E = keys.front(); E; E = E->next()) { + String name = E->get().operator String(); + _script_class_icon_paths[name] = d[name]; - String path = ScriptServer::get_global_class_path(name); - script_class_set_name(path, name); + String path = ScriptServer::get_global_class_path(name); + script_class_set_name(path, name); + } } } diff --git a/modules/bullet/bullet_physics_server.h b/modules/bullet/bullet_physics_server.h index 6b7dcd86e6..c8c782267e 100644 --- a/modules/bullet/bullet_physics_server.h +++ b/modules/bullet/bullet_physics_server.h @@ -397,6 +397,8 @@ public: virtual void flush_queries(); virtual void finish(); + virtual bool is_flushing_queries() const { return false; } + virtual int get_process_info(ProcessInfo p_info); CollisionObjectBullet *get_collisin_object(RID p_object) const; diff --git a/modules/bullet/collision_object_bullet.cpp b/modules/bullet/collision_object_bullet.cpp index 402a276f95..441fa7c8af 100644 --- a/modules/bullet/collision_object_bullet.cpp +++ b/modules/bullet/collision_object_bullet.cpp @@ -304,7 +304,11 @@ bool RigidCollisionObjectBullet::is_shape_disabled(int p_index) { } void RigidCollisionObjectBullet::shape_changed(int p_shape_index) { - bulletdelete(shapes.write[p_shape_index].bt_shape); + ShapeWrapper &shp = shapes.write[p_shape_index]; + if (shp.bt_shape == mainShape) { + mainShape = NULL; + } + bulletdelete(shp.bt_shape); reload_shapes(); } @@ -366,5 +370,8 @@ void RigidCollisionObjectBullet::body_scale_changed() { void RigidCollisionObjectBullet::internal_shape_destroy(int p_index, bool p_permanentlyFromThisBody) { ShapeWrapper &shp = shapes.write[p_index]; shp.shape->remove_owner(this, p_permanentlyFromThisBody); + if (shp.bt_shape == mainShape) { + mainShape = NULL; + } bulletdelete(shp.bt_shape); } diff --git a/modules/bullet/rigid_body_bullet.cpp b/modules/bullet/rigid_body_bullet.cpp index 37e7718969..85659e1523 100644 --- a/modules/bullet/rigid_body_bullet.cpp +++ b/modules/bullet/rigid_body_bullet.cpp @@ -797,7 +797,10 @@ void RigidBodyBullet::reload_shapes() { const btScalar mass = invMass == 0 ? 0 : 1 / invMass; if (mainShape) { - btVector3 inertia; + // inertia initialised zero here because some of bullet's collision + // shapes incorrectly do not set the vector in calculateLocalIntertia. + // Arbitrary zero is preferable to undefined behaviour. + btVector3 inertia(0, 0, 0); mainShape->calculateLocalInertia(mass, inertia); btBody->setMassProps(mass, inertia); } diff --git a/modules/gridmap/grid_map_editor_plugin.cpp b/modules/gridmap/grid_map_editor_plugin.cpp index fae88042af..126b49832a 100644 --- a/modules/gridmap/grid_map_editor_plugin.cpp +++ b/modules/gridmap/grid_map_editor_plugin.cpp @@ -802,7 +802,9 @@ void GridMapEditor::edit(GridMap *p_gridmap) { VisualServer::get_singleton()->instance_set_visible(grid_instance[i], false); } - VisualServer::get_singleton()->instance_set_visible(cursor_instance, false); + if (cursor_instance.is_valid()) { + VisualServer::get_singleton()->instance_set_visible(cursor_instance, false); + } return; } diff --git a/modules/squish/image_compress_squish.cpp b/modules/squish/image_compress_squish.cpp index 26cb76011c..a08ac7bd28 100644 --- a/modules/squish/image_compress_squish.cpp +++ b/modules/squish/image_compress_squish.cpp @@ -64,12 +64,13 @@ void image_decompress_squish(Image *p_image) { return; } - int dst_ofs = 0; - for (int i = 0; i <= mm_count; i++) { int src_ofs = 0, mipmap_size = 0, mipmap_w = 0, mipmap_h = 0; p_image->get_mipmap_offset_size_and_dimensions(i, src_ofs, mipmap_size, mipmap_w, mipmap_h); - squish::DecompressImage(&wb[dst_ofs], mipmap_w, mipmap_h, &rb[src_ofs], squish_flags); + int dst_ofs = Image::get_image_mipmap_offset(p_image->get_width(), p_image->get_height(), target_format, i); + squish::DecompressImage(&wb[dst_ofs], w, h, &rb[src_ofs], squish_flags); + w >>= 1; + h >>= 1; } p_image->create(p_image->get_width(), p_image->get_height(), p_image->has_mipmaps(), target_format, data); diff --git a/scene/2d/area_2d.cpp b/scene/2d/area_2d.cpp index 48537f3cfc..ae5891fa50 100644 --- a/scene/2d/area_2d.cpp +++ b/scene/2d/area_2d.cpp @@ -399,7 +399,7 @@ void Area2D::set_monitoring(bool p_enable) { if (p_enable == monitoring) return; if (locked) { - ERR_EXPLAIN("Function blocked during in/out signal. Use call_deferred(\"set_monitoring\",true/false)"); + ERR_EXPLAIN("Function blocked during in/out signal. Use set_deferred(\"monitoring\",true/false)"); } ERR_FAIL_COND(locked); @@ -424,10 +424,10 @@ bool Area2D::is_monitoring() const { void Area2D::set_monitorable(bool p_enable) { - if (locked) { - ERR_EXPLAIN("This function can't be used during the in/out signal."); + if (locked || Physics2DServer::get_singleton()->is_flushing_queries()) { + ERR_EXPLAIN("Function blocked during in/out signal. Use set_deferred(\"monitorable\",true/false)"); } - ERR_FAIL_COND(locked); + ERR_FAIL_COND(locked || Physics2DServer::get_singleton()->is_flushing_queries()); if (p_enable == monitorable) return; diff --git a/scene/3d/area.cpp b/scene/3d/area.cpp index 40a1029201..5e78368804 100644 --- a/scene/3d/area.cpp +++ b/scene/3d/area.cpp @@ -290,7 +290,7 @@ void Area::_notification(int p_what) { void Area::set_monitoring(bool p_enable) { if (locked) { - ERR_EXPLAIN("This function can't be used during the in/out signal."); + ERR_EXPLAIN("Function blocked during in/out signal. Use set_deferred(\"monitoring\",true/false)"); } ERR_FAIL_COND(locked); @@ -437,10 +437,10 @@ Array Area::get_overlapping_bodies() const { void Area::set_monitorable(bool p_enable) { - if (locked) { - ERR_EXPLAIN("This function can't be used during the in/out signal."); + if (locked || PhysicsServer::get_singleton()->is_flushing_queries()) { + ERR_EXPLAIN("Function blocked during in/out signal. Use set_deferred(\"monitorable\",true/false)"); } - ERR_FAIL_COND(locked); + ERR_FAIL_COND(locked || PhysicsServer::get_singleton()->is_flushing_queries()); if (p_enable == monitorable) return; diff --git a/scene/gui/scroll_container.cpp b/scene/gui/scroll_container.cpp index 26da16569a..9c22a049b8 100644 --- a/scene/gui/scroll_container.cpp +++ b/scene/gui/scroll_container.cpp @@ -246,7 +246,7 @@ void ScrollContainer::_notification(int p_what) { size.y -= h_scroll->get_minimum_size().y; if (v_scroll->is_visible_in_tree() && v_scroll->get_parent() == this) //scrolls may have been moved out for reasons - size.x -= h_scroll->get_minimum_size().x; + size.x -= v_scroll->get_minimum_size().x; for (int i = 0; i < get_child_count(); i++) { diff --git a/scene/main/canvas_layer.cpp b/scene/main/canvas_layer.cpp index 93f51a44f4..89bc8c1226 100644 --- a/scene/main/canvas_layer.cpp +++ b/scene/main/canvas_layer.cpp @@ -164,7 +164,9 @@ void CanvasLayer::_notification(int p_what) { } break; case NOTIFICATION_MOVED_IN_PARENT: { - VisualServer::get_singleton()->viewport_set_canvas_stacking(viewport, canvas, layer, get_position_in_parent()); + if (is_inside_tree()) + VisualServer::get_singleton()->viewport_set_canvas_stacking(viewport, canvas, layer, get_position_in_parent()); + } break; } } diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp index 82645aa17a..86992c38f0 100644 --- a/scene/main/viewport.cpp +++ b/scene/main/viewport.cpp @@ -1510,12 +1510,17 @@ void Viewport::_gui_call_input(Control *p_control, const Ref<InputEvent> &p_inpu Control *control = Object::cast_to<Control>(ci); if (control) { - control->emit_signal(SceneStringNames::get_singleton()->gui_input, ev); //signal should be first, so it's possible to override an event (and then accept it) + if (control->data.mouse_filter != Control::MOUSE_FILTER_IGNORE) { + control->emit_signal(SceneStringNames::get_singleton()->gui_input, ev); //signal should be first, so it's possible to override an event (and then accept it) + } if (gui.key_event_accepted) break; if (!control->is_inside_tree()) break; - control->call_multilevel(SceneStringNames::get_singleton()->_gui_input, ev); + + if (control->data.mouse_filter != Control::MOUSE_FILTER_IGNORE) { + control->call_multilevel(SceneStringNames::get_singleton()->_gui_input, ev); + } if (!control->is_inside_tree() || control->is_set_as_toplevel()) break; diff --git a/servers/audio/effects/audio_effect_filter.h b/servers/audio/effects/audio_effect_filter.h index 11978882bc..e8f12e5efa 100644 --- a/servers/audio/effects/audio_effect_filter.h +++ b/servers/audio/effects/audio_effect_filter.h @@ -96,6 +96,11 @@ VARIANT_ENUM_CAST(AudioEffectFilter::FilterDB) class AudioEffectLowPassFilter : public AudioEffectFilter { GDCLASS(AudioEffectLowPassFilter, AudioEffectFilter) + + void _validate_property(PropertyInfo &property) const { + if (property.name == "gain") property.usage = 0; + } + public: AudioEffectLowPassFilter() : AudioEffectFilter(AudioFilterSW::LOWPASS) {} @@ -103,6 +108,10 @@ public: class AudioEffectHighPassFilter : public AudioEffectFilter { GDCLASS(AudioEffectHighPassFilter, AudioEffectFilter) + void _validate_property(PropertyInfo &property) const { + if (property.name == "gain") property.usage = 0; + } + public: AudioEffectHighPassFilter() : AudioEffectFilter(AudioFilterSW::HIGHPASS) {} @@ -110,6 +119,10 @@ public: class AudioEffectBandPassFilter : public AudioEffectFilter { GDCLASS(AudioEffectBandPassFilter, AudioEffectFilter) + void _validate_property(PropertyInfo &property) const { + if (property.name == "gain") property.usage = 0; + } + public: AudioEffectBandPassFilter() : AudioEffectFilter(AudioFilterSW::BANDPASS) {} diff --git a/servers/physics/physics_server_sw.cpp b/servers/physics/physics_server_sw.cpp index 76a6138817..fddb531a4f 100644 --- a/servers/physics/physics_server_sw.cpp +++ b/servers/physics/physics_server_sw.cpp @@ -40,6 +40,12 @@ #include "joints/pin_joint_sw.h" #include "joints/slider_joint_sw.h" +#define FLUSH_QUERY_CHECK \ + if (flushing_queries) { \ + ERR_EXPLAIN("Can't change this state while flushing queries. Use call_deferred()/set_deferred() to change monitoring state instead"); \ + ERR_FAIL(); \ + } + RID PhysicsServerSW::shape_create(ShapeType p_shape) { ShapeSW *shape = NULL; @@ -352,6 +358,8 @@ void PhysicsServerSW::area_clear_shapes(RID p_area) { void PhysicsServerSW::area_set_shape_disabled(RID p_area, int p_shape_idx, bool p_disabled) { + FLUSH_QUERY_CHECK + AreaSW *area = area_owner.get(p_area); ERR_FAIL_COND(!area); ERR_FAIL_INDEX(p_shape_idx, area->get_shape_count()); @@ -435,6 +443,8 @@ void PhysicsServerSW::area_set_collision_mask(RID p_area, uint32_t p_mask) { void PhysicsServerSW::area_set_monitorable(RID p_area, bool p_monitorable) { + FLUSH_QUERY_CHECK + AreaSW *area = area_owner.get(p_area); ERR_FAIL_COND(!area); @@ -582,6 +592,8 @@ RID PhysicsServerSW::body_get_shape(RID p_body, int p_shape_idx) const { void PhysicsServerSW::body_set_shape_disabled(RID p_body, int p_shape_idx, bool p_disabled) { + FLUSH_QUERY_CHECK + BodySW *body = body_owner.get(p_body); ERR_FAIL_COND(!body); ERR_FAIL_INDEX(p_shape_idx, body->get_shape_count()); @@ -1459,6 +1471,8 @@ void PhysicsServerSW::flush_queries() { doing_sync = true; + flushing_queries = true; + uint64_t time_beg = OS::get_singleton()->get_ticks_usec(); for (Set<const SpaceSW *>::Element *E = active_spaces.front(); E; E = E->next()) { @@ -1467,6 +1481,8 @@ void PhysicsServerSW::flush_queries() { space->call_queries(); } + flushing_queries = false; + if (ScriptDebugger::get_singleton() && ScriptDebugger::get_singleton()->is_profiling()) { uint64_t total_time[SpaceSW::ELAPSED_TIME_MAX]; @@ -1580,6 +1596,7 @@ PhysicsServerSW::PhysicsServerSW() { collision_pairs = 0; active = true; + flushing_queries = false; }; PhysicsServerSW::~PhysicsServerSW(){ diff --git a/servers/physics/physics_server_sw.h b/servers/physics/physics_server_sw.h index 4131c5e248..b3c61403aa 100644 --- a/servers/physics/physics_server_sw.h +++ b/servers/physics/physics_server_sw.h @@ -51,6 +51,8 @@ class PhysicsServerSW : public PhysicsServer { int active_objects; int collision_pairs; + bool flushing_queries; + StepSW *stepper; Set<const SpaceSW *> active_spaces; @@ -365,6 +367,8 @@ public: virtual void flush_queries(); virtual void finish(); + virtual bool is_flushing_queries() const { return flushing_queries; } + int get_process_info(ProcessInfo p_info); PhysicsServerSW(); diff --git a/servers/physics_2d/physics_2d_server_sw.cpp b/servers/physics_2d/physics_2d_server_sw.cpp index 2df09057c4..45310ec4b3 100644 --- a/servers/physics_2d/physics_2d_server_sw.cpp +++ b/servers/physics_2d/physics_2d_server_sw.cpp @@ -36,6 +36,12 @@ #include "core/project_settings.h" #include "core/script_language.h" +#define FLUSH_QUERY_CHECK \ + if (flushing_queries) { \ + ERR_EXPLAIN("Can't change this state while flushing queries. Use call_deferred() or set_deferred() to change monitoring state instead"); \ + ERR_FAIL(); \ + } + RID Physics2DServerSW::_shape_create(ShapeType p_shape) { Shape2DSW *shape = NULL; @@ -401,6 +407,8 @@ void Physics2DServerSW::area_set_shape_transform(RID p_area, int p_shape_idx, co void Physics2DServerSW::area_set_shape_disabled(RID p_area, int p_shape, bool p_disabled) { + FLUSH_QUERY_CHECK + Area2DSW *area = area_owner.get(p_area); ERR_FAIL_COND(!area); @@ -539,6 +547,8 @@ void Physics2DServerSW::area_set_pickable(RID p_area, bool p_pickable) { void Physics2DServerSW::area_set_monitorable(RID p_area, bool p_monitorable) { + FLUSH_QUERY_CHECK + Area2DSW *area = area_owner.get(p_area); ERR_FAIL_COND(!area); @@ -617,6 +627,8 @@ RID Physics2DServerSW::body_get_space(RID p_body) const { void Physics2DServerSW::body_set_mode(RID p_body, BodyMode p_mode) { + FLUSH_QUERY_CHECK + Body2DSW *body = body_owner.get(p_body); ERR_FAIL_COND(!body); @@ -719,6 +731,8 @@ void Physics2DServerSW::body_clear_shapes(RID p_body) { void Physics2DServerSW::body_set_shape_disabled(RID p_body, int p_shape_idx, bool p_disabled) { + FLUSH_QUERY_CHECK + Body2DSW *body = body_owner.get(p_body); ERR_FAIL_COND(!body); @@ -1348,6 +1362,8 @@ void Physics2DServerSW::flush_queries() { if (!active) return; + flushing_queries = true; + uint64_t time_beg = OS::get_singleton()->get_ticks_usec(); for (Set<const Space2DSW *>::Element *E = active_spaces.front(); E; E = E->next()) { @@ -1356,6 +1372,8 @@ void Physics2DServerSW::flush_queries() { space->call_queries(); } + flushing_queries = false; + if (ScriptDebugger::get_singleton() && ScriptDebugger::get_singleton()->is_profiling()) { uint64_t total_time[Space2DSW::ELAPSED_TIME_MAX]; @@ -1434,6 +1452,7 @@ Physics2DServerSW::Physics2DServerSW() { active_objects = 0; collision_pairs = 0; using_threads = int(ProjectSettings::get_singleton()->get("physics/2d/thread_model")) == 2; + flushing_queries = false; }; Physics2DServerSW::~Physics2DServerSW(){ diff --git a/servers/physics_2d/physics_2d_server_sw.h b/servers/physics_2d/physics_2d_server_sw.h index f41c599579..4f33873219 100644 --- a/servers/physics_2d/physics_2d_server_sw.h +++ b/servers/physics_2d/physics_2d_server_sw.h @@ -54,6 +54,8 @@ class Physics2DServerSW : public Physics2DServer { bool using_threads; + bool flushing_queries; + Step2DSW *stepper; Set<const Space2DSW *> active_spaces; @@ -278,6 +280,8 @@ public: virtual void end_sync(); virtual void finish(); + virtual bool is_flushing_queries() const { return flushing_queries; } + int get_process_info(ProcessInfo p_info); Physics2DServerSW(); diff --git a/servers/physics_2d/physics_2d_server_wrap_mt.h b/servers/physics_2d/physics_2d_server_wrap_mt.h index 58517bf1a7..e736854077 100644 --- a/servers/physics_2d/physics_2d_server_wrap_mt.h +++ b/servers/physics_2d/physics_2d_server_wrap_mt.h @@ -312,6 +312,10 @@ public: virtual void flush_queries(); virtual void finish(); + virtual bool is_flushing_queries() const { + return physics_2d_server->is_flushing_queries(); + } + int get_process_info(ProcessInfo p_info) { return physics_2d_server->get_process_info(p_info); } diff --git a/servers/physics_2d_server.h b/servers/physics_2d_server.h index 2e91d89c53..32e1dd1a08 100644 --- a/servers/physics_2d_server.h +++ b/servers/physics_2d_server.h @@ -584,6 +584,8 @@ public: virtual void end_sync() = 0; virtual void finish() = 0; + virtual bool is_flushing_queries() const = 0; + enum ProcessInfo { INFO_ACTIVE_OBJECTS, diff --git a/servers/physics_server.h b/servers/physics_server.h index d80d76305a..cbb325dea3 100644 --- a/servers/physics_server.h +++ b/servers/physics_server.h @@ -744,6 +744,8 @@ public: virtual void flush_queries() = 0; virtual void finish() = 0; + virtual bool is_flushing_queries() const = 0; + enum ProcessInfo { INFO_ACTIVE_OBJECTS, |