mirror of
https://github.com/Relintai/pandemonium_engine.git
synced 2025-01-18 07:17:18 +01:00
Added some missing code from:
Implement properties arrays in the Inspector. - groud godotengine/godot@4bd7700
This commit is contained in:
parent
dbcb0ac6d9
commit
2e48acd426
@ -1854,6 +1854,8 @@ void EditorInspectorArray::_bind_methods() {
|
|||||||
ClassDB::bind_method(D_METHOD("_can_drop_data_fw"), &EditorInspectorArray::can_drop_data_fw);
|
ClassDB::bind_method(D_METHOD("_can_drop_data_fw"), &EditorInspectorArray::can_drop_data_fw);
|
||||||
ClassDB::bind_method(D_METHOD("_drop_data_fw"), &EditorInspectorArray::drop_data_fw);
|
ClassDB::bind_method(D_METHOD("_drop_data_fw"), &EditorInspectorArray::drop_data_fw);
|
||||||
|
|
||||||
|
ClassDB::bind_method(D_METHOD("_panel_gui_input"), &EditorInspectorArray::_panel_gui_input);
|
||||||
|
|
||||||
ClassDB::bind_method(D_METHOD("_panel_draw"), &EditorInspectorArray::_panel_draw);
|
ClassDB::bind_method(D_METHOD("_panel_draw"), &EditorInspectorArray::_panel_draw);
|
||||||
ClassDB::bind_method(D_METHOD("_rmb_popup_id_pressed"), &EditorInspectorArray::_rmb_popup_id_pressed);
|
ClassDB::bind_method(D_METHOD("_rmb_popup_id_pressed"), &EditorInspectorArray::_rmb_popup_id_pressed);
|
||||||
ClassDB::bind_method(D_METHOD("_add_button_pressed"), &EditorInspectorArray::_add_button_pressed);
|
ClassDB::bind_method(D_METHOD("_add_button_pressed"), &EditorInspectorArray::_add_button_pressed);
|
||||||
@ -1953,7 +1955,7 @@ EditorInspectorArray::EditorInspectorArray() {
|
|||||||
hbox_pagination->add_child(prev_page_button);
|
hbox_pagination->add_child(prev_page_button);
|
||||||
|
|
||||||
page_line_edit = memnew(LineEdit);
|
page_line_edit = memnew(LineEdit);
|
||||||
page_line_edit->connect("text_submitted", this, "_page_line_edit_text_submitted");
|
page_line_edit->connect("text_entered", this, "_page_line_edit_text_submitted");
|
||||||
page_line_edit->add_theme_constant_override("minimum_character_width", 2);
|
page_line_edit->add_theme_constant_override("minimum_character_width", 2);
|
||||||
hbox_pagination->add_child(page_line_edit);
|
hbox_pagination->add_child(page_line_edit);
|
||||||
|
|
||||||
@ -1985,7 +1987,7 @@ EditorInspectorArray::EditorInspectorArray() {
|
|||||||
|
|
||||||
new_size_line_edit = memnew(LineEdit);
|
new_size_line_edit = memnew(LineEdit);
|
||||||
new_size_line_edit->connect("text_changed", this, "_new_size_line_edit_text_changed");
|
new_size_line_edit->connect("text_changed", this, "_new_size_line_edit_text_changed");
|
||||||
new_size_line_edit->connect("text_submitted", this, "_new_size_line_edit_text_submitted");
|
new_size_line_edit->connect("text_entered", this, "_new_size_line_edit_text_submitted");
|
||||||
resize_dialog_vbox->add_margin_child(TTRC("New Size:"), new_size_line_edit);
|
resize_dialog_vbox->add_margin_child(TTRC("New Size:"), new_size_line_edit);
|
||||||
|
|
||||||
vbox->connect("visibility_changed", this, "_vbox_visibility_changed");
|
vbox->connect("visibility_changed", this, "_vbox_visibility_changed");
|
||||||
@ -2153,18 +2155,18 @@ void EditorInspector::update_tree() {
|
|||||||
valid_plugins.push_back(inspector_plugins[i]);
|
valid_plugins.push_back(inspector_plugins[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Decide if properties should be drawn in red.
|
||||||
bool draw_red = false;
|
bool draw_red = false;
|
||||||
|
|
||||||
{
|
{
|
||||||
Node *nod = Object::cast_to<Node>(object);
|
Node *nod = Object::cast_to<Node>(object);
|
||||||
Node *es = EditorNode::get_singleton()->get_edited_scene();
|
Node *es = EditorNode::get_singleton()->get_edited_scene();
|
||||||
if (nod && es != nod && nod->get_owner() != es) {
|
if (nod && es != nod && nod->get_owner() != es) {
|
||||||
|
// Draw in red edited nodes that are not in the currently edited scene.
|
||||||
draw_red = true;
|
draw_red = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TreeItem *current_category = NULL;
|
|
||||||
|
|
||||||
String filter = search_box ? search_box->get_text() : "";
|
String filter = search_box ? search_box->get_text() : "";
|
||||||
String group;
|
String group;
|
||||||
String group_base;
|
String group_base;
|
||||||
@ -2173,31 +2175,33 @@ void EditorInspector::update_tree() {
|
|||||||
List<PropertyInfo> plist;
|
List<PropertyInfo> plist;
|
||||||
object->get_property_list(&plist, true);
|
object->get_property_list(&plist, true);
|
||||||
|
|
||||||
HashMap<String, VBoxContainer *> item_path;
|
RBMap<VBoxContainer *, HashMap<String, VBoxContainer *>> vbox_per_path;
|
||||||
RBMap<VBoxContainer *, EditorInspectorSection *> section_map;
|
RBMap<String, EditorInspectorArray *> editor_inspector_array_per_prefix;
|
||||||
|
|
||||||
item_path[""] = main_vbox;
|
|
||||||
|
|
||||||
Color sscolor = get_theme_color("prop_subsection", "Editor");
|
Color sscolor = get_theme_color("prop_subsection", "Editor");
|
||||||
|
|
||||||
|
// Get the lists of editors to add the beginning.
|
||||||
for (List<Ref<EditorInspectorPlugin>>::Element *E = valid_plugins.front(); E; E = E->next()) {
|
for (List<Ref<EditorInspectorPlugin>>::Element *E = valid_plugins.front(); E; E = E->next()) {
|
||||||
Ref<EditorInspectorPlugin> ped = E->get();
|
Ref<EditorInspectorPlugin> ped = E->get();
|
||||||
ped->parse_begin(object);
|
ped->parse_begin(object);
|
||||||
_parse_added_editors(main_vbox, ped);
|
_parse_added_editors(main_vbox, ped);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (List<PropertyInfo>::Element *I = plist.front(); I; I = I->next()) {
|
// Get the lists of editors for properties.
|
||||||
PropertyInfo &p = I->get();
|
for (List<PropertyInfo>::Element *E_property = plist.front(); E_property; E_property = E_property->next()) {
|
||||||
|
PropertyInfo &p = E_property->get();
|
||||||
|
|
||||||
//make sure the property can be edited
|
//make sure the property can be edited
|
||||||
|
|
||||||
if (p.usage & PROPERTY_USAGE_GROUP) {
|
if (p.usage & PROPERTY_USAGE_GROUP) {
|
||||||
|
// Setup a property group.
|
||||||
group = p.name;
|
group = p.name;
|
||||||
group_base = p.hint_string;
|
group_base = p.hint_string;
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
} else if (p.usage & PROPERTY_USAGE_CATEGORY) {
|
} else if (p.usage & PROPERTY_USAGE_CATEGORY) {
|
||||||
|
// Setup a property category.
|
||||||
group = "";
|
group = "";
|
||||||
group_base = "";
|
group_base = "";
|
||||||
|
|
||||||
@ -2205,9 +2209,10 @@ void EditorInspector::update_tree() {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
List<PropertyInfo>::Element *N = I->next();
|
// Iterate over remaining properties. If no properties in category, skip the category.
|
||||||
|
List<PropertyInfo>::Element *N = E_property->next();
|
||||||
bool valid = true;
|
bool valid = true;
|
||||||
//if no properties in category, skip
|
|
||||||
while (N) {
|
while (N) {
|
||||||
if (N->get().usage & PROPERTY_USAGE_EDITOR) {
|
if (N->get().usage & PROPERTY_USAGE_EDITOR) {
|
||||||
break;
|
break;
|
||||||
@ -2219,9 +2224,10 @@ void EditorInspector::update_tree() {
|
|||||||
N = N->next();
|
N = N->next();
|
||||||
}
|
}
|
||||||
if (!valid) {
|
if (!valid) {
|
||||||
continue; //empty, ignore
|
continue; // Empty, ignore it.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Create an EditorInspectorCategory and add it to the inspector.
|
||||||
EditorInspectorCategory *category = memnew(EditorInspectorCategory);
|
EditorInspectorCategory *category = memnew(EditorInspectorCategory);
|
||||||
main_vbox->add_child(category);
|
main_vbox->add_child(category);
|
||||||
category_vbox = nullptr; //reset
|
category_vbox = nullptr; //reset
|
||||||
@ -2232,6 +2238,7 @@ void EditorInspector::update_tree() {
|
|||||||
|
|
||||||
category->bg_color = get_theme_color("prop_category", "Editor");
|
category->bg_color = get_theme_color("prop_category", "Editor");
|
||||||
if (use_doc_hints) {
|
if (use_doc_hints) {
|
||||||
|
// Sets the category tooltip to show documentation.
|
||||||
StringName type2 = p.name;
|
StringName type2 = p.name;
|
||||||
if (!class_descr_cache.has(type2)) {
|
if (!class_descr_cache.has(type2)) {
|
||||||
String descr;
|
String descr;
|
||||||
@ -2246,6 +2253,7 @@ void EditorInspector::update_tree() {
|
|||||||
category->set_tooltip(p.name + "::" + (class_descr_cache[type2] == "" ? "" : class_descr_cache[type2]));
|
category->set_tooltip(p.name + "::" + (class_descr_cache[type2] == "" ? "" : class_descr_cache[type2]));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add editors at the start of a category.
|
||||||
for (List<Ref<EditorInspectorPlugin>>::Element *E = valid_plugins.front(); E; E = E->next()) {
|
for (List<Ref<EditorInspectorPlugin>>::Element *E = valid_plugins.front(); E; E = E->next()) {
|
||||||
Ref<EditorInspectorPlugin> ped = E->get();
|
Ref<EditorInspectorPlugin> ped = E->get();
|
||||||
ped->parse_category(object, p.name);
|
ped->parse_category(object, p.name);
|
||||||
@ -2255,111 +2263,181 @@ void EditorInspector::update_tree() {
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
} else if (!(p.usage & PROPERTY_USAGE_EDITOR)) {
|
} else if (!(p.usage & PROPERTY_USAGE_EDITOR)) {
|
||||||
|
// Ignore properties that are not supposed to be in the inspector.
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (p.usage & PROPERTY_USAGE_HIGH_END_GFX && RS::get_singleton()->is_low_end()) {
|
if (p.usage & PROPERTY_USAGE_HIGH_END_GFX && RS::get_singleton()->is_low_end()) {
|
||||||
continue; //do not show this property in low end gfx
|
//do not show this property in low end gfx
|
||||||
}
|
|
||||||
|
|
||||||
if (p.name == "script" && (hide_script || bool(object->call("_hide_script_from_inspector")))) {
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
String basename = p.name;
|
if (p.name == "script" && (hide_script || bool(object->call("_hide_script_from_inspector")))) {
|
||||||
if (group != "") {
|
// Script should go into its own category.
|
||||||
if (group_base != "") {
|
continue;
|
||||||
if (basename.begins_with(group_base)) {
|
}
|
||||||
basename = basename.replace_first(group_base, "");
|
|
||||||
} else if (group_base.begins_with(basename)) {
|
// Get the path for property.
|
||||||
//keep it, this is used pretty often
|
String path = p.name;
|
||||||
} else {
|
|
||||||
group = ""; //no longer using group base, clear
|
// First check if we have an array that fits the prefix.
|
||||||
|
String array_prefix = "";
|
||||||
|
int array_index = -1;
|
||||||
|
for (RBMap<String, EditorInspectorArray *>::Element *E = editor_inspector_array_per_prefix.front(); E; E = E->next()) {
|
||||||
|
if (p.name.begins_with(E->key()) && E->key().length() > array_prefix.length()) {
|
||||||
|
array_prefix = E->key();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!array_prefix.empty()) {
|
||||||
|
path = path.trim_prefix(array_prefix);
|
||||||
|
int char_index = path.find("/");
|
||||||
|
if (char_index >= 0) {
|
||||||
|
path = path.right(-char_index - 1);
|
||||||
|
} else {
|
||||||
|
path = vformat(TTR("Element %s"), array_index);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Check if we exit or not a group. If there is a prefix, remove it from the property label string.
|
||||||
|
if (group != "") {
|
||||||
|
if (group_base != "") {
|
||||||
|
if (path.begins_with(group_base)) {
|
||||||
|
path = path.replace_first(group_base, "");
|
||||||
|
} else if (group_base.begins_with(path)) {
|
||||||
|
//keep it, this is used pretty often
|
||||||
|
} else {
|
||||||
|
group = ""; //no longer using group base, clear
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (group != "") {
|
||||||
|
path = group + "/" + path;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (group != "") {
|
// Get the property label's string.
|
||||||
basename = group + "/" + basename;
|
String property_label_string = (path.find("/") != -1) ? path.right(path.rfind("/") + 1) : path;
|
||||||
}
|
|
||||||
|
|
||||||
String name = (basename.find("/") != -1) ? basename.right(basename.rfind("/") + 1) : basename;
|
|
||||||
|
|
||||||
if (capitalize_paths) {
|
if (capitalize_paths) {
|
||||||
int dot = name.find(".");
|
int dot = property_label_string.find(".");
|
||||||
if (dot != -1) {
|
if (dot != -1) {
|
||||||
String ov = name.right(dot);
|
String ov = property_label_string.right(dot);
|
||||||
name = name.substr(0, dot);
|
property_label_string = property_label_string.substr(0, dot);
|
||||||
name = EditorPropertyNameProcessor::get_singleton()->process_name(name);
|
property_label_string = EditorPropertyNameProcessor::get_singleton()->process_name(property_label_string);
|
||||||
name += ov;
|
property_label_string += ov;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
name = EditorPropertyNameProcessor::get_singleton()->process_name(name);
|
property_label_string = EditorPropertyNameProcessor::get_singleton()->process_name(property_label_string);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
String path = basename.left(basename.rfind("/"));
|
// Remove the property from the path.
|
||||||
|
int idx = path.rfind("/");
|
||||||
|
if (idx > -1) {
|
||||||
|
path = path.left(idx);
|
||||||
|
} else {
|
||||||
|
path = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ignore properties that do not fit the filter.
|
||||||
if (use_filter && filter != "") {
|
if (use_filter && filter != "") {
|
||||||
String cat = path;
|
if (!filter.is_subsequence_ofi(path) && !filter.is_subsequence_ofi(property_label_string) && property_prefix.to_lower().find(filter.to_lower()) == -1) {
|
||||||
|
|
||||||
if (capitalize_paths) {
|
|
||||||
cat = EditorPropertyNameProcessor::get_singleton()->process_name(cat);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!filter.is_subsequence_ofi(cat) && !filter.is_subsequence_ofi(name) && property_prefix.to_lower().find(filter.to_lower()) == -1) {
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Recreate the category vbox if it was reset.
|
||||||
if (category_vbox == nullptr) {
|
if (category_vbox == nullptr) {
|
||||||
category_vbox = memnew(VBoxContainer);
|
category_vbox = memnew(VBoxContainer);
|
||||||
main_vbox->add_child(category_vbox);
|
main_vbox->add_child(category_vbox);
|
||||||
}
|
}
|
||||||
|
|
||||||
VBoxContainer *current_vbox = main_vbox;
|
// Find the correct section/vbox to add the property editor to.
|
||||||
|
VBoxContainer *root_vbox = array_prefix.empty() ? main_vbox : editor_inspector_array_per_prefix[array_prefix]->get_vbox(array_index);
|
||||||
{
|
if (!root_vbox) {
|
||||||
String acc_path = "";
|
continue;
|
||||||
int level = 1;
|
|
||||||
for (int i = 0; i < path.get_slice_count("/"); i++) {
|
|
||||||
String path_name = path.get_slice("/", i);
|
|
||||||
if (i > 0) {
|
|
||||||
acc_path += "/";
|
|
||||||
}
|
|
||||||
acc_path += path_name;
|
|
||||||
if (!item_path.has(acc_path)) {
|
|
||||||
EditorInspectorSection *section = memnew(EditorInspectorSection);
|
|
||||||
current_vbox->add_child(section);
|
|
||||||
sections.push_back(section);
|
|
||||||
|
|
||||||
String label = path_name;
|
|
||||||
if (capitalize_paths) {
|
|
||||||
label = EditorPropertyNameProcessor::get_singleton()->process_name(label);
|
|
||||||
}
|
|
||||||
|
|
||||||
Color c = sscolor;
|
|
||||||
c.a /= level;
|
|
||||||
section->setup(acc_path, label, object, c, use_folding);
|
|
||||||
section->set_tooltip(EditorPropertyNameProcessor::get_singleton()->make_tooltip_for_name(path_name));
|
|
||||||
|
|
||||||
VBoxContainer *vb = section->get_vbox();
|
|
||||||
item_path[acc_path] = vb;
|
|
||||||
section_map[vb] = section;
|
|
||||||
}
|
|
||||||
current_vbox = item_path[acc_path];
|
|
||||||
level = (MIN(level + 1, 4));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (current_vbox == main_vbox) {
|
|
||||||
//do not add directly to the main vbox, given it has no spacing
|
|
||||||
if (category_vbox == nullptr) {
|
|
||||||
category_vbox = memnew(VBoxContainer);
|
|
||||||
}
|
|
||||||
current_vbox = category_vbox;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!vbox_per_path.has(root_vbox)) {
|
||||||
|
vbox_per_path[root_vbox] = HashMap<String, VBoxContainer *>();
|
||||||
|
vbox_per_path[root_vbox][""] = root_vbox;
|
||||||
|
}
|
||||||
|
|
||||||
|
VBoxContainer *current_vbox = root_vbox;
|
||||||
|
String acc_path = "";
|
||||||
|
int level = 1;
|
||||||
|
|
||||||
|
Vector<String> components = path.split("/");
|
||||||
|
for (int i = 0; i < components.size(); i++) {
|
||||||
|
String component = components[i];
|
||||||
|
acc_path += (i > 0) ? "/" + component : component;
|
||||||
|
|
||||||
|
if (!vbox_per_path[root_vbox].has(acc_path)) {
|
||||||
|
// If the section does not exists, create it.
|
||||||
|
EditorInspectorSection *section = memnew(EditorInspectorSection);
|
||||||
|
current_vbox->add_child(section);
|
||||||
|
sections.push_back(section);
|
||||||
|
|
||||||
|
if (capitalize_paths) {
|
||||||
|
component = component.capitalize();
|
||||||
|
}
|
||||||
|
|
||||||
|
Color c = sscolor;
|
||||||
|
c.a /= level;
|
||||||
|
section->setup(acc_path, component, object, c, use_folding);
|
||||||
|
section->set_tooltip(EditorPropertyNameProcessor::get_singleton()->make_tooltip_for_name(acc_path));
|
||||||
|
|
||||||
|
vbox_per_path[root_vbox][acc_path] = section->get_vbox();
|
||||||
|
}
|
||||||
|
|
||||||
|
current_vbox = vbox_per_path[root_vbox][acc_path];
|
||||||
|
level = (MIN(level + 1, 4));
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we did not find a section to add the property to, add it to the category vbox instead (the category vbox handles margins correctly).
|
||||||
|
if (current_vbox == main_vbox) {
|
||||||
|
current_vbox = category_vbox;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the property is an array counter, if so create a dedicated array editor for the array.
|
||||||
|
if (p.usage & PROPERTY_USAGE_ARRAY) {
|
||||||
|
EditorInspectorArray *editor_inspector_array = nullptr;
|
||||||
|
StringName array_element_prefix;
|
||||||
|
Color c = sscolor;
|
||||||
|
c.a /= level;
|
||||||
|
if (p.type == Variant::NIL) {
|
||||||
|
// Setup the array to use a method to create/move/delete elements.
|
||||||
|
array_element_prefix = p.class_name;
|
||||||
|
editor_inspector_array = memnew(EditorInspectorArray);
|
||||||
|
|
||||||
|
String array_label = (path.find("/") != -1) ? path.substr(path.rfind("/") + 1) : path;
|
||||||
|
array_label = property_label_string.capitalize();
|
||||||
|
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->connect("page_change_request", this, "_page_change_request", varray(array_element_prefix));
|
||||||
|
editor_inspector_array->set_undo_redo(undo_redo);
|
||||||
|
} else if (p.type == Variant::INT) {
|
||||||
|
// Setup the array to use the count property and built-in functions to create/move/delete elements.
|
||||||
|
Vector<String> class_name_components = String(p.class_name).split(",");
|
||||||
|
if (class_name_components.size() == 2) {
|
||||||
|
array_element_prefix = class_name_components[1];
|
||||||
|
editor_inspector_array = memnew(EditorInspectorArray);
|
||||||
|
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, use_folding);
|
||||||
|
editor_inspector_array->connect("page_change_request", this, "_page_change_request", varray(array_element_prefix));
|
||||||
|
editor_inspector_array->set_undo_redo(undo_redo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (editor_inspector_array) {
|
||||||
|
current_vbox->add_child(editor_inspector_array);
|
||||||
|
editor_inspector_array_per_prefix[array_element_prefix] = editor_inspector_array;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Checkable and checked properties.
|
||||||
bool checkable = false;
|
bool checkable = false;
|
||||||
bool checked = false;
|
bool checked = false;
|
||||||
if (p.usage & PROPERTY_USAGE_CHECKABLE) {
|
if (p.usage & PROPERTY_USAGE_CHECKABLE) {
|
||||||
@ -2367,6 +2445,7 @@ void EditorInspector::update_tree() {
|
|||||||
checked = p.usage & PROPERTY_USAGE_CHECKED;
|
checked = p.usage & PROPERTY_USAGE_CHECKED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Mark properties that would require an editor restart (mostly when editing editor settings).
|
||||||
if (p.usage & PROPERTY_USAGE_RESTART_IF_CHANGED) {
|
if (p.usage & PROPERTY_USAGE_RESTART_IF_CHANGED) {
|
||||||
restart_request_props.insert(p.name);
|
restart_request_props.insert(p.name);
|
||||||
}
|
}
|
||||||
@ -2374,6 +2453,9 @@ void EditorInspector::update_tree() {
|
|||||||
String doc_hint;
|
String doc_hint;
|
||||||
|
|
||||||
if (use_doc_hints) {
|
if (use_doc_hints) {
|
||||||
|
// Build the doc hint, to use as tooltip.
|
||||||
|
|
||||||
|
// Get the class name.
|
||||||
StringName classname = object->get_class_name();
|
StringName classname = object->get_class_name();
|
||||||
if (object_class != String()) {
|
if (object_class != String()) {
|
||||||
classname = object_class;
|
classname = object_class;
|
||||||
@ -2385,6 +2467,7 @@ void EditorInspector::update_tree() {
|
|||||||
String descr;
|
String descr;
|
||||||
bool found = false;
|
bool found = false;
|
||||||
|
|
||||||
|
// Search for the property description in the cache.
|
||||||
RBMap<StringName, RBMap<StringName, String>>::Element *E = descr_cache.find(classname);
|
RBMap<StringName, RBMap<StringName, String>>::Element *E = descr_cache.find(classname);
|
||||||
if (E) {
|
if (E) {
|
||||||
RBMap<StringName, String>::Element *F = E->get().find(propname);
|
RBMap<StringName, String>::Element *F = E->get().find(propname);
|
||||||
@ -2395,6 +2478,7 @@ void EditorInspector::update_tree() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!found) {
|
if (!found) {
|
||||||
|
// Build the property description String and add it to the cache.
|
||||||
DocData *dd = EditorHelp::get_doc_data();
|
DocData *dd = EditorHelp::get_doc_data();
|
||||||
RBMap<String, DocData::ClassDoc>::Element *F = dd->class_list.find(classname);
|
RBMap<String, DocData::ClassDoc>::Element *F = dd->class_list.find(classname);
|
||||||
while (F && descr == String()) {
|
while (F && descr == String()) {
|
||||||
@ -2428,18 +2512,19 @@ void EditorInspector::update_tree() {
|
|||||||
doc_hint = descr;
|
doc_hint = descr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Seach for the inspector plugin that will handle the properties. Then add the correct property editor to it.
|
||||||
for (List<Ref<EditorInspectorPlugin>>::Element *E = valid_plugins.front(); E; E = E->next()) {
|
for (List<Ref<EditorInspectorPlugin>>::Element *E = valid_plugins.front(); E; E = E->next()) {
|
||||||
Ref<EditorInspectorPlugin> ped = E->get();
|
Ref<EditorInspectorPlugin> ped = E->get();
|
||||||
bool exclusive = ped->parse_property(object, p.type, p.name, p.hint, p.hint_string, p.usage);
|
bool exclusive = ped->parse_property(object, p.type, p.name, p.hint, p.hint_string, p.usage);
|
||||||
|
|
||||||
List<EditorInspectorPlugin::AddedEditor> editors = ped->added_editors; //make a copy, since plugins may be used again in a sub-inspector
|
List<EditorInspectorPlugin::AddedEditor> editors = ped->added_editors; // Make a copy, since plugins may be used again in a sub-inspector
|
||||||
ped->added_editors.clear();
|
ped->added_editors.clear();
|
||||||
|
|
||||||
for (List<EditorInspectorPlugin::AddedEditor>::Element *F = editors.front(); F; F = F->next()) {
|
for (List<EditorInspectorPlugin::AddedEditor>::Element *F = editors.front(); F; F = F->next()) {
|
||||||
EditorProperty *ep = Object::cast_to<EditorProperty>(F->get().property_editor);
|
EditorProperty *ep = Object::cast_to<EditorProperty>(F->get().property_editor);
|
||||||
|
|
||||||
if (ep) {
|
if (ep) {
|
||||||
//set all this before the control gets the ENTER_TREE notification
|
// Set all this before the control gets the ENTER_TREE notification
|
||||||
ep->object = object;
|
ep->object = object;
|
||||||
|
|
||||||
if (F->get().properties.size()) {
|
if (F->get().properties.size()) {
|
||||||
@ -2455,8 +2540,9 @@ void EditorInspector::update_tree() {
|
|||||||
ep->set_label(F->get().label);
|
ep->set_label(F->get().label);
|
||||||
} else {
|
} else {
|
||||||
//use existing one
|
//use existing one
|
||||||
ep->set_label(name);
|
ep->set_label(property_label_string);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < F->get().properties.size(); i++) {
|
for (int i = 0; i < F->get().properties.size(); i++) {
|
||||||
String prop = F->get().properties[i];
|
String prop = F->get().properties[i];
|
||||||
|
|
||||||
@ -2478,6 +2564,7 @@ void EditorInspector::update_tree() {
|
|||||||
current_vbox->add_child(F->get().property_editor);
|
current_vbox->add_child(F->get().property_editor);
|
||||||
|
|
||||||
if (ep) {
|
if (ep) {
|
||||||
|
// Eventually, set other properties/signals after the property editor got added to the tree.
|
||||||
ep->connect("property_changed", this, "_property_changed");
|
ep->connect("property_changed", this, "_property_changed");
|
||||||
if (p.usage & PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED) {
|
if (p.usage & PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED) {
|
||||||
ep->connect("property_changed", this, "_property_changed_update_all", varray(), CONNECT_DEFERRED);
|
ep->connect("property_changed", this, "_property_changed_update_all", varray(), CONNECT_DEFERRED);
|
||||||
@ -2506,18 +2593,18 @@ void EditorInspector::update_tree() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (exclusive) {
|
if (exclusive) {
|
||||||
|
// If we know the plugin is exclusive, we don't need to go through other plugins.
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get the lists of to add at the end.
|
||||||
for (List<Ref<EditorInspectorPlugin>>::Element *E = valid_plugins.front(); E; E = E->next()) {
|
for (List<Ref<EditorInspectorPlugin>>::Element *E = valid_plugins.front(); E; E = E->next()) {
|
||||||
Ref<EditorInspectorPlugin> ped = E->get();
|
Ref<EditorInspectorPlugin> ped = E->get();
|
||||||
ped->parse_end();
|
ped->parse_end();
|
||||||
_parse_added_editors(main_vbox, ped);
|
_parse_added_editors(main_vbox, ped);
|
||||||
}
|
}
|
||||||
|
|
||||||
//see if this property exists and should be kept
|
|
||||||
}
|
}
|
||||||
void EditorInspector::update_property(const String &p_prop) {
|
void EditorInspector::update_property(const String &p_prop) {
|
||||||
if (!editor_property_map.has(p_prop)) {
|
if (!editor_property_map.has(p_prop)) {
|
||||||
@ -2562,6 +2649,8 @@ void EditorInspector::edit(Object *p_object) {
|
|||||||
object->remove_change_receptor(this);
|
object->remove_change_receptor(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
per_array_page.clear();
|
||||||
|
|
||||||
object = p_object;
|
object = p_object;
|
||||||
|
|
||||||
if (object) {
|
if (object) {
|
||||||
@ -2701,6 +2790,15 @@ Variant EditorInspector::get_property_clipboard() const {
|
|||||||
return property_clipboard;
|
return property_clipboard;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void EditorInspector::_page_change_request(int p_new_page, const StringName &p_array_prefix) {
|
||||||
|
int prev_page = per_array_page.has(p_array_prefix) ? per_array_page[p_array_prefix] : 0;
|
||||||
|
int new_page = MAX(0, p_new_page);
|
||||||
|
if (new_page != prev_page) {
|
||||||
|
per_array_page[p_array_prefix] = new_page;
|
||||||
|
update_tree_pending = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void EditorInspector::_edit_request_change(Object *p_object, const String &p_property) {
|
void EditorInspector::_edit_request_change(Object *p_object, const String &p_property) {
|
||||||
if (object != p_object) { //may be undoing/redoing for a non edited object, so ignore
|
if (object != p_object) { //may be undoing/redoing for a non edited object, so ignore
|
||||||
return;
|
return;
|
||||||
@ -2800,7 +2898,7 @@ void EditorInspector::_property_changed_update_all(const String &p_path, const V
|
|||||||
update_tree();
|
update_tree();
|
||||||
}
|
}
|
||||||
|
|
||||||
void EditorInspector::_multiple_properties_changed(Vector<String> p_paths, Array p_values) {
|
void EditorInspector::_multiple_properties_changed(Vector<String> p_paths, Array p_values, bool p_changing) {
|
||||||
ERR_FAIL_COND(p_paths.size() == 0 || p_values.size() == 0);
|
ERR_FAIL_COND(p_paths.size() == 0 || p_values.size() == 0);
|
||||||
ERR_FAIL_COND(p_paths.size() != p_values.size());
|
ERR_FAIL_COND(p_paths.size() != p_values.size());
|
||||||
String names;
|
String names;
|
||||||
@ -2817,9 +2915,13 @@ void EditorInspector::_multiple_properties_changed(Vector<String> p_paths, Array
|
|||||||
emit_signal("restart_requested");
|
emit_signal("restart_requested");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
changing++;
|
if (p_changing) {
|
||||||
|
changing++;
|
||||||
|
}
|
||||||
undo_redo->commit_action();
|
undo_redo->commit_action();
|
||||||
changing--;
|
if (p_changing) {
|
||||||
|
changing--;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void EditorInspector::_property_keyed(const String &p_path, bool p_advance) {
|
void EditorInspector::_property_keyed(const String &p_path, bool p_advance) {
|
||||||
@ -3036,6 +3138,7 @@ void EditorInspector::_bind_methods() {
|
|||||||
ClassDB::bind_method("_property_changed", &EditorInspector::_property_changed, DEFVAL(""), DEFVAL(false));
|
ClassDB::bind_method("_property_changed", &EditorInspector::_property_changed, DEFVAL(""), DEFVAL(false));
|
||||||
ClassDB::bind_method("_multiple_properties_changed", &EditorInspector::_multiple_properties_changed);
|
ClassDB::bind_method("_multiple_properties_changed", &EditorInspector::_multiple_properties_changed);
|
||||||
ClassDB::bind_method("_property_changed_update_all", &EditorInspector::_property_changed_update_all);
|
ClassDB::bind_method("_property_changed_update_all", &EditorInspector::_property_changed_update_all);
|
||||||
|
ClassDB::bind_method("_page_change_request", &EditorInspector::_page_change_request);
|
||||||
|
|
||||||
ClassDB::bind_method("_edit_request_change", &EditorInspector::_edit_request_change);
|
ClassDB::bind_method("_edit_request_change", &EditorInspector::_edit_request_change);
|
||||||
ClassDB::bind_method("_node_removed", &EditorInspector::_node_removed);
|
ClassDB::bind_method("_node_removed", &EditorInspector::_node_removed);
|
||||||
|
@ -461,7 +461,7 @@ class EditorInspector : public ScrollContainer {
|
|||||||
|
|
||||||
void _property_changed(const String &p_path, const Variant &p_value, const String &p_name = "", bool changing = false);
|
void _property_changed(const String &p_path, const Variant &p_value, const String &p_name = "", bool changing = false);
|
||||||
void _property_changed_update_all(const String &p_path, const Variant &p_value, const String &p_name = "", bool p_changing = false);
|
void _property_changed_update_all(const String &p_path, const Variant &p_value, const String &p_name = "", bool p_changing = false);
|
||||||
void _multiple_properties_changed(Vector<String> p_paths, Array p_values);
|
void _multiple_properties_changed(Vector<String> p_paths, Array p_values, bool p_changing = false);
|
||||||
void _property_keyed(const String &p_path, bool p_advance);
|
void _property_keyed(const String &p_path, bool p_advance);
|
||||||
void _property_keyed_with_value(const String &p_path, const Variant &p_value, bool p_advance);
|
void _property_keyed_with_value(const String &p_path, const Variant &p_value, bool p_advance);
|
||||||
void _property_checked(const String &p_path, bool p_checked);
|
void _property_checked(const String &p_path, bool p_checked);
|
||||||
@ -473,6 +473,9 @@ class EditorInspector : public ScrollContainer {
|
|||||||
|
|
||||||
void _node_removed(Node *p_node);
|
void _node_removed(Node *p_node);
|
||||||
|
|
||||||
|
RBMap<StringName, int> per_array_page;
|
||||||
|
void _page_change_request(int p_new_page, const StringName &p_array_prefix);
|
||||||
|
|
||||||
void _changed_callback(Object *p_changed, const char *p_prop);
|
void _changed_callback(Object *p_changed, const char *p_prop);
|
||||||
void _edit_request_change(Object *p_object, const String &p_prop);
|
void _edit_request_change(Object *p_object, const String &p_prop);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user