diff options
38 files changed, 265 insertions, 118 deletions
diff --git a/.gitignore b/.gitignore index 3a05ed9e7d..fe504482b3 100644 --- a/.gitignore +++ b/.gitignore @@ -311,5 +311,8 @@ platform/windows/godot_res.res /.vs /.vscode +# Visual Studio Code workspace file +*.code-workspace + # Scons progress indicator .scons_node_count diff --git a/core/math/expression.cpp b/core/math/expression.cpp index a16267cf0a..0cfb54234c 100644 --- a/core/math/expression.cpp +++ b/core/math/expression.cpp @@ -2120,6 +2120,10 @@ Error Expression::parse(const String &p_expression, const Vector<String> &p_inpu } Variant Expression::execute(Array p_inputs, Object *p_base, bool p_show_error) { + if (error_set) { + ERR_EXPLAIN("There was previously a parse error: " + error_str); + ERR_FAIL_V(Variant()); + } execution_error = false; Variant output; diff --git a/core/ustring.cpp b/core/ustring.cpp index 1195cd0719..2191bb5e23 100644 --- a/core/ustring.cpp +++ b/core/ustring.cpp @@ -2774,16 +2774,13 @@ String String::format(const Variant &values, String placeholder) const { if (value_arr.size() == 2) { Variant v_key = value_arr[0]; - String key; - - key = v_key.get_construct_string(); + String key = v_key; if (key.left(1) == "\"" && key.right(key.length() - 1) == "\"") { key = key.substr(1, key.length() - 2); } Variant v_val = value_arr[1]; - String val; - val = v_val.get_construct_string(); + String val = v_val; if (val.left(1) == "\"" && val.right(val.length() - 1) == "\"") { val = val.substr(1, val.length() - 2); @@ -2795,8 +2792,7 @@ String String::format(const Variant &values, String placeholder) const { } } else { //Array structure ["RobotGuy","Logis","rookie"] Variant v_val = values_arr[i]; - String val; - val = v_val.get_construct_string(); + String val = v_val; if (val.left(1) == "\"" && val.right(val.length() - 1) == "\"") { val = val.substr(1, val.length() - 2); @@ -2815,8 +2811,8 @@ String String::format(const Variant &values, String placeholder) const { d.get_key_list(&keys); for (List<Variant>::Element *E = keys.front(); E; E = E->next()) { - String key = E->get().get_construct_string(); - String val = d[E->get()].get_construct_string(); + String key = E->get(); + String val = d[E->get()]; if (key.left(1) == "\"" && key.right(key.length() - 1) == "\"") { key = key.substr(1, key.length() - 2); diff --git a/doc/classes/VisualServer.xml b/doc/classes/VisualServer.xml index 225a1f2bba..ed6fdacec7 100644 --- a/doc/classes/VisualServer.xml +++ b/doc/classes/VisualServer.xml @@ -3613,7 +3613,7 @@ If [code]true[/code] sets the viewport active, else sets it inactive. </description> </method> - <method name="viewport_set_canvas_layer"> + <method name="viewport_set_canvas_stacking"> <return type="void"> </return> <argument index="0" name="viewport" type="RID"> @@ -3622,8 +3622,11 @@ </argument> <argument index="2" name="layer" type="int"> </argument> + <argument index="3" name="sublayer" type="int"> + </argument> <description> - Sets the renderlayer for a viewport's canvas. + Sets the stacking order for a viewport's canvas. + [code]layer[/code] is the actual canvas layer, while [code]sublayer[/code] specifies the stacking order of the canvas among those in the same layer. </description> </method> <method name="viewport_set_canvas_transform"> diff --git a/drivers/gles2/rasterizer_storage_gles2.cpp b/drivers/gles2/rasterizer_storage_gles2.cpp index d5865064cf..c4c5093540 100644 --- a/drivers/gles2/rasterizer_storage_gles2.cpp +++ b/drivers/gles2/rasterizer_storage_gles2.cpp @@ -613,8 +613,72 @@ Ref<Image> RasterizerStorageGLES2::texture_get_data(RID p_texture, int p_layer) return Ref<Image>(img); #else - ERR_EXPLAIN("Sorry, It's not possible to obtain images back in OpenGL ES"); - ERR_FAIL_V(Ref<Image>()); + Image::Format real_format; + GLenum gl_format; + GLenum gl_internal_format; + GLenum gl_type; + bool compressed; + _get_gl_image_and_format(Ref<Image>(), texture->format, texture->flags, real_format, gl_format, gl_internal_format, gl_type, compressed); + + PoolVector<uint8_t> data; + + int data_size = Image::get_image_data_size(texture->alloc_width, texture->alloc_height, Image::FORMAT_RGBA8, false); + + data.resize(data_size * 2); //add some memory at the end, just in case for buggy drivers + PoolVector<uint8_t>::Write wb = data.write(); + + GLuint temp_framebuffer; + glGenFramebuffers(1, &temp_framebuffer); + + GLuint temp_color_texture; + glGenTextures(1, &temp_color_texture); + + glBindFramebuffer(GL_FRAMEBUFFER, temp_framebuffer); + + glBindTexture(GL_TEXTURE_2D, temp_color_texture); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texture->alloc_width, texture->alloc_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, temp_color_texture, 0); + + glDepthMask(GL_FALSE); + glDisable(GL_DEPTH_TEST); + glDisable(GL_CULL_FACE); + glDisable(GL_BLEND); + glDepthFunc(GL_LEQUAL); + glColorMask(1, 1, 1, 1); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, texture->tex_id); + + glViewport(0, 0, texture->alloc_width, texture->alloc_height); + + shaders.copy.bind(); + + glClearColor(0.0, 0.0, 0.0, 0.0); + glClear(GL_COLOR_BUFFER_BIT); + bind_quad_array(); + glDrawArrays(GL_TRIANGLE_FAN, 0, 4); + glBindBuffer(GL_ARRAY_BUFFER, 0); + + glReadPixels(0, 0, texture->alloc_width, texture->alloc_height, GL_RGBA, GL_UNSIGNED_BYTE, &wb[0]); + + glDeleteTextures(1, &temp_color_texture); + + glBindFramebuffer(GL_FRAMEBUFFER, 0); + glDeleteFramebuffers(1, &temp_framebuffer); + + wb = PoolVector<uint8_t>::Write(); + + data.resize(data_size); + + Image *img = memnew(Image(texture->alloc_width, texture->alloc_height, false, Image::FORMAT_RGBA8, data)); + if (!texture->compressed) { + img->convert(real_format); + } + + return Ref<Image>(img); + #endif } diff --git a/drivers/gles3/rasterizer_storage_gles3.cpp b/drivers/gles3/rasterizer_storage_gles3.cpp index 8a73804eec..c06ef805a6 100644 --- a/drivers/gles3/rasterizer_storage_gles3.cpp +++ b/drivers/gles3/rasterizer_storage_gles3.cpp @@ -1116,8 +1116,78 @@ Ref<Image> RasterizerStorageGLES3::texture_get_data(RID p_texture, int p_layer) return Ref<Image>(img); #else - ERR_EXPLAIN("Sorry, It's not possible to obtain images back in OpenGL ES"); - ERR_FAIL_V(Ref<Image>()); + Image::Format real_format; + GLenum gl_format; + GLenum gl_internal_format; + GLenum gl_type; + bool compressed; + bool srgb; + _get_gl_image_and_format(Ref<Image>(), texture->format, texture->flags, real_format, gl_format, gl_internal_format, gl_type, compressed, srgb); + + PoolVector<uint8_t> data; + + int data_size = Image::get_image_data_size(texture->alloc_width, texture->alloc_height, Image::FORMAT_RGBA8, false); + + data.resize(data_size * 2); //add some memory at the end, just in case for buggy drivers + PoolVector<uint8_t>::Write wb = data.write(); + + GLuint temp_framebuffer; + glGenFramebuffers(1, &temp_framebuffer); + + GLuint temp_color_texture; + glGenTextures(1, &temp_color_texture); + + glBindFramebuffer(GL_FRAMEBUFFER, temp_framebuffer); + + glBindTexture(GL_TEXTURE_2D, temp_color_texture); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texture->alloc_width, texture->alloc_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); + + print_line(itos(texture->alloc_width) + " xx " + itos(texture->alloc_height) + " -> " + itos(real_format)); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, temp_color_texture, 0); + + glDepthMask(GL_FALSE); + glDisable(GL_DEPTH_TEST); + glDisable(GL_CULL_FACE); + glDisable(GL_BLEND); + glDepthFunc(GL_LEQUAL); + glColorMask(1, 1, 1, 1); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, texture->tex_id); + + glViewport(0, 0, texture->alloc_width, texture->alloc_height); + + shaders.copy.bind(); + + shaders.copy.set_conditional(CopyShaderGLES3::LINEAR_TO_SRGB, !srgb); + + glClearColor(0.0, 0.0, 0.0, 0.0); + glClear(GL_COLOR_BUFFER_BIT); + glBindVertexArray(resources.quadie_array); + glDrawArrays(GL_TRIANGLE_FAN, 0, 4); + glBindVertexArray(0); + + glReadPixels(0, 0, texture->alloc_width, texture->alloc_height, GL_RGBA, GL_UNSIGNED_BYTE, &wb[0]); + + shaders.copy.set_conditional(CopyShaderGLES3::LINEAR_TO_SRGB, false); + + glDeleteTextures(1, &temp_color_texture); + + glBindFramebuffer(GL_FRAMEBUFFER, 0); + glDeleteFramebuffers(1, &temp_framebuffer); + + wb = PoolVector<uint8_t>::Write(); + + data.resize(data_size); + + Image *img = memnew(Image(texture->alloc_width, texture->alloc_height, false, Image::FORMAT_RGBA8, data)); + if (!texture->compressed) { + img->convert(real_format); + } + + return Ref<Image>(img); #endif } diff --git a/editor/animation_track_editor.cpp b/editor/animation_track_editor.cpp index 3997469e95..37d26d8e0f 100644 --- a/editor/animation_track_editor.cpp +++ b/editor/animation_track_editor.cpp @@ -1685,15 +1685,10 @@ void AnimationTrackEdit::_zoom_changed() { } void AnimationTrackEdit::_path_entered(const String &p_text) { - - *block_animation_update_ptr = true; undo_redo->create_action("Change Track Path"); undo_redo->add_do_method(animation.ptr(), "track_set_path", track, p_text); undo_redo->add_undo_method(animation.ptr(), "track_set_path", track, animation->track_get_path(track)); undo_redo->commit_action(); - *block_animation_update_ptr = false; - update(); - path->hide(); } String AnimationTrackEdit::get_tooltip(const Point2 &p_pos) const { diff --git a/editor/editor_file_dialog.cpp b/editor/editor_file_dialog.cpp index 438d7ea306..b39f910182 100644 --- a/editor/editor_file_dialog.cpp +++ b/editor/editor_file_dialog.cpp @@ -580,7 +580,7 @@ void EditorFileDialog::_item_list_item_rmb_selected(int p_item, const Vector2 &p if (single_item_selected) { item_menu->add_separator(); Dictionary item_meta = item_list->get_item_metadata(p_item); - String item_text = item_meta["dir"] ? TTR("Open In File Manager") : TTR("Show In File Manager"); + String item_text = item_meta["dir"] ? TTR("Open in File Manager") : TTR("Show in File Manager"); item_menu->add_icon_item(get_icon("Filesystem", "EditorIcons"), item_text, ITEM_MENU_SHOW_IN_EXPLORER); } @@ -605,7 +605,7 @@ void EditorFileDialog::_item_list_rmb_clicked(const Vector2 &p_pos) { } item_menu->add_icon_item(get_icon("Reload", "EditorIcons"), TTR("Refresh"), ITEM_MENU_REFRESH, KEY_F5); item_menu->add_separator(); - item_menu->add_icon_item(get_icon("Filesystem", "EditorIcons"), TTR("Open In File Manager"), ITEM_MENU_SHOW_IN_EXPLORER); + item_menu->add_icon_item(get_icon("Filesystem", "EditorIcons"), TTR("Open in File Manager"), ITEM_MENU_SHOW_IN_EXPLORER); item_menu->set_position(item_list->get_global_position() + p_pos); item_menu->popup(); diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index e9ce2cb8ae..b18e4d0f35 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -3935,7 +3935,7 @@ void EditorNode::_scene_tab_input(const Ref<InputEvent> &p_input) { scene_tabs_context_menu->add_shortcut(ED_GET_SHORTCUT("editor/save_all_scenes"), FILE_SAVE_ALL_SCENES); if (scene_tabs->get_hovered_tab() >= 0) { scene_tabs_context_menu->add_separator(); - scene_tabs_context_menu->add_item(TTR("Show in filesystem"), FILE_SHOW_IN_FILESYSTEM); + scene_tabs_context_menu->add_item(TTR("Show in FileSystem"), FILE_SHOW_IN_FILESYSTEM); scene_tabs_context_menu->add_item(TTR("Play This Scene"), RUN_PLAY_SCENE); scene_tabs_context_menu->add_item(TTR("Close Tab"), FILE_CLOSE); } @@ -5181,7 +5181,7 @@ EditorNode::EditorNode() { p->add_separator(); p->add_shortcut(ED_SHORTCUT("editor/save_scene", TTR("Save Scene"), KEY_MASK_CMD + KEY_S), FILE_SAVE_SCENE); p->add_shortcut(ED_SHORTCUT("editor/save_scene_as", TTR("Save Scene As..."), KEY_MASK_SHIFT + KEY_MASK_CMD + KEY_S), FILE_SAVE_AS_SCENE); - p->add_shortcut(ED_SHORTCUT("editor/save_all_scenes", TTR("Save all Scenes"), KEY_MASK_ALT + KEY_MASK_SHIFT + KEY_MASK_CMD + KEY_S), FILE_SAVE_ALL_SCENES); + p->add_shortcut(ED_SHORTCUT("editor/save_all_scenes", TTR("Save All Scenes"), KEY_MASK_ALT + KEY_MASK_SHIFT + KEY_MASK_CMD + KEY_S), FILE_SAVE_ALL_SCENES); p->add_separator(); p->add_shortcut(ED_SHORTCUT("editor/close_scene", TTR("Close Scene"), KEY_MASK_SHIFT + KEY_MASK_CMD + KEY_W), FILE_CLOSE); p->add_separator(); diff --git a/editor/editor_properties.cpp b/editor/editor_properties.cpp index 5148c12160..b68ec97406 100644 --- a/editor/editor_properties.cpp +++ b/editor/editor_properties.cpp @@ -1802,8 +1802,13 @@ void EditorPropertyNodePath::_node_selected(const NodePath &p_path) { NodePath path = p_path; Node *base_node = Object::cast_to<Node>(get_edited_object()); - if (base_node == NULL && get_edited_object()->has_method("get_root_path")) { - base_node = get_edited_object()->call("get_root_path"); + if (base_node == NULL) { + if (Object::cast_to<Resource>(get_edited_object())) { + Node *to_node = get_node(p_path); + path = get_tree()->get_edited_scene_root()->get_path_to(to_node); + } else if (get_edited_object()->has_method("get_root_path")) { + base_node = get_edited_object()->call("get_root_path"); + } } if (base_node) { // for AnimationTrackKeyEdit path = base_node->get_path().rel_path_to(p_path); @@ -2216,7 +2221,7 @@ void EditorPropertyResource::_update_menu() { RES r = res; if (r.is_valid() && r->get_path().is_resource_file()) { menu->add_separator(); - menu->add_item(TTR("Show in File System"), OBJ_MENU_SHOW_IN_FILE_SYSTEM); + menu->add_item(TTR("Show in FileSystem"), OBJ_MENU_SHOW_IN_FILE_SYSTEM); } } else { } diff --git a/editor/filesystem_dock.cpp b/editor/filesystem_dock.cpp index 2136211faa..48bfa6fddb 100644 --- a/editor/filesystem_dock.cpp +++ b/editor/filesystem_dock.cpp @@ -2117,7 +2117,7 @@ void FileSystemDock::_file_and_folders_fill_popup(PopupMenu *p_popup, Vector<Str p_popup->add_item(TTR("New Resource..."), FILE_NEW_RESOURCE); String fpath = p_paths[0]; - String item_text = fpath.ends_with("/") ? TTR("Open In File Manager") : TTR("Show In File Manager"); + String item_text = fpath.ends_with("/") ? TTR("Open in File Manager") : TTR("Show in File Manager"); p_popup->add_item(item_text, FILE_SHOW_IN_EXPLORER); } } @@ -2128,8 +2128,8 @@ void FileSystemDock::_tree_rmb_select(const Vector2 &p_pos) { if (paths.size() == 1) { if (paths[0].ends_with("/")) { - tree_popup->add_item(TTR("Expand all"), FOLDER_EXPAND_ALL); - tree_popup->add_item(TTR("Collapse all"), FOLDER_COLLAPSE_ALL); + tree_popup->add_item(TTR("Expand All"), FOLDER_EXPAND_ALL); + tree_popup->add_item(TTR("Collapse All"), FOLDER_COLLAPSE_ALL); tree_popup->add_separator(); } } @@ -2175,7 +2175,7 @@ void FileSystemDock::_file_list_rmb_pressed(const Vector2 &p_pos) { file_list_popup->add_item(TTR("New Folder..."), FILE_NEW_FOLDER); file_list_popup->add_item(TTR("New Script..."), FILE_NEW_SCRIPT); file_list_popup->add_item(TTR("New Resource..."), FILE_NEW_RESOURCE); - file_list_popup->add_item(TTR("Show In File Manager"), FILE_SHOW_IN_EXPLORER); + file_list_popup->add_item(TTR("Show in File Manager"), FILE_SHOW_IN_EXPLORER); file_list_popup->set_position(files->get_global_position() + p_pos); file_list_popup->popup(); } diff --git a/editor/plugins/animation_blend_tree_editor_plugin.cpp b/editor/plugins/animation_blend_tree_editor_plugin.cpp index 205458fb1d..b83976270f 100644 --- a/editor/plugins/animation_blend_tree_editor_plugin.cpp +++ b/editor/plugins/animation_blend_tree_editor_plugin.cpp @@ -833,8 +833,6 @@ void AnimationNodeBlendTreeEditor::edit(const Ref<AnimationNode> &p_node) { if (p_node.is_valid()) { blend_tree = p_node; - } else { - blend_tree.unref(); } if (blend_tree.is_null()) { diff --git a/editor/plugins/script_editor_plugin.cpp b/editor/plugins/script_editor_plugin.cpp index ac69cc0df1..03b9f7938f 100644 --- a/editor/plugins/script_editor_plugin.cpp +++ b/editor/plugins/script_editor_plugin.cpp @@ -2998,7 +2998,7 @@ ScriptEditor::ScriptEditor(EditorNode *p_editor) { file_menu->get_popup()->add_separator(); file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/reload_script_soft", TTR("Soft Reload Script"), KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_R), FILE_TOOL_RELOAD_SOFT); file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/copy_path", TTR("Copy Script Path")), FILE_COPY_PATH); - file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/show_in_file_system", TTR("Show In File System")), SHOW_IN_FILE_SYSTEM); + file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/show_in_file_system", TTR("Show in FileSystem")), SHOW_IN_FILE_SYSTEM); file_menu->get_popup()->add_separator(); file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/history_previous", TTR("History Previous"), KEY_MASK_ALT | KEY_LEFT), WINDOW_PREV); diff --git a/editor/plugins/script_text_editor.cpp b/editor/plugins/script_text_editor.cpp index 27f5910d94..0796a93dc3 100644 --- a/editor/plugins/script_text_editor.cpp +++ b/editor/plugins/script_text_editor.cpp @@ -1583,8 +1583,8 @@ void ScriptTextEditor::register_editor() { ED_SHORTCUT("script_text_editor/complete_symbol", TTR("Complete Symbol"), KEY_MASK_CMD | KEY_SPACE); #endif ED_SHORTCUT("script_text_editor/trim_trailing_whitespace", TTR("Trim Trailing Whitespace"), KEY_MASK_CMD | KEY_MASK_ALT | KEY_T); - ED_SHORTCUT("script_text_editor/convert_indent_to_spaces", TTR("Convert Indent To Spaces"), KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_Y); - ED_SHORTCUT("script_text_editor/convert_indent_to_tabs", TTR("Convert Indent To Tabs"), KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_I); + ED_SHORTCUT("script_text_editor/convert_indent_to_spaces", TTR("Convert Indent to Spaces"), KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_Y); + ED_SHORTCUT("script_text_editor/convert_indent_to_tabs", TTR("Convert Indent to Tabs"), KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_I); ED_SHORTCUT("script_text_editor/auto_indent", TTR("Auto Indent"), KEY_MASK_CMD | KEY_I); #ifdef OSX_ENABLED diff --git a/editor/project_manager.cpp b/editor/project_manager.cpp index 83de5a646a..8c906e5f0b 100644 --- a/editor/project_manager.cpp +++ b/editor/project_manager.cpp @@ -1312,7 +1312,7 @@ void ProjectManager::_load_recent_projects() { show->set_modulate(Color(1, 1, 1, 0.5)); path_hb->add_child(show); show->connect("pressed", this, "_show_project", varray(path)); - show->set_tooltip(TTR("Show In File Manager")); + show->set_tooltip(TTR("Show in File Manager")); Label *fpath = memnew(Label(path)); fpath->set_name("path"); diff --git a/editor/property_editor.cpp b/editor/property_editor.cpp index 9ef6e4332c..8da75b7b3f 100644 --- a/editor/property_editor.cpp +++ b/editor/property_editor.cpp @@ -968,7 +968,7 @@ bool CustomPropertyEditor::edit(Object *p_owner, const String &p_name, Variant:: RES r = v; if (r.is_valid() && r->get_path().is_resource_file()) { menu->add_separator(); - menu->add_item(TTR("Show in File System"), OBJ_MENU_SHOW_IN_FILE_SYSTEM); + menu->add_item(TTR("Show in FileSystem"), OBJ_MENU_SHOW_IN_FILE_SYSTEM); } } else { } diff --git a/modules/csg/csg_shape.cpp b/modules/csg/csg_shape.cpp index 44044d2750..4eb798de11 100644 --- a/modules/csg/csg_shape.cpp +++ b/modules/csg/csg_shape.cpp @@ -598,8 +598,8 @@ CSGBrush *CSGMesh::_build_brush() { mw[j / 3] = mat; } } else { - int is = vertices.size(); - int as = avertices.size(); + int as = vertices.size(); + int is = avertices.size(); vertices.resize(as + is); smooth.resize((as + is) / 3); diff --git a/platform/android/os_android.cpp b/platform/android/os_android.cpp index 8e050c1d27..96ff226402 100644 --- a/platform/android/os_android.cpp +++ b/platform/android/os_android.cpp @@ -39,7 +39,7 @@ #include "file_access_android.h" #include "main/main.h" #include "servers/visual/visual_server_raster.h" -//#include "servers/visual/visual_server_wrap_mt.h" +#include "servers/visual/visual_server_wrap_mt.h" #ifdef ANDROID_NATIVE_ACTIVITY #include "dir_access_android.h" @@ -183,13 +183,11 @@ Error OS_Android::initialize(const VideoMode &p_desired, int p_video_driver, int video_driver_index = p_video_driver; visual_server = memnew(VisualServerRaster); - /* if (get_render_thread_mode() != RENDER_THREAD_UNSAFE) { - + if (get_render_thread_mode() != RENDER_THREAD_UNSAFE) { visual_server = memnew(VisualServerWrapMT(visual_server, false)); - };*/ + } visual_server->init(); - // visual_server->cursor_set_visible(false, 0); AudioDriverManager::initialize(p_audio_driver); diff --git a/platform/haiku/os_haiku.cpp b/platform/haiku/os_haiku.cpp index c80365f1f3..f9f12af817 100644 --- a/platform/haiku/os_haiku.cpp +++ b/platform/haiku/os_haiku.cpp @@ -117,16 +117,13 @@ Error OS_Haiku::initialize(const VideoMode &p_desired, int p_video_driver, int p #endif - visual_server = memnew(VisualServerRaster()); - - ERR_FAIL_COND_V(!visual_server, ERR_UNAVAILABLE); - - // TODO: enable multithreaded VS - /* + visual_server = memnew(VisualServerRaster); + // FIXME: Reimplement threaded rendering if (get_render_thread_mode() != RENDER_THREAD_UNSAFE) { - visual_server = memnew(VisualServerWrapMT(visual_server, get_render_thread_mode() == RENDER_SEPARATE_THREAD)); + visual_server = memnew(VisualServerWrapMT(visual_server, false)); } - */ + + ERR_FAIL_COND_V(!visual_server, ERR_UNAVAILABLE); video_driver_index = p_video_driver; diff --git a/platform/iphone/os_iphone.cpp b/platform/iphone/os_iphone.cpp index addef61ec7..e996a5905b 100644 --- a/platform/iphone/os_iphone.cpp +++ b/platform/iphone/os_iphone.cpp @@ -34,7 +34,7 @@ #include "drivers/gles3/rasterizer_gles3.h" #include "servers/visual/visual_server_raster.h" -//#include "servers/visual/visual_server_wrap_mt.h" +#include "servers/visual/visual_server_wrap_mt.h" #include "main/main.h" @@ -107,13 +107,11 @@ Error OSIPhone::initialize(const VideoMode &p_desired, int p_video_driver, int p RasterizerGLES3::register_config(); RasterizerGLES3::make_current(); - visual_server = memnew(VisualServerRaster()); - /* - FIXME: Reimplement threaded rendering? Or remove? + visual_server = memnew(VisualServerRaster); + // FIXME: Reimplement threaded rendering if (get_render_thread_mode() != RENDER_THREAD_UNSAFE) { visual_server = memnew(VisualServerWrapMT(visual_server, false)); - }; - */ + } visual_server->init(); //visual_server->cursor_set_visible(false, 0); diff --git a/platform/osx/os_osx.mm b/platform/osx/os_osx.mm index 1a5a56e933..77bf8a8146 100644 --- a/platform/osx/os_osx.mm +++ b/platform/osx/os_osx.mm @@ -1385,7 +1385,6 @@ Error OS_OSX::initialize(const VideoMode &p_desired, int p_video_driver, int p_a visual_server = memnew(VisualServerRaster); if (get_render_thread_mode() != RENDER_THREAD_UNSAFE) { - visual_server = memnew(VisualServerWrapMT(visual_server, get_render_thread_mode() == RENDER_SEPARATE_THREAD)); } diff --git a/platform/uwp/os_uwp.cpp b/platform/uwp/os_uwp.cpp index 6410378593..2209ecb20e 100644 --- a/platform/uwp/os_uwp.cpp +++ b/platform/uwp/os_uwp.cpp @@ -295,13 +295,10 @@ Error OSUWP::initialize(const VideoMode &p_desired, int p_video_driver, int p_au set_video_mode(vm); visual_server = memnew(VisualServerRaster); - // FIXME: Reimplement threaded rendering? Or remove? - /* + // FIXME: Reimplement threaded rendering if (get_render_thread_mode() != RENDER_THREAD_UNSAFE) { - - visual_server = memnew(VisualServerWrapMT(visual_server, get_render_thread_mode() == RENDER_SEPARATE_THREAD)); + visual_server = memnew(VisualServerWrapMT(visual_server, false)); } - */ visual_server->init(); input = memnew(InputDefault); diff --git a/platform/windows/os_windows.cpp b/platform/windows/os_windows.cpp index 3bbffd8fb7..f8705c4bff 100644 --- a/platform/windows/os_windows.cpp +++ b/platform/windows/os_windows.cpp @@ -1334,24 +1334,9 @@ Error OS_Windows::initialize(const VideoMode &p_desired, int p_video_driver, int visual_server = memnew(VisualServerRaster); if (get_render_thread_mode() != RENDER_THREAD_UNSAFE) { - visual_server = memnew(VisualServerWrapMT(visual_server, get_render_thread_mode() == RENDER_SEPARATE_THREAD)); } - /* - DEVMODE dmScreenSettings; // Device Mode - memset(&dmScreenSettings,0,sizeof(dmScreenSettings)); // Makes Sure Memory's Cleared - dmScreenSettings.dmSize=sizeof(dmScreenSettings); // Size Of The Devmode Structure - dmScreenSettings.dmPelsWidth = width; // Selected Screen Width - dmScreenSettings.dmPelsHeight = height; // Selected Screen Height - dmScreenSettings.dmBitsPerPel = bits; // Selected Bits Per Pixel - dmScreenSettings.dmFields=DM_BITSPERPEL|DM_PELSWIDTH|DM_PELSHEIGHT; - if (ChangeDisplaySettings(&dmScreenSettings,CDS_FULLSCREEN)!=DISP_CHANGE_SUCCESSFUL) - - - - - */ visual_server->init(); input = memnew(InputDefault); diff --git a/platform/x11/os_x11.cpp b/platform/x11/os_x11.cpp index 88c2c8aec6..8ba5833796 100644 --- a/platform/x11/os_x11.cpp +++ b/platform/x11/os_x11.cpp @@ -342,12 +342,12 @@ Error OS_X11::initialize(const VideoMode &p_desired, int p_video_driver, int p_a context_gl->set_use_vsync(current_videomode.use_vsync); #endif - visual_server = memnew(VisualServerRaster); + visual_server = memnew(VisualServerRaster); if (get_render_thread_mode() != RENDER_THREAD_UNSAFE) { - visual_server = memnew(VisualServerWrapMT(visual_server, get_render_thread_mode() == RENDER_SEPARATE_THREAD)); } + if (current_videomode.maximized) { current_videomode.maximized = false; set_window_maximized(true); diff --git a/scene/gui/popup_menu.cpp b/scene/gui/popup_menu.cpp index 3239641c2f..f84b75d8d8 100644 --- a/scene/gui/popup_menu.cpp +++ b/scene/gui/popup_menu.cpp @@ -557,6 +557,21 @@ void PopupMenu::_notification(int p_what) { mouse_over = -1; update(); } + + for (int i = 0; i < items.size(); i++) { + if (items[i].submenu == "") + continue; + + Node *n = get_node(items[i].submenu); + if (!n) + continue; + + PopupMenu *pm = Object::cast_to<PopupMenu>(n); + if (!pm || !pm->is_visible()) + continue; + + pm->hide(); + } } break; } } @@ -1012,8 +1027,7 @@ bool PopupMenu::activate_item_by_event(const Ref<InputEvent> &p_event, bool p_fo code |= KEY_MASK_SHIFT; } - int il = items.size(); - for (int i = 0; i < il; i++) { + for (int i = 0; i < items.size(); i++) { if (is_item_disabled(i) || items[i].shortcut_is_disabled) continue; diff --git a/scene/main/canvas_layer.cpp b/scene/main/canvas_layer.cpp index a2e890e7a7..0f5fd99281 100644 --- a/scene/main/canvas_layer.cpp +++ b/scene/main/canvas_layer.cpp @@ -35,7 +35,7 @@ void CanvasLayer::set_layer(int p_xform) { layer = p_xform; if (viewport.is_valid()) - VisualServer::get_singleton()->viewport_set_canvas_layer(viewport, canvas, layer); + VisualServer::get_singleton()->viewport_set_canvas_stacking(viewport, canvas, layer, get_position_in_parent()); } int CanvasLayer::get_layer() const { @@ -149,7 +149,7 @@ void CanvasLayer::_notification(int p_what) { viewport = vp->get_viewport_rid(); VisualServer::get_singleton()->viewport_attach_canvas(viewport, canvas); - VisualServer::get_singleton()->viewport_set_canvas_layer(viewport, canvas, layer); + VisualServer::get_singleton()->viewport_set_canvas_stacking(viewport, canvas, layer, get_position_in_parent()); VisualServer::get_singleton()->viewport_set_canvas_transform(viewport, canvas, transform); } break; @@ -159,6 +159,10 @@ void CanvasLayer::_notification(int p_what) { viewport = RID(); } break; + case NOTIFICATION_MOVED_IN_PARENT: { + + VisualServer::get_singleton()->viewport_set_canvas_stacking(viewport, canvas, layer, get_position_in_parent()); + } break; } } @@ -201,7 +205,7 @@ void CanvasLayer::set_custom_viewport(Node *p_viewport) { viewport = vp->get_viewport_rid(); VisualServer::get_singleton()->viewport_attach_canvas(viewport, canvas); - VisualServer::get_singleton()->viewport_set_canvas_layer(viewport, canvas, layer); + VisualServer::get_singleton()->viewport_set_canvas_stacking(viewport, canvas, layer, get_position_in_parent()); VisualServer::get_singleton()->viewport_set_canvas_transform(viewport, canvas, transform); } } diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp index 6bf1d12086..a28b6fd6de 100644 --- a/scene/main/viewport.cpp +++ b/scene/main/viewport.cpp @@ -1839,8 +1839,16 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) { MenuButton *popup_menu_parent = NULL; MenuButton *menu_button = Object::cast_to<MenuButton>(over); - if (popup_menu) + if (popup_menu) { popup_menu_parent = Object::cast_to<MenuButton>(popup_menu->get_parent()); + if (!popup_menu_parent) { + // Go through the parents to see if there's a MenuButton at the end. + while (Object::cast_to<PopupMenu>(popup_menu->get_parent())) { + popup_menu = Object::cast_to<PopupMenu>(popup_menu->get_parent()); + } + popup_menu_parent = Object::cast_to<MenuButton>(popup_menu->get_parent()); + } + } // If the mouse is over a menu button, this menu will open automatically // if there is already a pop-up menu open at the same hierarchical level. diff --git a/scene/resources/dynamic_font.cpp b/scene/resources/dynamic_font.cpp index 458cbf6718..7422c56eee 100644 --- a/scene/resources/dynamic_font.cpp +++ b/scene/resources/dynamic_font.cpp @@ -1029,7 +1029,7 @@ void DynamicFont::_bind_methods() { Mutex *DynamicFont::dynamic_font_mutex = NULL; -SelfList<DynamicFont>::List DynamicFont::dynamic_fonts; +SelfList<DynamicFont>::List *DynamicFont::dynamic_fonts = NULL; DynamicFont::DynamicFont() : font_list(this) { @@ -1041,29 +1041,31 @@ DynamicFont::DynamicFont() : spacing_char = 0; spacing_space = 0; outline_color = Color(1, 1, 1); - if (dynamic_font_mutex) + if (dynamic_font_mutex) { dynamic_font_mutex->lock(); - dynamic_fonts.add(&font_list); - if (dynamic_font_mutex) + dynamic_fonts->add(&font_list); dynamic_font_mutex->unlock(); + } } DynamicFont::~DynamicFont() { - - if (dynamic_font_mutex) + if (dynamic_font_mutex) { dynamic_font_mutex->lock(); - dynamic_fonts.remove(&font_list); - if (dynamic_font_mutex) + dynamic_fonts->remove(&font_list); dynamic_font_mutex->unlock(); + } } void DynamicFont::initialize_dynamic_fonts() { + dynamic_fonts = memnew(SelfList<DynamicFont>::List()); dynamic_font_mutex = Mutex::create(); } void DynamicFont::finish_dynamic_fonts() { memdelete(dynamic_font_mutex); dynamic_font_mutex = NULL; + memdelete(dynamic_fonts); + dynamic_fonts = NULL; } void DynamicFont::update_oversampling() { @@ -1073,7 +1075,7 @@ void DynamicFont::update_oversampling() { if (dynamic_font_mutex) dynamic_font_mutex->lock(); - SelfList<DynamicFont> *E = dynamic_fonts.first(); + SelfList<DynamicFont> *E = dynamic_fonts->first(); while (E) { if (E->self()->data_at_size.is_valid()) { diff --git a/scene/resources/dynamic_font.h b/scene/resources/dynamic_font.h index afda48a566..bd3f84d62c 100644 --- a/scene/resources/dynamic_font.h +++ b/scene/resources/dynamic_font.h @@ -285,7 +285,7 @@ public: SelfList<DynamicFont> font_list; static Mutex *dynamic_font_mutex; - static SelfList<DynamicFont>::List dynamic_fonts; + static SelfList<DynamicFont>::List *dynamic_fonts; static void initialize_dynamic_fonts(); static void finish_dynamic_fonts(); diff --git a/scene/resources/primitive_meshes.cpp b/scene/resources/primitive_meshes.cpp index 63aa44e1d8..28af3d3220 100644 --- a/scene/resources/primitive_meshes.cpp +++ b/scene/resources/primitive_meshes.cpp @@ -1282,7 +1282,7 @@ void PrismMesh::_bind_methods() { ClassDB::bind_method(D_METHOD("get_subdivide_depth"), &PrismMesh::get_subdivide_depth); ADD_PROPERTY(PropertyInfo(Variant::REAL, "left_to_right", PROPERTY_HINT_RANGE, "-2.0,2.0,0.1"), "set_left_to_right", "get_left_to_right"); - ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "size"), "set_size", "get_size"); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "size"), "set_size", "get_size"); ADD_PROPERTY(PropertyInfo(Variant::INT, "subdivide_width", PROPERTY_HINT_RANGE, "0,100,1,or_greater"), "set_subdivide_width", "get_subdivide_width"); ADD_PROPERTY(PropertyInfo(Variant::INT, "subdivide_height", PROPERTY_HINT_RANGE, "0,100,1,or_greater"), "set_subdivide_height", "get_subdivide_height"); ADD_PROPERTY(PropertyInfo(Variant::INT, "subdivide_depth", PROPERTY_HINT_RANGE, "0,100,1,or_greater"), "set_subdivide_depth", "get_subdivide_depth"); diff --git a/servers/physics/area_pair_sw.cpp b/servers/physics/area_pair_sw.cpp index d2fef0ab77..5e295edcd1 100644 --- a/servers/physics/area_pair_sw.cpp +++ b/servers/physics/area_pair_sw.cpp @@ -147,10 +147,10 @@ Area2PairSW::~Area2PairSW() { if (colliding) { - if (area_b->has_area_monitor_callback() && area_a->is_monitorable()) + if (area_b->has_area_monitor_callback()) area_b->remove_area_from_query(area_a, shape_a, shape_b); - if (area_a->has_area_monitor_callback() && area_b->is_monitorable()) + if (area_a->has_area_monitor_callback()) area_a->remove_area_from_query(area_b, shape_b, shape_a); } diff --git a/servers/physics_2d/area_pair_2d_sw.cpp b/servers/physics_2d/area_pair_2d_sw.cpp index 9d515d2183..cdd35cf657 100644 --- a/servers/physics_2d/area_pair_2d_sw.cpp +++ b/servers/physics_2d/area_pair_2d_sw.cpp @@ -147,10 +147,10 @@ Area2Pair2DSW::~Area2Pair2DSW() { if (colliding) { - if (area_b->has_area_monitor_callback() && area_a->is_monitorable()) + if (area_b->has_area_monitor_callback()) area_b->remove_area_from_query(area_a, shape_a, shape_b); - if (area_a->has_area_monitor_callback() && area_b->is_monitorable()) + if (area_a->has_area_monitor_callback()) area_a->remove_area_from_query(area_b, shape_b, shape_a); } diff --git a/servers/visual/visual_server_raster.h b/servers/visual/visual_server_raster.h index 62ba2eab69..fc77dcc562 100644 --- a/servers/visual/visual_server_raster.h +++ b/servers/visual/visual_server_raster.h @@ -474,7 +474,7 @@ public: BIND2(viewport_set_transparent_background, RID, bool) BIND2(viewport_set_global_canvas_transform, RID, const Transform2D &) - BIND3(viewport_set_canvas_layer, RID, RID, int) + BIND4(viewport_set_canvas_stacking, RID, RID, int, int) BIND2(viewport_set_shadow_atlas_size, RID, int) BIND3(viewport_set_shadow_atlas_quadrant_subdivision, RID, int, int) BIND2(viewport_set_msaa, RID, ViewportMSAA) diff --git a/servers/visual/visual_server_viewport.cpp b/servers/visual/visual_server_viewport.cpp index b286533590..571b71db85 100644 --- a/servers/visual/visual_server_viewport.cpp +++ b/servers/visual/visual_server_viewport.cpp @@ -137,7 +137,7 @@ void VisualServerViewport::_draw_viewport(Viewport *p_viewport, ARVRInterface::E } } - canvas_map[Viewport::CanvasKey(E->key(), E->get().layer)] = &E->get(); + canvas_map[Viewport::CanvasKey(E->key(), E->get().layer, E->get().sublayer)] = &E->get(); } if (lights_with_shadow) { @@ -176,7 +176,7 @@ void VisualServerViewport::_draw_viewport(Viewport *p_viewport, ARVRInterface::E VSG::rasterizer->restore_render_target(); - if (scenario_draw_canvas_bg && canvas_map.front() && canvas_map.front()->key().layer > scenario_canvas_max_layer) { + if (scenario_draw_canvas_bg && canvas_map.front() && canvas_map.front()->key().get_layer() > scenario_canvas_max_layer) { Ref<ARVRInterface> arvr_interface = ARVRServer::get_singleton()->get_primary_interface(); if (!can_draw_3d) { @@ -209,7 +209,7 @@ void VisualServerViewport::_draw_viewport(Viewport *p_viewport, ARVRInterface::E VSG::canvas->render_canvas(canvas, xform, canvas_lights, lights_with_mask, clip_rect); i++; - if (scenario_draw_canvas_bg && E->key().layer >= scenario_canvas_max_layer) { + if (scenario_draw_canvas_bg && E->key().get_layer() >= scenario_canvas_max_layer) { Ref<ARVRInterface> arvr_interface = ARVRServer::get_singleton()->get_primary_interface(); if (!can_draw_3d) { @@ -496,6 +496,7 @@ void VisualServerViewport::viewport_attach_canvas(RID p_viewport, RID p_canvas) canvas->viewports.insert(p_viewport); viewport->canvas_map[p_canvas] = Viewport::CanvasData(); viewport->canvas_map[p_canvas].layer = 0; + viewport->canvas_map[p_canvas].sublayer = 0; viewport->canvas_map[p_canvas].canvas = canvas; } @@ -534,13 +535,14 @@ void VisualServerViewport::viewport_set_global_canvas_transform(RID p_viewport, viewport->global_transform = p_transform; } -void VisualServerViewport::viewport_set_canvas_layer(RID p_viewport, RID p_canvas, int p_layer) { +void VisualServerViewport::viewport_set_canvas_stacking(RID p_viewport, RID p_canvas, int p_layer, int p_sublayer) { Viewport *viewport = viewport_owner.getornull(p_viewport); ERR_FAIL_COND(!viewport); ERR_FAIL_COND(!viewport->canvas_map.has(p_canvas)); viewport->canvas_map[p_canvas].layer = p_layer; + viewport->canvas_map[p_canvas].sublayer = p_sublayer; } void VisualServerViewport::viewport_set_shadow_atlas_size(RID p_viewport, int p_size) { diff --git a/servers/visual/visual_server_viewport.h b/servers/visual/visual_server_viewport.h index cb7912d6f4..66baa48458 100644 --- a/servers/visual/visual_server_viewport.h +++ b/servers/visual/visual_server_viewport.h @@ -78,17 +78,21 @@ public: struct CanvasKey { - int layer; + int64_t stacking; RID canvas; bool operator<(const CanvasKey &p_canvas) const { - if (layer == p_canvas.layer) return canvas < p_canvas.canvas; - return layer < p_canvas.layer; + if (stacking == p_canvas.stacking) + return canvas < p_canvas.canvas; + return stacking < p_canvas.stacking; + } + CanvasKey() { + stacking = 0; } - CanvasKey() { layer = 0; } - CanvasKey(const RID &p_canvas, int p_layer) { + CanvasKey(const RID &p_canvas, int p_layer, int p_sublayer) { canvas = p_canvas; - layer = p_layer; + stacking = ((int64_t)p_layer << 32) + p_sublayer; } + int get_layer() const { return stacking >> 32; } }; struct CanvasData { @@ -96,6 +100,7 @@ public: CanvasBase *canvas; Transform2D transform; int layer; + int sublayer; }; Transform2D global_transform; @@ -176,7 +181,7 @@ public: void viewport_set_transparent_background(RID p_viewport, bool p_enabled); void viewport_set_global_canvas_transform(RID p_viewport, const Transform2D &p_transform); - void viewport_set_canvas_layer(RID p_viewport, RID p_canvas, int p_layer); + void viewport_set_canvas_stacking(RID p_viewport, RID p_canvas, int p_layer, int p_sublayer); void viewport_set_shadow_atlas_size(RID p_viewport, int p_size); void viewport_set_shadow_atlas_quadrant_subdivision(RID p_viewport, int p_quadrant, int p_subdiv); diff --git a/servers/visual/visual_server_wrap_mt.h b/servers/visual/visual_server_wrap_mt.h index e4d69121f0..0b435a26aa 100644 --- a/servers/visual/visual_server_wrap_mt.h +++ b/servers/visual/visual_server_wrap_mt.h @@ -400,7 +400,7 @@ public: FUNC2(viewport_set_transparent_background, RID, bool) FUNC2(viewport_set_global_canvas_transform, RID, const Transform2D &) - FUNC3(viewport_set_canvas_layer, RID, RID, int) + FUNC4(viewport_set_canvas_stacking, RID, RID, int, int) FUNC2(viewport_set_shadow_atlas_size, RID, int) FUNC3(viewport_set_shadow_atlas_quadrant_subdivision, RID, int, int) FUNC2(viewport_set_msaa, RID, ViewportMSAA) diff --git a/servers/visual_server.cpp b/servers/visual_server.cpp index 164be132b8..b8477daa66 100644 --- a/servers/visual_server.cpp +++ b/servers/visual_server.cpp @@ -1890,7 +1890,7 @@ void VisualServer::_bind_methods() { ClassDB::bind_method(D_METHOD("viewport_set_canvas_transform", "viewport", "canvas", "offset"), &VisualServer::viewport_set_canvas_transform); ClassDB::bind_method(D_METHOD("viewport_set_transparent_background", "viewport", "enabled"), &VisualServer::viewport_set_transparent_background); ClassDB::bind_method(D_METHOD("viewport_set_global_canvas_transform", "viewport", "transform"), &VisualServer::viewport_set_global_canvas_transform); - ClassDB::bind_method(D_METHOD("viewport_set_canvas_layer", "viewport", "canvas", "layer"), &VisualServer::viewport_set_canvas_layer); + ClassDB::bind_method(D_METHOD("viewport_set_canvas_stacking", "viewport", "canvas", "layer", "sublayer"), &VisualServer::viewport_set_canvas_stacking); ClassDB::bind_method(D_METHOD("viewport_set_shadow_atlas_size", "viewport", "size"), &VisualServer::viewport_set_shadow_atlas_size); ClassDB::bind_method(D_METHOD("viewport_set_shadow_atlas_quadrant_subdivision", "viewport", "quadrant", "subdivision"), &VisualServer::viewport_set_shadow_atlas_quadrant_subdivision); ClassDB::bind_method(D_METHOD("viewport_set_msaa", "viewport", "msaa"), &VisualServer::viewport_set_msaa); diff --git a/servers/visual_server.h b/servers/visual_server.h index 9d98fca21b..4db6a6a39b 100644 --- a/servers/visual_server.h +++ b/servers/visual_server.h @@ -644,7 +644,7 @@ public: virtual void viewport_set_transparent_background(RID p_viewport, bool p_enabled) = 0; virtual void viewport_set_global_canvas_transform(RID p_viewport, const Transform2D &p_transform) = 0; - virtual void viewport_set_canvas_layer(RID p_viewport, RID p_canvas, int p_layer) = 0; + virtual void viewport_set_canvas_stacking(RID p_viewport, RID p_canvas, int p_layer, int p_sublayer) = 0; virtual void viewport_set_shadow_atlas_size(RID p_viewport, int p_size) = 0; virtual void viewport_set_shadow_atlas_quadrant_subdivision(RID p_viewport, int p_quadrant, int p_subdiv) = 0; |