diff options
30 files changed, 164 insertions, 87 deletions
diff --git a/doc/classes/ProjectSettings.xml b/doc/classes/ProjectSettings.xml index 3dbf7c75e5..1f07a13c94 100644 --- a/doc/classes/ProjectSettings.xml +++ b/doc/classes/ProjectSettings.xml @@ -640,10 +640,22 @@ If [code]true[/code], Blender 3D scene files with the [code].blend[/code] extension will be imported by converting them to glTF 2.0. This requires configuring a path to a Blender executable in the editor settings at [code]filesystem/import/blender/blender3_path[/code]. Blender 3.0 or later is required. </member> + <member name="filesystem/import/blender/enabled.android" type="bool" setter="" getter="" default="false"> + Override for [member filesystem/import/blender/enabled] on Android where Blender can't easily be accessed from Godot. + </member> + <member name="filesystem/import/blender/enabled.web" type="bool" setter="" getter="" default="false"> + Override for [member filesystem/import/blender/enabled] on the Web where Blender can't easily be accessed from Godot. + </member> <member name="filesystem/import/fbx/enabled" type="bool" setter="" getter="" default="true"> If [code]true[/code], Autodesk FBX 3D scene files with the [code].fbx[/code] extension will be imported by converting them to glTF 2.0. This requires configuring a path to a FBX2glTF executable in the editor settings at [code]filesystem/import/fbx/fbx2gltf_path[/code]. </member> + <member name="filesystem/import/fbx/enabled.android" type="bool" setter="" getter="" default="false"> + Override for [member filesystem/import/fbx/enabled] on Android where FBX2glTF can't easily be accessed from Godot. + </member> + <member name="filesystem/import/fbx/enabled.web" type="bool" setter="" getter="" default="false"> + Override for [member filesystem/import/fbx/enabled] on the Web where FBX2glTF can't easily be accessed from Godot. + </member> <member name="gui/common/default_scroll_deadzone" type="int" setter="" getter="" default="0"> Default value for [member ScrollContainer.scroll_deadzone], which will be used for all [ScrollContainer]s unless overridden. </member> diff --git a/doc/classes/Tween.xml b/doc/classes/Tween.xml index c7fc78c1d3..5186972477 100644 --- a/doc/classes/Tween.xml +++ b/doc/classes/Tween.xml @@ -36,9 +36,18 @@ tween.tween_property(sprite, "position", Vector2(0, 0), 1) [/codeblock] In the example above, all children of a node are moved one after another to position (0, 0). + You should avoid using more than one [Tween] per object's property. If two or more tweens animate one property at the same time, the last one created will take priority and assign the final value. If you want to interrupt and restart an animation, consider assigning the [Tween] to a variable: + [codeblock] + var tween + func animate(): + if tween: + tween.kill() # Abort the previous animation. + tween = create_tween() + [/codeblock] Some [Tweener]s use transitions and eases. The first accepts a [enum TransitionType] constant, and refers to the way the timing of the animation is handled (see [url=https://easings.net/]easings.net[/url] for some examples). The second accepts an [enum EaseType] constant, and controls where the [code]trans_type[/code] is applied to the interpolation (in the beginning, the end, or both). If you don't know which transition and easing to pick, you can try different [enum TransitionType] constants with [constant EASE_IN_OUT], and use the one that looks best. [url=https://raw.githubusercontent.com/godotengine/godot-docs/master/img/tween_cheatsheet.png]Tween easing and transition types cheatsheet[/url] [b]Note:[/b] All [Tween]s will automatically start by default. To prevent a [Tween] from autostarting, you can call [method stop] immediately after it is created. + [b]Note:[/b] [Tween]s are processing after all of nodes in the current frame, i.e. after [method Node._process] or [method Node._physics_process] (depending on [enum TweenProcessMode]). </description> <tutorials> </tutorials> diff --git a/doc/tools/make_rst.py b/doc/tools/make_rst.py index cd7de085d8..a8569413ec 100755 --- a/doc/tools/make_rst.py +++ b/doc/tools/make_rst.py @@ -1480,6 +1480,8 @@ def format_text_block( ) tag_text = f"``{link_target}``" + escape_pre = True + escape_post = True # Formatting directives. diff --git a/drivers/gles3/rasterizer_gles3.cpp b/drivers/gles3/rasterizer_gles3.cpp index cc96294ca5..3575837794 100644 --- a/drivers/gles3/rasterizer_gles3.cpp +++ b/drivers/gles3/rasterizer_gles3.cpp @@ -280,11 +280,6 @@ void RasterizerGLES3::_blit_render_target_to_screen(RID p_render_target, Display GLES3::RenderTarget *rt = texture_storage->get_render_target(p_render_target); ERR_FAIL_COND(!rt); - // TODO: do we need a keep 3d linear option? - - // Make sure we are drawing to the right context. - DisplayServer::get_singleton()->gl_window_make_current(p_screen); - if (rt->external.fbo != 0) { glBindFramebuffer(GL_READ_FRAMEBUFFER, rt->external.fbo); } else { @@ -298,9 +293,6 @@ void RasterizerGLES3::_blit_render_target_to_screen(RID p_render_target, Display // is this p_screen useless in a multi window environment? void RasterizerGLES3::blit_render_targets_to_screen(DisplayServer::WindowID p_screen, const BlitToScreen *p_render_targets, int p_amount) { - // All blits are going to the system framebuffer, so just bind once. - glBindFramebuffer(GL_FRAMEBUFFER, GLES3::TextureStorage::system_fbo); - for (int i = 0; i < p_amount; i++) { const BlitToScreen &blit = p_render_targets[i]; diff --git a/drivers/gles3/shaders/scene.glsl b/drivers/gles3/shaders/scene.glsl index c7fdd6ebd8..efd6036ba9 100644 --- a/drivers/gles3/shaders/scene.glsl +++ b/drivers/gles3/shaders/scene.glsl @@ -629,11 +629,12 @@ void light_compute(vec3 N, vec3 L, vec3 V, float A, vec3 light_color, float atte float diffuse_brdf_NL; // BRDF times N.L for calculating diffuse radiance #if defined(DIFFUSE_LAMBERT_WRAP) - // energy conserving lambert wrap shader - diffuse_brdf_NL = max(0.0, (NdotL + roughness) / ((1.0 + roughness) * (1.0 + roughness))); + // Energy conserving lambert wrap shader. + // https://web.archive.org/web/20210228210901/http://blog.stevemcauley.com/2011/12/03/energy-conserving-wrapped-diffuse/ + diffuse_brdf_NL = max(0.0, (NdotL + roughness) / ((1.0 + roughness) * (1.0 + roughness))) * (1.0 / M_PI); #elif defined(DIFFUSE_TOON) - diffuse_brdf_NL = smoothstep(-roughness, max(roughness, 0.01), NdotL); + diffuse_brdf_NL = smoothstep(-roughness, max(roughness, 0.01), NdotL) * (1.0 / M_PI); #elif defined(DIFFUSE_BURLEY) diff --git a/drivers/gles3/storage/texture_storage.cpp b/drivers/gles3/storage/texture_storage.cpp index b8ab4d6839..a801b3285a 100644 --- a/drivers/gles3/storage/texture_storage.cpp +++ b/drivers/gles3/storage/texture_storage.cpp @@ -1199,7 +1199,7 @@ void TextureStorage::_update_render_target(RenderTarget *rt) { rt->color_internal_format = rt->is_transparent ? GL_RGBA8 : GL_RGB10_A2; rt->color_format = GL_RGBA; - rt->color_type = rt->is_transparent ? GL_BYTE : GL_UNSIGNED_INT_2_10_10_10_REV; + rt->color_type = rt->is_transparent ? GL_UNSIGNED_BYTE : GL_UNSIGNED_INT_2_10_10_10_REV; rt->image_format = Image::FORMAT_RGBA8; glDisable(GL_SCISSOR_TEST); diff --git a/editor/editor_themes.cpp b/editor/editor_themes.cpp index 64ddecc588..edbd2dd62f 100644 --- a/editor/editor_themes.cpp +++ b/editor/editor_themes.cpp @@ -191,25 +191,6 @@ static Ref<StyleBoxLine> make_line_stylebox(Color p_color, int p_thickness = 1, return style; } -static Ref<Texture2D> flip_icon(Ref<Texture2D> p_texture, bool p_flip_y = false, bool p_flip_x = false) { - if (!p_flip_y && !p_flip_x) { - return p_texture; - } - - Ref<Image> img = p_texture->get_image(); - ERR_FAIL_NULL_V(img, Ref<Texture2D>()); - img = img->duplicate(); - - if (p_flip_y) { - img->flip_y(); - } - if (p_flip_x) { - img->flip_x(); - } - - return ImageTexture::create_from_image(img); -} - #ifdef MODULE_SVG_ENABLED // See also `generate_icon()` in `scene/resources/default_theme.cpp`. static Ref<ImageTexture> editor_generate_icon(int p_index, float p_scale, float p_saturation, const HashMap<Color, Color> &p_convert_colors = HashMap<Color, Color>()) { @@ -1567,14 +1548,13 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { theme->set_stylebox("camera", "GraphEditMinimap", style_minimap_camera); theme->set_stylebox("node", "GraphEditMinimap", style_minimap_node); - Ref<Texture2D> minimap_resizer_icon = theme->get_icon(SNAME("GuiResizer"), SNAME("EditorIcons")); Color minimap_resizer_color; if (dark_theme) { minimap_resizer_color = Color(1, 1, 1, 0.65); } else { minimap_resizer_color = Color(0, 0, 0, 0.65); } - theme->set_icon("resizer", "GraphEditMinimap", flip_icon(minimap_resizer_icon, true, true)); + theme->set_icon("resizer", "GraphEditMinimap", theme->get_icon(SNAME("GuiResizerTopLeft"), SNAME("EditorIcons"))); theme->set_color("resizer_color", "GraphEditMinimap", minimap_resizer_color); // GraphNode diff --git a/editor/icons/GuiResizerTopLeft.svg b/editor/icons/GuiResizerTopLeft.svg new file mode 100644 index 0000000000..a67c2c0722 --- /dev/null +++ b/editor/icons/GuiResizerTopLeft.svg @@ -0,0 +1 @@ +<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m4 12c.55228 0 1-.44772 1-1v-6h6c.55228 0 1-.44772 1-1s-.44772-1-1-1h-7c-.55226.000055-.99994.44774-1 1v7c0 .55228.44772 1 1 1z" fill="#fff" fill-opacity=".58824"/></svg> diff --git a/editor/icons/PreviewEnvironment.svg b/editor/icons/PreviewEnvironment.svg new file mode 100644 index 0000000000..e0b0257daf --- /dev/null +++ b/editor/icons/PreviewEnvironment.svg @@ -0,0 +1 @@ +<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g fill="#e0e0e0" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"><path d="m8 1a7 7 0 0 0 -7 7 7 7 0 0 0 7 7 7 7 0 0 0 7-7 7 7 0 0 0 -7-7zm-1.7305 2.3125c-.83125 1.5372-1.2685 3.1037-1.2695 4.6816-.64057-.11251-1.3005-.27158-1.9766-.47266a5 5 0 0 1 3.2461-4.209zm3.4629.00391a5 5 0 0 1 3.2383 4.1875c-.65187.17448-1.3077.32867-1.9727.44922-.0084-1.5627-.44294-3.1141-1.2656-4.6367zm-1.7324.0078088c1.0126 1.593 1.5 3.1425 1.5 4.6758 0 .054042-.00662.10803-.00781.16211-.96392.096801-1.9566.1103-2.9844.027344-.00163-.063192-.00781-.12632-.00781-.18945 0-1.5333.48744-3.0828 1.5-4.6758zm4.8789 5.7578a5 5 0 0 1 -3.1484 3.6055002c.57106-1.0564.95277-2.1268 1.1367-3.2051002.68204-.10905 1.3556-.23789 2.0117-.40039zm-9.7461.033203c.68377.18153 1.3555.33345 2.0098.43164.18781 1.0551002.56647 2.1026002 1.125 3.1367002a5 5 0 0 1 -3.1348-3.5684002zm6.168.55469c-.22615.9886602-.65424 1.9884002-1.3008 3.0059002-.63811-1.0042-1.0645-1.9908-1.293-2.9668002.89027.054126 1.7517.029377 2.5938-.039062z"/><path d="m8 1v2.3242c1.0126 1.593 1.5 3.1425 1.5 4.6758 0 .054042-.00662.10803-.00781.16211-.4894.049148-.98713.077552-1.4922.082031v1.4922c.43915-.0076.87287-.031628 1.3008-.066406-.22615.98866-.65424 1.9884-1.3008 3.0059v2.3242a7 7 0 0 0 7.000001-7 7 7 0 0 0 -7.000001-7zm1.7324 2.3164a5 5 0 0 1 3.2383 4.1875c-.65187.17448-1.3077.32867-1.9727.44922-.00845-1.5627-.44294-3.1141-1.2656-4.6367zm3.1465 5.7656a5 5 0 0 1 -3.1484 3.6055c.57106-1.0564.95277-2.1268 1.1367-3.2051.68204-.10905 1.3556-.23789 2.0117-.40039z"/></g></svg> diff --git a/editor/icons/PreviewSun.svg b/editor/icons/PreviewSun.svg new file mode 100644 index 0000000000..a8c652be65 --- /dev/null +++ b/editor/icons/PreviewSun.svg @@ -0,0 +1 @@ +<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m7 1v3h2v-3zm-2.5352 2.0508-1.4141 1.4141 1.4141 1.4141 1.4141-1.4141zm7.0703 0-1.4141 1.4141 1.4141 1.4141 1.4141-1.4141zm-3.5352 1.9492c-1.6569 0-3 1.3432-3 3s1.3431 3 3 3 3-1.3432 3-3-1.3431-3-3-3zm-7 2v2h3v-2zm11 0v2h3v-2zm-7.5352 3.1211-1.4141 1.4141 1.4141 1.4141 1.4141-1.4141zm7.0703 0-1.4141 1.4141 1.4141 1.4141 1.4141-1.4141zm-4.5352 1.8789v3h2v-3z" fill="#e0e0e0"/></svg> diff --git a/editor/plugins/node_3d_editor_plugin.cpp b/editor/plugins/node_3d_editor_plugin.cpp index 34d2cc3cd4..c8b49678d2 100644 --- a/editor/plugins/node_3d_editor_plugin.cpp +++ b/editor/plugins/node_3d_editor_plugin.cpp @@ -5516,8 +5516,8 @@ Dictionary Node3DEditor::get_state() const { pd["sun_color"] = sun_color->get_pick_color(); pd["sun_energy"] = sun_energy->get_value(); - pd["sun_disabled"] = sun_button->is_pressed(); - pd["environ_disabled"] = environ_button->is_pressed(); + pd["sun_enabled"] = sun_button->is_pressed(); + pd["environ_enabled"] = environ_button->is_pressed(); d["preview_sun_env"] = pd; } @@ -5648,8 +5648,8 @@ void Node3DEditor::set_state(const Dictionary &p_state) { sun_color->set_pick_color(pd["sun_color"]); sun_energy->set_value(pd["sun_energy"]); - sun_button->set_pressed(pd["sun_disabled"]); - environ_button->set_pressed(pd["environ_disabled"]); + sun_button->set_pressed(pd["sun_enabled"]); + environ_button->set_pressed(pd["environ_enabled"]); sun_environ_updating = false; @@ -5657,8 +5657,8 @@ void Node3DEditor::set_state(const Dictionary &p_state) { _update_preview_environment(); } else { _load_default_preview_settings(); - sun_button->set_pressed(false); - environ_button->set_pressed(false); + sun_button->set_pressed(true); + environ_button->set_pressed(true); _preview_settings_changed(); _update_preview_environment(); } @@ -7159,8 +7159,8 @@ void Node3DEditor::_update_theme() { view_menu->get_popup()->set_item_icon(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_3_VIEWPORTS_ALT), get_theme_icon(SNAME("Panels3Alt"), SNAME("EditorIcons"))); view_menu->get_popup()->set_item_icon(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_4_VIEWPORTS), get_theme_icon(SNAME("Panels4"), SNAME("EditorIcons"))); - sun_button->set_icon(get_theme_icon(SNAME("DirectionalLight3D"), SNAME("EditorIcons"))); - environ_button->set_icon(get_theme_icon(SNAME("WorldEnvironment"), SNAME("EditorIcons"))); + sun_button->set_icon(get_theme_icon(SNAME("PreviewSun"), SNAME("EditorIcons"))); + environ_button->set_icon(get_theme_icon(SNAME("PreviewEnvironment"), SNAME("EditorIcons"))); sun_environ_settings->set_icon(get_theme_icon(SNAME("GuiTabMenuHl"), SNAME("EditorIcons"))); sun_title->add_theme_font_override("font", get_theme_font(SNAME("title_font"), SNAME("Window"))); @@ -7636,7 +7636,7 @@ void Node3DEditor::_load_default_preview_settings() { } void Node3DEditor::_update_preview_environment() { - bool disable_light = directional_light_count > 0 || sun_button->is_pressed(); + bool disable_light = directional_light_count > 0 || !sun_button->is_pressed(); sun_button->set_disabled(directional_light_count > 0); @@ -7664,7 +7664,7 @@ void Node3DEditor::_update_preview_environment() { sun_angle_altitude->set_value(-Math::rad_to_deg(sun_rotation.x)); sun_angle_azimuth->set_value(180.0 - Math::rad_to_deg(sun_rotation.y)); - bool disable_env = world_env_count > 0 || environ_button->is_pressed(); + bool disable_env = world_env_count > 0 || !environ_button->is_pressed(); environ_button->set_disabled(world_env_count > 0); @@ -7855,6 +7855,8 @@ Node3DEditor::Node3DEditor() { sun_button->set_flat(true); sun_button->connect("pressed", callable_mp(this, &Node3DEditor::_update_preview_environment), CONNECT_DEFERRED); sun_button->set_disabled(true); + // Preview is enabled by default - ensure this applies on editor startup when there is no state yet. + sun_button->set_pressed(true); main_menu_hbox->add_child(sun_button); @@ -7864,6 +7866,8 @@ Node3DEditor::Node3DEditor() { environ_button->set_flat(true); environ_button->connect("pressed", callable_mp(this, &Node3DEditor::_update_preview_environment), CONNECT_DEFERRED); environ_button->set_disabled(true); + // Preview is enabled by default - ensure this applies on editor startup when there is no state yet. + environ_button->set_pressed(true); main_menu_hbox->add_child(environ_button); diff --git a/editor/plugins/version_control_editor_plugin.cpp b/editor/plugins/version_control_editor_plugin.cpp index 761140b2d5..336ce9e4c8 100644 --- a/editor/plugins/version_control_editor_plugin.cpp +++ b/editor/plugins/version_control_editor_plugin.cpp @@ -1124,6 +1124,8 @@ VersionControlEditorPlugin::VersionControlEditorPlugin() { set_up_password->connect(SNAME("text_changed"), callable_mp(this, &VersionControlEditorPlugin::_update_set_up_warning)); set_up_password_input->add_child(set_up_password); + const String home_dir = OS::get_singleton()->has_environment("HOME") ? OS::get_singleton()->get_environment("HOME") : OS::get_singleton()->get_system_dir(OS::SYSTEM_DIR_DOCUMENTS); + HBoxContainer *set_up_ssh_public_key_input = memnew(HBoxContainer); set_up_ssh_public_key_input->set_h_size_flags(Control::SIZE_EXPAND_FILL); set_up_settings_vbc->add_child(set_up_ssh_public_key_input); @@ -1147,10 +1149,7 @@ VersionControlEditorPlugin::VersionControlEditorPlugin() { set_up_ssh_public_key_file_dialog->set_access(FileDialog::ACCESS_FILESYSTEM); set_up_ssh_public_key_file_dialog->set_file_mode(FileDialog::FILE_MODE_OPEN_FILE); set_up_ssh_public_key_file_dialog->set_show_hidden_files(true); - // TODO: Make this start at the user's home folder - Ref<DirAccess> d = DirAccess::open(OS::get_singleton()->get_system_dir(OS::SYSTEM_DIR_DOCUMENTS)); - d->change_dir("../"); - set_up_ssh_public_key_file_dialog->set_current_dir(d->get_current_dir()); + set_up_ssh_public_key_file_dialog->set_current_dir(home_dir); set_up_ssh_public_key_file_dialog->connect(SNAME("file_selected"), callable_mp(this, &VersionControlEditorPlugin::_ssh_public_key_selected)); set_up_ssh_public_key_input_hbc->add_child(set_up_ssh_public_key_file_dialog); @@ -1183,8 +1182,7 @@ VersionControlEditorPlugin::VersionControlEditorPlugin() { set_up_ssh_private_key_file_dialog->set_access(FileDialog::ACCESS_FILESYSTEM); set_up_ssh_private_key_file_dialog->set_file_mode(FileDialog::FILE_MODE_OPEN_FILE); set_up_ssh_private_key_file_dialog->set_show_hidden_files(true); - // TODO: Make this start at the user's home folder - set_up_ssh_private_key_file_dialog->set_current_dir(d->get_current_dir()); + set_up_ssh_private_key_file_dialog->set_current_dir(home_dir); set_up_ssh_private_key_file_dialog->connect("file_selected", callable_mp(this, &VersionControlEditorPlugin::_ssh_private_key_selected)); set_up_ssh_private_key_input_hbc->add_child(set_up_ssh_private_key_file_dialog); diff --git a/editor/plugins/visual_shader_editor_plugin.cpp b/editor/plugins/visual_shader_editor_plugin.cpp index 2af8da02a3..ee8148f00a 100644 --- a/editor/plugins/visual_shader_editor_plugin.cpp +++ b/editor/plugins/visual_shader_editor_plugin.cpp @@ -5198,9 +5198,9 @@ VisualShaderEditor::VisualShaderEditor() { add_options.push_back(AddOption("Tangent", "Input/Fragment", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "tangent", "TANGENT"), { "tangent" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL)); add_options.push_back(AddOption("Vertex", "Input/Fragment", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "vertex", "VERTEX"), { "vertex" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL)); add_options.push_back(AddOption("View", "Input/Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_and_light_shader_modes, "view", "VIEW"), { "view" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL)); - add_options.push_back(AddOption("ViewIndex", "Input/Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "view_index", "VIEW_INDEX"), { "view_index" }, VisualShaderNode::PORT_TYPE_SCALAR_INT, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL)); - add_options.push_back(AddOption("ViewMonoLeft", "Input/Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "view_mono_left", "VIEW_MONO_LEFT"), { "view_mono_left" }, VisualShaderNode::PORT_TYPE_SCALAR_INT, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL)); - add_options.push_back(AddOption("ViewRight", "Input/Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "view_right", "VIEW_RIGHT"), { "view_right" }, VisualShaderNode::PORT_TYPE_SCALAR_INT, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL)); + add_options.push_back(AddOption("ViewIndex", "Input/Fragment", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "view_index", "VIEW_INDEX"), { "view_index" }, VisualShaderNode::PORT_TYPE_SCALAR_INT, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL)); + add_options.push_back(AddOption("ViewMonoLeft", "Input/Fragment", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "view_mono_left", "VIEW_MONO_LEFT"), { "view_mono_left" }, VisualShaderNode::PORT_TYPE_SCALAR_INT, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL)); + add_options.push_back(AddOption("ViewRight", "Input/Fragment", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "view_right", "VIEW_RIGHT"), { "view_right" }, VisualShaderNode::PORT_TYPE_SCALAR_INT, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL)); add_options.push_back(AddOption("NodePositionWorld", "Input/Fragment", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "node_position_world", "NODE_POSITION_WORLD"), { "node_position_world" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL)); add_options.push_back(AddOption("CameraPositionWorld", "Input/Fragment", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "camera_position_world", "CAMERA_POSITION_WORLD"), { "camera_position_world" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL)); add_options.push_back(AddOption("CameraDirectionWorld", "Input/Fragment", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "camera_direction_world", "CAMERA_DIRECTION_WORLD"), { "camera_direction_world" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL)); diff --git a/editor/project_manager.cpp b/editor/project_manager.cpp index 2439d13435..f11874a994 100644 --- a/editor/project_manager.cpp +++ b/editor/project_manager.cpp @@ -2769,9 +2769,10 @@ ProjectManager::ProjectManager() { settings_hb->add_child(h_spacer); language_btn = memnew(OptionButton); - language_btn->set_flat(true); language_btn->set_icon(get_theme_icon(SNAME("Environment"), SNAME("EditorIcons"))); language_btn->set_focus_mode(Control::FOCUS_NONE); + language_btn->set_fit_to_longest_item(false); + language_btn->set_flat(true); language_btn->connect("item_selected", callable_mp(this, &ProjectManager::_language_selected)); #ifdef ANDROID_ENABLED // The language selection dropdown doesn't work on Android (as the setting isn't saved), see GH-60353. diff --git a/modules/gltf/register_types.cpp b/modules/gltf/register_types.cpp index dbbccc9bcc..6e7f7d6fed 100644 --- a/modules/gltf/register_types.cpp +++ b/modules/gltf/register_types.cpp @@ -142,6 +142,11 @@ void initialize_gltf_module(ModuleInitializationLevel p_level) { GLOBAL_DEF_RST("filesystem/import/fbx/enabled", true); GDREGISTER_CLASS(EditorSceneFormatImporterBlend); GDREGISTER_CLASS(EditorSceneFormatImporterFBX); + // Can't (a priori) run external app on these platforms. + GLOBAL_DEF_RST("filesystem/import/blender/enabled.android", false); + GLOBAL_DEF_RST("filesystem/import/blender/enabled.web", false); + GLOBAL_DEF_RST("filesystem/import/fbx/enabled.android", false); + GLOBAL_DEF_RST("filesystem/import/fbx/enabled.web", false); ClassDB::set_current_api(prev_api); EditorNode::add_init_callback(_editor_init); diff --git a/modules/multiplayer/multiplayer_spawner.cpp b/modules/multiplayer/multiplayer_spawner.cpp index 6f60318b3b..9d0864e4d5 100644 --- a/modules/multiplayer/multiplayer_spawner.cpp +++ b/modules/multiplayer/multiplayer_spawner.cpp @@ -101,6 +101,7 @@ int MultiplayerSpawner::get_spawnable_scene_count() const { return spawnable_scenes.size(); } String MultiplayerSpawner::get_spawnable_scene(int p_idx) const { + ERR_FAIL_INDEX_V(p_idx, (int)spawnable_scenes.size(), ""); return spawnable_scenes[p_idx].path; } void MultiplayerSpawner::clear_spawnable_scenes() { diff --git a/platform/android/java/app/config.gradle b/platform/android/java/app/config.gradle index fbd97fae0b..0346625e4b 100644 --- a/platform/android/java/app/config.gradle +++ b/platform/android/java/app/config.gradle @@ -127,16 +127,36 @@ ext.generateGodotLibraryVersion = { List<String> requiredKeys -> if (requiredKeys.empty) { libraryVersionName = map.values().join(".") try { + if (map.containsKey("status")) { + int statusCode = 0 + String statusValue = map["status"] + if (statusValue == null) { + statusCode = 0 + } else if (statusValue.startsWith("alpha")) { + statusCode = 1 + } else if (statusValue.startsWith("beta")) { + statusCode = 2 + } else if (statusValue.startsWith("rc")) { + statusCode = 3 + } else if (statusValue.startsWith("stable")) { + statusCode = 4 + } else { + statusCode = 0 + } + + libraryVersionCode = statusCode + } + if (map.containsKey("patch")) { - libraryVersionCode = Integer.parseInt(map["patch"]) + libraryVersionCode += Integer.parseInt(map["patch"]) * 10 } if (map.containsKey("minor")) { - libraryVersionCode += (Integer.parseInt(map["minor"]) * 100) + libraryVersionCode += (Integer.parseInt(map["minor"]) * 1000) } if (map.containsKey("major")) { - libraryVersionCode += (Integer.parseInt(map["major"]) * 10000) + libraryVersionCode += (Integer.parseInt(map["major"]) * 100000) } } catch (NumberFormatException ignore) { libraryVersionCode = 1 diff --git a/platform/android/java/editor/build.gradle b/platform/android/java/editor/build.gradle index 729966ee69..9152492e9d 100644 --- a/platform/android/java/editor/build.gradle +++ b/platform/android/java/editor/build.gradle @@ -12,6 +12,25 @@ dependencies { implementation "androidx.window:window:1.0.0" } +ext { + // Build number added as a suffix to the version code, and incremented for each build/upload to + // the Google Play store. + // This should be reset on each stable release of Godot. + editorBuildNumber = 0 + // Value by which the Godot version code should be offset by to make room for the build number + editorBuildNumberOffset = 100 +} + +def generateVersionCode() { + int libraryVersionCode = getGodotLibraryVersionCode() + return (libraryVersionCode * editorBuildNumberOffset) + editorBuildNumber +} + +def generateVersionName() { + String libraryVersionName = getGodotLibraryVersionName() + return libraryVersionName + ".$editorBuildNumber" +} + android { compileSdkVersion versions.compileSdk buildToolsVersion versions.buildTools @@ -20,8 +39,8 @@ android { defaultConfig { // The 'applicationId' suffix allows to install Godot 3.x(v3) and 4.x(v4) on the same device applicationId "org.godotengine.editor.v4" - versionCode getGodotLibraryVersionCode() - versionName getGodotLibraryVersionName() + versionCode generateVersionCode() + versionName generateVersionName() minSdkVersion versions.minSdk targetSdkVersion versions.targetSdk diff --git a/platform/android/java/editor/src/main/AndroidManifest.xml b/platform/android/java/editor/src/main/AndroidManifest.xml index abf506a83c..6aa5f06f31 100644 --- a/platform/android/java/editor/src/main/AndroidManifest.xml +++ b/platform/android/java/editor/src/main/AndroidManifest.xml @@ -7,7 +7,7 @@ <supports-screens android:largeScreens="true" android:normalScreens="true" - android:smallScreens="true" + android:smallScreens="false" android:xlargeScreens="true" /> <uses-feature diff --git a/platform/linuxbsd/gl_manager_x11.cpp b/platform/linuxbsd/gl_manager_x11.cpp index 04c1df71fb..838be2c042 100644 --- a/platform/linuxbsd/gl_manager_x11.cpp +++ b/platform/linuxbsd/gl_manager_x11.cpp @@ -256,7 +256,11 @@ void GLManager_X11::release_current() { if (!_current_window) { return; } - glXMakeCurrent(_x_windisp.x11_display, None, nullptr); + + if (!glXMakeCurrent(_x_windisp.x11_display, None, nullptr)) { + ERR_PRINT("glXMakeCurrent failed"); + } + _current_window = nullptr; } void GLManager_X11::window_make_current(DisplayServer::WindowID p_window_id) { @@ -276,7 +280,9 @@ void GLManager_X11::window_make_current(DisplayServer::WindowID p_window_id) { const GLDisplay &disp = get_display(win.gldisplay_id); - glXMakeCurrent(disp.x11_display, win.x11_window, disp.context->glx_context); + if (!glXMakeCurrent(disp.x11_display, win.x11_window, disp.context->glx_context)) { + ERR_PRINT("glXMakeCurrent failed"); + } _internal_set_current_window(&win); } @@ -290,13 +296,12 @@ void GLManager_X11::make_current() { return; } const GLDisplay &disp = get_current_display(); - glXMakeCurrent(_x_windisp.x11_display, _x_windisp.x11_window, disp.context->glx_context); + if (!glXMakeCurrent(_x_windisp.x11_display, _x_windisp.x11_window, disp.context->glx_context)) { + ERR_PRINT("glXMakeCurrent failed"); + } } void GLManager_X11::swap_buffers() { - // NO NEED TO CALL SWAP BUFFERS for each window... - // see https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glXSwapBuffers.xml - if (!_current_window) { return; } @@ -315,13 +320,6 @@ void GLManager_X11::swap_buffers() { } } - // print_line("\tswap_buffers"); - - // only for debugging without drawing anything - // glClearColor(Math::randf(), 0, 1, 1); - //glClear(GL_COLOR_BUFFER_BIT); - - //const GLDisplay &disp = get_current_display(); glXSwapBuffers(_x_windisp.x11_display, _x_windisp.x11_window); } diff --git a/platform/macos/gl_manager_macos_legacy.mm b/platform/macos/gl_manager_macos_legacy.mm index e6bb7aaa85..dec4821b86 100644 --- a/platform/macos/gl_manager_macos_legacy.mm +++ b/platform/macos/gl_manager_macos_legacy.mm @@ -167,9 +167,8 @@ void GLManager_MacOS::make_current() { } void GLManager_MacOS::swap_buffers() { - for (const KeyValue<DisplayServer::WindowID, GLWindow> &E : windows) { - [E.value.context flushBuffer]; - } + GLWindow &win = windows[current_window]; + [win.context flushBuffer]; } void GLManager_MacOS::window_update(DisplayServer::WindowID p_window_id) { diff --git a/platform/web/display_server_web.cpp b/platform/web/display_server_web.cpp index 38ac6b23f4..f6a61b18e4 100644 --- a/platform/web/display_server_web.cpp +++ b/platform/web/display_server_web.cpp @@ -997,7 +997,7 @@ void DisplayServerWeb::window_set_mode(WindowMode p_mode, WindowID p_window) { } break; case WINDOW_MODE_MAXIMIZED: case WINDOW_MODE_MINIMIZED: - WARN_PRINT("WindowMode MAXIMIZED and MINIMIZED are not supported in Web platform."); + // WindowMode MAXIMIZED and MINIMIZED are not supported in Web platform. break; default: break; diff --git a/platform/windows/gl_manager_windows.cpp b/platform/windows/gl_manager_windows.cpp index d509ff8c51..7689751f1b 100644 --- a/platform/windows/gl_manager_windows.cpp +++ b/platform/windows/gl_manager_windows.cpp @@ -289,12 +289,7 @@ void GLManager_Windows::make_current() { } void GLManager_Windows::swap_buffers() { - // on other platforms, OpenGL swaps buffers for all windows (on all displays, really?) - // Windows swaps buffers on a per-window basis - // REVISIT: this could be structurally bad, should we have "dirty" flags then? - for (KeyValue<DisplayServer::WindowID, GLWindow> &entry : _windows) { - SwapBuffers(entry.value.hDC); - } + SwapBuffers(_current_window->hDC); } Error GLManager_Windows::initialize() { diff --git a/scene/2d/animated_sprite_2d.cpp b/scene/2d/animated_sprite_2d.cpp index 09255ba834..7fe464d2f4 100644 --- a/scene/2d/animated_sprite_2d.cpp +++ b/scene/2d/animated_sprite_2d.cpp @@ -108,6 +108,7 @@ void AnimatedSprite2D::_validate_property(PropertyInfo &p_property) const { if (!frames.is_valid()) { return; } + if (p_property.name == "animation") { p_property.hint = PROPERTY_HINT_ENUM; List<StringName> names; @@ -137,9 +138,15 @@ void AnimatedSprite2D::_validate_property(PropertyInfo &p_property) const { p_property.hint_string = String(animation) + "," + p_property.hint_string; } } + return; } if (p_property.name == "frame") { + if (playing) { + p_property.usage = PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_READ_ONLY; + return; + } + p_property.hint = PROPERTY_HINT_RANGE; if (frames->has_animation(animation) && frames->get_frame_count(animation) > 0) { p_property.hint_string = "0," + itos(frames->get_frame_count(animation) - 1) + ",1"; @@ -384,6 +391,7 @@ void AnimatedSprite2D::set_playing(bool p_playing) { playing = p_playing; _reset_timeout(); set_process_internal(playing); + notify_property_list_changed(); } bool AnimatedSprite2D::is_playing() const { diff --git a/scene/3d/sprite_3d.cpp b/scene/3d/sprite_3d.cpp index a4a6c211d7..7a89bf81bb 100644 --- a/scene/3d/sprite_3d.cpp +++ b/scene/3d/sprite_3d.cpp @@ -997,6 +997,7 @@ void AnimatedSprite3D::_validate_property(PropertyInfo &p_property) const { if (!frames.is_valid()) { return; } + if (p_property.name == "animation") { p_property.hint = PROPERTY_HINT_ENUM; List<StringName> names; @@ -1026,9 +1027,15 @@ void AnimatedSprite3D::_validate_property(PropertyInfo &p_property) const { p_property.hint_string = String(animation) + "," + p_property.hint_string; } } + return; } if (p_property.name == "frame") { + if (playing) { + p_property.usage = PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_READ_ONLY; + return; + } + p_property.hint = PROPERTY_HINT_RANGE; if (frames->has_animation(animation) && frames->get_frame_count(animation) > 0) { p_property.hint_string = "0," + itos(frames->get_frame_count(animation) - 1) + ",1"; @@ -1222,6 +1229,7 @@ void AnimatedSprite3D::set_playing(bool p_playing) { playing = p_playing; _reset_timeout(); set_process_internal(playing); + notify_property_list_changed(); } bool AnimatedSprite3D::is_playing() const { diff --git a/servers/rendering/renderer_rd/effects/ss_effects.cpp b/servers/rendering/renderer_rd/effects/ss_effects.cpp index 971e9243e3..582c5abbdd 100644 --- a/servers/rendering/renderer_rd/effects/ss_effects.cpp +++ b/servers/rendering/renderer_rd/effects/ss_effects.cpp @@ -443,6 +443,11 @@ void SSEffects::downsample_depth(RID p_depth_buffer, const Vector<RID> &p_depth_ RD::get_singleton()->draw_command_begin_label("Downsample Depth"); if (p_invalidate_uniform_set || use_full_mips != ss_effects.used_full_mips_last_frame || use_half_size != ss_effects.used_half_size_last_frame || use_mips != ss_effects.used_mips_last_frame) { + if (ss_effects.downsample_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(ss_effects.downsample_uniform_set)) { + RD::get_singleton()->free(ss_effects.downsample_uniform_set); + ss_effects.downsample_uniform_set = RID(); + } + Vector<RD::Uniform> uniforms; { RD::Uniform u; @@ -516,6 +521,7 @@ void SSEffects::downsample_depth(RID p_depth_buffer, const Vector<RID> &p_depth_ ss_effects.used_full_mips_last_frame = use_full_mips; ss_effects.used_half_size_last_frame = use_half_size; + ss_effects.used_mips_last_frame = use_mips; } /* SSIL */ diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl index 4e6e29b315..2fba1351f7 100644 --- a/servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl +++ b/servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl @@ -97,11 +97,12 @@ void light_compute(vec3 N, vec3 L, vec3 V, float A, vec3 light_color, float atte float diffuse_brdf_NL; // BRDF times N.L for calculating diffuse radiance #if defined(DIFFUSE_LAMBERT_WRAP) - // energy conserving lambert wrap shader - diffuse_brdf_NL = max(0.0, (NdotL + roughness) / ((1.0 + roughness) * (1.0 + roughness))); + // Energy conserving lambert wrap shader. + // https://web.archive.org/web/20210228210901/http://blog.stevemcauley.com/2011/12/03/energy-conserving-wrapped-diffuse/ + diffuse_brdf_NL = max(0.0, (NdotL + roughness) / ((1.0 + roughness) * (1.0 + roughness))) * (1.0 / M_PI); #elif defined(DIFFUSE_TOON) - diffuse_brdf_NL = smoothstep(-roughness, max(roughness, 0.01), NdotL); + diffuse_brdf_NL = smoothstep(-roughness, max(roughness, 0.01), NdotL) * (1.0 / M_PI); #elif defined(DIFFUSE_BURLEY) diff --git a/servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.cpp b/servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.cpp index 84b65371e0..16fdbc07f5 100644 --- a/servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.cpp +++ b/servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.cpp @@ -128,6 +128,11 @@ void RenderSceneBuffersRD::cleanup() { ss_effects.linear_depth_slices.clear(); } + if (ss_effects.downsample_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(ss_effects.downsample_uniform_set)) { + RD::get_singleton()->free(ss_effects.downsample_uniform_set); + ss_effects.downsample_uniform_set = RID(); + } + sse->ssao_free(ss_effects.ssao); sse->ssil_free(ss_effects.ssil); sse->ssr_free(ssr); diff --git a/servers/rendering/renderer_viewport.cpp b/servers/rendering/renderer_viewport.cpp index d466f90e79..5771def45f 100644 --- a/servers/rendering/renderer_viewport.cpp +++ b/servers/rendering/renderer_viewport.cpp @@ -714,7 +714,14 @@ void RendererViewport::draw_viewports() { blit_to_screen_list[vp->viewport_to_screen] = Vector<BlitToScreen>(); } - blit_to_screen_list[vp->viewport_to_screen].push_back(blit); + if (OS::get_singleton()->get_current_rendering_driver_name() == "opengl3") { + Vector<BlitToScreen> blit_to_screen_vec; + blit_to_screen_vec.push_back(blit); + RSG::rasterizer->blit_render_targets_to_screen(vp->viewport_to_screen, blit_to_screen_vec.ptr(), 1); + RSG::rasterizer->end_frame(true); + } else { + blit_to_screen_list[vp->viewport_to_screen].push_back(blit); + } } } diff --git a/servers/rendering/rendering_server_default.cpp b/servers/rendering/rendering_server_default.cpp index 1f686069bd..9103b0cf56 100644 --- a/servers/rendering/rendering_server_default.cpp +++ b/servers/rendering/rendering_server_default.cpp @@ -91,7 +91,10 @@ void RenderingServerDefault::_draw(bool p_swap_buffers, double frame_step) { RSG::viewport->draw_viewports(); RSG::canvas_render->update(); - RSG::rasterizer->end_frame(p_swap_buffers); + if (OS::get_singleton()->get_current_rendering_driver_name() != "opengl3") { + // Already called for gl_compatibility renderer. + RSG::rasterizer->end_frame(p_swap_buffers); + } XRServer *xr_server = XRServer::get_singleton(); if (xr_server != nullptr) { |