|
@@ -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;
|
|
|
|