Make Inspector search inside sub-resources

This commit is contained in:
Michael Alexsander 2024-12-03 12:20:28 -03:00
parent 1aaf20b1f1
commit 753900188a
No known key found for this signature in database
GPG key ID: A9C91EE110F4EABA
4 changed files with 168 additions and 17 deletions

View file

@ -37,6 +37,7 @@
#include "editor/editor_feature_profile.h"
#include "editor/editor_main_screen.h"
#include "editor/editor_node.h"
#include "editor/editor_properties.h"
#include "editor/editor_property_name_processor.h"
#include "editor/editor_settings.h"
#include "editor/editor_string_names.h"
@ -70,6 +71,126 @@ bool EditorInspector::_property_path_matches(const String &p_property_path, cons
return false;
}
bool EditorInspector::_resource_properties_matches(const Ref<Resource> &p_resource, const String &p_filter) {
String group;
String group_base;
String subgroup;
String subgroup_base;
List<PropertyInfo> plist;
p_resource->get_property_list(&plist, true);
// Employ a lighter version of the update_tree() property listing to find a match.
for (PropertyInfo &p : plist) {
if (p.usage & PROPERTY_USAGE_SUBGROUP) {
subgroup = p.name;
subgroup_base = p.hint_string.get_slicec(',', 0);
continue;
} else if (p.usage & PROPERTY_USAGE_GROUP) {
group = p.name;
group_base = p.hint_string.get_slicec(',', 0);
subgroup = "";
subgroup_base = "";
continue;
} else if (p.usage & PROPERTY_USAGE_CATEGORY) {
group = "";
group_base = "";
subgroup = "";
subgroup_base = "";
continue;
} else if (p.name.begins_with("metadata/_") || !(p.usage & PROPERTY_USAGE_EDITOR) || _is_property_disabled_by_feature_profile(p.name) ||
(p_filter.is_empty() && restrict_to_basic && !(p.usage & PROPERTY_USAGE_EDITOR_BASIC_SETTING))) {
// Ignore properties that are not supposed to be in the inspector.
continue;
}
if (p.usage & PROPERTY_USAGE_HIGH_END_GFX && RS::get_singleton()->is_low_end()) {
// Do not show this property in low end gfx.
continue;
}
if (p.name == "script") {
// The script is always hidden in sub inspectors.
continue;
}
if (p.name.begins_with("metadata/") && bool(object->call(SNAME("_hide_metadata_from_inspector")))) {
// Hide metadata from inspector if required.
continue;
}
String path = p.name;
// Check if we exit or not a subgroup. If there is a prefix, remove it from the property label string.
if (!subgroup.is_empty() && !subgroup_base.is_empty()) {
if (path.begins_with(subgroup_base)) {
path = path.trim_prefix(subgroup_base);
} else if (subgroup_base.begins_with(path)) {
// Keep it, this is used pretty often.
} else {
subgroup = ""; // The prefix changed, we are no longer in the subgroup.
}
}
// Check if we exit or not a group. If there is a prefix, remove it from the property label string.
if (!group.is_empty() && !group_base.is_empty() && subgroup.is_empty()) {
if (path.begins_with(group_base)) {
path = path.trim_prefix(group_base);
} else if (group_base.begins_with(path)) {
// Keep it, this is used pretty often.
} else {
group = ""; // The prefix changed, we are no longer in the group.
subgroup = "";
}
}
// Add the group and subgroup to the path.
if (!subgroup.is_empty()) {
path = subgroup + "/" + path;
}
if (!group.is_empty()) {
path = group + "/" + path;
}
// Get the property label's string.
String name_override = (path.contains_char('/')) ? path.substr(path.rfind_char('/') + 1) : path;
const int dot = name_override.find_char('.');
if (dot != -1) {
name_override = name_override.substr(0, dot);
}
// Remove the property from the path.
int idx = path.rfind_char('/');
if (idx > -1) {
path = path.left(idx);
} else {
path = "";
}
// Check if the property matches the filter.
const String property_path = (path.is_empty() ? "" : path + "/") + name_override;
if (_property_path_matches(property_path, p_filter, property_name_style)) {
return true;
}
// Check if the sub-resource has any properties that match the filter.
if (p.hint && p.hint == PROPERTY_HINT_RESOURCE_TYPE) {
Ref<Resource> res = p_resource->get(p.name);
if (res.is_valid() && _resource_properties_matches(res, p_filter)) {
return true;
}
}
}
return false;
}
String EditorProperty::get_tooltip_string(const String &p_string) const {
// Trim to 100 characters to prevent the tooltip from being too long.
constexpr int TOOLTIP_MAX_LENGTH = 100;
@ -2923,6 +3044,7 @@ void EditorInspector::update_tree() {
HashMap<String, HashMap<String, LocalVector<EditorProperty *>>> favorites_to_add;
Color sscolor = get_theme_color(SNAME("prop_subsection"), EditorStringName(Editor));
bool sub_inspectors_enabled = EDITOR_GET("interface/inspector/open_resources_in_current_inspector");
// Get the lists of editors to add the beginning.
for (Ref<EditorInspectorPlugin> &ped : valid_plugins) {
@ -3100,7 +3222,7 @@ void EditorInspector::update_tree() {
continue;
}
if (p.name.begins_with("metadata/") && bool(object->call("_hide_metadata_from_inspector"))) {
if (p.name.begins_with("metadata/") && bool(object->call(SNAME("_hide_metadata_from_inspector")))) {
// Hide metadata from inspector if required.
continue;
}
@ -3207,10 +3329,25 @@ void EditorInspector::update_tree() {
}
// Ignore properties that do not fit the filter.
bool sub_inspector_use_filter = false;
if (use_filter && !filter.is_empty()) {
const String property_path = property_prefix + (path.is_empty() ? "" : path + "/") + name_override;
if (!_property_path_matches(property_path, filter, property_name_style)) {
continue;
if (!sub_inspectors_enabled || p.hint != PROPERTY_HINT_RESOURCE_TYPE) {
continue;
}
Ref<Resource> res = object->get(p.name);
if (res.is_null()) {
continue;
}
// Check if the sub-resource has any properties that match the filter.
if (!_resource_properties_matches(res, filter)) {
continue;
}
sub_inspector_use_filter = true;
}
}
@ -3523,6 +3660,13 @@ void EditorInspector::update_tree() {
}
}
if (sub_inspector_use_filter) {
EditorPropertyResource *epr = Object::cast_to<EditorPropertyResource>(ep);
if (epr) {
epr->set_use_filter(true);
}
}
Node *section_search = current_vbox->get_parent();
while (section_search) {
EditorInspectorSection *section = Object::cast_to<EditorInspectorSection>(section_search);
@ -3877,14 +4021,10 @@ void EditorInspector::set_use_filter(bool p_use) {
void EditorInspector::register_text_enter(Node *p_line_edit) {
search_box = Object::cast_to<LineEdit>(p_line_edit);
if (search_box) {
search_box->connect(SceneStringName(text_changed), callable_mp(this, &EditorInspector::_filter_changed));
search_box->connect(SceneStringName(text_changed), callable_mp(this, &EditorInspector::update_tree).unbind(1));
}
}
void EditorInspector::_filter_changed(const String &p_text) {
update_tree();
}
void EditorInspector::set_use_folding(bool p_use_folding, bool p_update_tree) {
use_folding = p_use_folding;

View file

@ -496,6 +496,7 @@ class EditorInspector : public ScrollContainer {
GDCLASS(EditorInspector, ScrollContainer);
friend class EditorInspectorCategory;
friend class EditorPropertyResource;
enum {
MAX_PLUGINS = 1024
@ -585,6 +586,7 @@ class EditorInspector : public ScrollContainer {
void _property_checked(const String &p_path, bool p_checked);
void _property_pinned(const String &p_path, bool p_pinned);
bool _property_path_matches(const String &p_property_path, const String &p_filter, EditorPropertyNameProcessor::Style p_style);
bool _resource_properties_matches(const Ref<Resource> &p_resource, const String &p_filter);
void _resource_selected(const String &p_path, Ref<Resource> p_resource);
void _property_selected(const String &p_path, int p_focusable);
@ -604,7 +606,6 @@ class EditorInspector : public ScrollContainer {
void _keying_changed();
void _filter_changed(const String &p_text);
void _parse_added_editors(VBoxContainer *current_vbox, EditorInspectorSection *p_section, Ref<EditorInspectorPlugin> ped);
void _vscroll_changed(double);

View file

@ -3292,6 +3292,9 @@ void EditorPropertyResource::update_property() {
sub_inspector->set_draw_focus_border(false);
sub_inspector->set_use_filter(use_filter);
sub_inspector->register_text_enter(parent_inspector->search_box);
sub_inspector->set_mouse_filter(MOUSE_FILTER_STOP);
add_child(sub_inspector);
set_bottom_editor(sub_inspector);
@ -3318,16 +3321,14 @@ void EditorPropertyResource::update_property() {
_update_property_bg();
}
} else {
if (sub_inspector) {
set_bottom_editor(nullptr);
memdelete(sub_inspector);
sub_inspector = nullptr;
} else if (sub_inspector) {
set_bottom_editor(nullptr);
memdelete(sub_inspector);
sub_inspector = nullptr;
if (opened_editor) {
EditorNode::get_singleton()->hide_unused_editors();
opened_editor = false;
}
if (opened_editor) {
EditorNode::get_singleton()->hide_unused_editors();
opened_editor = false;
}
}
}
@ -3357,6 +3358,13 @@ void EditorPropertyResource::set_use_sub_inspector(bool p_enable) {
use_sub_inspector = p_enable;
}
void EditorPropertyResource::set_use_filter(bool p_use) {
use_filter = p_use;
if (sub_inspector) {
update_property();
}
}
void EditorPropertyResource::fold_resource() {
bool unfolded = get_edited_object()->editor_is_section_unfolded(get_edited_property());
if (unfolded) {

View file

@ -673,6 +673,7 @@ class EditorPropertyResource : public EditorProperty {
bool use_sub_inspector = false;
EditorInspector *sub_inspector = nullptr;
bool opened_editor = false;
bool use_filter = false;
void _resource_selected(const Ref<Resource> &p_resource, bool p_inspect);
void _resource_changed(const Ref<Resource> &p_resource);
@ -701,6 +702,7 @@ public:
void expand_revertable() override;
void set_use_sub_inspector(bool p_enable);
void set_use_filter(bool p_use);
void fold_resource();
virtual bool is_colored(ColorationMode p_mode) override;