Merge pull request #111469 from Raftatul/Copy/PasteGroup/CategoryProperties
Add support for copy/paste of section/category properties
This commit is contained in:
commit
0848acfe4b
3 changed files with 303 additions and 17 deletions
|
|
@ -33,9 +33,12 @@
|
|||
|
||||
#include "core/input/input.h"
|
||||
#include "core/os/keyboard.h"
|
||||
#include "core/variant/typed_dictionary.h"
|
||||
#include "editor/debugger/editor_debugger_inspector.h"
|
||||
#include "editor/debugger/editor_debugger_node.h"
|
||||
#include "editor/doc/doc_tools.h"
|
||||
#include "editor/docks/inspector_dock.h"
|
||||
#include "editor/editor_interface.h"
|
||||
#include "editor/editor_main_screen.h"
|
||||
#include "editor/editor_node.h"
|
||||
#include "editor/editor_string_names.h"
|
||||
|
|
@ -1437,6 +1440,12 @@ void EditorProperty::menu_option(int p_option) {
|
|||
return;
|
||||
}
|
||||
}
|
||||
|
||||
Dictionary dict = InspectorDock::get_inspector_singleton()->get_property_clipboard();
|
||||
if (dict.has("@pastebin_category_name") || dict.has("@pastebin_section_name")) {
|
||||
return;
|
||||
}
|
||||
|
||||
emit_changed(property, EditorInspector::get_property_clipboard());
|
||||
} break;
|
||||
case MENU_COPY_PROPERTY_PATH: {
|
||||
|
|
@ -1853,8 +1862,131 @@ Size2 EditorInspectorCategory::get_minimum_size() const {
|
|||
return ms;
|
||||
}
|
||||
|
||||
void EditorInspectorCategory::_collect_properties(const Object *p_object, LocalVector<String> &r_properties) const {
|
||||
List<PropertyInfo> property_list;
|
||||
p_object->get_property_list(&property_list, true);
|
||||
|
||||
String current_category;
|
||||
for (const PropertyInfo &prop_info : property_list) {
|
||||
if (prop_info.usage & PROPERTY_USAGE_GROUP) {
|
||||
continue;
|
||||
}
|
||||
if (prop_info.usage & PROPERTY_USAGE_CATEGORY) {
|
||||
current_category = prop_info.name;
|
||||
continue;
|
||||
}
|
||||
if (!(prop_info.usage & PROPERTY_USAGE_EDITOR)) {
|
||||
continue;
|
||||
}
|
||||
if (!current_category.ends_with(info.name)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
r_properties.push_back(prop_info.name);
|
||||
}
|
||||
}
|
||||
|
||||
void EditorInspectorCategory::_handle_menu_option(int p_option) {
|
||||
switch (p_option) {
|
||||
case MENU_COPY_VALUE: {
|
||||
const Object *object = EditorInterface::get_singleton()->get_inspector()->get_edited_object();
|
||||
String category_name = info.name;
|
||||
if (!EditorNode::get_editor_data().is_type_recognized(info.name) && ResourceLoader::exists(info.hint_string, "Script")) {
|
||||
Ref<Script> scr = ResourceLoader::load(info.hint_string, "Script");
|
||||
if (scr.is_valid()) {
|
||||
category_name = scr->get_doc_class_name();
|
||||
}
|
||||
}
|
||||
Dictionary clipboard;
|
||||
LocalVector<String> properties;
|
||||
_collect_properties(object, properties);
|
||||
|
||||
clipboard["@pastebin_category_name"] = category_name;
|
||||
for (const String &property_name : properties) {
|
||||
clipboard[property_name] = object->get(property_name);
|
||||
}
|
||||
InspectorDock::get_inspector_singleton()->set_property_clipboard(clipboard);
|
||||
} break;
|
||||
|
||||
case MENU_PASTE_VALUE: {
|
||||
Object *object = EditorInterface::get_singleton()->get_inspector()->get_edited_object();
|
||||
const Dictionary clipboard = InspectorDock::get_inspector_singleton()->get_property_clipboard();
|
||||
if (!clipboard.has("@pastebin_category_name")) {
|
||||
break;
|
||||
}
|
||||
const String pastebin_category_name = clipboard["@pastebin_category_name"];
|
||||
String category_name = info.name;
|
||||
|
||||
if (!EditorNode::get_editor_data().is_type_recognized(info.name) && ResourceLoader::exists(info.hint_string, "Script")) {
|
||||
Ref<Script> scr = ResourceLoader::load(info.hint_string, "Script");
|
||||
if (scr.is_valid()) {
|
||||
category_name = scr->get_doc_class_name();
|
||||
}
|
||||
}
|
||||
|
||||
EditorUndoRedoManager *ur = EditorUndoRedoManager::get_singleton();
|
||||
if (const MultiNodeEdit *multi_node_edit = Object::cast_to<MultiNodeEdit>(object)) {
|
||||
const Node *es = EditorNode::get_singleton()->get_edited_scene();
|
||||
const String action_name = vformat(TTR("Set category %s on %d nodes"), category_name, multi_node_edit->get_node_count());
|
||||
ur->create_action(action_name);
|
||||
|
||||
for (int i = 0; i < multi_node_edit->get_node_count(); i++) {
|
||||
const NodePath E = multi_node_edit->get_node(i);
|
||||
Node *n = es->get_node(E);
|
||||
if (!n) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (const KeyValue<Variant, Variant> &pair : clipboard) {
|
||||
String property_name = pair.key;
|
||||
ur->add_do_property(n, property_name, pair.value);
|
||||
ur->add_undo_property(n, property_name, n->get(property_name));
|
||||
}
|
||||
}
|
||||
|
||||
ur->commit_action();
|
||||
} else if (EditorDebuggerRemoteObjects *remote_objects = Object::cast_to<EditorDebuggerRemoteObjects>(object)) {
|
||||
const int size = remote_objects->remote_object_ids.size();
|
||||
ur->create_action(size == 1 ? vformat(TTR("Set category %s"), category_name) : vformat(TTR("Set %s on %d objects"), category_name, size), UndoRedo::MERGE_ENDS);
|
||||
|
||||
for (const KeyValue<Variant, Variant> &pair : clipboard) {
|
||||
const String property_name = pair.key;
|
||||
String name = property_name;
|
||||
if (!remote_objects->prop_values.has(name) || String(name).begins_with("Constants/")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Change it back to the real name when fetching.
|
||||
if (name == "Script") {
|
||||
name = "script";
|
||||
} else if (name.begins_with("Metadata/")) {
|
||||
name = name.replace_first("Metadata/", "metadata/");
|
||||
}
|
||||
|
||||
Dictionary values = remote_objects->prop_values[property_name];
|
||||
Dictionary old_values = values.duplicate();
|
||||
for (const uint64_t key : values.keys()) {
|
||||
values.set(key, pair.value);
|
||||
}
|
||||
ur->add_do_method(remote_objects, SNAME("emit_signal"), SNAME("values_edited"), name, values, "");
|
||||
ur->add_undo_method(remote_objects, SNAME("emit_signal"), SNAME("values_edited"), name, old_values, "");
|
||||
}
|
||||
|
||||
ur->commit_action();
|
||||
} else {
|
||||
const String action_name = vformat(TTR("Set category %s on node %s"), category_name, object->get("name"));
|
||||
ur->create_action(action_name);
|
||||
|
||||
for (const KeyValue<Variant, Variant> &pair : clipboard) {
|
||||
const String property_name = pair.key;
|
||||
ur->add_do_property(object, property_name, pair.value);
|
||||
ur->add_undo_property(object, property_name, object->get(property_name));
|
||||
}
|
||||
|
||||
ur->commit_action();
|
||||
}
|
||||
} break;
|
||||
|
||||
case MENU_OPEN_DOCS: {
|
||||
ScriptEditor::get_singleton()->goto_help("class:" + doc_class_name);
|
||||
EditorNode::get_singleton()->get_editor_main_screen()->select(EditorMainScreen::EDITOR_SCRIPT);
|
||||
|
|
@ -1877,6 +2009,11 @@ void EditorInspectorCategory::_popup_context_menu(const Point2i &p_position) {
|
|||
if (is_favorite) {
|
||||
menu->add_item(TTRC("Unfavorite All"), MENU_UNFAVORITE_ALL);
|
||||
} else {
|
||||
const Dictionary clipboard = InspectorDock::get_inspector_singleton()->get_property_clipboard();
|
||||
|
||||
menu->add_icon_item(theme_cache.icon_copy, TTRC("Copy Category Values"), MENU_COPY_VALUE);
|
||||
menu->add_icon_item(theme_cache.icon_paste, TTRC("Paste Category Values"), MENU_PASTE_VALUE);
|
||||
|
||||
menu->add_item(TTRC("Open Documentation"), MENU_OPEN_DOCS);
|
||||
menu->set_item_disabled(-1, !EditorHelp::get_doc_data()->class_list.has(doc_class_name));
|
||||
}
|
||||
|
|
@ -2323,9 +2460,10 @@ Control *EditorInspectorSection::make_custom_tooltip(const String &p_text) const
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
void EditorInspectorSection::setup(const String &p_section, const String &p_label, Object *p_object, const Color &p_bg_color, bool p_foldable, int p_indent_depth, int p_level) {
|
||||
void EditorInspectorSection::setup(const String &p_inspector_path, const String &p_section, const String &p_label, Object *p_object, const Color &p_bg_color, bool p_foldable, int p_indent_depth, int p_level) {
|
||||
section = p_section;
|
||||
label = p_label;
|
||||
inspector_path = p_inspector_path;
|
||||
object = p_object;
|
||||
bg_color = p_bg_color;
|
||||
foldable = p_foldable;
|
||||
|
|
@ -2416,6 +2554,12 @@ void EditorInspectorSection::gui_input(const Ref<InputEvent> &p_event) {
|
|||
fold();
|
||||
}
|
||||
}
|
||||
} else if ((!checkable || checked) && !inspector_path.is_empty() && mb.is_valid() && mb->is_pressed() && mb->get_button_index() == MouseButton::RIGHT) {
|
||||
accept_event();
|
||||
_update_popup();
|
||||
menu->set_position(get_screen_position() + get_local_mouse_position());
|
||||
menu->reset_size();
|
||||
menu->popup();
|
||||
} else if (mb.is_valid() && !mb->is_pressed()) {
|
||||
queue_redraw();
|
||||
}
|
||||
|
|
@ -2559,6 +2703,122 @@ void EditorInspectorSection::update_property() {
|
|||
}
|
||||
}
|
||||
|
||||
void EditorInspectorSection::_update_popup() {
|
||||
if (!menu) {
|
||||
menu = memnew(PopupMenu);
|
||||
add_child(menu);
|
||||
menu->connect(SceneStringName(id_pressed), callable_mp(this, &EditorInspectorSection::menu_option));
|
||||
|
||||
menu->add_icon_item(theme_cache.icon_copy, TTRC("Copy Section Values"), MENU_COPY_VALUE);
|
||||
menu->add_icon_item(theme_cache.icon_paste, TTRC("Paste Section Values"), MENU_PASTE_VALUE);
|
||||
}
|
||||
}
|
||||
|
||||
void EditorInspectorSection::_collect_properties(LocalVector<String> &r_properties) const {
|
||||
List<PropertyInfo> property_list;
|
||||
object->get_property_list(&property_list, true);
|
||||
|
||||
String current_category;
|
||||
String current_group;
|
||||
String current_subgroup;
|
||||
for (const PropertyInfo &prop_info : property_list) {
|
||||
if (prop_info.usage & PROPERTY_USAGE_GROUP) {
|
||||
current_group = prop_info.name;
|
||||
continue;
|
||||
}
|
||||
if (prop_info.usage & PROPERTY_USAGE_SUBGROUP) {
|
||||
current_subgroup = prop_info.name;
|
||||
continue;
|
||||
}
|
||||
if (prop_info.usage & PROPERTY_USAGE_CATEGORY) {
|
||||
current_category = prop_info.name;
|
||||
if (!EditorNode::get_editor_data().is_type_recognized(prop_info.name) && ResourceLoader::exists(prop_info.hint_string, "Script")) {
|
||||
Ref<Script> scr = ResourceLoader::load(prop_info.hint_string, "Script");
|
||||
if (scr.is_valid()) {
|
||||
current_category = scr->get_doc_class_name();
|
||||
}
|
||||
}
|
||||
current_group = "";
|
||||
current_subgroup = "";
|
||||
continue;
|
||||
}
|
||||
if (!(prop_info.usage & PROPERTY_USAGE_EDITOR)) {
|
||||
continue;
|
||||
}
|
||||
if (prop_info.name.get_slice_count("/") > 1) {
|
||||
current_group = prop_info.name.get_slicec('/', 0);
|
||||
}
|
||||
if (!(current_category + "/" + current_group + "/" + current_subgroup).begins_with(get_inspector_path())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
r_properties.push_back(prop_info.name);
|
||||
}
|
||||
}
|
||||
|
||||
void EditorInspectorSection::menu_option(int p_option) const {
|
||||
switch (p_option) {
|
||||
case MENU_COPY_VALUE: {
|
||||
LocalVector<String> properties;
|
||||
Dictionary clipboard;
|
||||
_collect_properties(properties);
|
||||
|
||||
clipboard["@pastebin_section_name"] = get_inspector_path();
|
||||
for (const String &property_name : properties) {
|
||||
clipboard[property_name] = object->get(property_name);
|
||||
}
|
||||
InspectorDock::get_inspector_singleton()->set_property_clipboard(clipboard);
|
||||
} break;
|
||||
case MENU_PASTE_VALUE: {
|
||||
Dictionary clipboard = InspectorDock::get_inspector_singleton()->get_property_clipboard();
|
||||
if (!clipboard.has("@pastebin_section_name")) {
|
||||
break;
|
||||
}
|
||||
const String section_path = clipboard["@pastebin_section_name"];
|
||||
if (!get_inspector_path().begins_with(section_path)) {
|
||||
break;
|
||||
}
|
||||
|
||||
LocalVector<String> properties;
|
||||
|
||||
_collect_properties(properties);
|
||||
EditorUndoRedoManager *ur = EditorUndoRedoManager::get_singleton();
|
||||
|
||||
if (const MultiNodeEdit *multi_node_edit = Object::cast_to<MultiNodeEdit>(object)) {
|
||||
const Node *es = EditorNode::get_singleton()->get_edited_scene();
|
||||
const String action_name = vformat(TTR("Set section %s on %d nodes"), section_path, multi_node_edit->get_node_count());
|
||||
ur->create_action(action_name);
|
||||
|
||||
for (int i = 0; i < multi_node_edit->get_node_count(); i++) {
|
||||
const NodePath E = multi_node_edit->get_node(i);
|
||||
Node *n = es->get_node(E);
|
||||
if (!n) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (const String &property_name : properties) {
|
||||
ur->add_do_property(n, property_name, clipboard[property_name]);
|
||||
ur->add_undo_property(n, property_name, n->get(property_name));
|
||||
}
|
||||
}
|
||||
|
||||
ur->commit_action();
|
||||
} else {
|
||||
const String action_name = vformat(TTR("Set section %s on node %s"), section_path, object->get("name"));
|
||||
ur->create_action(action_name);
|
||||
|
||||
for (const String &property_name : properties) {
|
||||
ur->add_do_property(object, property_name, clipboard[property_name]);
|
||||
ur->add_undo_property(object, property_name, object->get(property_name));
|
||||
}
|
||||
|
||||
ur->commit_action();
|
||||
}
|
||||
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void EditorInspectorSection::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("setup", "section", "label", "object", "bg_color", "foldable", "indent_depth", "level"), &EditorInspectorSection::setup, DEFVAL(0), DEFVAL(1));
|
||||
ClassDB::bind_method(D_METHOD("get_vbox"), &EditorInspectorSection::get_vbox);
|
||||
|
|
@ -3350,7 +3610,7 @@ void EditorInspectorArray::_bind_methods() {
|
|||
ADD_SIGNAL(MethodInfo("page_change_request"));
|
||||
}
|
||||
|
||||
void EditorInspectorArray::setup_with_move_element_function(Object *p_object, const String &p_label, const StringName &p_array_element_prefix, int p_page, const Color &p_bg_color, bool p_foldable, bool p_movable, bool p_is_const, bool p_numbered, int p_page_length, const String &p_add_item_text) {
|
||||
void EditorInspectorArray::setup_with_move_element_function(Object *p_object, const String &p_category, const String &p_label, const StringName &p_array_element_prefix, int p_page, const Color &p_bg_color, bool p_foldable, bool p_movable, bool p_is_const, bool p_numbered, int p_page_length, const String &p_add_item_text) {
|
||||
count_property = "";
|
||||
mode = MODE_USE_MOVE_ARRAY_ELEMENT_FUNCTION;
|
||||
array_element_prefix = p_array_element_prefix;
|
||||
|
|
@ -3360,12 +3620,12 @@ void EditorInspectorArray::setup_with_move_element_function(Object *p_object, co
|
|||
page_length = p_page_length;
|
||||
numbered = p_numbered;
|
||||
|
||||
EditorInspectorSection::setup(String(p_array_element_prefix) + "_array", p_label, p_object, p_bg_color, p_foldable, 0);
|
||||
EditorInspectorSection::setup(p_category + "/" + p_label.to_lower(), String(p_array_element_prefix) + "_array", p_label, p_object, p_bg_color, p_foldable, 0);
|
||||
|
||||
_setup();
|
||||
}
|
||||
|
||||
void EditorInspectorArray::setup_with_count_property(Object *p_object, const String &p_label, const StringName &p_count_property, const StringName &p_array_element_prefix, int p_page, const Color &p_bg_color, bool p_foldable, bool p_movable, bool p_is_const, bool p_numbered, int p_page_length, const String &p_add_item_text, const String &p_swap_method) {
|
||||
void EditorInspectorArray::setup_with_count_property(Object *p_object, const String &p_category, const String &p_label, const StringName &p_count_property, const StringName &p_array_element_prefix, int p_page, const Color &p_bg_color, bool p_foldable, bool p_movable, bool p_is_const, bool p_numbered, int p_page_length, const String &p_add_item_text, const String &p_swap_method) {
|
||||
count_property = p_count_property;
|
||||
mode = MODE_USE_COUNT_PROPERTY;
|
||||
array_element_prefix = p_array_element_prefix;
|
||||
|
|
@ -3377,7 +3637,7 @@ void EditorInspectorArray::setup_with_count_property(Object *p_object, const Str
|
|||
swap_method = p_swap_method;
|
||||
|
||||
add_button->set_text(p_add_item_text);
|
||||
EditorInspectorSection::setup(String(count_property) + "_array", p_label, p_object, p_bg_color, p_foldable, 0);
|
||||
EditorInspectorSection::setup(p_category + "/" + p_label.to_lower(), String(count_property) + "_array", p_label, p_object, p_bg_color, p_foldable, 0);
|
||||
|
||||
_setup();
|
||||
}
|
||||
|
|
@ -3612,6 +3872,8 @@ void EditorInspector::initialize_section_theme(EditorInspectorSection::ThemeCach
|
|||
p_cache.icon_gui_checked = p_control->get_editor_theme_icon(SNAME("GuiChecked"));
|
||||
p_cache.icon_gui_unchecked = p_control->get_editor_theme_icon(SNAME("GuiUnchecked"));
|
||||
p_cache.icon_gui_animation_key = p_control->get_editor_theme_icon(SNAME("Key"));
|
||||
p_cache.icon_copy = p_control->get_editor_theme_icon(SNAME("ActionCopy"));
|
||||
p_cache.icon_paste = p_control->get_editor_theme_icon(SNAME("ActionPaste"));
|
||||
|
||||
p_cache.indent_box = p_control->get_theme_stylebox(SNAME("indent_box"), SNAME("EditorInspectorSection"));
|
||||
p_cache.key_hover = p_control->get_theme_stylebox(SceneStringName(hover), SceneStringName(FlatButton));
|
||||
|
|
@ -3633,6 +3895,9 @@ void EditorInspector::initialize_category_theme(EditorInspectorCategory::ThemeCa
|
|||
p_cache.bold_font = p_control->get_theme_font(SNAME("bold"), EditorStringName(EditorFonts));
|
||||
p_cache.bold_font_size = p_control->get_theme_font_size(SNAME("bold_size"), EditorStringName(EditorFonts));
|
||||
|
||||
p_cache.icon_copy = p_control->get_editor_theme_icon(SNAME("ActionCopy"));
|
||||
p_cache.icon_paste = p_control->get_editor_theme_icon(SNAME("ActionPaste"));
|
||||
|
||||
p_cache.icon_favorites = p_control->get_editor_theme_icon(SNAME("Favorites"));
|
||||
p_cache.icon_unfavorite = p_control->get_editor_theme_icon(SNAME("Unfavorite"));
|
||||
p_cache.icon_help = p_control->get_editor_theme_icon(SNAME("Help"));
|
||||
|
|
@ -4312,7 +4577,7 @@ void EditorInspector::update_tree() {
|
|||
|
||||
Color c = sscolor;
|
||||
c.a /= level;
|
||||
section->setup(acc_path, label, object, c, use_folding, section_depth, level);
|
||||
section->setup((doc_name.is_empty() ? acc_path : String(doc_name) + (acc_path.is_empty() ? "" : "/" + acc_path)), acc_path, label, object, c, use_folding, section_depth, level);
|
||||
section->set_tooltip_text(tooltip);
|
||||
|
||||
section->connect("section_toggled_by_user", callable_mp(this, &EditorInspector::_section_toggled_by_user));
|
||||
|
|
@ -4379,7 +4644,7 @@ void EditorInspector::update_tree() {
|
|||
String array_label = path.contains_char('/') ? path.substr(path.rfind_char('/') + 1) : path;
|
||||
array_label = EditorPropertyNameProcessor::get_singleton()->process_name(property_label_string, property_name_style, p.name, doc_name);
|
||||
int page = per_array_page.has(array_element_prefix) ? per_array_page[array_element_prefix] : 0;
|
||||
editor_inspector_array->setup_with_move_element_function(object, array_label, array_element_prefix, page, c, use_folding);
|
||||
editor_inspector_array->setup_with_move_element_function(object, p.hint_string, array_label, array_element_prefix, page, c, use_folding);
|
||||
editor_inspector_array->connect("page_change_request", callable_mp(this, &EditorInspector::_page_change_request).bind(array_element_prefix));
|
||||
} else if (p.type == Variant::INT) {
|
||||
// Setup the array to use the count property and built-in functions to create/move/delete elements.
|
||||
|
|
@ -4388,7 +4653,7 @@ void EditorInspector::update_tree() {
|
|||
editor_inspector_array = memnew(EditorInspectorArray(all_read_only));
|
||||
int page = per_array_page.has(array_element_prefix) ? per_array_page[array_element_prefix] : 0;
|
||||
|
||||
editor_inspector_array->setup_with_count_property(object, class_name_components[0], p.name, array_element_prefix, page, c, foldable, movable, is_const, numbered, page_size, add_button_text, swap_method);
|
||||
editor_inspector_array->setup_with_count_property(object, p.hint_string, class_name_components[0], p.name, array_element_prefix, page, c, foldable, movable, is_const, numbered, page_size, add_button_text, swap_method);
|
||||
editor_inspector_array->connect("page_change_request", callable_mp(this, &EditorInspector::_page_change_request).bind(array_element_prefix));
|
||||
}
|
||||
}
|
||||
|
|
@ -4735,7 +5000,8 @@ void EditorInspector::update_tree() {
|
|||
get_root_inspector()->get_v_scroll_bar()->connect(SceneStringName(value_changed), callable_mp(section, &EditorInspectorSection::reset_timer).unbind(1));
|
||||
favorites_groups_vbox->add_child(section);
|
||||
parent_vbox = section->get_vbox();
|
||||
section->setup("", section_name, object, sscolor, false);
|
||||
|
||||
section->setup("", "", section_name, object, sscolor, false);
|
||||
section->set_tooltip_text(tooltip);
|
||||
|
||||
if (togglable_editor_inspector_sections.has(section_name)) {
|
||||
|
|
@ -4774,7 +5040,7 @@ void EditorInspector::update_tree() {
|
|||
get_root_inspector()->get_v_scroll_bar()->connect(SceneStringName(value_changed), callable_mp(section, &EditorInspectorSection::reset_timer).unbind(1));
|
||||
vbox->add_child(section);
|
||||
vbox = section->get_vbox();
|
||||
section->setup("", section_name, object, sscolor, false);
|
||||
section->setup("", "", section_name, object, sscolor, false);
|
||||
section->set_tooltip_text(tooltip);
|
||||
|
||||
if (togglable_editor_inspector_sections.has(KV.key + "/" + section_name)) {
|
||||
|
|
|
|||
|
|
@ -381,6 +381,8 @@ class EditorInspectorCategory : public Control {
|
|||
|
||||
// Right-click context menu options.
|
||||
enum ClassMenuOption {
|
||||
MENU_COPY_VALUE,
|
||||
MENU_PASTE_VALUE,
|
||||
MENU_OPEN_DOCS,
|
||||
MENU_UNFAVORITE_ALL,
|
||||
};
|
||||
|
|
@ -395,6 +397,8 @@ class EditorInspectorCategory : public Control {
|
|||
Ref<Font> bold_font;
|
||||
int bold_font_size = 0;
|
||||
|
||||
Ref<Texture2D> icon_copy;
|
||||
Ref<Texture2D> icon_paste;
|
||||
Ref<Texture2D> icon_favorites;
|
||||
Ref<Texture2D> icon_unfavorite;
|
||||
Ref<Texture2D> icon_help;
|
||||
|
|
@ -411,6 +415,7 @@ class EditorInspectorCategory : public Control {
|
|||
bool is_favorite = false;
|
||||
bool menu_icon_dirty = true;
|
||||
|
||||
void _collect_properties(const Object *p_object, LocalVector<String> &r_properties) const;
|
||||
void _handle_menu_option(int p_option);
|
||||
void _popup_context_menu(const Point2i &p_position);
|
||||
void _update_icon();
|
||||
|
|
@ -440,8 +445,14 @@ class EditorInspectorSection : public Container {
|
|||
|
||||
friend class EditorInspector;
|
||||
|
||||
enum MenuItems {
|
||||
MENU_COPY_VALUE,
|
||||
MENU_PASTE_VALUE,
|
||||
};
|
||||
|
||||
String label;
|
||||
String section;
|
||||
String inspector_path;
|
||||
Color bg_color;
|
||||
bool vbox_added = false; // Optimization.
|
||||
bool foldable = false;
|
||||
|
|
@ -463,6 +474,8 @@ class EditorInspectorSection : public Container {
|
|||
|
||||
bool checkbox_only = false;
|
||||
|
||||
PopupMenu *menu = nullptr;
|
||||
|
||||
HashSet<StringName> revertable_properties;
|
||||
|
||||
void _test_unfold();
|
||||
|
|
@ -501,6 +514,8 @@ class EditorInspectorSection : public Container {
|
|||
Ref<Texture2D> icon_gui_checked;
|
||||
Ref<Texture2D> icon_gui_unchecked;
|
||||
Ref<Texture2D> icon_gui_animation_key;
|
||||
Ref<Texture2D> icon_copy;
|
||||
Ref<Texture2D> icon_paste;
|
||||
|
||||
Ref<StyleBoxFlat> indent_box;
|
||||
Ref<StyleBoxFlat> key_hover;
|
||||
|
|
@ -521,9 +536,10 @@ public:
|
|||
virtual Size2 get_minimum_size() const override;
|
||||
virtual Control *make_custom_tooltip(const String &p_text) const override;
|
||||
|
||||
void setup(const String &p_section, const String &p_label, Object *p_object, const Color &p_bg_color, bool p_foldable, int p_indent_depth = 0, int p_level = 1);
|
||||
void setup(const String &p_inspector_path, const String &p_section, const String &p_label, Object *p_object, const Color &p_bg_color, bool p_foldable, int p_indent_depth = 0, int p_level = 1);
|
||||
String get_section() const;
|
||||
String get_label() const { return label; }
|
||||
String get_inspector_path() const { return inspector_path; }
|
||||
VBoxContainer *get_vbox();
|
||||
void unfold();
|
||||
void fold();
|
||||
|
|
@ -539,6 +555,10 @@ public:
|
|||
void _property_edited(const String &p_property);
|
||||
void update_property();
|
||||
|
||||
void _update_popup();
|
||||
void _collect_properties(LocalVector<String> &r_properties) const;
|
||||
void menu_option(int p_option) const;
|
||||
|
||||
EditorInspectorSection();
|
||||
~EditorInspectorSection();
|
||||
};
|
||||
|
|
@ -658,8 +678,8 @@ protected:
|
|||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
void setup_with_move_element_function(Object *p_object, const String &p_label, const StringName &p_array_element_prefix, int p_page, const Color &p_bg_color, bool p_foldable, bool p_movable = true, bool p_is_const = false, bool p_numbered = false, int p_page_length = 5, const String &p_add_item_text = "");
|
||||
void setup_with_count_property(Object *p_object, const String &p_label, const StringName &p_count_property, const StringName &p_array_element_prefix, int p_page, const Color &p_bg_color, bool p_foldable, bool p_movable = true, bool p_is_const = false, bool p_numbered = false, int p_page_length = 5, const String &p_add_item_text = "", const String &p_swap_method = "");
|
||||
void setup_with_move_element_function(Object *p_object, const String &p_category, const String &p_label, const StringName &p_array_element_prefix, int p_page, const Color &p_bg_color, bool p_foldable, bool p_movable = true, bool p_is_const = false, bool p_numbered = false, int p_page_length = 5, const String &p_add_item_text = "");
|
||||
void setup_with_count_property(Object *p_object, const String &p_category, const String &p_label, const StringName &p_count_property, const StringName &p_array_element_prefix, int p_page, const Color &p_bg_color, bool p_foldable, bool p_movable = true, bool p_is_const = false, bool p_numbered = false, int p_page_length = 5, const String &p_add_item_text = "", const String &p_swap_method = "");
|
||||
VBoxContainer *get_vbox(int p_index);
|
||||
|
||||
void show_menu(int p_index, const Vector2 &p_offset);
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@
|
|||
|
||||
void BonePropertiesEditor::create_editors() {
|
||||
section = memnew(EditorInspectorSection);
|
||||
section->setup("trf_properties", label, this, Color(0.0f, 0.0f, 0.0f), true);
|
||||
section->setup("", "trf_properties", label, this, Color(0.0f, 0.0f, 0.0f), true);
|
||||
section->unfold();
|
||||
add_child(section);
|
||||
|
||||
|
|
@ -107,7 +107,7 @@ void BonePropertiesEditor::create_editors() {
|
|||
|
||||
// Transform/Matrix section.
|
||||
rest_section = memnew(EditorInspectorSection);
|
||||
rest_section->setup("trf_properties_transform", "Rest", this, Color(0.0f, 0.0f, 0.0f), true);
|
||||
rest_section->setup("", "trf_properties_transform", "Rest", this, Color(0.0f, 0.0f, 0.0f), true);
|
||||
section->get_vbox()->add_child(rest_section);
|
||||
|
||||
// Transform/Matrix property.
|
||||
|
|
@ -119,7 +119,7 @@ void BonePropertiesEditor::create_editors() {
|
|||
|
||||
// Bone Metadata property
|
||||
meta_section = memnew(EditorInspectorSection);
|
||||
meta_section->setup("bone_meta", TTR("Bone Metadata"), this, Color(.0f, .0f, .0f), true);
|
||||
meta_section->setup("", "bone_meta", TTR("Bone Metadata"), this, Color(.0f, .0f, .0f), true);
|
||||
section->get_vbox()->add_child(meta_section);
|
||||
|
||||
EditorInspectorActionButton *add_metadata_button = memnew(EditorInspectorActionButton(TTRC("Add Bone Metadata"), SNAME("Add")));
|
||||
|
|
@ -1161,7 +1161,7 @@ void Skeleton3DEditor::create_editors() {
|
|||
|
||||
// Bone tree.
|
||||
bones_section = memnew(EditorInspectorSection);
|
||||
bones_section->setup("bones", "Bones", skeleton, Color(0.0f, 0.0, 0.0f), true);
|
||||
bones_section->setup("", "bones", "Bones", skeleton, Color(0.0f, 0.0, 0.0f), true);
|
||||
add_child(bones_section);
|
||||
bones_section->unfold();
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue