Merge pull request #63429 from RandomShaper/indicate_overridden

This commit is contained in:
Rémi Verschelde 2022-07-31 23:54:38 +02:00 committed by GitHub
commit 6c5330154e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 175 additions and 26 deletions

View File

@ -101,6 +101,13 @@
Used by sub-inspectors. Emit it if what was selected was an Object ID.
</description>
</signal>
<signal name="property_can_revert_changed">
<argument index="0" name="property" type="StringName" />
<argument index="1" name="can_revert" type="bool" />
<description>
Emitted when the revertability (i.e., whether it has a non-default value and thus is displayed with a revert icon) of a property has changed.
</description>
</signal>
<signal name="property_changed">
<argument index="0" name="property" type="StringName" />
<argument index="1" name="value" type="Variant" />

View File

@ -471,6 +471,9 @@ void EditorProperty::update_revert_and_pin_status() {
bool new_can_revert = EditorPropertyRevert::can_property_revert(object, property, &current) && !is_read_only();
if (new_can_revert != can_revert || new_pinned != pinned) {
if (new_can_revert != can_revert) {
emit_signal(SNAME("property_can_revert_changed"), property, new_can_revert);
}
can_revert = new_can_revert;
pinned = new_pinned;
update();
@ -784,6 +787,9 @@ void EditorProperty::expand_all_folding() {
void EditorProperty::collapse_all_folding() {
}
void EditorProperty::expand_revertable() {
}
void EditorProperty::set_selectable(bool p_selectable) {
selectable = p_selectable;
}
@ -966,6 +972,7 @@ void EditorProperty::_bind_methods() {
ADD_SIGNAL(MethodInfo("property_keyed_with_value", PropertyInfo(Variant::STRING_NAME, "property"), PropertyInfo(Variant::NIL, "value", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NIL_IS_VARIANT)));
ADD_SIGNAL(MethodInfo("property_checked", PropertyInfo(Variant::STRING_NAME, "property"), PropertyInfo(Variant::BOOL, "checked")));
ADD_SIGNAL(MethodInfo("property_pinned", PropertyInfo(Variant::STRING_NAME, "property"), PropertyInfo(Variant::BOOL, "pinned")));
ADD_SIGNAL(MethodInfo("property_can_revert_changed", PropertyInfo(Variant::STRING_NAME, "property"), PropertyInfo(Variant::BOOL, "can_revert")));
ADD_SIGNAL(MethodInfo("resource_selected", PropertyInfo(Variant::STRING, "path"), PropertyInfo(Variant::OBJECT, "resource", PROPERTY_HINT_RESOURCE_TYPE, "Resource")));
ADD_SIGNAL(MethodInfo("object_id_selected", PropertyInfo(Variant::STRING_NAME, "property"), PropertyInfo(Variant::INT, "id")));
ADD_SIGNAL(MethodInfo("selected", PropertyInfo(Variant::STRING, "path"), PropertyInfo(Variant::INT, "focusable_idx")));
@ -1225,12 +1232,15 @@ void EditorInspectorSection::_notification(int p_what) {
// Get the section header font.
Ref<Font> font = get_theme_font(SNAME("bold"), SNAME("EditorFonts"));
int font_size = get_theme_font_size(SNAME("bold_size"), SNAME("EditorFonts"));
Color font_color = get_theme_color(SNAME("font_color"), SNAME("Editor"));
// Get the right direction arrow texture, if the section is foldable.
Ref<Texture2D> arrow;
bool folded = foldable;
if (foldable) {
if (object->editor_is_section_unfolded(section)) {
arrow = get_theme_icon(SNAME("arrow"), SNAME("Tree"));
folded = false;
} else {
if (is_layout_rtl()) {
arrow = get_theme_icon(SNAME("arrow_collapsed_mirrored"), SNAME("Tree"));
@ -1274,28 +1284,71 @@ void EditorInspectorSection::_notification(int p_what) {
}
draw_rect(header_rect, c);
// Draw header title and folding arrow.
const int arrow_margin = 2;
const int arrow_width = arrow.is_valid() ? arrow->get_width() : 0;
Color color = get_theme_color(SNAME("font_color"));
float text_width = get_size().width - Math::round(arrow_width + arrow_margin * EDSCALE) - section_indent;
Point2 text_offset = Point2(0, font->get_ascent(font_size) + (header_height - font->get_height(font_size)) / 2);
HorizontalAlignment text_align = HORIZONTAL_ALIGNMENT_LEFT;
if (rtl) {
text_align = HORIZONTAL_ALIGNMENT_RIGHT;
} else {
text_offset.x = section_indent + Math::round(arrow_width + arrow_margin * EDSCALE);
}
draw_string(font, text_offset.floor(), label, text_align, text_width, font_size, color);
// Draw header title, folding arrow and coutn of revertable properties.
{
int separation = Math::round(2 * EDSCALE);
if (arrow.is_valid()) {
Point2 arrow_position = Point2(0, (header_height - arrow->get_height()) / 2);
if (rtl) {
arrow_position.x = get_size().width - section_indent - arrow->get_width() - Math::round(arrow_margin * EDSCALE);
} else {
arrow_position.x = section_indent + Math::round(arrow_margin * EDSCALE);
int margin_start = section_indent + separation;
int margin_end = separation;
// - Arrow.
if (arrow.is_valid()) {
Point2 arrow_position;
if (rtl) {
arrow_position.x = get_size().width - (margin_start + arrow->get_width());
} else {
arrow_position.x = margin_start;
}
arrow_position.y = (header_height - arrow->get_height()) / 2;
draw_texture(arrow, arrow_position);
margin_start += arrow->get_width();
}
draw_texture(arrow, arrow_position.floor());
int available = get_size().width - (margin_start + margin_end);
// - Count of revertable properties.
String num_revertable_str;
int num_revertable_width = 0;
if (folded && revertable_properties.size()) {
int label_width = font->get_string_size(label, HORIZONTAL_ALIGNMENT_LEFT, available, font_size, TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_CONSTRAIN_ELLIPSIS).x;
Ref<Font> light_font = get_theme_font(SNAME("main"), SNAME("EditorFonts"));
int light_font_size = get_theme_font_size(SNAME("main_size"), SNAME("EditorFonts"));
Color light_font_color = get_theme_color(SNAME("disabled_font_color"), SNAME("Editor"));
// Can we fit the long version of the revertable count text?
if (revertable_properties.size() == 1) {
num_revertable_str = "(1 change)";
} else {
num_revertable_str = vformat("(%d changes)", revertable_properties.size());
}
num_revertable_width = light_font->get_string_size(num_revertable_str, HORIZONTAL_ALIGNMENT_LEFT, -1.0f, light_font_size, TextServer::JUSTIFICATION_NONE).x;
if (label_width + separation + num_revertable_width > available) {
// We'll have to use the short version.
num_revertable_str = vformat("(%d)", revertable_properties.size());
num_revertable_width = light_font->get_string_size(num_revertable_str, HORIZONTAL_ALIGNMENT_LEFT, -1.0f, light_font_size, TextServer::JUSTIFICATION_NONE).x;
}
Point2 text_offset = Point2(
margin_end,
light_font->get_ascent(light_font_size) + (header_height - light_font->get_height(light_font_size)) / 2);
if (!rtl) {
text_offset.x = get_size().width - (text_offset.x + num_revertable_width);
}
draw_string(light_font, text_offset, num_revertable_str, HORIZONTAL_ALIGNMENT_LEFT, -1.0f, light_font_size, light_font_color, TextServer::JUSTIFICATION_NONE);
margin_end += num_revertable_width + separation;
available -= num_revertable_width + separation;
}
// - Label.
Point2 text_offset = Point2(
margin_start,
font->get_ascent(font_size) + (header_height - font->get_height(font_size)) / 2);
if (rtl) {
text_offset.x = margin_end;
}
HorizontalAlignment text_align = rtl ? HORIZONTAL_ALIGNMENT_RIGHT : HORIZONTAL_ALIGNMENT_LEFT;
draw_string(font, text_offset, label, text_align, available, font_size, font_color, TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_CONSTRAIN_ELLIPSIS);
}
// Draw dropping highlight.
@ -1471,6 +1524,22 @@ void EditorInspectorSection::fold() {
update();
}
bool EditorInspectorSection::has_revertable_properties() const {
return !revertable_properties.is_empty();
}
void EditorInspectorSection::property_can_revert_changed(const String &p_path, bool p_can_revert) {
bool had_revertable_properties = has_revertable_properties();
if (p_can_revert) {
revertable_properties.insert(p_path);
} else {
revertable_properties.erase(p_path);
}
if (has_revertable_properties() != had_revertable_properties) {
update();
}
}
void EditorInspectorSection::_bind_methods() {
ClassDB::bind_method(D_METHOD("setup", "section", "label", "object", "bg_color", "foldable"), &EditorInspectorSection::setup);
ClassDB::bind_method(D_METHOD("get_vbox"), &EditorInspectorSection::get_vbox);
@ -2330,7 +2399,7 @@ String EditorInspector::get_selected_path() const {
return property_selected;
}
void EditorInspector::_parse_added_editors(VBoxContainer *current_vbox, Ref<EditorInspectorPlugin> ped) {
void EditorInspector::_parse_added_editors(VBoxContainer *current_vbox, EditorInspectorSection *p_section, Ref<EditorInspectorPlugin> ped) {
for (const EditorInspectorPlugin::AddedEditor &F : ped->added_editors) {
EditorProperty *ep = Object::cast_to<EditorProperty>(F.property_editor);
current_vbox->add_child(F.property_editor);
@ -2370,6 +2439,10 @@ void EditorInspector::_parse_added_editors(VBoxContainer *current_vbox, Ref<Edit
}
}
if (p_section) {
ep->connect("property_can_revert_changed", callable_mp(p_section, &EditorInspectorSection::property_can_revert_changed));
}
ep->set_read_only(read_only);
ep->update_property();
ep->_update_pin_flags();
@ -2476,7 +2549,7 @@ void EditorInspector::update_tree() {
// Get the lists of editors to add the beginning.
for (Ref<EditorInspectorPlugin> &ped : valid_plugins) {
ped->parse_begin(object);
_parse_added_editors(main_vbox, ped);
_parse_added_editors(main_vbox, nullptr, ped);
}
StringName type_name;
@ -2601,7 +2674,7 @@ void EditorInspector::update_tree() {
// Add editors at the start of a category.
for (Ref<EditorInspectorPlugin> &ped : valid_plugins) {
ped->parse_category(object, p.name);
_parse_added_editors(main_vbox, ped);
_parse_added_editors(main_vbox, nullptr, ped);
}
continue;
@ -2793,7 +2866,7 @@ void EditorInspector::update_tree() {
// Add editors at the start of a group.
for (Ref<EditorInspectorPlugin> &ped : valid_plugins) {
ped->parse_group(object, path);
_parse_added_editors(section->get_vbox(), ped);
_parse_added_editors(section->get_vbox(), section, ped);
}
vbox_per_path[root_vbox][acc_path] = section->get_vbox();
@ -2975,6 +3048,12 @@ void EditorInspector::update_tree() {
editor_property_map[prop].push_back(ep);
}
}
EditorInspectorSection *section = Object::cast_to<EditorInspectorSection>(current_vbox->get_parent());
if (section) {
ep->connect("property_can_revert_changed", callable_mp(section, &EditorInspectorSection::property_can_revert_changed));
}
ep->set_draw_warning(draw_warning);
ep->set_use_folding(use_folding);
ep->set_checkable(checkable);
@ -3027,7 +3106,7 @@ void EditorInspector::update_tree() {
// Get the lists of to add at the end.
for (Ref<EditorInspectorPlugin> &ped : valid_plugins) {
ped->parse_end(object);
_parse_added_editors(main_vbox, ped);
_parse_added_editors(main_vbox, nullptr, ped);
}
}
@ -3180,6 +3259,44 @@ void EditorInspector::expand_all_folding() {
}
}
void EditorInspector::expand_revertable() {
HashSet<EditorInspectorSection *> sections_to_unfold[2];
for (EditorInspectorSection *E : sections) {
if (E->has_revertable_properties()) {
sections_to_unfold[0].insert(E);
}
}
// Climb up the hierachy doing double buffering with the sets.
int a = 0;
int b = 1;
while (sections_to_unfold[a].size()) {
for (EditorInspectorSection *E : sections_to_unfold[a]) {
E->unfold();
Node *n = E->get_parent();
while (n) {
if (Object::cast_to<EditorInspector>(n)) {
break;
}
if (Object::cast_to<EditorInspectorSection>(n) && !sections_to_unfold[a].has((EditorInspectorSection *)n)) {
sections_to_unfold[b].insert((EditorInspectorSection *)n);
}
n = n->get_parent();
}
}
sections_to_unfold[a].clear();
SWAP(a, b);
}
for (const KeyValue<StringName, List<EditorProperty *>> &F : editor_property_map) {
for (EditorProperty *E : F.value) {
E->expand_revertable();
}
}
}
void EditorInspector::set_scroll_offset(int p_offset) {
set_v_scroll(p_offset);
}

View File

@ -184,6 +184,7 @@ public:
virtual void expand_all_folding();
virtual void collapse_all_folding();
virtual void expand_revertable();
virtual Variant get_drag_data(const Point2 &p_point) override;
virtual void update_cache();
@ -281,6 +282,8 @@ class EditorInspectorSection : public Container {
Timer *dropping_unfold_timer = nullptr;
bool dropping = false;
HashSet<StringName> revertable_properties;
void _test_unfold();
protected:
@ -299,6 +302,9 @@ public:
void unfold();
void fold();
bool has_revertable_properties() const;
void property_can_revert_changed(const String &p_path, bool p_can_revert);
EditorInspectorSection();
~EditorInspectorSection();
};
@ -517,7 +523,7 @@ class EditorInspector : public ScrollContainer {
void _edit_request_change(Object *p_object, const String &p_prop);
void _filter_changed(const String &p_text);
void _parse_added_editors(VBoxContainer *current_vbox, Ref<EditorInspectorPlugin> ped);
void _parse_added_editors(VBoxContainer *current_vbox, EditorInspectorSection *p_section, Ref<EditorInspectorPlugin> ped);
void _vscroll_changed(double);
@ -579,6 +585,7 @@ public:
void collapse_all_folding();
void expand_all_folding();
void expand_revertable();
void set_scroll_offset(int p_offset);
int get_scroll_offset() const;

View File

@ -3918,6 +3918,12 @@ void EditorPropertyResource::expand_all_folding() {
}
}
void EditorPropertyResource::expand_revertable() {
if (sub_inspector) {
sub_inspector->expand_revertable();
}
}
void EditorPropertyResource::set_use_sub_inspector(bool p_enable) {
use_sub_inspector = p_enable;
}

View File

@ -856,6 +856,7 @@ public:
void collapse_all_folding() override;
void expand_all_folding() override;
void expand_revertable() override;
void set_use_sub_inspector(bool p_enable);

View File

@ -65,6 +65,9 @@ void InspectorDock::_menu_option_confirm(int p_option, bool p_confirmed) {
case COLLAPSE_ALL: {
_menu_collapseall();
} break;
case EXPAND_REVERTABLE: {
_menu_expand_revertable();
} break;
case RESOURCE_SAVE: {
_save_resource(false);
@ -401,6 +404,10 @@ void InspectorDock::_menu_expandall() {
inspector->expand_all_folding();
}
void InspectorDock::_menu_expand_revertable() {
inspector->expand_revertable();
}
void InspectorDock::_warning_pressed() {
warning_dialog->popup_centered();
}
@ -519,6 +526,8 @@ void InspectorDock::update(Object *p_object) {
p->clear();
p->add_icon_shortcut(get_theme_icon(SNAME("GuiTreeArrowDown"), SNAME("EditorIcons")), ED_SHORTCUT("property_editor/expand_all", TTR("Expand All")), EXPAND_ALL);
p->add_icon_shortcut(get_theme_icon(SNAME("GuiTreeArrowRight"), SNAME("EditorIcons")), ED_SHORTCUT("property_editor/collapse_all", TTR("Collapse All")), COLLAPSE_ALL);
// Calling it 'revertable' internally, because that's what the implementation is based on, but labeling it as 'non-default' because that's more user friendly, even if not 100% accurate.
p->add_shortcut(ED_SHORTCUT("property_editor/expand_revertable", TTR("Expand Non-Default")), EXPAND_REVERTABLE);
p->add_separator(TTR("Property Name Style"));
p->add_radio_check_item(TTR("Raw"), PROPERTY_NAME_STYLE_RAW);

View File

@ -61,6 +61,7 @@ class InspectorDock : public VBoxContainer {
COLLAPSE_ALL,
EXPAND_ALL,
EXPAND_REVERTABLE,
// Matches `EditorPropertyNameProcessor::Style`.
PROPERTY_NAME_STYLE_RAW,
@ -124,6 +125,7 @@ class InspectorDock : public VBoxContainer {
void _edit_back();
void _menu_collapseall();
void _menu_expandall();
void _menu_expand_revertable();
void _select_history(int p_idx);
void _prepare_history();