diff options
35 files changed, 330 insertions, 109 deletions
diff --git a/core/io/packet_peer.cpp b/core/io/packet_peer.cpp index ae0520df6e..9e53d773ba 100644 --- a/core/io/packet_peer.cpp +++ b/core/io/packet_peer.cpp @@ -37,7 +37,8 @@ PacketPeer::PacketPeer() : last_get_error(OK), - allow_object_decoding(false) { + allow_object_decoding(false), + encode_buffer_max_size(8 * 1024 * 1024) { } void PacketPeer::set_allow_object_decoding(bool p_enable) { @@ -50,6 +51,19 @@ bool PacketPeer::is_object_decoding_allowed() const { return allow_object_decoding; } +void PacketPeer::set_encode_buffer_max_size(int p_max_size) { + + ERR_FAIL_COND_MSG(p_max_size < 1024, "Max encode buffer must be at least 1024 bytes"); + ERR_FAIL_COND_MSG(p_max_size > 256 * 1024 * 1024, "Max encode buffer cannot exceed 256 MiB"); + encode_buffer_max_size = next_power_of_2(p_max_size); + encode_buffer.resize(0); +} + +int PacketPeer::get_encode_buffer_max_size() const { + + return encode_buffer_max_size; +} + Error PacketPeer::get_packet_buffer(PoolVector<uint8_t> &r_buffer) { const uint8_t *buffer; @@ -100,12 +114,18 @@ Error PacketPeer::put_var(const Variant &p_packet, bool p_full_objects) { if (len == 0) return OK; - uint8_t *buf = (uint8_t *)alloca(len); - ERR_FAIL_COND_V_MSG(!buf, ERR_OUT_OF_MEMORY, "Out of memory."); - err = encode_variant(p_packet, buf, len, p_full_objects || allow_object_decoding); + ERR_FAIL_COND_V_MSG(len > encode_buffer_max_size, ERR_OUT_OF_MEMORY, "Failed to encode variant, encode size is bigger then encode_buffer_max_size. Consider raising it via 'set_encode_buffer_max_size'."); + + if (unlikely(encode_buffer.size() < len)) { + encode_buffer.resize(0); // Avoid realloc + encode_buffer.resize(next_power_of_2(len)); + } + + PoolVector<uint8_t>::Write w = encode_buffer.write(); + err = encode_variant(p_packet, w.ptr(), len, p_full_objects || allow_object_decoding); ERR_FAIL_COND_V_MSG(err != OK, err, "Error when trying to encode Variant."); - return put_packet(buf, len); + return put_packet(w.ptr(), len); } Variant PacketPeer::_bnd_get_var(bool p_allow_objects) { @@ -142,7 +162,10 @@ void PacketPeer::_bind_methods() { ClassDB::bind_method(D_METHOD("set_allow_object_decoding", "enable"), &PacketPeer::set_allow_object_decoding); ClassDB::bind_method(D_METHOD("is_object_decoding_allowed"), &PacketPeer::is_object_decoding_allowed); + ClassDB::bind_method(D_METHOD("get_encode_buffer_max_size"), &PacketPeer::get_encode_buffer_max_size); + ClassDB::bind_method(D_METHOD("set_encode_buffer_max_size", "max_size"), &PacketPeer::set_encode_buffer_max_size); + ADD_PROPERTY(PropertyInfo(Variant::INT, "encode_buffer_max_size"), "set_encode_buffer_max_size", "get_encode_buffer_max_size"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "allow_object_decoding"), "set_allow_object_decoding", "is_object_decoding_allowed"); }; diff --git a/core/io/packet_peer.h b/core/io/packet_peer.h index f1870e8ef1..2b13f2e952 100644 --- a/core/io/packet_peer.h +++ b/core/io/packet_peer.h @@ -51,6 +51,9 @@ class PacketPeer : public Reference { bool allow_object_decoding; + int encode_buffer_max_size; + PoolVector<uint8_t> encode_buffer; + public: virtual int get_available_packet_count() const = 0; virtual Error get_packet(const uint8_t **r_buffer, int &r_buffer_size) = 0; ///< buffer is GONE after next get_packet @@ -69,6 +72,9 @@ public: void set_allow_object_decoding(bool p_enable); bool is_object_decoding_allowed() const; + void set_encode_buffer_max_size(int p_max_size); + int get_encode_buffer_max_size() const; + PacketPeer(); ~PacketPeer() {} }; diff --git a/doc/classes/CPUParticles2D.xml b/doc/classes/CPUParticles2D.xml index dac00051a9..0a376278f8 100644 --- a/doc/classes/CPUParticles2D.xml +++ b/doc/classes/CPUParticles2D.xml @@ -361,7 +361,7 @@ Particles will be emitted at a position chosen randomly among [member emission_points]. Particle velocity and rotation will be set based on [member emission_normals]. Particle color will be modulated by [member emission_colors]. </constant> <constant name="EMISSION_SHAPE_MAX" value="5" enum="EmissionShape"> - Represents the size of the [enum EmissionShape] enum. + Represents the size of the [enum EmissionShape] enum. </constant> </constants> </class> diff --git a/doc/classes/ConfigFile.xml b/doc/classes/ConfigFile.xml index d99f90d09a..68966b6f59 100644 --- a/doc/classes/ConfigFile.xml +++ b/doc/classes/ConfigFile.xml @@ -26,6 +26,7 @@ config.save("user://settings.cfg") [/codeblock] Keep in mind that section and property names can't contain spaces. Anything after a space will be ignored on save and on load. + ConfigFiles can also contain manually written comment lines starting with a semicolon ([code];[/code]). Those lines will be ignored when parsing the file. Note that comments will be lost when saving the ConfigFile. This can still be useful for dedicated server configuration files, which are typically never overwritten without explicit user action. </description> <tutorials> </tutorials> diff --git a/doc/classes/GraphNode.xml b/doc/classes/GraphNode.xml index 8fda9c20a5..1729d20e54 100644 --- a/doc/classes/GraphNode.xml +++ b/doc/classes/GraphNode.xml @@ -1,11 +1,12 @@ <?xml version="1.0" encoding="UTF-8" ?> <class name="GraphNode" inherits="Container" category="Core" version="3.2"> <brief_description> - A GraphNode is a container with several input and output slots allowing connections between GraphNodes. Slots can have different, incompatible types. + A GraphNode is a container with potentially several input and output slots allowing connections between GraphNodes. Slots can have different, incompatible types. </brief_description> <description> - A GraphNode is a container defined by a title. It can have one or more input and output slots, which can be enabled (shown) or disabled (not shown) and have different (incompatible) types. Colors can also be assigned to slots. A tuple of input and output slots is defined for each GUI element included in the GraphNode. Input and output connections are left and right slots, but only enabled slots are counted as connections. - To add a slot to GraphNode, add any [Control]-derived child node to it. + A GraphNode is a container. Each GraphNode can have several input and output slots, sometimes refered to as ports, allowing connections between GraphNodes. To add a slot to GraphNode, add any [Control]-derived child node to it. + After adding at least one child to GraphNode new sections will be automatically created in the Inspector called 'Slot'. When 'Slot' is expanded you will see list with index number for each slot. You can click on each of them to expand further. + In the Inspector you can enable (show) or disable (hide) slots. By default all slots are disabled so you may not see any slots on your GraphNode initially. You can assign a type to each slot. Only slots of the same type will be able to connect to each other. You can also assign colors to slots. A tuple of input and output slots is defined for each GUI element included in the GraphNode. Input connections are on the left and output connections are on the right side of GraphNode. Only enabled slots are counted as connections. </description> <tutorials> </tutorials> @@ -192,14 +193,14 @@ </member> <member name="resizable" type="bool" setter="set_resizable" getter="is_resizable" default="false"> If [code]true[/code], the user can resize the GraphNode. - [b]Note:[/b] Dragging the handle will only trigger the [signal resize_request] signal, the GraphNode needs to be resized manually. + [b]Note:[/b] Dragging the handle will only emit the [signal resize_request] signal, the GraphNode needs to be resized manually. </member> <member name="selected" type="bool" setter="set_selected" getter="is_selected" default="false"> If [code]true[/code], the GraphNode is selected. </member> <member name="show_close" type="bool" setter="set_show_close_button" getter="is_close_button_visible" default="false"> If [code]true[/code], the close button will be visible. - [b]Note:[/b] Pressing it will only trigger the [signal close_request] signal, the GraphNode needs to be removed manually. + [b]Note:[/b] Pressing it will only emit the [signal close_request] signal, the GraphNode needs to be removed manually. </member> <member name="title" type="String" setter="set_title" getter="get_title" default=""""> The text displayed in the GraphNode's title bar. diff --git a/doc/classes/KinematicCollision.xml b/doc/classes/KinematicCollision.xml index 46e4176e9f..b193847e92 100644 --- a/doc/classes/KinematicCollision.xml +++ b/doc/classes/KinematicCollision.xml @@ -37,7 +37,7 @@ The colliding body's shape's normal at the point of collision. </member> <member name="position" type="Vector3" setter="" getter="get_position" default="Vector3( 0, 0, 0 )"> - The point of collision. + The point of collision, in global coordinates. </member> <member name="remainder" type="Vector3" setter="" getter="get_remainder" default="Vector3( 0, 0, 0 )"> The moving object's remaining movement vector. diff --git a/doc/classes/KinematicCollision2D.xml b/doc/classes/KinematicCollision2D.xml index 4c9337f82d..8860c05d40 100644 --- a/doc/classes/KinematicCollision2D.xml +++ b/doc/classes/KinematicCollision2D.xml @@ -37,7 +37,7 @@ The colliding body's shape's normal at the point of collision. </member> <member name="position" type="Vector2" setter="" getter="get_position" default="Vector2( 0, 0 )"> - The point of collision. + The point of collision, in global coordinates. </member> <member name="remainder" type="Vector2" setter="" getter="get_remainder" default="Vector2( 0, 0 )"> The moving object's remaining movement vector. diff --git a/doc/classes/Timer.xml b/doc/classes/Timer.xml index 3e4b68d91d..9e8eb3314d 100644 --- a/doc/classes/Timer.xml +++ b/doc/classes/Timer.xml @@ -37,6 +37,7 @@ <members> <member name="autostart" type="bool" setter="set_autostart" getter="has_autostart" default="false"> If [code]true[/code], the timer will automatically start when entering the scene tree. + [b]Note:[/b] This property is automatically set to [code]false[/code] after the timer enters the scene tree and starts. </member> <member name="one_shot" type="bool" setter="set_one_shot" getter="is_one_shot" default="false"> If [code]true[/code], the timer will stop when reaching 0. If [code]false[/code], it will restart. diff --git a/doc/classes/VideoPlayer.xml b/doc/classes/VideoPlayer.xml index 804489f7f1..3ed53aa447 100644 --- a/doc/classes/VideoPlayer.xml +++ b/doc/classes/VideoPlayer.xml @@ -13,7 +13,7 @@ <return type="String"> </return> <description> - Returns the video stream's name. + Returns the video stream's name, or [code]"<No Stream>"[/code] if no video stream is assigned. </description> </method> <method name="get_video_texture" qualifiers="const"> @@ -28,20 +28,22 @@ </return> <description> Returns [code]true[/code] if the video is playing. + [b]Note:[/b] The video is still considered playing if paused during playback. </description> </method> <method name="play"> <return type="void"> </return> <description> - Starts the video playback. + Starts the video playback from the beginning. If the video is paused, this will not unpause the video. </description> </method> <method name="stop"> <return type="void"> </return> <description> - Stops the video playback. + Stops the video playback and sets the stream position to 0. + [b]Note:[/b] Although the stream position will be set to 0, the first frame of the video stream won't become the current frame. </description> </method> </methods> diff --git a/drivers/alsamidi/midi_driver_alsamidi.cpp b/drivers/alsamidi/midi_driver_alsamidi.cpp index ff9d866aee..10581a460c 100644 --- a/drivers/alsamidi/midi_driver_alsamidi.cpp +++ b/drivers/alsamidi/midi_driver_alsamidi.cpp @@ -128,6 +128,7 @@ Error MIDIDriverALSAMidi::open() { snd_device_name_free_hint(hints); mutex = Mutex::create(); + exit_thread = false; thread = Thread::create(MIDIDriverALSAMidi::thread_func, this); return OK; diff --git a/drivers/gles3/rasterizer_storage_gles3.cpp b/drivers/gles3/rasterizer_storage_gles3.cpp index 801763609e..0a528552cc 100644 --- a/drivers/gles3/rasterizer_storage_gles3.cpp +++ b/drivers/gles3/rasterizer_storage_gles3.cpp @@ -1834,7 +1834,7 @@ void RasterizerStorageGLES3::sky_set_texture(RID p_sky, RID p_panorama, int p_ra glGenFramebuffers(1, &tmp_fb); glBindFramebuffer(GL_FRAMEBUFFER, tmp_fb); - int size = 64; + int size = 32; bool use_float = config.framebuffer_half_float_supported; @@ -1854,6 +1854,24 @@ void RasterizerStorageGLES3::sky_set_texture(RID p_sky, RID p_panorama, int p_ra glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, sky->irradiance, 0); + GLuint tmp_fb2; + GLuint tmp_tex; + { + //generate another one for rendering, as can't read and write from a single texarray it seems + glGenFramebuffers(1, &tmp_fb2); + glBindFramebuffer(GL_FRAMEBUFFER, tmp_fb2); + glGenTextures(1, &tmp_tex); + glBindTexture(GL_TEXTURE_2D, tmp_tex); + glTexImage2D(GL_TEXTURE_2D, 0, internal_format, p_radiance_size, 2.0 * p_radiance_size, 0, format, type, NULL); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tmp_tex, 0); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR_MIPMAP_LINEAR); +#ifdef DEBUG_ENABLED + GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); + ERR_FAIL_COND(status != GL_FRAMEBUFFER_COMPLETE); +#endif + } + shaders.cubemap_filter.set_conditional(CubemapFilterShaderGLES3::USE_DUAL_PARABOLOID, true); shaders.cubemap_filter.set_conditional(CubemapFilterShaderGLES3::USE_SOURCE_PANORAMA, true); shaders.cubemap_filter.set_conditional(CubemapFilterShaderGLES3::COMPUTE_IRRADIANCE, true); @@ -1863,8 +1881,10 @@ void RasterizerStorageGLES3::sky_set_texture(RID p_sky, RID p_panorama, int p_ra // level that corresponds to a panorama of 1024x512 shaders.cubemap_filter.set_uniform(CubemapFilterShaderGLES3::SOURCE_MIP_LEVEL, MAX(Math::floor(Math::log(float(texture->width)) / Math::log(2.0f)) - 10.0f, 0.0f)); + // Compute Irradiance for a large texture, specified by radiance size and then pull out a low mipmap corresponding to 32x32 + int vp_size = p_radiance_size; for (int i = 0; i < 2; i++) { - glViewport(0, i * size, size, size); + glViewport(0, i * vp_size, vp_size, vp_size); glBindVertexArray(resources.quadie_array); shaders.cubemap_filter.set_uniform(CubemapFilterShaderGLES3::Z_FLIP, i > 0); @@ -1872,13 +1892,32 @@ void RasterizerStorageGLES3::sky_set_texture(RID p_sky, RID p_panorama, int p_ra glDrawArrays(GL_TRIANGLE_FAN, 0, 4); glBindVertexArray(0); } + glGenerateMipmap(GL_TEXTURE_2D); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, tmp_tex); + glBindFramebuffer(GL_FRAMEBUFFER, tmp_fb); shaders.cubemap_filter.set_conditional(CubemapFilterShaderGLES3::USE_DUAL_PARABOLOID, false); shaders.cubemap_filter.set_conditional(CubemapFilterShaderGLES3::USE_SOURCE_PANORAMA, false); shaders.cubemap_filter.set_conditional(CubemapFilterShaderGLES3::COMPUTE_IRRADIANCE, false); + shaders.copy.set_conditional(CopyShaderGLES3::USE_LOD, true); + shaders.copy.bind(); + shaders.copy.set_uniform(CopyShaderGLES3::MIP_LEVEL, MAX(Math::floor(Math::log(float(p_radiance_size)) / Math::log(2.0f)) - 5.0f, 0.0f)); // Mip level that corresponds to a 32x32 texture + + glViewport(0, 0, size, size * 2.0); + glBindVertexArray(resources.quadie_array); + glDrawArrays(GL_TRIANGLE_FAN, 0, 4); + glBindVertexArray(0); + + shaders.copy.set_conditional(CopyShaderGLES3::USE_LOD, false); + glBindFramebuffer(GL_FRAMEBUFFER, RasterizerStorageGLES3::system_fbo); + glActiveTexture(GL_TEXTURE0); + glBindTexture(texture->target, texture->tex_id); glDeleteFramebuffers(1, &tmp_fb); + glDeleteFramebuffers(1, &tmp_fb2); + glDeleteTextures(1, &tmp_tex); } // Now compute radiance @@ -1955,7 +1994,6 @@ void RasterizerStorageGLES3::sky_set_texture(RID p_sky, RID p_panorama, int p_ra glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D_ARRAY, sky->radiance); shaders.cubemap_filter.set_uniform(CubemapFilterShaderGLES3::SOURCE_ARRAY_INDEX, j - 1); //read from previous to ensure better blur - shaders.cubemap_filter.set_uniform(CubemapFilterShaderGLES3::SOURCE_RESOLUTION, float(size / 2)); } for (int i = 0; i < 2; i++) { @@ -2085,7 +2123,6 @@ void RasterizerStorageGLES3::sky_set_texture(RID p_sky, RID p_panorama, int p_ra glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, sky->radiance); shaders.cubemap_filter.set_uniform(CubemapFilterShaderGLES3::SOURCE_MIP_LEVEL, float(lod - 1)); //read from previous to ensure better blur - shaders.cubemap_filter.set_uniform(CubemapFilterShaderGLES3::SOURCE_RESOLUTION, float(size)); } for (int i = 0; i < 2; i++) { diff --git a/drivers/gles3/shaders/copy.glsl b/drivers/gles3/shaders/copy.glsl index 1952e201aa..a3cdb3a543 100644 --- a/drivers/gles3/shaders/copy.glsl +++ b/drivers/gles3/shaders/copy.glsl @@ -104,6 +104,10 @@ uniform sampler2D CbCr; //texunit:1 /* clang-format on */ +#ifdef USE_LOD +uniform float mip_level; +#endif + #if defined(USE_TEXTURE3D) || defined(USE_TEXTURE2DARRAY) uniform float layer; #endif @@ -190,8 +194,12 @@ void main() { color.gb = textureLod(CbCr, uv_interp, 0.0).rg - vec2(0.5, 0.5); color.a = 1.0; #else +#ifdef USE_LOD + vec4 color = textureLod(source, uv_interp, mip_level); +#else vec4 color = textureLod(source, uv_interp, 0.0); #endif +#endif #ifdef LINEAR_TO_SRGB // regular Linear -> SRGB conversion diff --git a/drivers/gles3/shaders/cubemap_filter.glsl b/drivers/gles3/shaders/cubemap_filter.glsl index 3f3313c3a7..e1872eb433 100644 --- a/drivers/gles3/shaders/cubemap_filter.glsl +++ b/drivers/gles3/shaders/cubemap_filter.glsl @@ -23,6 +23,7 @@ precision highp int; #ifdef USE_SOURCE_PANORAMA uniform sampler2D source_panorama; //texunit:0 +uniform float source_resolution; #endif #ifdef USE_SOURCE_DUAL_PARABOLOID_ARRAY @@ -44,7 +45,6 @@ uniform samplerCube source_cube; //texunit:0 uniform int face_id; uniform float roughness; -uniform float source_resolution; in highp vec2 uv_interp; @@ -183,12 +183,12 @@ vec2 Hammersley(uint i, uint N) { #ifdef LOW_QUALITY #define SAMPLE_COUNT 64u -#define SAMPLE_DELTA 0.05 +#define SAMPLE_DELTA 0.1 #else #define SAMPLE_COUNT 512u -#define SAMPLE_DELTA 0.01 +#define SAMPLE_DELTA 0.03 #endif @@ -332,6 +332,7 @@ void main() { if (ndotl > 0.0) { +#ifdef USE_SOURCE_PANORAMA float D = DistributionGGX(N, H, roughness); float ndoth = max(dot(N, H), 0.0); float hdotv = max(dot(H, V), 0.0); @@ -342,17 +343,14 @@ void main() { float mipLevel = roughness == 0.0 ? 0.0 : 0.5 * log2(saSample / saTexel); -#ifdef USE_SOURCE_PANORAMA sum.rgb += texturePanorama(L, source_panorama, mipLevel).rgb * ndotl; #endif #ifdef USE_SOURCE_DUAL_PARABOLOID_ARRAY - sum.rgb += textureDualParaboloidArray(L).rgb * ndotl; #endif #ifdef USE_SOURCE_DUAL_PARABOLOID - sum.rgb += textureDualParaboloid(L).rgb * ndotl; #endif diff --git a/editor/editor_audio_buses.cpp b/editor/editor_audio_buses.cpp index 365238222f..3f773c646a 100644 --- a/editor/editor_audio_buses.cpp +++ b/editor/editor_audio_buses.cpp @@ -1249,7 +1249,7 @@ void EditorAudioBuses::_load_default_layout() { String layout_path = ProjectSettings::get_singleton()->get("audio/default_bus_layout"); - Ref<AudioBusLayout> state = ResourceLoader::load(layout_path); + Ref<AudioBusLayout> state = ResourceLoader::load(layout_path, "", true); if (state.is_null()) { EditorNode::get_singleton()->show_warning(vformat(TTR("There is no '%s' file."), layout_path)); return; @@ -1266,7 +1266,7 @@ void EditorAudioBuses::_load_default_layout() { void EditorAudioBuses::_file_dialog_callback(const String &p_string) { if (file_dialog->get_mode() == EditorFileDialog::MODE_OPEN_FILE) { - Ref<AudioBusLayout> state = ResourceLoader::load(p_string); + Ref<AudioBusLayout> state = ResourceLoader::load(p_string, "", true); if (state.is_null()) { EditorNode::get_singleton()->show_warning(TTR("Invalid file, not an audio bus layout.")); return; @@ -1404,7 +1404,7 @@ void EditorAudioBuses::open_layout(const String &p_path) { EditorNode::get_singleton()->make_bottom_panel_item_visible(this); - Ref<AudioBusLayout> state = ResourceLoader::load(p_path); + Ref<AudioBusLayout> state = ResourceLoader::load(p_path, "", true); if (state.is_null()) { EditorNode::get_singleton()->show_warning(TTR("Invalid file, not an audio bus layout.")); return; diff --git a/editor/editor_themes.cpp b/editor/editor_themes.cpp index 2cacc767c8..621f531687 100644 --- a/editor/editor_themes.cpp +++ b/editor/editor_themes.cpp @@ -1218,7 +1218,7 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { Ref<Theme> create_custom_theme(const Ref<Theme> p_theme) { Ref<Theme> theme; - String custom_theme = EditorSettings::get_singleton()->get("interface/theme/custom_theme"); + const String custom_theme = EditorSettings::get_singleton()->get("interface/theme/custom_theme"); if (custom_theme != "") { theme = ResourceLoader::load(custom_theme); } diff --git a/editor/plugins/animation_blend_tree_editor_plugin.cpp b/editor/plugins/animation_blend_tree_editor_plugin.cpp index def3f4bfec..2de224c043 100644 --- a/editor/plugins/animation_blend_tree_editor_plugin.cpp +++ b/editor/plugins/animation_blend_tree_editor_plugin.cpp @@ -147,7 +147,7 @@ void AnimationNodeBlendTreeEditor::_update_graph() { node->add_child(name); node->set_slot(0, false, 0, Color(), true, 0, get_color("font_color", "Label")); name->connect("text_entered", this, "_node_renamed", varray(agnode)); - name->connect("focus_exited", this, "_node_renamed_focus_out", varray(name, agnode)); + name->connect("focus_exited", this, "_node_renamed_focus_out", varray(name, agnode), CONNECT_DEFERRED); base = 1; node->set_show_close_button(true); node->connect("close_request", this, "_delete_request", varray(E->get()), CONNECT_DEFERRED); diff --git a/editor/plugins/animation_tree_player_editor_plugin.cpp b/editor/plugins/animation_tree_player_editor_plugin.cpp index a85def5c6d..2b365feec5 100644 --- a/editor/plugins/animation_tree_player_editor_plugin.cpp +++ b/editor/plugins/animation_tree_player_editor_plugin.cpp @@ -34,6 +34,7 @@ #include "core/os/input.h" #include "core/os/keyboard.h" #include "core/project_settings.h" +#include "editor/editor_scale.h" #include "scene/gui/menu_button.h" #include "scene/gui/panel.h" #include "scene/main/viewport.h" @@ -923,17 +924,18 @@ void AnimationTreePlayerEditor::_notification(int p_what) { _draw_cos_line(source, dest, col); } + const Ref<Font> f = get_font("font", "Label"); + const Point2 status_offset = Point2(5, 25) * EDSCALE + Point2(0, f->get_ascent()); + switch (anim_tree->get_last_error()) { case AnimationTreePlayer::CONNECT_OK: { - Ref<Font> f = get_font("font", "Label"); - f->draw(get_canvas_item(), Point2(5, 25 + f->get_ascent()), TTR("Animation tree is valid."), Color(0, 1, 0.6, 0.8)); + f->draw(get_canvas_item(), status_offset, TTR("Animation tree is valid."), Color(0, 1, 0.6, 0.8)); } break; default: { - Ref<Font> f = get_font("font", "Label"); - f->draw(get_canvas_item(), Point2(5, 25 + f->get_ascent()), TTR("Animation tree is invalid."), Color(1, 0.6, 0.0, 0.8)); + f->draw(get_canvas_item(), status_offset, TTR("Animation tree is invalid."), Color(1, 0.6, 0.0, 0.8)); } break; } @@ -1300,7 +1302,7 @@ AnimationTreePlayerEditor::AnimationTreePlayerEditor() { p->connect("id_pressed", this, "_add_menu_item"); play_button = memnew(Button); - play_button->set_position(Point2(25, 0)); + play_button->set_position(Point2(25, 0) * EDSCALE); play_button->set_size(Point2(25, 15)); add_child(play_button); play_button->set_toggle_mode(true); @@ -1439,7 +1441,7 @@ AnimationTreePlayerEditorPlugin::AnimationTreePlayerEditorPlugin(EditorNode *p_n editor = p_node; anim_tree_editor = memnew(AnimationTreePlayerEditor); - anim_tree_editor->set_custom_minimum_size(Size2(0, 300)); + anim_tree_editor->set_custom_minimum_size(Size2(0, 300) * EDSCALE); button = editor->add_bottom_panel_item(TTR("AnimationTree"), anim_tree_editor); button->hide(); diff --git a/editor/plugins/asset_library_editor_plugin.cpp b/editor/plugins/asset_library_editor_plugin.cpp index bdef108ef2..c1f62e8342 100644 --- a/editor/plugins/asset_library_editor_plugin.cpp +++ b/editor/plugins/asset_library_editor_plugin.cpp @@ -435,7 +435,10 @@ void EditorAssetLibraryItemDownload::_notification(int p_what) { String::humanize_size(download->get_body_size()))); } else { // Total file size is unknown, so it cannot be displayed. - status->set_text(TTR("Downloading...")); + progress->set_modulate(Color(0, 0, 0, 0)); + status->set_text(vformat( + TTR("Downloading...") + " (%s)", + String::humanize_size(download->get_downloaded_bytes()))); } } diff --git a/editor/plugins/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp index 437a6722d0..e1fafde6b9 100644 --- a/editor/plugins/canvas_item_editor_plugin.cpp +++ b/editor/plugins/canvas_item_editor_plugin.cpp @@ -4236,7 +4236,7 @@ void CanvasItemEditor::_button_zoom_minus() { } void CanvasItemEditor::_button_zoom_reset() { - _zoom_on_position(1.0 * EDSCALE, viewport_scrollable->get_size() / 2.0); + _zoom_on_position(1.0 * MAX(1, EDSCALE), viewport_scrollable->get_size() / 2.0); } void CanvasItemEditor::_button_zoom_plus() { @@ -5038,7 +5038,7 @@ void CanvasItemEditor::set_state(const Dictionary &p_state) { if (state.has("zoom")) { // Compensate the editor scale, so that the editor scale can be changed // and the zoom level will still be the same (relative to the editor scale). - zoom = float(p_state["zoom"]) * EDSCALE; + zoom = float(p_state["zoom"]) * MAX(1, EDSCALE); _update_zoom_label(); } diff --git a/editor/project_manager.cpp b/editor/project_manager.cpp index ca3431d3ec..9bbb9bd38c 100644 --- a/editor/project_manager.cpp +++ b/editor/project_manager.cpp @@ -2419,12 +2419,11 @@ ProjectManager::ProjectManager() { FileDialog::set_default_show_hidden_files(EditorSettings::get_singleton()->get("filesystem/file_dialog/show_hidden_files")); set_anchors_and_margins_preset(Control::PRESET_WIDE); - set_theme(create_editor_theme()); + set_theme(create_custom_theme()); gui_base = memnew(Control); add_child(gui_base); gui_base->set_anchors_and_margins_preset(Control::PRESET_WIDE); - gui_base->set_theme(create_custom_theme()); Panel *panel = memnew(Panel); gui_base->add_child(panel); diff --git a/editor/rename_dialog.cpp b/editor/rename_dialog.cpp index ce37b9e7f6..32fcdab4c6 100644 --- a/editor/rename_dialog.cpp +++ b/editor/rename_dialog.cpp @@ -109,14 +109,8 @@ RenameDialog::RenameDialog(SceneTreeEditor *p_scene_tree_editor, UndoRedo *p_und const int feature_min_height = 160 * EDSCALE; - Ref<Theme> collapse_theme = create_editor_theme(); - collapse_theme->set_icon("checked", "CheckBox", collapse_theme->get_icon("GuiTreeArrowDown", "EditorIcons")); - collapse_theme->set_icon("unchecked", "CheckBox", collapse_theme->get_icon("GuiTreeArrowRight", "EditorIcons")); - - CheckBox *chk_collapse_features = memnew(CheckBox); + CheckButton *chk_collapse_features = memnew(CheckButton); chk_collapse_features->set_text(TTR("Advanced Options")); - chk_collapse_features->set_theme(collapse_theme); - chk_collapse_features->set_focus_mode(FOCUS_NONE); vbc->add_child(chk_collapse_features); tabc_features = memnew(TabContainer); diff --git a/modules/mono/class_db_api_json.cpp b/modules/mono/class_db_api_json.cpp index c1d6f4dccf..b04e53bd81 100644 --- a/modules/mono/class_db_api_json.cpp +++ b/modules/mono/class_db_api_json.cpp @@ -71,6 +71,13 @@ void class_db_api_to_json(const String &p_output_file, ClassDB::APIType p_api) { while ((k = t->method_map.next(k))) { + String name = k->operator String(); + + ERR_CONTINUE(name.empty()); + + if (name[0] == '_') + continue; // Ignore non-virtual methods that start with an underscore + snames.push_back(*k); } diff --git a/modules/mono/csharp_script.cpp b/modules/mono/csharp_script.cpp index 0f6b8357b8..210267e681 100644 --- a/modules/mono/csharp_script.cpp +++ b/modules/mono/csharp_script.cpp @@ -106,7 +106,7 @@ Error CSharpLanguage::execute_file(const String &p_path) { void CSharpLanguage::init() { #ifdef DEBUG_METHODS_ENABLED - if (OS::get_singleton()->get_cmdline_args().find("--class_db_to_json")) { + if (OS::get_singleton()->get_cmdline_args().find("--class-db-json")) { class_db_api_to_json("user://class_db_api.json", ClassDB::API_CORE); #ifdef TOOLS_ENABLED class_db_api_to_json("user://class_db_api_editor.json", ClassDB::API_EDITOR); diff --git a/modules/recast/register_types.cpp b/modules/recast/register_types.cpp index a1286c58c8..ea0ab00771 100644 --- a/modules/recast/register_types.cpp +++ b/modules/recast/register_types.cpp @@ -38,17 +38,17 @@ EditorNavigationMeshGenerator *_nav_mesh_generator = NULL; void register_recast_types() { #ifdef TOOLS_ENABLED - EditorPlugins::add_by_type<NavigationMeshEditorPlugin>(); - _nav_mesh_generator = memnew(EditorNavigationMeshGenerator); - ClassDB::APIType prev_api = ClassDB::get_current_api(); ClassDB::set_current_api(ClassDB::API_EDITOR); - ClassDB::register_class<EditorNavigationMeshGenerator>(); + EditorPlugins::add_by_type<NavigationMeshEditorPlugin>(); + _nav_mesh_generator = memnew(EditorNavigationMeshGenerator); - ClassDB::set_current_api(prev_api); + ClassDB::register_class<EditorNavigationMeshGenerator>(); Engine::get_singleton()->add_singleton(Engine::Singleton("NavigationMeshGenerator", EditorNavigationMeshGenerator::get_singleton())); + + ClassDB::set_current_api(prev_api); #endif } diff --git a/modules/visual_script/visual_script_nodes.cpp b/modules/visual_script/visual_script_nodes.cpp index 0a9f228b0a..86c1080182 100644 --- a/modules/visual_script/visual_script_nodes.cpp +++ b/modules/visual_script/visual_script_nodes.cpp @@ -2377,10 +2377,7 @@ VisualScriptEngineSingleton::TypeGuess VisualScriptEngineSingleton::guess_output return tg; } -void VisualScriptEngineSingleton::_bind_methods() { - - ClassDB::bind_method(D_METHOD("set_singleton", "name"), &VisualScriptEngineSingleton::set_singleton); - ClassDB::bind_method(D_METHOD("get_singleton"), &VisualScriptEngineSingleton::get_singleton); +void VisualScriptEngineSingleton::_validate_property(PropertyInfo &property) const { String cc; @@ -2397,7 +2394,16 @@ void VisualScriptEngineSingleton::_bind_methods() { cc += E->get().name; } - ADD_PROPERTY(PropertyInfo(Variant::STRING, "constant", PROPERTY_HINT_ENUM, cc), "set_singleton", "get_singleton"); + property.hint = PROPERTY_HINT_ENUM; + property.hint_string = cc; +} + +void VisualScriptEngineSingleton::_bind_methods() { + + ClassDB::bind_method(D_METHOD("set_singleton", "name"), &VisualScriptEngineSingleton::set_singleton); + ClassDB::bind_method(D_METHOD("get_singleton"), &VisualScriptEngineSingleton::get_singleton); + + ADD_PROPERTY(PropertyInfo(Variant::STRING, "constant"), "set_singleton", "get_singleton"); } VisualScriptEngineSingleton::VisualScriptEngineSingleton() { diff --git a/modules/visual_script/visual_script_nodes.h b/modules/visual_script/visual_script_nodes.h index fe44af277f..0df5071491 100644 --- a/modules/visual_script/visual_script_nodes.h +++ b/modules/visual_script/visual_script_nodes.h @@ -614,6 +614,9 @@ class VisualScriptEngineSingleton : public VisualScriptNode { String singleton; +protected: + void _validate_property(PropertyInfo &property) const; + static void _bind_methods(); public: diff --git a/platform/android/api/api.cpp b/platform/android/api/api.cpp new file mode 100644 index 0000000000..7a8ff93414 --- /dev/null +++ b/platform/android/api/api.cpp @@ -0,0 +1,56 @@ +#include "api.h" + +#include "core/engine.h" +#include "java_class_wrapper.h" + +#if !defined(ANDROID_ENABLED) +static JavaClassWrapper *java_class_wrapper = NULL; +#endif + +void register_android_api() { + +#if !defined(ANDROID_ENABLED) + java_class_wrapper = memnew(JavaClassWrapper); // Dummy +#endif + + ClassDB::register_class<JavaClass>(); + ClassDB::register_class<JavaClassWrapper>(); + Engine::get_singleton()->add_singleton(Engine::Singleton("JavaClassWrapper", JavaClassWrapper::get_singleton())); +} + +void unregister_android_api() { + +#if !defined(ANDROID_ENABLED) + memdelete(java_class_wrapper); +#endif +} + +void JavaClassWrapper::_bind_methods() { + + ClassDB::bind_method(D_METHOD("wrap", "name"), &JavaClassWrapper::wrap); +} + +#if !defined(ANDROID_ENABLED) + +Variant JavaClass::call(const StringName &, const Variant **, int, Variant::CallError &) { + return Variant(); +} + +JavaClass::JavaClass() { +} + +Variant JavaObject::call(const StringName &, const Variant **, int, Variant::CallError &) { + return Variant(); +} + +JavaClassWrapper *JavaClassWrapper::singleton = NULL; + +Ref<JavaClass> JavaClassWrapper::wrap(const String &) { + return Ref<JavaClass>(); +} + +JavaClassWrapper::JavaClassWrapper() { + singleton = this; +} + +#endif diff --git a/platform/android/api/api.h b/platform/android/api/api.h new file mode 100644 index 0000000000..c7296d92a7 --- /dev/null +++ b/platform/android/api/api.h @@ -0,0 +1,32 @@ +/*************************************************************************/ +/* api.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +void register_android_api(); +void unregister_android_api(); diff --git a/platform/android/java_class_wrapper.h b/platform/android/api/java_class_wrapper.h index 8075b297b0..6c06d57ac1 100644 --- a/platform/android/java_class_wrapper.h +++ b/platform/android/api/java_class_wrapper.h @@ -32,16 +32,22 @@ #define JAVA_CLASS_WRAPPER_H #include "core/reference.h" + +#ifdef ANDROID_ENABLED #include <android/log.h> #include <jni.h> +#endif +#ifdef ANDROID_ENABLED class JavaObject; +#endif class JavaClass : public Reference { GDCLASS(JavaClass, Reference); - enum ArgumentType { +#ifdef ANDROID_ENABLED + enum ArgumentType{ ARG_TYPE_VOID, ARG_TYPE_BOOLEAN, @@ -159,6 +165,7 @@ class JavaClass : public Reference { friend class JavaClassWrapper; Map<StringName, List<MethodInfo> > methods; jclass _class; +#endif public: virtual Variant call(const StringName &p_method, const Variant **p_args, int p_argcount, Variant::CallError &r_error); @@ -170,22 +177,27 @@ class JavaObject : public Reference { GDCLASS(JavaObject, Reference); +#ifdef ANDROID_ENABLED Ref<JavaClass> base_class; friend class JavaClass; jobject instance; +#endif public: virtual Variant call(const StringName &p_method, const Variant **p_args, int p_argcount, Variant::CallError &r_error); +#ifdef ANDROID_ENABLED JavaObject(const Ref<JavaClass> &p_base, jobject *p_instance); ~JavaObject(); +#endif }; class JavaClassWrapper : public Object { GDCLASS(JavaClassWrapper, Object); +#ifdef ANDROID_ENABLED Map<String, Ref<JavaClass> > class_cache; friend class JavaClass; jclass activityClass; @@ -211,6 +223,7 @@ class JavaClassWrapper : public Object { jobject classLoader; bool _get_type_sig(JNIEnv *env, jobject obj, uint32_t &sig, String &strsig); +#endif static JavaClassWrapper *singleton; @@ -222,7 +235,11 @@ public: Ref<JavaClass> wrap(const String &p_class); +#ifdef ANDROID_ENABLED JavaClassWrapper(jobject p_activity = NULL); +#else + JavaClassWrapper(); +#endif }; #endif // JAVA_CLASS_WRAPPER_H diff --git a/platform/android/java_class_wrapper.cpp b/platform/android/java_class_wrapper.cpp index feebea2738..fe2fd89710 100644 --- a/platform/android/java_class_wrapper.cpp +++ b/platform/android/java_class_wrapper.cpp @@ -28,7 +28,7 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "java_class_wrapper.h" +#include "api/java_class_wrapper.h" #include "string_android.h" #include "thread_jandroid.h" @@ -546,11 +546,6 @@ JavaObject::~JavaObject() { //////////////////// -void JavaClassWrapper::_bind_methods() { - - ClassDB::bind_method(D_METHOD("wrap", "name"), &JavaClassWrapper::wrap); -} - bool JavaClassWrapper::_get_type_sig(JNIEnv *env, jobject obj, uint32_t &sig, String &strsig) { jstring name2 = (jstring)env->CallObjectMethod(obj, Class_getName); diff --git a/platform/android/java_godot_lib_jni.cpp b/platform/android/java_godot_lib_jni.cpp index 858ff89cbc..dedb2ee114 100644 --- a/platform/android/java_godot_lib_jni.cpp +++ b/platform/android/java_godot_lib_jni.cpp @@ -33,6 +33,7 @@ #include "java_godot_wrapper.h" #include "android/asset_manager_jni.h" +#include "api/java_class_wrapper.h" #include "audio_driver_jandroid.h" #include "core/engine.h" #include "core/os/keyboard.h" @@ -40,7 +41,6 @@ #include "dir_access_jandroid.h" #include "file_access_android.h" #include "file_access_jandroid.h" -#include "java_class_wrapper.h" #include "main/input_default.h" #include "main/main.h" #include "net_socket_android.h" @@ -739,7 +739,6 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_setup(JNIEnv *env, jo } java_class_wrapper = memnew(JavaClassWrapper(godot_java->get_activity())); - Engine::get_singleton()->add_singleton(Engine::Singleton("JavaClassWrapper", java_class_wrapper)); _initialize_java_modules(); } diff --git a/platform/iphone/os_iphone.cpp b/platform/iphone/os_iphone.cpp index 7b1d0e6db1..3e5ab7b886 100644 --- a/platform/iphone/os_iphone.cpp +++ b/platform/iphone/os_iphone.cpp @@ -356,14 +356,32 @@ void OSIPhone::delete_main_loop() { void OSIPhone::finalize() { - if (main_loop) // should not happen? - memdelete(main_loop); + delete_main_loop(); + + memdelete(input); + memdelete(ios); + +#ifdef GAME_CENTER_ENABLED + memdelete(game_center); +#endif + +#ifdef STOREKIT_ENABLED + memdelete(store_kit); +#endif + +#ifdef ICLOUD_ENABLED + memdelete(icloud); +#endif visual_server->finish(); memdelete(visual_server); // memdelete(rasterizer); - memdelete(input); + // Free unhandled events before close + for (int i = 0; i < MAX_EVENTS; i++) { + event_queue[i].unref(); + }; + event_count = 0; }; void OSIPhone::set_mouse_show(bool p_show){}; diff --git a/platform/javascript/os_javascript.cpp b/platform/javascript/os_javascript.cpp index 592def8011..632a7df9e8 100644 --- a/platform/javascript/os_javascript.cpp +++ b/platform/javascript/os_javascript.cpp @@ -49,6 +49,7 @@ #define DOM_BUTTON_RIGHT 2 #define DOM_BUTTON_XBUTTON1 3 #define DOM_BUTTON_XBUTTON2 4 +#define GODOT_CANVAS_SELECTOR "#canvas" // Window (canvas) @@ -70,18 +71,23 @@ static bool is_canvas_focused() { /* clang-format on */ } -static Point2 correct_canvas_position(int x, int y) { +static Point2 compute_position_in_canvas(int x, int y) { + int canvas_x = EM_ASM_INT({ + return document.getElementById('canvas').getBoundingClientRect().x; + }); + int canvas_y = EM_ASM_INT({ + return document.getElementById('canvas').getBoundingClientRect().y; + }); int canvas_width; int canvas_height; - emscripten_get_canvas_element_size(NULL, &canvas_width, &canvas_height); + emscripten_get_canvas_element_size(GODOT_CANVAS_SELECTOR, &canvas_width, &canvas_height); double element_width; double element_height; - emscripten_get_element_css_size(NULL, &element_width, &element_height); + emscripten_get_element_css_size(GODOT_CANVAS_SELECTOR, &element_width, &element_height); - x = (int)(canvas_width / element_width * x); - y = (int)(canvas_height / element_height * y); - return Point2(x, y); + return Point2((int)(canvas_width / element_width * (x - canvas_x)), + (int)(canvas_height / element_height * (y - canvas_y))); } static bool cursor_inside_canvas = true; @@ -135,14 +141,14 @@ void OS_JavaScript::set_window_size(const Size2 p_size) { emscripten_exit_soft_fullscreen(); window_maximized = false; } - emscripten_set_canvas_element_size(NULL, p_size.x, p_size.y); + emscripten_set_canvas_element_size(GODOT_CANVAS_SELECTOR, p_size.x, p_size.y); } } Size2 OS_JavaScript::get_window_size() const { int canvas[2]; - emscripten_get_canvas_element_size(NULL, canvas, canvas + 1); + emscripten_get_canvas_element_size(GODOT_CANVAS_SELECTOR, canvas, canvas + 1); return Size2(canvas[0], canvas[1]); } @@ -162,7 +168,7 @@ void OS_JavaScript::set_window_maximized(bool p_enabled) { strategy.canvasResolutionScaleMode = EMSCRIPTEN_FULLSCREEN_CANVAS_SCALE_STDDEF; strategy.filteringMode = EMSCRIPTEN_FULLSCREEN_FILTERING_DEFAULT; strategy.canvasResizedCallback = NULL; - emscripten_enter_soft_fullscreen(NULL, &strategy); + emscripten_enter_soft_fullscreen(GODOT_CANVAS_SELECTOR, &strategy); window_maximized = p_enabled; } } @@ -191,7 +197,7 @@ void OS_JavaScript::set_window_fullscreen(bool p_enabled) { strategy.canvasResolutionScaleMode = EMSCRIPTEN_FULLSCREEN_CANVAS_SCALE_STDDEF; strategy.filteringMode = EMSCRIPTEN_FULLSCREEN_FILTERING_DEFAULT; strategy.canvasResizedCallback = NULL; - EMSCRIPTEN_RESULT result = emscripten_request_fullscreen_strategy(NULL, false, &strategy); + EMSCRIPTEN_RESULT result = emscripten_request_fullscreen_strategy(GODOT_CANVAS_SELECTOR, false, &strategy); ERR_FAIL_COND_MSG(result == EMSCRIPTEN_RESULT_FAILED_NOT_DEFERRED, "Enabling fullscreen is only possible from an input callback for the HTML5 platform."); ERR_FAIL_COND_MSG(result != EMSCRIPTEN_RESULT_SUCCESS, "Enabling fullscreen is only possible from an input callback for the HTML5 platform."); // Not fullscreen yet, so prevent "windowed" canvas dimensions from @@ -298,7 +304,7 @@ EM_BOOL OS_JavaScript::mouse_button_callback(int p_event_type, const EmscriptenM Ref<InputEventMouseButton> ev; ev.instance(); ev->set_pressed(p_event_type == EMSCRIPTEN_EVENT_MOUSEDOWN); - ev->set_position(correct_canvas_position(p_event->canvasX, p_event->canvasY)); + ev->set_position(compute_position_in_canvas(p_event->clientX, p_event->clientY)); ev->set_global_position(ev->get_position()); dom2godot_mod(p_event, ev); @@ -363,7 +369,7 @@ EM_BOOL OS_JavaScript::mousemove_callback(int p_event_type, const EmscriptenMous OS_JavaScript *os = get_singleton(); int input_mask = os->input->get_mouse_button_mask(); - Point2 pos = correct_canvas_position(p_event->canvasX, p_event->canvasY); + Point2 pos = compute_position_in_canvas(p_event->clientX, p_event->clientY); // For motion outside the canvas, only read mouse movement if dragging // started inside the canvas; imitating desktop app behaviour. if (!cursor_inside_canvas && !input_mask) @@ -697,7 +703,7 @@ EM_BOOL OS_JavaScript::touch_press_callback(int p_event_type, const EmscriptenTo if (!touch.isChanged) continue; ev->set_index(touch.identifier); - ev->set_position(correct_canvas_position(touch.canvasX, touch.canvasY)); + ev->set_position(compute_position_in_canvas(touch.clientX, touch.clientY)); os->touches[i] = ev->get_position(); ev->set_pressed(p_event_type == EMSCRIPTEN_EVENT_TOUCHSTART); @@ -722,7 +728,7 @@ EM_BOOL OS_JavaScript::touchmove_callback(int p_event_type, const EmscriptenTouc if (!touch.isChanged) continue; ev->set_index(touch.identifier); - ev->set_position(correct_canvas_position(touch.canvasX, touch.canvasY)); + ev->set_position(compute_position_in_canvas(touch.clientX, touch.clientY)); Point2 &prev = os->touches[i]; ev->set_relative(ev->get_position() - prev); prev = ev->get_position(); @@ -921,7 +927,7 @@ Error OS_JavaScript::initialize(const VideoMode &p_desired, int p_video_driver, } } - EMSCRIPTEN_WEBGL_CONTEXT_HANDLE ctx = emscripten_webgl_create_context(NULL, &attributes); + EMSCRIPTEN_WEBGL_CONTEXT_HANDLE ctx = emscripten_webgl_create_context(GODOT_CANVAS_SELECTOR, &attributes); if (emscripten_webgl_make_context_current(ctx) != EMSCRIPTEN_RESULT_SUCCESS) { gl_initialization_error = true; } @@ -984,21 +990,21 @@ Error OS_JavaScript::initialize(const VideoMode &p_desired, int p_video_driver, // These callbacks from Emscripten's html5.h suffice to access most // JavaScript APIs. For APIs that are not (sufficiently) exposed, EM_ASM // is used below. - SET_EM_CALLBACK("#window", mousemove, mousemove_callback) - SET_EM_CALLBACK("#canvas", mousedown, mouse_button_callback) - SET_EM_CALLBACK("#window", mouseup, mouse_button_callback) - SET_EM_CALLBACK("#window", wheel, wheel_callback) - SET_EM_CALLBACK("#window", touchstart, touch_press_callback) - SET_EM_CALLBACK("#window", touchmove, touchmove_callback) - SET_EM_CALLBACK("#window", touchend, touch_press_callback) - SET_EM_CALLBACK("#window", touchcancel, touch_press_callback) - SET_EM_CALLBACK("#canvas", keydown, keydown_callback) - SET_EM_CALLBACK("#canvas", keypress, keypress_callback) - SET_EM_CALLBACK("#canvas", keyup, keyup_callback) - SET_EM_CALLBACK(NULL, fullscreenchange, fullscreen_change_callback) + SET_EM_CALLBACK(EMSCRIPTEN_EVENT_TARGET_WINDOW, mousemove, mousemove_callback) + SET_EM_CALLBACK(GODOT_CANVAS_SELECTOR, mousedown, mouse_button_callback) + SET_EM_CALLBACK(EMSCRIPTEN_EVENT_TARGET_WINDOW, mouseup, mouse_button_callback) + SET_EM_CALLBACK(EMSCRIPTEN_EVENT_TARGET_WINDOW, wheel, wheel_callback) + SET_EM_CALLBACK(EMSCRIPTEN_EVENT_TARGET_WINDOW, touchstart, touch_press_callback) + SET_EM_CALLBACK(EMSCRIPTEN_EVENT_TARGET_WINDOW, touchmove, touchmove_callback) + SET_EM_CALLBACK(EMSCRIPTEN_EVENT_TARGET_WINDOW, touchend, touch_press_callback) + SET_EM_CALLBACK(EMSCRIPTEN_EVENT_TARGET_WINDOW, touchcancel, touch_press_callback) + SET_EM_CALLBACK(GODOT_CANVAS_SELECTOR, keydown, keydown_callback) + SET_EM_CALLBACK(GODOT_CANVAS_SELECTOR, keypress, keypress_callback) + SET_EM_CALLBACK(GODOT_CANVAS_SELECTOR, keyup, keyup_callback) + SET_EM_CALLBACK(EMSCRIPTEN_EVENT_TARGET_DOCUMENT, fullscreenchange, fullscreen_change_callback) SET_EM_CALLBACK_NOTARGET(gamepadconnected, gamepad_change_callback) SET_EM_CALLBACK_NOTARGET(gamepaddisconnected, gamepad_change_callback) -#undef SET_EM_CALLBACK_NODATA +#undef SET_EM_CALLBACK_NOTARGET #undef SET_EM_CALLBACK #undef EM_CHECK @@ -1079,15 +1085,15 @@ bool OS_JavaScript::main_loop_iterate() { strategy.canvasResolutionScaleMode = EMSCRIPTEN_FULLSCREEN_CANVAS_SCALE_STDDEF; strategy.filteringMode = EMSCRIPTEN_FULLSCREEN_FILTERING_DEFAULT; strategy.canvasResizedCallback = NULL; - emscripten_enter_soft_fullscreen(NULL, &strategy); + emscripten_enter_soft_fullscreen(GODOT_CANVAS_SELECTOR, &strategy); } else { - emscripten_set_canvas_element_size(NULL, windowed_size.width, windowed_size.height); + emscripten_set_canvas_element_size(GODOT_CANVAS_SELECTOR, windowed_size.width, windowed_size.height); } just_exited_fullscreen = false; } int canvas[2]; - emscripten_get_canvas_element_size(NULL, canvas, canvas + 1); + emscripten_get_canvas_element_size(GODOT_CANVAS_SELECTOR, canvas, canvas + 1); video_mode.width = canvas[0]; video_mode.height = canvas[1]; if (!window_maximized && !video_mode.fullscreen && !just_exited_fullscreen && !entering_fullscreen) { diff --git a/scene/main/scene_tree.cpp b/scene/main/scene_tree.cpp index 7c43d8fb14..238d6c20cc 100644 --- a/scene/main/scene_tree.cpp +++ b/scene/main/scene_tree.cpp @@ -459,10 +459,7 @@ void SceneTree::input_event(const Ref<InputEvent> &p_event) { } void SceneTree::init() { - - //_quit=false; initialized = true; - root->_set_tree(this); MainLoop::init(); } @@ -1285,6 +1282,14 @@ void SceneTree::_change_scene(Node *p_to) { current_scene = NULL; } + // If we're quitting, abort. + if (unlikely(_quit)) { + if (p_to) { // Prevent memory leak. + memdelete(p_to); + } + return; + } + if (p_to) { current_scene = p_to; root->add_child(p_to); @@ -1292,15 +1297,14 @@ void SceneTree::_change_scene(Node *p_to) { } Error SceneTree::change_scene(const String &p_path) { - Ref<PackedScene> new_scene = ResourceLoader::load(p_path); if (new_scene.is_null()) return ERR_CANT_OPEN; return change_scene_to(new_scene); } -Error SceneTree::change_scene_to(const Ref<PackedScene> &p_scene) { +Error SceneTree::change_scene_to(const Ref<PackedScene> &p_scene) { Node *new_scene = NULL; if (p_scene.is_valid()) { new_scene = p_scene->instance(); @@ -1310,8 +1314,8 @@ Error SceneTree::change_scene_to(const Ref<PackedScene> &p_scene) { call_deferred("_change_scene", new_scene); return OK; } -Error SceneTree::reload_current_scene() { +Error SceneTree::reload_current_scene() { ERR_FAIL_COND_V(!current_scene, ERR_UNCONFIGURED); String fname = current_scene->get_filename(); return change_scene(fname); @@ -1322,6 +1326,7 @@ void SceneTree::add_current_scene(Node *p_current) { current_scene = p_current; root->add_child(p_current); } + #ifdef DEBUG_ENABLED static void _fill_array(Node *p_node, Array &array, int p_level) { diff --git a/servers/visual/shader_language.cpp b/servers/visual/shader_language.cpp index 3e0a28ac1d..121519be0f 100644 --- a/servers/visual/shader_language.cpp +++ b/servers/visual/shader_language.cpp @@ -856,6 +856,7 @@ void ShaderLanguage::clear() { completion_type = COMPLETION_NONE; completion_block = NULL; completion_function = StringName(); + completion_class = SubClassTag::TAG_GLOBAL; error_line = 0; tk_line = 1; |