Add "Open Documentation" button to EditorProperty context menu

This commit is contained in:
FireForge 2022-03-28 15:37:01 -05:00
parent d26442e709
commit dcf42cff86
3 changed files with 47 additions and 23 deletions

View file

@ -39,6 +39,7 @@
#include "editor/editor_property_name_processor.h"
#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
#include "editor/plugins/script_editor_plugin.h"
#include "multi_node_edit.h"
#include "scene/gui/center_container.h"
#include "scene/property_utils.h"
@ -410,6 +411,10 @@ StringName EditorProperty::get_edited_property() const {
return property;
}
void EditorProperty::set_doc_path(const String &p_doc_path) {
doc_path = p_doc_path;
}
void EditorProperty::update_property() {
GDVIRTUAL_CALL(_update_property);
}
@ -906,6 +911,10 @@ void EditorProperty::menu_option(int p_option) {
emit_signal(SNAME("property_pinned"), property, !pinned);
update();
} break;
case MENU_OPEN_DOCUMENTATION: {
ScriptEditor::get_singleton()->goto_help(doc_path);
EditorNode::get_singleton()->set_visible_editor(EditorNode::EDITOR_SCRIPT);
} break;
}
}
@ -985,20 +994,25 @@ void EditorProperty::_update_popup() {
add_child(menu);
menu->connect("id_pressed", callable_mp(this, &EditorProperty::menu_option));
}
menu->add_shortcut(ED_GET_SHORTCUT("property_editor/copy_property"), MENU_COPY_PROPERTY);
menu->add_shortcut(ED_GET_SHORTCUT("property_editor/paste_property"), MENU_PASTE_PROPERTY);
menu->add_shortcut(ED_GET_SHORTCUT("property_editor/copy_property_path"), MENU_COPY_PROPERTY_PATH);
menu->add_icon_shortcut(get_theme_icon(SNAME("ActionCopy"), SNAME("EditorIcons")), ED_GET_SHORTCUT("property_editor/copy_property"), MENU_COPY_PROPERTY);
menu->add_icon_shortcut(get_theme_icon(SNAME("ActionPaste"), SNAME("EditorIcons")), ED_GET_SHORTCUT("property_editor/paste_property"), MENU_PASTE_PROPERTY);
menu->add_icon_shortcut(get_theme_icon(SNAME("CopyNodePath"), SNAME("EditorIcons")), ED_GET_SHORTCUT("property_editor/copy_property_path"), MENU_COPY_PROPERTY_PATH);
menu->set_item_disabled(MENU_PASTE_PROPERTY, is_read_only());
if (!pin_hidden) {
menu->add_separator();
if (can_pin) {
menu->add_check_item(TTR("Pin value"), MENU_PIN_VALUE);
menu->add_icon_check_item(get_theme_icon(SNAME("Pin"), SNAME("EditorIcons")), TTR("Pin Value"), MENU_PIN_VALUE);
menu->set_item_checked(menu->get_item_index(MENU_PIN_VALUE), pinned);
menu->set_item_tooltip(menu->get_item_index(MENU_PIN_VALUE), TTR("Pinning a value forces it to be saved even if it's equal to the default."));
} else {
menu->add_check_item(vformat(TTR("Pin value [Disabled because '%s' is editor-only]"), property), MENU_PIN_VALUE);
menu->add_icon_check_item(get_theme_icon(SNAME("Pin"), SNAME("EditorIcons")), vformat(TTR("Pin Value [Disabled because '%s' is editor-only]"), property), MENU_PIN_VALUE);
menu->set_item_disabled(menu->get_item_index(MENU_PIN_VALUE), true);
}
menu->set_item_tooltip(menu->get_item_index(MENU_PIN_VALUE), TTR("Pinning a value forces it to be saved even if it's equal to the default."));
}
if (!doc_path.is_empty()) {
menu->add_separator();
menu->add_icon_item(get_theme_icon(SNAME("Help"), SNAME("EditorIcons")), TTR("Open Documentation"), MENU_OPEN_DOCUMENTATION);
}
}
@ -2844,7 +2858,7 @@ void EditorInspector::update_tree() {
restart_request_props.insert(p.name);
}
String doc_hint;
PropertyDocInfo doc_info;
if (use_doc_hints) {
// Build the doc hint, to use as tooltip.
@ -2856,16 +2870,15 @@ void EditorInspector::update_tree() {
}
StringName propname = property_prefix + p.name;
String descr;
bool found = false;
// Search for the property description in the cache.
HashMap<StringName, HashMap<StringName, String>>::Iterator E = descr_cache.find(classname);
HashMap<StringName, HashMap<StringName, PropertyDocInfo>>::Iterator E = doc_info_cache.find(classname);
if (E) {
HashMap<StringName, String>::Iterator F = E->value.find(propname);
HashMap<StringName, PropertyDocInfo>::Iterator F = E->value.find(propname);
if (F) {
found = true;
descr = F->value;
doc_info = F->value;
}
}
@ -2873,10 +2886,11 @@ void EditorInspector::update_tree() {
// Build the property description String and add it to the cache.
DocTools *dd = EditorHelp::get_doc_data();
HashMap<String, DocData::ClassDoc>::Iterator F = dd->class_list.find(classname);
while (F && descr.is_empty()) {
while (F && doc_info.description.is_empty()) {
for (int i = 0; i < F->value.properties.size(); i++) {
if (F->value.properties[i].name == propname.operator String()) {
descr = DTR(F->value.properties[i].description);
doc_info.description = DTR(F->value.properties[i].description);
doc_info.path = "class_property:" + F->value.name + ":" + F->value.properties[i].name;
break;
}
}
@ -2885,7 +2899,8 @@ void EditorInspector::update_tree() {
if (slices.size() == 2 && slices[0].begins_with("theme_override_")) {
for (int i = 0; i < F->value.theme_properties.size(); i++) {
if (F->value.theme_properties[i].name == slices[1]) {
descr = DTR(F->value.theme_properties[i].description);
doc_info.description = DTR(F->value.theme_properties[i].description);
doc_info.path = "class_theme_item:" + F->value.name + ":" + F->value.theme_properties[i].name;
break;
}
}
@ -2897,10 +2912,9 @@ void EditorInspector::update_tree() {
break;
}
}
descr_cache[classname][propname] = descr;
}
doc_hint = descr;
doc_info_cache[classname][propname] = doc_info;
}
}
Vector<EditorInspectorPlugin::AddedEditor> editors;
@ -2983,11 +2997,12 @@ void EditorInspector::update_tree() {
ep->connect("multiple_properties_changed", callable_mp(this, &EditorInspector::_multiple_properties_changed));
ep->connect("resource_selected", callable_mp(this, &EditorInspector::_resource_selected), varray(), CONNECT_DEFERRED);
ep->connect("object_id_selected", callable_mp(this, &EditorInspector::_object_id_selected), varray(), CONNECT_DEFERRED);
if (!doc_hint.is_empty()) {
ep->set_tooltip(property_prefix + p.name + "::" + doc_hint);
if (!doc_info.description.is_empty()) {
ep->set_tooltip(property_prefix + p.name + "::" + doc_info.description);
} else {
ep->set_tooltip(property_prefix + p.name);
}
ep->set_doc_path(doc_info.path);
ep->update_property();
ep->_update_pin_flags();
ep->update_revert_and_pin_status();
@ -3473,7 +3488,7 @@ void EditorInspector::_property_pinned(const String &p_path, bool p_pinned) {
void EditorInspector::_property_selected(const String &p_path, int p_focusable) {
property_selected = p_path;
property_focusable = p_focusable;
//deselect the others
// Deselect the others.
for (const KeyValue<StringName, List<EditorProperty *>> &F : editor_property_map) {
if (F.key == property_selected) {
continue;

View file

@ -62,6 +62,7 @@ public:
MENU_PASTE_PROPERTY,
MENU_COPY_PROPERTY_PATH,
MENU_PIN_VALUE,
MENU_OPEN_DOCUMENTATION,
};
private:
@ -71,6 +72,7 @@ private:
Object *object = nullptr;
StringName property;
String property_path;
String doc_path;
int property_usage;
@ -148,6 +150,8 @@ public:
Object *get_edited_object();
StringName get_edited_property() const;
void set_doc_path(const String &p_doc_path);
virtual void update_property();
void update_revert_and_pin_status();
@ -439,7 +443,7 @@ class EditorInspector : public ScrollContainer {
VBoxContainer *main_vbox = nullptr;
//map use to cache the instantiated editors
// Map used to cache the instantiated editors.
HashMap<StringName, List<EditorProperty *>> editor_property_map;
List<EditorInspectorSection *> sections;
HashSet<StringName> pending;
@ -473,7 +477,12 @@ class EditorInspector : public ScrollContainer {
int property_focusable;
int update_scroll_request;
HashMap<StringName, HashMap<StringName, String>> descr_cache;
struct PropertyDocInfo {
String description;
String path;
};
HashMap<StringName, HashMap<StringName, PropertyDocInfo>> doc_info_cache;
HashMap<StringName, String> class_descr_cache;
HashSet<StringName> restart_request_props;

View file

@ -1 +1 @@
<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g fill="#e0e0e0" transform="translate(0 -1036.4)"><circle cx="3" cy="1048.4"/><path d="m2 1c-.55226.0001-.99994.4477-1 1v12c.0000552.5523.44774.9999 1 1h12c.55226-.0001.99994-.4477 1-1v-8l-5-5zm1 2h6v3c0 .554.44599 1 1 1h3v6h-10zm3 5-2 4h2l2-4zm4 0-2 4h2l2-4z" fill-opacity=".78431" transform="translate(0 1036.4)"/></g></svg>
<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g fill="#e0e0e0" transform="translate(0 -1036.4)"><circle cx="3" cy="1048.4"/><path d="m2 1c-.55226.0001-.99994.4477-1 1v12c.0000552.5523.44774.9999 1 1h12c.55226-.0001.99994-.4477 1-1v-8l-5-5zm1 2h6v3c0 .554.44599 1 1 1h3v6h-10zm3 5-2 4h2l2-4zm4 0-2 4h2l2-4z" transform="translate(0 1036.4)"/></g></svg>

Before

Width:  |  Height:  |  Size: 411 B

After

Width:  |  Height:  |  Size: 389 B