Fix quick open dialog recursive problem
This commit is contained in:
parent
788beb36dc
commit
3b9c77b614
4 changed files with 81 additions and 69 deletions
|
|
@ -5392,6 +5392,73 @@ void EditorNode::add_io_warning(const String &p_warning) {
|
|||
}
|
||||
}
|
||||
|
||||
bool EditorNode::find_recursive_resources(const Variant &p_variant, HashSet<Resource *> &r_resources_found) {
|
||||
switch (p_variant.get_type()) {
|
||||
case Variant::ARRAY: {
|
||||
Array a = p_variant;
|
||||
for (int i = 0; i < a.size(); i++) {
|
||||
Variant v2 = a[i];
|
||||
if (v2.get_type() != Variant::ARRAY && v2.get_type() != Variant::DICTIONARY && v2.get_type() != Variant::OBJECT) {
|
||||
continue;
|
||||
}
|
||||
if (find_recursive_resources(v2, r_resources_found)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} break;
|
||||
case Variant::DICTIONARY: {
|
||||
Dictionary d = p_variant;
|
||||
for (const KeyValue<Variant, Variant> &kv : d) {
|
||||
const Variant &k = kv.key;
|
||||
const Variant &v2 = kv.value;
|
||||
if (k.get_type() == Variant::ARRAY || k.get_type() == Variant::DICTIONARY || k.get_type() == Variant::OBJECT) {
|
||||
if (find_recursive_resources(k, r_resources_found)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (v2.get_type() == Variant::ARRAY || v2.get_type() == Variant::DICTIONARY || v2.get_type() == Variant::OBJECT) {
|
||||
if (find_recursive_resources(v2, r_resources_found)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
} break;
|
||||
case Variant::OBJECT: {
|
||||
Ref<Resource> r = p_variant;
|
||||
|
||||
if (r.is_null()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (r_resources_found.has(r.ptr())) {
|
||||
return true;
|
||||
}
|
||||
|
||||
r_resources_found.insert(r.ptr());
|
||||
|
||||
List<PropertyInfo> plist;
|
||||
r->get_property_list(&plist);
|
||||
for (const PropertyInfo &pinfo : plist) {
|
||||
if (!(pinfo.usage & PROPERTY_USAGE_STORAGE)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (pinfo.type != Variant::ARRAY && pinfo.type != Variant::DICTIONARY && pinfo.type != Variant::OBJECT) {
|
||||
continue;
|
||||
}
|
||||
if (find_recursive_resources(r->get(pinfo.name), r_resources_found)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
r_resources_found.erase(r.ptr());
|
||||
} break;
|
||||
default: {
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool EditorNode::_find_scene_in_use(Node *p_node, const String &p_path) const {
|
||||
if (p_node->get_scene_file_path() == p_path) {
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -767,6 +767,7 @@ public:
|
|||
static void disambiguate_filenames(const Vector<String> p_full_paths, Vector<String> &r_filenames);
|
||||
static void add_io_error(const String &p_error);
|
||||
static void add_io_warning(const String &p_warning);
|
||||
static bool find_recursive_resources(const Variant &p_variant, HashSet<Resource *> &r_resources_found);
|
||||
|
||||
static void progress_add_task(const String &p_task, const String &p_label, int p_steps, bool p_can_cancel = false);
|
||||
static bool progress_task_step(const String &p_task, const String &p_state, int p_step = -1, bool p_force_refresh = true);
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@
|
|||
#include "editor/editor_undo_redo_manager.h"
|
||||
#include "editor/file_system/editor_file_system.h"
|
||||
#include "editor/file_system/editor_paths.h"
|
||||
#include "editor/gui/editor_toaster.h"
|
||||
#include "editor/inspector/editor_resource_preview.h"
|
||||
#include "editor/inspector/multi_node_edit.h"
|
||||
#include "editor/settings/editor_settings.h"
|
||||
|
|
@ -232,6 +233,16 @@ void EditorQuickOpenDialog::preview_property() {
|
|||
Ref<Resource> loaded_resource = ResourceLoader::load(container->get_selected());
|
||||
ERR_FAIL_COND_MSG(loaded_resource.is_null(), "Cannot load resource from path '" + container->get_selected() + "'.");
|
||||
|
||||
Resource *res = Object::cast_to<Resource>(property_object);
|
||||
if (res) {
|
||||
HashSet<Resource *> resources_found;
|
||||
resources_found.insert(res);
|
||||
if (EditorNode::find_recursive_resources(loaded_resource, resources_found)) {
|
||||
EditorToaster::get_singleton()->popup_str(TTR("Recursion detected, quick preview failed."), EditorToaster::SEVERITY_ERROR);
|
||||
loaded_resource = Ref<Resource>();
|
||||
}
|
||||
}
|
||||
|
||||
// MultiNodeEdit has adding to the undo/redo stack baked into its set function.
|
||||
// As such, we have to specifically call a version of its setter that doesn't
|
||||
// create undo/redo actions.
|
||||
|
|
|
|||
|
|
@ -3339,82 +3339,15 @@ void EditorPropertyResource::_resource_selected(const Ref<Resource> &p_resource,
|
|||
}
|
||||
}
|
||||
|
||||
static bool _find_recursive_resources(const Variant &v, HashSet<Resource *> &resources_found) {
|
||||
switch (v.get_type()) {
|
||||
case Variant::ARRAY: {
|
||||
Array a = v;
|
||||
for (int i = 0; i < a.size(); i++) {
|
||||
Variant v2 = a[i];
|
||||
if (v2.get_type() != Variant::ARRAY && v2.get_type() != Variant::DICTIONARY && v2.get_type() != Variant::OBJECT) {
|
||||
continue;
|
||||
}
|
||||
if (_find_recursive_resources(v2, resources_found)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} break;
|
||||
case Variant::DICTIONARY: {
|
||||
Dictionary d = v;
|
||||
for (const KeyValue<Variant, Variant> &kv : d) {
|
||||
const Variant &k = kv.key;
|
||||
const Variant &v2 = kv.value;
|
||||
if (k.get_type() == Variant::ARRAY || k.get_type() == Variant::DICTIONARY || k.get_type() == Variant::OBJECT) {
|
||||
if (_find_recursive_resources(k, resources_found)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (v2.get_type() == Variant::ARRAY || v2.get_type() == Variant::DICTIONARY || v2.get_type() == Variant::OBJECT) {
|
||||
if (_find_recursive_resources(v2, resources_found)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
} break;
|
||||
case Variant::OBJECT: {
|
||||
Ref<Resource> r = v;
|
||||
|
||||
if (r.is_null()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (resources_found.has(r.ptr())) {
|
||||
return true;
|
||||
}
|
||||
|
||||
resources_found.insert(r.ptr());
|
||||
|
||||
List<PropertyInfo> plist;
|
||||
r->get_property_list(&plist);
|
||||
for (const PropertyInfo &pinfo : plist) {
|
||||
if (!(pinfo.usage & PROPERTY_USAGE_STORAGE)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (pinfo.type != Variant::ARRAY && pinfo.type != Variant::DICTIONARY && pinfo.type != Variant::OBJECT) {
|
||||
continue;
|
||||
}
|
||||
if (_find_recursive_resources(r->get(pinfo.name), resources_found)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
resources_found.erase(r.ptr());
|
||||
} break;
|
||||
default: {
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void EditorPropertyResource::_resource_changed(const Ref<Resource> &p_resource) {
|
||||
Resource *r = Object::cast_to<Resource>(get_edited_object());
|
||||
if (r) {
|
||||
// Check for recursive setting of resource
|
||||
HashSet<Resource *> resources_found;
|
||||
resources_found.insert(r);
|
||||
bool found = _find_recursive_resources(p_resource, resources_found);
|
||||
bool found = EditorNode::find_recursive_resources(p_resource, resources_found);
|
||||
if (found) {
|
||||
EditorNode::get_singleton()->show_warning(TTR("Recursion detected, unable to assign resource to property."));
|
||||
callable_mp(EditorNode::get_singleton(), &EditorNode::show_warning).call_deferred(TTR("Recursion detected, unable to assign resource to property."), TTR("Warning!"));
|
||||
emit_changed(get_edited_property(), Ref<Resource>());
|
||||
update_property();
|
||||
return;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue