diff --git a/editor/docks/filesystem_dock.cpp b/editor/docks/filesystem_dock.cpp index 529786c5e70..020d37b4701 100644 --- a/editor/docks/filesystem_dock.cpp +++ b/editor/docks/filesystem_dock.cpp @@ -1925,6 +1925,8 @@ void FileSystemDock::_convert_dialog_action() { Ref original_resource = selected_resources.get(i); Ref new_resource = converted_resources.get(i); + // Notify plugins that the original resource is removed. + emit_signal(SNAME("file_removed"), original_resource->get_path()); // Overwrite the path. new_resource->set_path(original_resource->get_path(), true); diff --git a/editor/inspector/editor_resource_picker.cpp b/editor/inspector/editor_resource_picker.cpp index 141c05498eb..8a4ea9d6e9b 100644 --- a/editor/inspector/editor_resource_picker.cpp +++ b/editor/inspector/editor_resource_picker.cpp @@ -484,8 +484,11 @@ void EditorResourcePicker::_edit_menu_cbk(int p_which) { Vector> conversions = EditorNode::get_singleton()->find_resource_conversion_plugin_for_resource(edited_resource); ERR_FAIL_INDEX(to_type, conversions.size()); - edited_resource = conversions[to_type]->convert(edited_resource); - _resource_changed(); + Ref converted_resource = conversions[to_type]->convert(edited_resource); + if (converted_resource.is_valid()) { + edited_resource = converted_resource; + _resource_changed(); + } break; } diff --git a/editor/shader/visual_shader_editor_plugin.cpp b/editor/shader/visual_shader_editor_plugin.cpp index 33b6088a112..bb6562a9b17 100644 --- a/editor/shader/visual_shader_editor_plugin.cpp +++ b/editor/shader/visual_shader_editor_plugin.cpp @@ -41,6 +41,7 @@ #include "editor/editor_string_names.h" #include "editor/editor_undo_redo_manager.h" #include "editor/file_system/editor_paths.h" +#include "editor/gui/editor_toaster.h" #include "editor/inspector/editor_properties.h" #include "editor/inspector/editor_properties_vector.h" #include "editor/scene/curve_editor_plugin.h" @@ -8446,6 +8447,20 @@ bool VisualShaderConversionPlugin::handles(const Ref &p_resource) cons Ref VisualShaderConversionPlugin::convert(const Ref &p_resource) const { Ref vshader = p_resource; ERR_FAIL_COND_V(vshader.is_null(), Ref()); + int embed = vshader->has_node_embeds(); + + EditorToaster *toast = EditorToaster::get_singleton(); + if (toast == nullptr) { + ERR_FAIL_COND_V_MSG(embed == 2, Ref(), "Cannot convert VisualShader to GDShader because VisualShader has embedded subresources."); + if (embed == 1) { + WARN_PRINT("Visual Shader conversion cannot convert external dependencies. Resource references from Nodes will have to be rebound as ShaderParameters on a Material."); + } + } else if (embed == 2) { + toast->popup_str(TTR("Cannot convert VisualShader to GDShader because VisualShader has embedded subresources."), EditorToaster::SEVERITY_ERROR); + return Ref(); + } else if (embed == 1) { + toast->popup_str(TTR("Visual Shader conversion cannot convert external dependencies. Resource references from Nodes will have to be rebound as ShaderParameters on a Material."), EditorToaster::SEVERITY_WARNING); + } Ref shader; shader.instantiate(); diff --git a/scene/resources/visual_shader.cpp b/scene/resources/visual_shader.cpp index cd5ce0a6657..a2abb10d7a4 100644 --- a/scene/resources/visual_shader.cpp +++ b/scene/resources/visual_shader.cpp @@ -967,6 +967,37 @@ void VisualShader::set_node_position(Type p_type, int p_id, const Vector2 &p_pos g->nodes[p_id].position = p_position; } +// Returns 0 if no embeds, 1 if external embeds, 2 if builtin embeds +int VisualShader::has_node_embeds() const { + bool external_embeds = false; + for (int i = 0; i < TYPE_MAX; i++) { + for (const KeyValue &E : graph[i].nodes) { + List props; + E.value.node->get_property_list(&props); + // For classes that inherit from VisualShaderNode, the class properties start at the 12th, and the last value is always 'script' + for (int j = 12; j < props.size() - 1; j++) { + // VisualShaderNodeCustom cannot have embeds + if (props.get(j).name == "VisualShaderNodeCustom") { + break; + } + // Ref properties get classed as type Variant::Object + if (props.get(j).type == Variant::OBJECT) { + Ref res = E.value.node->get(props.get(j).name); + if (res.is_valid()) { + if (res->is_built_in()) { + return 2; + } else { + external_embeds = true; + } + } + } + } + } + } + + return external_embeds; +} + Vector2 VisualShader::get_node_position(Type p_type, int p_id) const { ERR_FAIL_INDEX_V(p_type, TYPE_MAX, Vector2()); const Graph *g = &graph[p_type]; diff --git a/scene/resources/visual_shader.h b/scene/resources/visual_shader.h index 6ca86c7b47b..5e707092f21 100644 --- a/scene/resources/visual_shader.h +++ b/scene/resources/visual_shader.h @@ -183,6 +183,7 @@ public: // internal methods void add_node(Type p_type, const Ref &p_node, const Vector2 &p_position, int p_id); void set_node_position(Type p_type, int p_id, const Vector2 &p_position); + int has_node_embeds() const; void add_varying(const String &p_name, VaryingMode p_mode, VaryingType p_type); void remove_varying(const String &p_name);