summaryrefslogtreecommitdiff
path: root/editor/editor_inspector.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'editor/editor_inspector.cpp')
-rw-r--r--editor/editor_inspector.cpp258
1 files changed, 224 insertions, 34 deletions
diff --git a/editor/editor_inspector.cpp b/editor/editor_inspector.cpp
index 21ad71fe06..f94b7cd6ee 100644
--- a/editor/editor_inspector.cpp
+++ b/editor/editor_inspector.cpp
@@ -1,3 +1,33 @@
+/*************************************************************************/
+/* editor_inspector.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
#include "editor_inspector.h"
#include "array_property_edit.h"
#include "dictionary_property_edit.h"
@@ -7,7 +37,8 @@
#include "scene/resources/packed_scene.h"
// TODO:
-// arrays
+// arrays and dictionary
+// replace property editor in sectionedpropertyeditor
Size2 EditorProperty::get_minimum_size() const {
@@ -21,6 +52,9 @@ Size2 EditorProperty::get_minimum_size() const {
continue;
if (!c->is_visible())
continue;
+ if (c == bottom_editor)
+ continue;
+
Size2 minsize = c->get_combined_minimum_size();
ms.width = MAX(ms.width, minsize.width);
ms.height = MAX(ms.height, minsize.height);
@@ -36,10 +70,14 @@ Size2 EditorProperty::get_minimum_size() const {
ms.width += check->get_width() + get_constant("hseparator", "Tree");
}
- if (label_layout == LABEL_LAYOUT_TOP) {
+ if (bottom_editor != NULL) {
Ref<Font> font = get_font("font", "Tree");
ms.height += font->get_height();
ms.height += get_constant("vseparation", "Tree");
+ Size2 bems = bottom_editor->get_combined_minimum_size();
+ bems.width += get_constant("item_margin", "Tree");
+ ms.height += bems.height;
+ ms.width = MAX(ms.width, bems.width);
}
return ms;
@@ -51,9 +89,12 @@ void EditorProperty::_notification(int p_what) {
Size2 size = get_size();
Rect2 rect;
+ Rect2 bottom_rect;
- if (label_layout == LABEL_LAYOUT_LEFT) {
+ {
int child_room = size.width / 2;
+ Ref<Font> font = get_font("font", "Tree");
+ int height = font->get_height();
//compute room needed
for (int i = 0; i < get_child_count(); i++) {
@@ -63,22 +104,23 @@ void EditorProperty::_notification(int p_what) {
continue;
if (c->is_set_as_toplevel())
continue;
+ if (c == bottom_editor)
+ continue;
Size2 minsize = c->get_combined_minimum_size();
child_room = MAX(child_room, minsize.width);
+ height = MAX(height, minsize.height);
}
text_size = MAX(0, size.width - child_room + 4 * EDSCALE);
- rect = Rect2(text_size, 0, size.width - text_size, size.height);
- } else {
- Ref<Font> font = get_font("font", "Tree");
+ rect = Rect2(text_size, 0, size.width - text_size, height);
+
+ if (bottom_editor) {
- text_size = size.width;
- rect.position.x = 0;
- rect.position.y = font->get_height() + get_constant("vseparation", "Tree");
- rect.size = get_size();
- rect.size.height -= rect.position.y;
+ int m = get_constant("item_margin", "Tree");
+ bottom_rect = Rect2(m, rect.size.height + get_constant("vseparation", "Tree"), size.width - m, bottom_editor->get_combined_minimum_size().height);
+ }
}
if (keying) {
@@ -101,10 +143,16 @@ void EditorProperty::_notification(int p_what) {
continue;
if (c->is_set_as_toplevel())
continue;
+ if (c == bottom_editor)
+ continue;
fit_child_in_rect(c, rect);
}
+ if (bottom_editor) {
+ fit_child_in_rect(bottom_editor, bottom_rect);
+ }
+
update(); //need to redraw text
}
@@ -112,8 +160,8 @@ void EditorProperty::_notification(int p_what) {
Ref<Font> font = get_font("font", "Tree");
Size2 size = get_size();
- if (label_layout == LABEL_LAYOUT_TOP) {
- size.height = font->get_height();
+ if (bottom_editor) {
+ size.height = bottom_editor->get_margin(MARGIN_TOP);
} else if (label_reference) {
size.height = label_reference->get_size().height;
}
@@ -472,6 +520,8 @@ bool EditorProperty::is_draw_red() const {
void EditorProperty::_focusable_focused(int p_index) {
+ if (!selectable)
+ return;
bool already_selected = selected;
selected = true;
selected_focusable = p_index;
@@ -548,7 +598,7 @@ void EditorProperty::_gui_input(const Ref<InputEvent> &p_event) {
if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT) {
- if (!selected) {
+ if (!selected && selectable) {
selected = true;
emit_signal("selected", property, -1);
update();
@@ -596,7 +646,10 @@ void EditorProperty::set_label_reference(Control *p_control) {
label_reference = p_control;
}
+void EditorProperty::set_bottom_editor(Control *p_control) {
+ bottom_editor = p_control;
+}
Variant EditorProperty::get_drag_data(const Point2 &p_point) {
if (property == StringName())
@@ -614,10 +667,33 @@ Variant EditorProperty::get_drag_data(const Point2 &p_point) {
return dp;
}
-void EditorProperty::set_label_layout(LabelLayout p_layout) {
- label_layout = p_layout;
- queue_sort();
- update();
+void EditorProperty::set_use_folding(bool p_use_folding) {
+
+ use_folding = p_use_folding;
+}
+
+bool EditorProperty::is_using_folding() const {
+
+ return use_folding;
+}
+
+void EditorProperty::expand_all_folding() {
+}
+
+void EditorProperty::collapse_all_folding() {
+}
+
+void EditorProperty::set_selectable(bool p_selectable) {
+ selectable = p_selectable;
+}
+
+bool EditorProperty::is_selectable() const {
+ return selectable;
+}
+
+void EditorProperty::set_object_and_property(Object *p_object, const StringName &p_property) {
+ object = p_object;
+ property = p_property;
}
void EditorProperty::_bind_methods() {
@@ -655,6 +731,7 @@ void EditorProperty::_bind_methods() {
ADD_SIGNAL(MethodInfo("property_changed", PropertyInfo(Variant::STRING, "property"), PropertyInfo(Variant::NIL, "value", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NIL_IS_VARIANT)));
ADD_SIGNAL(MethodInfo("multiple_properties_changed", PropertyInfo(Variant::POOL_STRING_ARRAY, "properties"), PropertyInfo(Variant::ARRAY, "value")));
ADD_SIGNAL(MethodInfo("property_keyed", PropertyInfo(Variant::STRING, "property")));
+ ADD_SIGNAL(MethodInfo("property_keyed_with_value", PropertyInfo(Variant::STRING, "property"), PropertyInfo(Variant::NIL, "value", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NIL_IS_VARIANT)));
ADD_SIGNAL(MethodInfo("property_checked", PropertyInfo(Variant::STRING, "property"), PropertyInfo(Variant::STRING, "bool")));
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, "property"), PropertyInfo(Variant::INT, "id")));
@@ -667,6 +744,7 @@ void EditorProperty::_bind_methods() {
EditorProperty::EditorProperty() {
+ selectable = true;
text_size = 0;
read_only = false;
checkable = false;
@@ -677,11 +755,12 @@ EditorProperty::EditorProperty() {
revert_hover = false;
check_hover = false;
can_revert = false;
+ use_folding = false;
property_usage = 0;
selected = false;
selected_focusable = -1;
label_reference = NULL;
- label_layout = LABEL_LAYOUT_LEFT;
+ bottom_editor = NULL;
}
////////////////////////////////////////////////
////////////////////////////////////////////////
@@ -725,6 +804,14 @@ void EditorInspectorPlugin::parse_begin(Object *p_object) {
get_script_instance()->call("parse_begin", p_object);
}
}
+
+void EditorInspectorPlugin::parse_category(Object *p_object, const String &p_parse_category) {
+
+ if (get_script_instance()) {
+ get_script_instance()->call("parse_category", p_object, p_parse_category);
+ }
+}
+
bool EditorInspectorPlugin::parse_property(Object *p_object, Variant::Type p_type, const String &p_path, PropertyHint p_hint, const String &p_hint_text, int p_usage) {
if (get_script_instance()) {
@@ -759,6 +846,10 @@ void EditorInspectorPlugin::_bind_methods() {
BIND_VMETHOD(vm);
vm.name = "parse_begin";
BIND_VMETHOD(vm);
+ vm.name = "parse_category";
+ vm.arguments.push_back(PropertyInfo(Variant::STRING, "category"));
+ BIND_VMETHOD(vm);
+ vm.arguments.pop_back();
vm.name = "parse_property";
vm.return_val.type = Variant::BOOL;
vm.arguments.push_back(PropertyInfo(Variant::INT, "type"));
@@ -1066,6 +1157,55 @@ String EditorInspector::get_selected_path() const {
return property_selected;
}
+void EditorInspector::_parse_added_editors(VBoxContainer *current_vbox, Ref<EditorInspectorPlugin> ped) {
+
+ for (List<EditorInspectorPlugin::AddedEditor>::Element *F = ped->added_editors.front(); F; F = F->next()) {
+
+ EditorProperty *ep = Object::cast_to<EditorProperty>(F->get().property_editor);
+ current_vbox->add_child(F->get().property_editor);
+
+ if (ep) {
+
+ ep->object = object;
+ ep->connect("property_changed", this, "_property_changed");
+ ep->connect("property_keyed", this, "_property_keyed");
+ ep->connect("property_keyed_with_value", this, "_property_keyed_with_value");
+ ep->connect("property_checked", this, "_property_checked");
+ ep->connect("selected", this, "_property_selected");
+ ep->connect("multiple_properties_changed", this, "_multiple_properties_changed");
+ ep->connect("resource_selected", this, "_resource_selected", varray(), CONNECT_DEFERRED);
+ ep->connect("object_id_selected", this, "_object_id_selected", varray(), CONNECT_DEFERRED);
+
+ if (F->get().properties.size()) {
+
+ if (F->get().properties.size() == 1) {
+ //since it's one, associate:
+ ep->property = F->get().properties[0];
+ ep->property_usage = 0;
+ }
+
+ if (F->get().label != String()) {
+ ep->set_label(F->get().label);
+ }
+
+ for (int i = 0; i < F->get().properties.size(); i++) {
+ String prop = F->get().properties[i];
+
+ if (!editor_property_map.has(prop)) {
+ editor_property_map[prop] = List<EditorProperty *>();
+ }
+ editor_property_map[prop].push_back(ep);
+ }
+ }
+
+ ep->set_read_only(read_only);
+ ep->update_property();
+ ep->update_reload_status();
+ }
+ }
+ ped->added_editors.clear();
+}
+
void EditorInspector::update_tree() {
//to update properly if all is refreshed
@@ -1109,6 +1249,12 @@ void EditorInspector::update_tree() {
Color sscolor = get_color("prop_subsection", "Editor");
+ for (List<Ref<EditorInspectorPlugin> >::Element *E = valid_plugins.front(); E; E = E->next()) {
+ Ref<EditorInspectorPlugin> ped = E->get();
+ ped->parse_begin(object);
+ _parse_added_editors(main_vbox, ped);
+ }
+
for (List<PropertyInfo>::Element *I = plist.front(); I; I = I->next()) {
PropertyInfo &p = I->get();
@@ -1171,6 +1317,13 @@ void EditorInspector::update_tree() {
category->set_tooltip(TTR("Class:") + " " + p.name + (class_descr_cache[type] == "" ? "" : "\n\n" + class_descr_cache[type]));
}
+
+ for (List<Ref<EditorInspectorPlugin> >::Element *E = valid_plugins.front(); E; E = E->next()) {
+ Ref<EditorInspectorPlugin> ped = E->get();
+ ped->parse_category(object, p.name);
+ _parse_added_editors(main_vbox, ped);
+ }
+
continue;
} else if (!(p.usage & PROPERTY_USAGE_EDITOR))
@@ -1309,7 +1462,10 @@ void EditorInspector::update_tree() {
for (List<Ref<EditorInspectorPlugin> >::Element *E = valid_plugins.front(); E; E = E->next()) {
Ref<EditorInspectorPlugin> ped = E->get();
ped->parse_property(object, p.type, p.name, p.hint, p.hint_string, p.usage);
- for (List<EditorInspectorPlugin::AddedEditor>::Element *F = ped->added_editors.front(); F; F = F->next()) {
+ List<EditorInspectorPlugin::AddedEditor> editors = ped->added_editors; //make a copy, since plugins may be used again in a sub-inspector
+ ped->added_editors.clear();
+
+ for (List<EditorInspectorPlugin::AddedEditor>::Element *F = editors.front(); F; F = F->next()) {
EditorProperty *ep = Object::cast_to<EditorProperty>(F->get().property_editor);
current_vbox->add_child(F->get().property_editor);
@@ -1319,13 +1475,19 @@ void EditorInspector::update_tree() {
ep->object = object;
ep->connect("property_changed", this, "_property_changed");
ep->connect("property_keyed", this, "_property_keyed");
+ ep->connect("property_keyed_with_value", this, "_property_keyed_with_value");
ep->connect("property_checked", this, "_property_checked");
ep->connect("selected", this, "_property_selected");
ep->connect("multiple_properties_changed", this, "_multiple_properties_changed");
ep->connect("resource_selected", this, "_resource_selected", varray(), CONNECT_DEFERRED);
ep->connect("object_id_selected", this, "_object_id_selected", varray(), CONNECT_DEFERRED);
- ep->set_tooltip(doc_hint);
+ if (doc_hint != String()) {
+ ep->set_tooltip(TTR("Property: ") + p.name + "\n\n" + doc_hint);
+ } else {
+ ep->set_tooltip(TTR("Property: ") + p.name);
+ }
ep->set_draw_red(draw_red);
+ ep->set_use_folding(use_folding);
ep->set_checkable(checkable);
ep->set_checked(checked);
ep->set_keying(keying);
@@ -1364,10 +1526,15 @@ void EditorInspector::update_tree() {
}
}
}
- ped->added_editors.clear();
}
}
+ for (List<Ref<EditorInspectorPlugin> >::Element *E = valid_plugins.front(); E; E = E->next()) {
+ Ref<EditorInspectorPlugin> ped = E->get();
+ ped->parse_end();
+ _parse_added_editors(main_vbox, ped);
+ }
+
//see if this property exists and should be kept
}
void EditorInspector::update_property(const String &p_prop) {
@@ -1382,14 +1549,14 @@ void EditorInspector::update_property(const String &p_prop) {
void EditorInspector::_clear() {
- editor_property_map.clear();
- sections.clear();
- pending.clear();
- property_selected = StringName();
- property_focusable = -1;
while (main_vbox->get_child_count()) {
memdelete(main_vbox->get_child(0));
}
+ property_selected = StringName();
+ property_focusable = -1;
+ editor_property_map.clear();
+ sections.clear();
+ pending.clear();
}
void EditorInspector::refresh() {
@@ -1399,17 +1566,21 @@ void EditorInspector::refresh() {
refresh_countdown = EditorSettings::get_singleton()->get("docks/property_editor/auto_refresh_interval");
}
-void EditorInspector::edit(Object *p_object) {
- if (object != p_object) {
- _clear();
- }
+Object *EditorInspector::get_edited_object() {
+ return object;
+}
+void EditorInspector::edit(Object *p_object) {
+ if (object == p_object)
+ return;
if (object) {
+ _clear();
object->remove_change_receptor(this);
}
object = p_object;
+
if (object) {
object->add_change_receptor(this);
update_tree();
@@ -1484,12 +1655,23 @@ void EditorInspector::collapse_all_folding() {
for (List<EditorInspectorSection *>::Element *E = sections.front(); E; E = E->next()) {
E->get()->fold();
}
+
+ for (Map<StringName, List<EditorProperty *> >::Element *F = editor_property_map.front(); F; F = F->next()) {
+ for (List<EditorProperty *>::Element *E = F->get().front(); E; E = E->next()) {
+ E->get()->collapse_all_folding();
+ }
+ }
}
void EditorInspector::expand_all_folding() {
for (List<EditorInspectorSection *>::Element *E = sections.front(); E; E = E->next()) {
E->get()->unfold();
}
+ for (Map<StringName, List<EditorProperty *> >::Element *F = editor_property_map.front(); F; F = F->next()) {
+ for (List<EditorProperty *>::Element *E = F->get().front(); E; E = E->next()) {
+ E->get()->expand_all_folding();
+ }
+ }
}
void EditorInspector::set_scroll_offset(int p_offset) {
@@ -1619,6 +1801,14 @@ void EditorInspector::_property_keyed(const String &p_path) {
emit_signal("property_keyed", p_path, object->get(p_path), false); //second param is deprecated
}
+void EditorInspector::_property_keyed_with_value(const String &p_path, const Variant &p_value) {
+
+ if (!object)
+ return;
+
+ emit_signal("property_keyed", p_path, p_value, false); //second param is deprecated
+}
+
void EditorInspector::_property_checked(const String &p_path, bool p_checked) {
if (!object)
@@ -1757,6 +1947,7 @@ void EditorInspector::_bind_methods() {
ClassDB::bind_method("_node_removed", &EditorInspector::_node_removed);
ClassDB::bind_method("_filter_changed", &EditorInspector::_filter_changed);
ClassDB::bind_method("_property_keyed", &EditorInspector::_property_keyed);
+ ClassDB::bind_method("_property_keyed_with_value", &EditorInspector::_property_keyed_with_value);
ClassDB::bind_method("_property_checked", &EditorInspector::_property_checked);
ClassDB::bind_method("_property_selected", &EditorInspector::_property_selected);
ClassDB::bind_method("_resource_selected", &EditorInspector::_resource_selected);
@@ -1773,9 +1964,8 @@ EditorInspector::EditorInspector() {
main_vbox = memnew(VBoxContainer);
main_vbox->set_h_size_flags(SIZE_EXPAND_FILL);
add_child(main_vbox);
- main_vbox->set_name("pipirulo");
- set_h_scroll(false);
- set_v_scroll(true);
+ set_enable_h_scroll(false);
+ set_enable_v_scroll(true);
show_categories = false;
hide_script = true;