summaryrefslogtreecommitdiff
path: root/editor
diff options
context:
space:
mode:
Diffstat (limited to 'editor')
-rw-r--r--editor/editor_autoload_settings.cpp193
-rw-r--r--editor/editor_autoload_settings.h10
-rw-r--r--editor/editor_inspector.cpp258
-rw-r--r--editor/editor_inspector.h64
-rw-r--r--editor/editor_node.cpp640
-rw-r--r--editor/editor_node.h66
-rw-r--r--editor/editor_plugin.cpp18
-rw-r--r--editor/editor_plugin.h4
-rw-r--r--editor/editor_properties.cpp294
-rw-r--r--editor/editor_properties.h56
-rw-r--r--editor/editor_properties_array_dict.cpp999
-rw-r--r--editor/editor_properties_array_dict.h115
-rw-r--r--editor/editor_settings.cpp5
-rw-r--r--editor/editor_settings.h2
-rw-r--r--editor/editor_spin_slider.cpp30
-rw-r--r--editor/editor_spin_slider.h30
-rw-r--r--editor/filesystem_dock.cpp8
-rw-r--r--editor/find_in_files.cpp11
-rw-r--r--editor/groups_editor.cpp3
-rw-r--r--editor/icons/icon_oriented_path_follow.svg5
-rw-r--r--editor/import/editor_import_collada.cpp2
-rw-r--r--editor/import/resource_importer_bitmask.cpp30
-rw-r--r--editor/import/resource_importer_bitmask.h30
-rw-r--r--editor/import_dock.cpp1
-rw-r--r--editor/inspector_dock.cpp564
-rw-r--r--editor/inspector_dock.h137
-rw-r--r--editor/plugins/asset_library_editor_plugin.cpp81
-rw-r--r--editor/plugins/canvas_item_editor_plugin.cpp129
-rw-r--r--editor/plugins/canvas_item_editor_plugin.h2
-rw-r--r--editor/plugins/collision_polygon_2d_editor_plugin.cpp1
-rw-r--r--editor/plugins/curve_editor_plugin.cpp96
-rw-r--r--editor/plugins/curve_editor_plugin.h23
-rw-r--r--editor/plugins/gradient_editor_plugin.cpp99
-rw-r--r--editor/plugins/gradient_editor_plugin.h35
-rw-r--r--editor/plugins/line_2d_editor_plugin.cpp1
-rw-r--r--editor/plugins/navigation_polygon_editor_plugin.cpp1
-rw-r--r--editor/plugins/polygon_2d_editor_plugin.cpp1
-rw-r--r--editor/plugins/script_editor_plugin.cpp8
-rw-r--r--editor/plugins/skeleton_2d_editor_plugin.cpp30
-rw-r--r--editor/plugins/skeleton_2d_editor_plugin.h30
-rw-r--r--editor/plugins/sprite_editor_plugin.cpp30
-rw-r--r--editor/plugins/sprite_editor_plugin.h30
-rw-r--r--editor/plugins/style_box_editor_plugin.cpp87
-rw-r--r--editor/plugins/style_box_editor_plugin.h26
-rw-r--r--editor/plugins/texture_region_editor_plugin.cpp46
-rw-r--r--editor/plugins/texture_region_editor_plugin.h4
-rw-r--r--editor/plugins/tile_set_editor_plugin.cpp10
-rw-r--r--editor/project_manager.cpp17
-rw-r--r--editor/scene_tree_dock.cpp20
-rw-r--r--editor/scene_tree_dock.h1
-rw-r--r--editor/translations/editor.pot8
51 files changed, 3280 insertions, 1111 deletions
diff --git a/editor/editor_autoload_settings.cpp b/editor/editor_autoload_settings.cpp
index 708bff252a..de9203232c 100644
--- a/editor/editor_autoload_settings.cpp
+++ b/editor/editor_autoload_settings.cpp
@@ -52,6 +52,13 @@ void EditorAutoloadSettings::_notification(int p_what) {
file_dialog->add_filter("*." + E->get());
}
+
+ for (List<AutoLoadInfo>::Element *E = autoload_cache.front(); E; E = E->next()) {
+ AutoLoadInfo &info = E->get();
+ if (info.node && info.in_editor) {
+ get_tree()->get_root()->call_deferred("add_child", info.node);
+ }
+ }
}
}
@@ -291,6 +298,36 @@ void EditorAutoloadSettings::_autoload_file_callback(const String &p_path) {
autoload_add_name->set_text(p_path.get_file().get_basename());
}
+Node *EditorAutoloadSettings::_create_autoload(const String &p_path) {
+ RES res = ResourceLoader::load(p_path);
+ ERR_EXPLAIN("Can't autoload: " + p_path);
+ ERR_FAIL_COND_V(res.is_null(), NULL);
+ Node *n = NULL;
+ if (res->is_class("PackedScene")) {
+ Ref<PackedScene> ps = res;
+ n = ps->instance();
+ } else if (res->is_class("Script")) {
+ Ref<Script> s = res;
+ StringName ibt = s->get_instance_base_type();
+ bool valid_type = ClassDB::is_parent_class(ibt, "Node");
+ ERR_EXPLAIN("Script does not inherit a Node: " + p_path);
+ ERR_FAIL_COND_V(!valid_type, NULL);
+
+ Object *obj = ClassDB::instance(ibt);
+
+ ERR_EXPLAIN("Cannot instance script for autoload, expected 'Node' inheritance, got: " + String(ibt));
+ ERR_FAIL_COND_V(obj == NULL, NULL);
+
+ n = Object::cast_to<Node>(obj);
+ n->set_script(s.get_ref_ptr());
+ }
+
+ ERR_EXPLAIN("Path in autoload not a node or script: " + p_path);
+ ERR_FAIL_COND_V(!n, NULL);
+
+ return n;
+}
+
void EditorAutoloadSettings::update_autoload() {
if (updating_autoload)
@@ -299,15 +336,11 @@ void EditorAutoloadSettings::update_autoload() {
updating_autoload = true;
Map<String, AutoLoadInfo> to_remove;
- Map<String, AutoLoadInfo> to_remove_singleton;
- List<AutoLoadInfo> to_add;
- List<String> to_add_singleton; // Only for when the node is still the same
+ List<AutoLoadInfo *> to_add;
for (List<AutoLoadInfo>::Element *E = autoload_cache.front(); E; E = E->next()) {
- to_remove.insert(E->get().name, E->get());
- if (E->get().is_singleton) {
- to_remove_singleton.insert(E->get().name, E->get());
- }
+ AutoLoadInfo &info = E->get();
+ to_remove.insert(info.name, info);
}
autoload_cache.clear();
@@ -331,11 +364,6 @@ void EditorAutoloadSettings::update_autoload() {
if (name.empty())
continue;
- AutoLoadInfo old_info;
- if (to_remove.has(name)) {
- old_info = to_remove[name];
- }
-
AutoLoadInfo info;
info.is_singleton = path.begins_with("*");
@@ -347,28 +375,31 @@ void EditorAutoloadSettings::update_autoload() {
info.path = path;
info.order = ProjectSettings::get_singleton()->get_order(pi.name);
- if (old_info.name == info.name) {
+ bool need_to_add = true;
+ if (to_remove.has(name)) {
+ AutoLoadInfo &old_info = to_remove[name];
if (old_info.path == info.path) {
- // Still the same resource, check singleton status
- to_remove.erase(name);
- if (info.is_singleton) {
- if (old_info.is_singleton) {
- to_remove_singleton.erase(name);
+ // Still the same resource, check status
+ info.node = old_info.node;
+ if (info.node) {
+ Ref<Script> scr = info.node->get_script();
+ info.in_editor = scr.is_valid() && scr->is_tool();
+ if (info.is_singleton == old_info.is_singleton && info.in_editor == old_info.in_editor) {
+ to_remove.erase(name);
+ need_to_add = false;
} else {
- to_add_singleton.push_back(name);
+ info.node = NULL;
}
}
- } else {
- // Resource changed
- to_add.push_back(info);
}
- } else {
- // New autoload
- to_add.push_back(info);
}
autoload_cache.push_back(info);
+ if (need_to_add) {
+ to_add.push_back(&(autoload_cache.back()->get()));
+ }
+
TreeItem *item = tree->create_item(root);
item->set_text(0, name);
item->set_editable(0, true);
@@ -387,71 +418,54 @@ void EditorAutoloadSettings::update_autoload() {
item->set_selectable(3, false);
}
- // Remove autoload constants
- for (Map<String, AutoLoadInfo>::Element *E = to_remove_singleton.front(); E; E = E->next()) {
- for (int i = 0; i < ScriptServer::get_language_count(); i++) {
- ScriptServer::get_language(i)->remove_named_global_constant(E->get().name);
- }
- }
-
- // Remove obsolete nodes from the tree
+ // Remove deleted/changed autoloads
for (Map<String, AutoLoadInfo>::Element *E = to_remove.front(); E; E = E->next()) {
AutoLoadInfo &info = E->get();
- Node *al = get_node("/root/" + info.name);
- ERR_CONTINUE(!al);
- get_tree()->get_root()->remove_child(al);
- memdelete(al);
- }
+ if (info.is_singleton) {
+ for (int i = 0; i < ScriptServer::get_language_count(); i++) {
+ ScriptServer::get_language(i)->remove_named_global_constant(info.name);
+ }
+ }
+ if (info.in_editor) {
+ ERR_CONTINUE(!info.node);
+ get_tree()->get_root()->remove_child(info.node);
+ }
- // Register new singletons already in the tree
- for (List<String>::Element *E = to_add_singleton.front(); E; E = E->next()) {
- Node *al = get_node("/root/" + E->get());
- ERR_CONTINUE(!al);
- for (int i = 0; i < ScriptServer::get_language_count(); i++) {
- ScriptServer::get_language(i)->add_named_global_constant(E->get(), al);
+ if (info.node) {
+ memdelete(info.node);
+ info.node = NULL;
}
}
- // Add new nodes to the tree
+ // Load new/changed autoloads
List<Node *> nodes_to_add;
- for (List<AutoLoadInfo>::Element *E = to_add.front(); E; E = E->next()) {
- AutoLoadInfo &info = E->get();
+ for (List<AutoLoadInfo *>::Element *E = to_add.front(); E; E = E->next()) {
+ AutoLoadInfo *info = E->get();
- RES res = ResourceLoader::load(info.path);
- ERR_EXPLAIN("Can't autoload: " + info.path);
- ERR_CONTINUE(res.is_null());
- Node *n = NULL;
- if (res->is_class("PackedScene")) {
- Ref<PackedScene> ps = res;
- n = ps->instance();
- } else if (res->is_class("Script")) {
- Ref<Script> s = res;
- StringName ibt = s->get_instance_base_type();
- bool valid_type = ClassDB::is_parent_class(ibt, "Node");
- ERR_EXPLAIN("Script does not inherit a Node: " + info.path);
- ERR_CONTINUE(!valid_type);
-
- Object *obj = ClassDB::instance(ibt);
-
- ERR_EXPLAIN("Cannot instance script for autoload, expected 'Node' inheritance, got: " + String(ibt));
- ERR_CONTINUE(obj == NULL);
-
- n = Object::cast_to<Node>(obj);
- n->set_script(s.get_ref_ptr());
- }
+ info->node = _create_autoload(info->path);
- ERR_EXPLAIN("Path in autoload not a node or script: " + info.path);
- ERR_CONTINUE(!n);
- n->set_name(info.name);
+ ERR_CONTINUE(!info->node);
+ info->node->set_name(info->name);
- //defer so references are all valid on _ready()
- nodes_to_add.push_back(n);
+ Ref<Script> scr = info->node->get_script();
+ info->in_editor = scr.is_valid() && scr->is_tool();
- if (info.is_singleton) {
+ if (info->in_editor) {
+ //defer so references are all valid on _ready()
+ nodes_to_add.push_back(info->node);
+ }
+
+ if (info->is_singleton) {
for (int i = 0; i < ScriptServer::get_language_count(); i++) {
- ScriptServer::get_language(i)->add_named_global_constant(info.name, n);
+ ScriptServer::get_language(i)->add_named_global_constant(info->name, info->node);
}
}
+
+ if (!info->in_editor && !info->is_singleton) {
+ // No reason to keep this node
+ memdelete(info->node);
+ info->node = NULL;
+ }
}
for (List<Node *>::Element *E = nodes_to_add.front(); E; E = E->next()) {
@@ -728,6 +742,24 @@ EditorAutoloadSettings::EditorAutoloadSettings() {
info.name = name;
info.path = path;
info.order = ProjectSettings::get_singleton()->get_order(pi.name);
+ info.node = _create_autoload(path);
+
+ if (info.node) {
+ Ref<Script> scr = info.node->get_script();
+ info.in_editor = scr.is_valid() && scr->is_tool();
+ info.node->set_name(info.name);
+ }
+
+ if (info.is_singleton) {
+ for (int i = 0; i < ScriptServer::get_language_count(); i++) {
+ ScriptServer::get_language(i)->add_named_global_constant(info.name, info.node);
+ }
+ }
+
+ if (!info.is_singleton && !info.in_editor) {
+ memdelete(info.node);
+ info.node = NULL;
+ }
autoload_cache.push_back(info);
}
@@ -796,3 +828,12 @@ EditorAutoloadSettings::EditorAutoloadSettings() {
add_child(tree, true);
}
+
+EditorAutoloadSettings::~EditorAutoloadSettings() {
+ for (List<AutoLoadInfo>::Element *E = autoload_cache.front(); E; E = E->next()) {
+ AutoLoadInfo &info = E->get();
+ if (info.node && !info.in_editor) {
+ memdelete(info.node);
+ }
+ }
+}
diff --git a/editor/editor_autoload_settings.h b/editor/editor_autoload_settings.h
index 1797c10e61..0b75faa009 100644
--- a/editor/editor_autoload_settings.h
+++ b/editor/editor_autoload_settings.h
@@ -52,11 +52,19 @@ class EditorAutoloadSettings : public VBoxContainer {
String name;
String path;
bool is_singleton;
+ bool in_editor;
int order;
+ Node *node;
bool operator==(const AutoLoadInfo &p_info) {
return order == p_info.order;
}
+
+ AutoLoadInfo() {
+ is_singleton = false;
+ in_editor = false;
+ node = NULL;
+ }
};
List<AutoLoadInfo> autoload_cache;
@@ -78,6 +86,7 @@ class EditorAutoloadSettings : public VBoxContainer {
void _autoload_activated();
void _autoload_open(const String &fpath);
void _autoload_file_callback(const String &p_path);
+ Node *_create_autoload(const String &p_path);
Variant get_drag_data_fw(const Point2 &p_point, Control *p_control);
bool can_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_control) const;
@@ -93,6 +102,7 @@ public:
void autoload_remove(const String &p_name);
EditorAutoloadSettings();
+ ~EditorAutoloadSettings();
};
#endif
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;
diff --git a/editor/editor_inspector.h b/editor/editor_inspector.h
index 64be316b0e..a6b183799f 100644
--- a/editor/editor_inspector.h
+++ b/editor/editor_inspector.h
@@ -1,18 +1,45 @@
+/*************************************************************************/
+/* editor_inspector.h */
+/*************************************************************************/
+/* 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. */
+/*************************************************************************/
+
#ifndef EDITOR_INSPECTOR_H
#define EDITOR_INSPECTOR_H
-#include "editor_data.h"
+#include "scene/gui/box_container.h"
+#include "scene/gui/line_edit.h"
#include "scene/gui/scroll_container.h"
+class UndoRedo;
+
class EditorProperty : public Container {
GDCLASS(EditorProperty, Container)
-public:
- enum LabelLayout {
- LABEL_LAYOUT_LEFT,
- LABEL_LAYOUT_TOP,
- };
-
private:
String label;
int text_size;
@@ -20,8 +47,6 @@ private:
Object *object;
StringName property;
- LabelLayout label_layout;
-
int property_usage;
bool read_only;
@@ -39,17 +64,21 @@ private:
bool can_revert;
+ bool use_folding;
+
bool _might_be_in_instance();
bool _is_property_different(const Variant &p_current, const Variant &p_orig, int p_usage);
bool _is_instanced_node_with_original_property_different();
bool _get_instanced_node_original_property(const StringName &p_prop, Variant &value);
void _focusable_focused(int p_index);
+ bool selectable;
bool selected;
int selected_focusable;
Vector<Control *> focusables;
Control *label_reference;
+ Control *bottom_editor;
protected:
void _notification(int p_what);
@@ -92,10 +121,20 @@ public:
bool is_selected() const;
void set_label_reference(Control *p_control);
+ void set_bottom_editor(Control *p_editor);
+
+ void set_use_folding(bool p_use_folding);
+ bool is_using_folding() const;
+
+ virtual void expand_all_folding();
+ virtual void collapse_all_folding();
virtual Variant get_drag_data(const Point2 &p_point);
- void set_label_layout(LabelLayout p_layout);
+ void set_selectable(bool p_selectable);
+ bool is_selectable() const;
+
+ void set_object_and_property(Object *p_object, const StringName &p_property);
EditorProperty();
};
@@ -121,6 +160,7 @@ public:
virtual bool can_handle(Object *p_object);
virtual void parse_begin(Object *p_object);
+ virtual void parse_category(Object *p_object, const String &p_parse_category);
virtual bool parse_property(Object *p_object, Variant::Type p_type, const String &p_path, PropertyHint p_hint, const String &p_hint_text, int p_usage);
virtual void parse_end();
};
@@ -219,6 +259,8 @@ class EditorInspector : public ScrollContainer {
void _property_changed(const String &p_path, const Variant &p_value);
void _multiple_properties_changed(Vector<String> p_paths, Array p_values);
void _property_keyed(const String &p_path);
+ void _property_keyed_with_value(const String &p_path, const Variant &p_value);
+
void _property_checked(const String &p_path, bool p_checked);
void _resource_selected(const String &p_path, RES p_resource);
@@ -231,6 +273,7 @@ class EditorInspector : public ScrollContainer {
void _edit_request_change(Object *p_changed, const String &p_prop);
void _filter_changed(const String &p_text);
+ void _parse_added_editors(VBoxContainer *current_vbox, Ref<EditorInspectorPlugin> ped);
protected:
static void _bind_methods();
@@ -251,6 +294,7 @@ public:
void refresh();
void edit(Object *p_object);
+ Object *get_edited_object();
void set_keying(bool p_active);
void set_read_only(bool p_read_only);
diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp
index 49f70e3215..dd3b6c2c4c 100644
--- a/editor/editor_node.cpp
+++ b/editor/editor_node.cpp
@@ -295,7 +295,6 @@ void EditorNode::_notification(int p_what) {
get_tree()->get_root()->set_as_audio_listener_2d(false);
get_tree()->set_auto_accept_quit(false);
get_tree()->connect("files_dropped", this, "_dropped_files");
- property_editable_warning->set_icon(gui_base->get_icon("NodeWarning", "EditorIcons"));
}
if (p_what == NOTIFICATION_EXIT_TREE) {
@@ -324,7 +323,7 @@ void EditorNode::_notification(int p_what) {
}
if (p_what == EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED) {
- scene_tabs->set_tab_close_display_policy((bool(EDITOR_DEF("interface/scene_tabs/always_show_close_button", false)) ? Tabs::CLOSE_BUTTON_SHOW_ALWAYS : Tabs::CLOSE_BUTTON_SHOW_ACTIVE_ONLY));
+ scene_tabs->set_tab_close_display_policy((bool(EDITOR_GET("interface/scene_tabs/always_show_close_button")) ? Tabs::CLOSE_BUTTON_SHOW_ALWAYS : Tabs::CLOSE_BUTTON_SHOW_ACTIVE_ONLY));
Ref<Theme> theme = create_editor_theme(theme_base->get_theme());
theme_base->set_theme(theme);
@@ -343,8 +342,8 @@ void EditorNode::_notification(int p_what) {
settings_menu->add_style_override("hover", gui_base->get_stylebox("MenuHover", "EditorStyles"));
help_menu->add_style_override("hover", gui_base->get_stylebox("MenuHover", "EditorStyles"));
- if (bool(EDITOR_DEF("interface/scene_tabs/resize_if_many_tabs", true))) {
- scene_tabs->set_min_width(int(EDITOR_DEF("interface/scene_tabs/minimum_width", 50)) * EDSCALE);
+ if (EDITOR_GET("interface/scene_tabs/resize_if_many_tabs")) {
+ scene_tabs->set_min_width(int(EDITOR_GET("interface/scene_tabs/minimum_width")) * EDSCALE);
} else {
scene_tabs->set_min_width(0);
}
@@ -382,16 +381,6 @@ void EditorNode::_notification(int p_what) {
distraction_free->set_icon(gui_base->get_icon("DistractionFree", "EditorIcons"));
scene_tab_add->set_icon(gui_base->get_icon("Add", "EditorIcons"));
- resource_new_button->set_icon(gui_base->get_icon("New", "EditorIcons"));
- resource_load_button->set_icon(gui_base->get_icon("Load", "EditorIcons"));
- resource_save_button->set_icon(gui_base->get_icon("Save", "EditorIcons"));
-
- property_back->set_icon(gui_base->get_icon("Back", "EditorIcons"));
- property_forward->set_icon(gui_base->get_icon("Forward", "EditorIcons"));
- editor_history_menu->set_icon(gui_base->get_icon("History", "EditorIcons"));
-
- search_button->set_icon(gui_base->get_icon("Search", "EditorIcons"));
- object_menu->set_icon(gui_base->get_icon("Tools", "EditorIcons"));
// clear_button->set_icon(gui_base->get_icon("Close", "EditorIcons")); don't have access to that node. needs to become a class property
update_menu->set_icon(gui_base->get_icon("Collapse", "EditorIcons"));
dock_tab_move_left->set_icon(theme->get_icon("Back", "EditorIcons"));
@@ -549,8 +538,8 @@ void EditorNode::_vp_resized() {
void EditorNode::_node_renamed() {
- if (inspector)
- inspector->update_tree();
+ if (get_inspector())
+ get_inspector()->update_tree();
}
void EditorNode::_editor_select_next() {
@@ -582,38 +571,16 @@ Error EditorNode::load_resource(const String &p_scene) {
RES res = ResourceLoader::load(p_scene);
ERR_FAIL_COND_V(!res.is_valid(), ERR_CANT_OPEN);
- edit_resource(res);
+ inspector_dock->edit_resource(res);
return OK;
}
-void EditorNode::edit_resource(const Ref<Resource> &p_resource) {
-
- _resource_selected(p_resource, "");
-}
-
void EditorNode::edit_node(Node *p_node) {
push_item(p_node);
}
-void EditorNode::open_resource(const String &p_type) {
-
- file->set_mode(EditorFileDialog::MODE_OPEN_FILE);
-
- List<String> extensions;
- ResourceLoader::get_recognized_extensions_for_type(p_type, &extensions);
-
- file->clear_filters();
- for (int i = 0; i < extensions.size(); i++) {
-
- file->add_filter("*." + extensions[i] + " ; " + extensions[i].to_upper());
- }
-
- file->popup_centered_ratio();
- current_option = RESOURCE_LOAD;
-}
-
void EditorNode::save_resource_in_path(const Ref<Resource> &p_resource, const String &p_path) {
editor_data.apply_changes_in_editors();
@@ -1145,20 +1112,6 @@ void EditorNode::_mark_unsaved_scenes() {
void EditorNode::_dialog_action(String p_file) {
switch (current_option) {
-
- case RESOURCE_LOAD: {
-
- RES res = ResourceLoader::load(p_file);
- if (res.is_null()) {
-
- current_option = -1;
- accept->get_ok()->set_text("Ugh");
- accept->set_text(TTR("Failed to load resource."));
- return;
- };
-
- push_item(res.operator->());
- } break;
case FILE_NEW_INHERITED_SCENE: {
load_scene(p_file, false, true);
@@ -1352,7 +1305,7 @@ void EditorNode::_dialog_action(String p_file) {
void EditorNode::push_item(Object *p_object, const String &p_property) {
if (!p_object) {
- inspector->edit(NULL);
+ get_inspector()->edit(NULL);
node_dock->set_node(NULL);
scene_tree_dock->set_selected(NULL);
return;
@@ -1370,89 +1323,6 @@ void EditorNode::push_item(Object *p_object, const String &p_property) {
_edit_current();
}
-void EditorNode::_select_history(int p_idx) {
-
- //push it to the top, it is not correct, but it's more useful
- ObjectID id = editor_history.get_history_obj(p_idx);
- Object *obj = ObjectDB::get_instance(id);
- if (!obj)
- return;
- push_item(obj);
-}
-
-void EditorNode::_prepare_history() {
-
- int history_to = MAX(0, editor_history.get_history_len() - 25);
-
- editor_history_menu->get_popup()->clear();
-
- Ref<Texture> base_icon = gui_base->get_icon("Object", "EditorIcons");
- Set<ObjectID> already;
- for (int i = editor_history.get_history_len() - 1; i >= history_to; i--) {
-
- ObjectID id = editor_history.get_history_obj(i);
- Object *obj = ObjectDB::get_instance(id);
- if (!obj || already.has(id)) {
- if (history_to > 0) {
- history_to--;
- }
- continue;
- }
-
- already.insert(id);
-
- Ref<Texture> icon = gui_base->get_icon("Object", "EditorIcons");
- if (gui_base->has_icon(obj->get_class(), "EditorIcons"))
- icon = gui_base->get_icon(obj->get_class(), "EditorIcons");
- else
- icon = base_icon;
-
- String text;
- if (Object::cast_to<Resource>(obj)) {
- Resource *r = Object::cast_to<Resource>(obj);
- if (r->get_path().is_resource_file())
- text = r->get_path().get_file();
- else if (r->get_name() != String()) {
- text = r->get_name();
- } else {
- text = r->get_class();
- }
- } else if (Object::cast_to<Node>(obj)) {
- text = Object::cast_to<Node>(obj)->get_name();
- } else if (obj->is_class("ScriptEditorDebuggerInspectedObject")) {
- text = obj->call("get_title");
- } else {
- text = obj->get_class();
- }
-
- if (i == editor_history.get_history_pos()) {
- text = "[" + text + "]";
- }
- editor_history_menu->get_popup()->add_icon_item(icon, text, i);
- }
-}
-
-void EditorNode::_property_editor_forward() {
-
- if (editor_history.next())
- _edit_current();
-}
-void EditorNode::_property_editor_back() {
-
- if (editor_history.previous() || editor_history.get_path_size() == 1)
- _edit_current();
-}
-
-void EditorNode::_menu_collapseall() {
-
- inspector->collapse_all_folding();
-}
-
-void EditorNode::_menu_expandall() {
-
- inspector->expand_all_folding();
-}
-
void EditorNode::_save_default_environment() {
Ref<Environment> fallback = get_tree()->get_root()->get_world()->get_fallback_environment();
@@ -1494,52 +1364,38 @@ static bool overrides_external_editor(Object *p_object) {
return script->get_language()->overrides_external_editor();
}
-void EditorNode::_property_editable_warning_pressed() {
-
- property_editable_warning_dialog->popup_centered_minsize();
-}
-
void EditorNode::_edit_current() {
uint32_t current = editor_history.get_current();
Object *current_obj = current > 0 ? ObjectDB::get_instance(current) : NULL;
- property_back->set_disabled(editor_history.is_at_beginning());
- property_forward->set_disabled(editor_history.is_at_end());
-
this->current = current_obj;
- editor_path->update_path();
-
- String editable_warning; //none by default
- property_editable_warning->hide(); //hide by default
if (!current_obj) {
scene_tree_dock->set_selected(NULL);
- inspector->edit(NULL);
+ get_inspector()->edit(NULL);
node_dock->set_node(NULL);
- object_menu->set_disabled(true);
+ inspector_dock->update(NULL);
_display_top_editors(false);
return;
}
- object_menu->set_disabled(true);
-
bool capitalize = bool(EDITOR_DEF("interface/editor/capitalize_properties", true));
bool is_resource = current_obj->is_class("Resource");
bool is_node = current_obj->is_class("Node");
- resource_save_button->set_disabled(!is_resource);
+
+ String editable_warning; //none by default
if (is_resource) {
Resource *current_res = Object::cast_to<Resource>(current_obj);
ERR_FAIL_COND(!current_res);
scene_tree_dock->set_selected(NULL);
- inspector->edit(current_res);
+ get_inspector()->edit(current_res);
node_dock->set_node(NULL);
- object_menu->set_disabled(false);
EditorNode::get_singleton()->get_import_dock()->set_edit_path(current_res->get_path());
int subr_idx = current_res->get_path().find("::");
@@ -1562,7 +1418,7 @@ void EditorNode::_edit_current() {
Node *current_node = Object::cast_to<Node>(current_obj);
ERR_FAIL_COND(!current_node);
- inspector->edit(current_node);
+ get_inspector()->edit(current_node);
if (current_node->is_inside_tree()) {
node_dock->set_node(current_node);
scene_tree_dock->set_selected(current_node);
@@ -1570,7 +1426,6 @@ void EditorNode::_edit_current() {
node_dock->set_node(NULL);
scene_tree_dock->set_selected(NULL);
}
- object_menu->get_popup()->clear();
if (get_edited_scene() && get_edited_scene()->get_filename() != String()) {
String source_scene = get_edited_scene()->get_filename();
@@ -1586,17 +1441,14 @@ void EditorNode::_edit_current() {
capitalize = false;
}
- inspector->edit(current_obj);
+ get_inspector()->edit(current_obj);
node_dock->set_node(NULL);
}
- if (editable_warning != String()) {
- property_editable_warning->show(); //hide by default
- property_editable_warning_dialog->set_text(editable_warning);
- }
+ inspector_dock->set_warning(editable_warning);
- if (inspector->is_capitalize_paths_enabled() != capitalize) {
- inspector->set_enable_capitalize_paths(capitalize);
+ if (get_inspector()->is_capitalize_paths_enabled() != capitalize) {
+ get_inspector()->set_enable_capitalize_paths(capitalize);
}
/* Take care of PLUGIN EDITOR */
@@ -1654,75 +1506,8 @@ void EditorNode::_edit_current() {
_hide_top_editors();
}
- object_menu->set_disabled(false);
-
- PopupMenu *p = object_menu->get_popup();
-
- p->clear();
- p->add_shortcut(ED_SHORTCUT("property_editor/expand_all", TTR("Expand all properties")), EXPAND_ALL);
- p->add_shortcut(ED_SHORTCUT("property_editor/collapse_all", TTR("Collapse all properties")), COLLAPSE_ALL);
- p->add_separator();
- p->add_shortcut(ED_SHORTCUT("property_editor/copy_params", TTR("Copy Params")), OBJECT_COPY_PARAMS);
- p->add_shortcut(ED_SHORTCUT("property_editor/paste_params", TTR("Paste Params")), OBJECT_PASTE_PARAMS);
- p->add_separator();
- p->add_shortcut(ED_SHORTCUT("property_editor/paste_resource", TTR("Paste Resource")), RESOURCE_PASTE);
- if (is_resource) {
- p->add_shortcut(ED_SHORTCUT("property_editor/copy_resource", TTR("Copy Resource")), RESOURCE_COPY);
- p->add_shortcut(ED_SHORTCUT("property_editor/unref_resource", TTR("Make Built-In")), RESOURCE_UNREF);
- }
-
- if (is_resource || is_node) {
- p->add_separator();
- p->add_shortcut(ED_SHORTCUT("property_editor/make_subresources_unique", TTR("Make Sub-Resources Unique")), OBJECT_UNIQUE_RESOURCES);
- p->add_separator();
- p->add_icon_shortcut(gui_base->get_icon("HelpSearch", "EditorIcons"), ED_SHORTCUT("property_editor/open_help", TTR("Open in Help")), OBJECT_REQUEST_HELP);
- }
-
- List<MethodInfo> methods;
- current_obj->get_method_list(&methods);
-
- if (!methods.empty()) {
-
- bool found = false;
- List<MethodInfo>::Element *I = methods.front();
- int i = 0;
- while (I) {
-
- if (I->get().flags & METHOD_FLAG_EDITOR) {
- if (!found) {
- p->add_separator();
- found = true;
- }
- p->add_item(I->get().name.capitalize(), OBJECT_METHOD_BASE + i);
- }
- i++;
- I = I->next();
- }
- }
-
- update_keying();
-}
-
-void EditorNode::_resource_created() {
-
- Object *c = create_dialog->instance_selected();
-
- ERR_FAIL_COND(!c);
- Resource *r = Object::cast_to<Resource>(c);
- ERR_FAIL_COND(!r);
-
- REF res(r);
-
- push_item(c);
-}
-
-void EditorNode::_resource_selected(const RES &p_res, const String &p_property) {
-
- if (p_res.is_null())
- return;
-
- RES r = p_res;
- push_item(r.operator->(), p_property);
+ inspector_dock->update(current_obj);
+ inspector_dock->update_keying();
}
void EditorNode::_run(bool p_current, const String &p_custom) {
@@ -1796,7 +1581,7 @@ void EditorNode::_run(bool p_current, const String &p_custom) {
}
}
- if (bool(EDITOR_DEF("run/auto_save/save_before_running", true))) {
+ if (bool(EDITOR_GET("run/auto_save/save_before_running"))) {
if (unsaved_cache) {
@@ -1823,11 +1608,11 @@ void EditorNode::_run(bool p_current, const String &p_custom) {
if (!call_build())
return;
- if (bool(EDITOR_DEF("run/output/always_clear_output_on_play", true))) {
+ if (bool(EDITOR_GET("run/output/always_clear_output_on_play"))) {
log->clear();
}
- if (bool(EDITOR_DEF("run/output/always_open_output_on_play", true))) {
+ if (bool(EDITOR_GET("run/output/always_open_output_on_play"))) {
make_bottom_panel_item_visible(log);
}
@@ -2163,136 +1948,6 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) {
scene_tabs->set_current_tab(cur_idx);
} break;
- case RESOURCE_NEW: {
-
- create_dialog->popup_create(true);
- } break;
- case RESOURCE_LOAD: {
-
- open_resource();
- } break;
- case RESOURCE_SAVE: {
-
- uint32_t current = editor_history.get_current();
- Object *current_obj = current > 0 ? ObjectDB::get_instance(current) : NULL;
-
- ERR_FAIL_COND(!Object::cast_to<Resource>(current_obj))
-
- RES current_res = RES(Object::cast_to<Resource>(current_obj));
-
- save_resource(current_res);
-
- } break;
- case RESOURCE_SAVE_AS: {
-
- uint32_t current = editor_history.get_current();
- Object *current_obj = current > 0 ? ObjectDB::get_instance(current) : NULL;
-
- ERR_FAIL_COND(!Object::cast_to<Resource>(current_obj))
-
- RES current_res = RES(Object::cast_to<Resource>(current_obj));
-
- save_resource_as(current_res);
-
- } break;
- case RESOURCE_UNREF: {
-
- uint32_t current = editor_history.get_current();
- Object *current_obj = current > 0 ? ObjectDB::get_instance(current) : NULL;
-
- ERR_FAIL_COND(!Object::cast_to<Resource>(current_obj))
-
- RES current_res = RES(Object::cast_to<Resource>(current_obj));
- current_res->set_path("");
- _edit_current();
- } break;
- case RESOURCE_COPY: {
-
- uint32_t current = editor_history.get_current();
- Object *current_obj = current > 0 ? ObjectDB::get_instance(current) : NULL;
-
- ERR_FAIL_COND(!Object::cast_to<Resource>(current_obj))
-
- RES current_res = RES(Object::cast_to<Resource>(current_obj));
-
- EditorSettings::get_singleton()->set_resource_clipboard(current_res);
-
- } break;
- case RESOURCE_PASTE: {
-
- RES r = EditorSettings::get_singleton()->get_resource_clipboard();
- if (r.is_valid()) {
- push_item(EditorSettings::get_singleton()->get_resource_clipboard().ptr(), String());
- }
-
- } break;
- case OBJECT_REQUEST_HELP: {
-
- if (current) {
- _editor_select(EDITOR_SCRIPT);
- emit_signal("request_help", current->get_class());
- }
-
- } break;
- case OBJECT_COPY_PARAMS: {
-
- editor_data.apply_changes_in_editors();
- if (current)
- editor_data.copy_object_params(current);
- } break;
- case OBJECT_PASTE_PARAMS: {
-
- editor_data.apply_changes_in_editors();
- if (current)
- editor_data.paste_object_params(current);
- editor_data.get_undo_redo().clear_history();
- } break;
- case OBJECT_UNIQUE_RESOURCES: {
-
- editor_data.apply_changes_in_editors();
- if (current) {
- List<PropertyInfo> props;
- current->get_property_list(&props);
- Map<RES, RES> duplicates;
- for (List<PropertyInfo>::Element *E = props.front(); E; E = E->next()) {
-
- if (!(E->get().usage & PROPERTY_USAGE_STORAGE))
- continue;
-
- Variant v = current->get(E->get().name);
- if (v.is_ref()) {
- REF ref = v;
- if (ref.is_valid()) {
-
- RES res = ref;
- if (res.is_valid()) {
-
- if (!duplicates.has(res)) {
- duplicates[res] = res->duplicate();
- }
- res = duplicates[res];
-
- current->set(E->get().name, res);
- }
- }
- }
- }
- }
-
- editor_data.get_undo_redo().clear_history();
-
- _set_editing_top_editors(NULL);
- _set_editing_top_editors(current);
-
- } break;
- case COLLAPSE_ALL: {
- _menu_collapseall();
-
- } break;
- case EXPAND_ALL: {
- _menu_expandall();
-
- } break;
case RUN_PLAY: {
_menu_option_confirm(RUN_STOP, true);
_run(false);
@@ -2326,7 +1981,7 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) {
play_custom_scene_button->set_icon(gui_base->get_icon("PlayCustom", "EditorIcons"));
stop_button->set_disabled(true);
- if (bool(EDITOR_DEF("run/output/always_close_output_on_stop", true))) {
+ if (bool(EDITOR_GET("run/output/always_close_output_on_stop"))) {
for (int i = 0; i < bottom_panel_items.size(); i++) {
if (bottom_panel_items[i].control == log) {
_bottom_panel_switch(false, i);
@@ -2346,7 +2001,7 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) {
} break;
case RUN_PLAY_NATIVE: {
- bool autosave = EDITOR_DEF("run/auto_save/save_before_running", true);
+ bool autosave = EDITOR_GET("run/auto_save/save_before_running");
if (autosave) {
_menu_option_confirm(FILE_SAVE_ALL_SCENES, false);
}
@@ -2372,10 +2027,10 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) {
case RUN_PROJECT_MANAGER: {
if (!p_confirmed) {
- bool save_each = EDITOR_DEF("interface/editor/save_each_scene_on_quit", true);
+ bool save_each = EDITOR_GET("interface/editor/save_each_scene_on_quit");
if (_next_unsaved_scene(!save_each) == -1) {
- bool confirm = EDITOR_DEF("interface/editor/quit_confirmation", true);
+ bool confirm = EDITOR_GET("interface/editor/quit_confirmation");
if (confirm) {
confirmation->get_ok()->set_text(p_option == FILE_QUIT ? TTR("Quit") : TTR("Yes"));
@@ -2555,22 +2210,7 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) {
} break;
default: {
-
- if (p_option >= OBJECT_METHOD_BASE) {
-
- ERR_FAIL_COND(!current);
-
- int idx = p_option - OBJECT_METHOD_BASE;
-
- List<MethodInfo> methods;
- current->get_method_list(&methods);
-
- ERR_FAIL_INDEX(idx, methods.size());
- String name = methods[idx].name;
-
- if (current)
- current->call(name);
- } else if (p_option >= IMPORT_PLUGIN_BASE) {
+ if (p_option >= IMPORT_PLUGIN_BASE) {
}
}
}
@@ -3244,42 +2884,14 @@ SceneTreeDock *EditorNode::get_scene_tree_dock() {
return scene_tree_dock;
}
+InspectorDock *EditorNode::get_inspector_dock() {
-void EditorNode::_instance_request(const Vector<String> &p_files) {
-
- request_instance_scenes(p_files);
-}
-
-void EditorNode::_property_keyed(const String &p_keyed, const Variant &p_value, bool p_advance) {
-
- AnimationPlayerEditor::singleton->get_key_editor()->insert_value_key(p_keyed, p_value, p_advance);
-}
-
-void EditorNode::_transform_keyed(Object *sp, const String &p_sub, const Transform &p_key) {
-
- Spatial *s = Object::cast_to<Spatial>(sp);
- if (!s)
- return;
- AnimationPlayerEditor::singleton->get_key_editor()->insert_transform_key(s, p_sub, p_key);
+ return inspector_dock;
}
-void EditorNode::update_keying() {
-
- bool valid = false;
-
- if (AnimationPlayerEditor::singleton->get_key_editor()->has_keying()) {
-
- if (editor_history.get_path_size() >= 1) {
-
- Object *obj = ObjectDB::get_instance(editor_history.get_path_object(0));
- if (Object::cast_to<Node>(obj)) {
-
- valid = true;
- }
- }
- }
+void EditorNode::_instance_request(const Vector<String> &p_files) {
- inspector->set_keying(valid);
+ request_instance_scenes(p_files);
}
void EditorNode::_close_messages() {
@@ -4044,7 +3656,7 @@ void EditorNode::_load_docks_from_config(Ref<ConfigFile> p_layout, const String
}
void EditorNode::_load_open_scenes_from_config(Ref<ConfigFile> p_layout, const String &p_section) {
- if (!bool(EDITOR_DEF("interface/scene_tabs/restore_scenes_on_load", false))) {
+ if (!bool(EDITOR_GET("interface/scene_tabs/restore_scenes_on_load"))) {
return;
}
@@ -4138,7 +3750,7 @@ void EditorNode::_scene_tab_script_edited(int p_tab) {
Ref<Script> script = editor_data.get_scene_root_script(p_tab);
if (script.is_valid())
- edit_resource(script);
+ inspector_dock->edit_resource(script);
}
void EditorNode::_scene_tab_closed(int p_tab) {
@@ -4166,7 +3778,7 @@ void EditorNode::_scene_tab_closed(int p_tab) {
}
void EditorNode::_scene_tab_hover(int p_tab) {
- if (bool(EDITOR_DEF("interface/scene_tabs/show_thumbnail_on_hover", true)) == false) {
+ if (bool(EDITOR_GET("interface/scene_tabs/show_thumbnail_on_hover")) == false) {
return;
}
int current_tab = scene_tabs->get_current_tab();
@@ -4236,30 +3848,6 @@ void EditorNode::_scene_tab_changed(int p_tab) {
editor_data.get_undo_redo().commit_action();
}
-void EditorNode::_toggle_search_bar(bool p_pressed) {
-
- inspector->set_use_filter(p_pressed);
-
- if (p_pressed) {
-
- search_bar->show();
- search_box->grab_focus();
- search_box->select_all();
- } else {
-
- search_bar->hide();
- }
-}
-
-void EditorNode::_clear_search_box() {
-
- if (search_box->get_text() == "")
- return;
-
- search_box->clear();
- inspector->update_tree();
-}
-
ToolButton *EditorNode::add_bottom_panel_item(String p_text, Control *p_item) {
ToolButton *tb = memnew(ToolButton);
@@ -4778,9 +4366,6 @@ void EditorNode::_bind_methods() {
ClassDB::bind_method("_tool_menu_option", &EditorNode::_tool_menu_option);
ClassDB::bind_method("_menu_confirm_current", &EditorNode::_menu_confirm_current);
ClassDB::bind_method("_dialog_action", &EditorNode::_dialog_action);
- ClassDB::bind_method("_resource_selected", &EditorNode::_resource_selected, DEFVAL(""));
- ClassDB::bind_method("_property_editor_forward", &EditorNode::_property_editor_forward);
- ClassDB::bind_method("_property_editor_back", &EditorNode::_property_editor_back);
ClassDB::bind_method("_editor_select", &EditorNode::_editor_select);
ClassDB::bind_method("_node_renamed", &EditorNode::_node_renamed);
ClassDB::bind_method("edit_node", &EditorNode::edit_node);
@@ -4790,16 +4375,12 @@ void EditorNode::_bind_methods() {
ClassDB::bind_method("set_edited_scene", &EditorNode::set_edited_scene);
ClassDB::bind_method("open_request", &EditorNode::open_request);
ClassDB::bind_method("_instance_request", &EditorNode::_instance_request);
- ClassDB::bind_method("update_keying", &EditorNode::update_keying);
- ClassDB::bind_method("_property_keyed", &EditorNode::_property_keyed);
- ClassDB::bind_method("_transform_keyed", &EditorNode::_transform_keyed);
ClassDB::bind_method("_close_messages", &EditorNode::_close_messages);
ClassDB::bind_method("_show_messages", &EditorNode::_show_messages);
ClassDB::bind_method("_vp_resized", &EditorNode::_vp_resized);
ClassDB::bind_method("_quick_opened", &EditorNode::_quick_opened);
ClassDB::bind_method("_quick_run", &EditorNode::_quick_run);
- ClassDB::bind_method("_resource_created", &EditorNode::_resource_created);
ClassDB::bind_method("_open_recent_scene", &EditorNode::_open_recent_scene);
ClassDB::bind_method("stop_child_process", &EditorNode::stop_child_process);
@@ -4833,15 +4414,9 @@ void EditorNode::_bind_methods() {
ClassDB::bind_method("_discard_changes", &EditorNode::_discard_changes);
ClassDB::bind_method("_update_recent_scenes", &EditorNode::_update_recent_scenes);
- ClassDB::bind_method("_prepare_history", &EditorNode::_prepare_history);
- ClassDB::bind_method("_select_history", &EditorNode::_select_history);
-
- ClassDB::bind_method("_toggle_search_bar", &EditorNode::_toggle_search_bar);
- ClassDB::bind_method("_clear_search_box", &EditorNode::_clear_search_box);
ClassDB::bind_method("_clear_undo_history", &EditorNode::_clear_undo_history);
ClassDB::bind_method("_dropped_files", &EditorNode::_dropped_files);
ClassDB::bind_method("_toggle_distraction_free_mode", &EditorNode::_toggle_distraction_free_mode);
- ClassDB::bind_method("_property_editable_warning_pressed", &EditorNode::_property_editable_warning_pressed);
ClassDB::bind_method(D_METHOD("get_gui_base"), &EditorNode::get_gui_base);
ClassDB::bind_method(D_METHOD("_bottom_panel_switch"), &EditorNode::_bottom_panel_switch);
@@ -4855,7 +4430,6 @@ void EditorNode::_bind_methods() {
ADD_SIGNAL(MethodInfo("play_pressed"));
ADD_SIGNAL(MethodInfo("pause_pressed"));
ADD_SIGNAL(MethodInfo("stop_pressed"));
- ADD_SIGNAL(MethodInfo("request_help"));
ADD_SIGNAL(MethodInfo("request_help_search"));
ADD_SIGNAL(MethodInfo("request_help_index"));
ADD_SIGNAL(MethodInfo("script_add_function_request", PropertyInfo(Variant::OBJECT, "obj"), PropertyInfo(Variant::STRING, "function"), PropertyInfo(Variant::POOL_STRING_ARRAY, "args")));
@@ -5042,6 +4616,22 @@ EditorNode::EditorNode() {
ClassDB::set_class_enabled("CollisionShape2D", true);
ClassDB::set_class_enabled("CollisionPolygon2D", true);
+ //defs here, use EDITOR_GET in logic
+ EDITOR_DEF("interface/scene_tabs/always_show_close_button", false);
+ EDITOR_DEF("interface/scene_tabs/resize_if_many_tabs", true);
+ EDITOR_DEF("interface/scene_tabs/minimum_width", 50);
+ EDITOR_DEF("run/output/always_clear_output_on_play", true);
+ EDITOR_DEF("run/output/always_open_output_on_play", true);
+ EDITOR_DEF("run/output/always_close_output_on_stop", true);
+ EDITOR_DEF("run/auto_save/save_before_running", true);
+ EDITOR_DEF("interface/editor/save_each_scene_on_quit", true);
+ EDITOR_DEF("interface/editor/quit_confirmation", true);
+ EDITOR_DEF("interface/scene_tabs/restore_scenes_on_load", false);
+ EDITOR_DEF("interface/scene_tabs/show_thumbnail_on_hover", true);
+ EDITOR_DEF("interface/inspector/capitalize_properties", true);
+ EDITOR_DEF("interface/inspector/open_resources_in_new_inspector", false);
+ EDITOR_DEF("run/auto_save/save_before_running", true);
+
theme_base = memnew(Control);
add_child(theme_base);
theme_base->set_anchors_and_margins_preset(Control::PRESET_WIDE);
@@ -5565,129 +5155,11 @@ EditorNode::EditorNode() {
dock_slot[DOCK_SLOT_RIGHT_UL]->set_tab_title(scene_tree_dock->get_index(), TTR("Scene"));
dock_slot[DOCK_SLOT_LEFT_BR]->hide();
- VBoxContainer *prop_editor_base = memnew(VBoxContainer);
- prop_editor_base->set_name("Inspector");
- dock_slot[DOCK_SLOT_RIGHT_BL]->add_child(prop_editor_base);
- dock_slot[DOCK_SLOT_RIGHT_BL]->set_tab_title(prop_editor_base->get_index(), TTR("Inspector"));
-
- HBoxContainer *prop_editor_hb = memnew(HBoxContainer);
-
- prop_editor_base->add_child(prop_editor_hb);
- prop_editor_vb = prop_editor_base;
-
- resource_new_button = memnew(ToolButton);
- resource_new_button->set_tooltip(TTR("Create a new resource in memory and edit it."));
- resource_new_button->set_icon(gui_base->get_icon("New", "EditorIcons"));
- prop_editor_hb->add_child(resource_new_button);
- resource_new_button->connect("pressed", this, "_menu_option", varray(RESOURCE_NEW));
- resource_new_button->set_focus_mode(Control::FOCUS_NONE);
-
- resource_load_button = memnew(ToolButton);
- resource_load_button->set_tooltip(TTR("Load an existing resource from disk and edit it."));
- resource_load_button->set_icon(gui_base->get_icon("Load", "EditorIcons"));
- prop_editor_hb->add_child(resource_load_button);
- resource_load_button->connect("pressed", this, "_menu_option", varray(RESOURCE_LOAD));
- resource_load_button->set_focus_mode(Control::FOCUS_NONE);
-
- resource_save_button = memnew(MenuButton);
- resource_save_button->set_tooltip(TTR("Save the currently edited resource."));
- resource_save_button->set_icon(gui_base->get_icon("Save", "EditorIcons"));
- prop_editor_hb->add_child(resource_save_button);
- resource_save_button->get_popup()->add_item(TTR("Save"), RESOURCE_SAVE);
- resource_save_button->get_popup()->add_item(TTR("Save As..."), RESOURCE_SAVE_AS);
- resource_save_button->get_popup()->connect("id_pressed", this, "_menu_option");
- resource_save_button->set_focus_mode(Control::FOCUS_NONE);
- resource_save_button->set_disabled(true);
-
- prop_editor_hb->add_spacer();
-
- property_back = memnew(ToolButton);
- property_back->set_icon(gui_base->get_icon("Back", "EditorIcons"));
- property_back->set_flat(true);
- property_back->set_tooltip(TTR("Go to the previous edited object in history."));
- property_back->set_disabled(true);
-
- prop_editor_hb->add_child(property_back);
-
- property_forward = memnew(ToolButton);
- property_forward->set_icon(gui_base->get_icon("Forward", "EditorIcons"));
- property_forward->set_flat(true);
- property_forward->set_tooltip(TTR("Go to the next edited object in history."));
- property_forward->set_disabled(true);
-
- prop_editor_hb->add_child(property_forward);
-
- editor_history_menu = memnew(MenuButton);
- editor_history_menu->set_tooltip(TTR("History of recently edited objects."));
- editor_history_menu->set_icon(gui_base->get_icon("History", "EditorIcons"));
- prop_editor_hb->add_child(editor_history_menu);
- editor_history_menu->connect("about_to_show", this, "_prepare_history");
- editor_history_menu->get_popup()->connect("id_pressed", this, "_select_history");
-
- prop_editor_hb = memnew(HBoxContainer); //again...
- prop_editor_base->add_child(prop_editor_hb);
-
- editor_path = memnew(EditorPath(&editor_history));
- editor_path->set_h_size_flags(Control::SIZE_EXPAND_FILL);
- prop_editor_hb->add_child(editor_path);
-
- search_button = memnew(ToolButton);
- search_button->set_toggle_mode(true);
- search_button->set_pressed(false);
- search_button->set_icon(gui_base->get_icon("Search", "EditorIcons"));
- prop_editor_hb->add_child(search_button);
- search_button->connect("toggled", this, "_toggle_search_bar");
-
- object_menu = memnew(MenuButton);
- object_menu->set_icon(gui_base->get_icon("Tools", "EditorIcons"));
- prop_editor_hb->add_child(object_menu);
- object_menu->set_tooltip(TTR("Object properties."));
-
- create_dialog = memnew(CreateDialog);
- gui_base->add_child(create_dialog);
- create_dialog->set_base_type("Resource");
- create_dialog->connect("create", this, "_resource_created");
-
- search_bar = memnew(HBoxContainer);
- search_bar->set_h_size_flags(Control::SIZE_EXPAND_FILL);
- prop_editor_base->add_child(search_bar);
- search_bar->hide();
-
- Label *l = memnew(Label(TTR("Search:") + " "));
- search_bar->add_child(l);
-
- search_box = memnew(LineEdit);
- search_box->set_h_size_flags(Control::SIZE_EXPAND_FILL);
- search_bar->add_child(search_box);
-
- ToolButton *clear_button = memnew(ToolButton);
- clear_button->set_icon(gui_base->get_icon("Close", "EditorIcons"));
- search_bar->add_child(clear_button);
- clear_button->connect("pressed", this, "_clear_search_box");
-
- property_editable_warning = memnew(Button);
- property_editable_warning->set_text(TTR("Changes may be lost!"));
- prop_editor_base->add_child(property_editable_warning);
- property_editable_warning_dialog = memnew(AcceptDialog);
- gui_base->add_child(property_editable_warning_dialog);
- property_editable_warning->hide();
- property_editable_warning->connect("pressed", this, "_property_editable_warning_pressed");
-
- inspector = memnew(EditorInspector);
- inspector->set_autoclear(true);
- inspector->set_show_categories(true);
- inspector->set_v_size_flags(Control::SIZE_EXPAND_FILL);
- inspector->set_use_doc_hints(true);
- inspector->set_hide_script(false);
- inspector->set_enable_capitalize_paths(bool(EDITOR_DEF("interface/editor/capitalize_properties", true)));
- inspector->set_use_folding(!bool(EDITOR_DEF("interface/editor/disable_inspector_folding", false)));
-
- // inspector->hide_top_label();
- inspector->register_text_enter(search_box);
+ inspector_dock = memnew(InspectorDock(this, editor_data));
+ dock_slot[DOCK_SLOT_RIGHT_BL]->add_child(inspector_dock);
+ dock_slot[DOCK_SLOT_RIGHT_BL]->set_tab_title(inspector_dock->get_index(), TTR("Inspector"));
Button *property_editable_warning;
- prop_editor_base->add_child(inspector);
- inspector->set_undo_redo(&editor_data.get_undo_redo());
import_dock = memnew(ImportDock);
dock_slot[DOCK_SLOT_RIGHT_UL]->add_child(import_dock);
@@ -5813,18 +5285,12 @@ EditorNode::EditorNode() {
gui_base->add_child(file_script);
file_script->connect("file_selected", this, "_dialog_action");
- property_forward->connect("pressed", this, "_property_editor_forward");
- property_back->connect("pressed", this, "_property_editor_back");
-
file_menu->get_popup()->connect("id_pressed", this, "_menu_option");
- object_menu->get_popup()->connect("id_pressed", this, "_menu_option");
settings_menu->get_popup()->connect("id_pressed", this, "_menu_option");
file->connect("file_selected", this, "_dialog_action");
file_templates->connect("file_selected", this, "_dialog_action");
- inspector->connect("resource_selected", this, "_resource_selected");
- inspector->connect("property_keyed", this, "_property_keyed");
//plugin stuff
diff --git a/editor/editor_node.h b/editor/editor_node.h
index 86b85663ab..bef5bc816c 100644
--- a/editor/editor_node.h
+++ b/editor/editor_node.h
@@ -40,7 +40,6 @@
#include "editor/editor_inspector.h"
#include "editor/editor_log.h"
#include "editor/editor_name_dialog.h"
-#include "editor/editor_path.h"
#include "editor/editor_plugin.h"
#include "editor/editor_resource_preview.h"
#include "editor/editor_run.h"
@@ -53,6 +52,7 @@
#include "editor/filesystem_dock.h"
#include "editor/groups_editor.h"
#include "editor/import_dock.h"
+#include "editor/inspector_dock.h"
#include "editor/node_dock.h"
#include "editor/pane_drag.h"
#include "editor/progress_dialog.h"
@@ -142,22 +142,10 @@ private:
EDIT_REVERT,
TOOLS_ORPHAN_RESOURCES,
TOOLS_CUSTOM,
- RESOURCE_NEW,
- RESOURCE_LOAD,
RESOURCE_SAVE,
RESOURCE_SAVE_AS,
- RESOURCE_UNREF,
- RESOURCE_COPY,
- RESOURCE_PASTE,
- OBJECT_COPY_PARAMS,
- OBJECT_PASTE_PARAMS,
- OBJECT_UNIQUE_RESOURCES,
- OBJECT_REQUEST_HELP,
RUN_PLAY,
- COLLAPSE_ALL,
- EXPAND_ALL,
-
RUN_STOP,
RUN_PLAY_SCENE,
RUN_PLAY_NATIVE,
@@ -195,8 +183,6 @@ private:
IMPORT_PLUGIN_BASE = 100,
- OBJECT_METHOD_BASE = 500,
-
TOOL_MENU_BASE = 1000
};
@@ -247,7 +233,6 @@ private:
PopupMenu *tool_menu;
ToolButton *export_button;
ToolButton *prev_scene;
- MenuButton *object_menu;
ToolButton *play_button;
MenuButton *native_play_button;
ToolButton *pause_button;
@@ -264,24 +249,13 @@ private:
Ref<Theme> theme;
PopupMenu *recent_scenes;
- Button *property_back;
- Button *property_forward;
SceneTreeDock *scene_tree_dock;
- EditorInspector *inspector;
- Button *property_editable_warning;
- AcceptDialog *property_editable_warning_dialog;
- void _property_editable_warning_pressed();
+ InspectorDock *inspector_dock;
NodeDock *node_dock;
ImportDock *import_dock;
- VBoxContainer *prop_editor_vb;
FileSystemDock *filesystem_dock;
EditorRunNative *run_native;
- HBoxContainer *search_bar;
- LineEdit *search_box;
-
- CreateDialog *create_dialog;
-
ConfirmationDialog *confirmation;
ConfirmationDialog *save_confirmation;
ConfirmationDialog *import_confirmation;
@@ -314,11 +288,6 @@ private:
String defer_export_platform;
bool defer_export_debug;
Node *_last_instanced_scene;
- EditorPath *editor_path;
- ToolButton *resource_new_button;
- ToolButton *resource_load_button;
- MenuButton *resource_save_button;
- MenuButton *editor_history_menu;
EditorLog *log;
CenterContainer *tabs_center;
@@ -422,23 +391,12 @@ private:
void _dialog_display_load_error(String p_file, Error p_error);
int current_option;
- void _resource_created();
- void _resource_selected(const RES &p_res, const String &p_property = "");
void _menu_option(int p_option);
void _menu_confirm_current();
void _menu_option_confirm(int p_option, bool p_confirmed);
void _tool_menu_option(int p_idx);
void _update_debug_options();
- void _property_editor_forward();
- void _property_editor_back();
-
- void _menu_collapseall();
- void _menu_expandall();
-
- void _select_history(int p_idx);
- void _prepare_history();
-
void _fs_changed();
void _resources_reimported(const Vector<String> &p_resources);
void _sources_changed(bool p_exist);
@@ -462,9 +420,6 @@ private:
void _instance_request(const Vector<String> &p_files);
- void _property_keyed(const String &p_keyed, const Variant &p_value, bool p_advance);
- void _transform_keyed(Object *sp, const String &p_sub, const Transform &p_key);
-
void _hide_top_editors();
void _display_top_editors(bool p_display);
void _set_top_editors(Vector<EditorPlugin *> p_editor_plugins_over);
@@ -578,8 +533,6 @@ private:
void _update_layouts_menu();
void _layout_menu_option(int p_id);
- void _toggle_search_bar(bool p_pressed);
- void _clear_search_box();
void _clear_undo_history();
void _update_addon_config();
@@ -640,8 +593,8 @@ public:
EditorPluginList *get_editor_plugins_over() { return editor_plugins_over; }
EditorPluginList *get_editor_plugins_force_over() { return editor_plugins_force_over; }
EditorPluginList *get_editor_plugins_force_input_forwarding() { return editor_plugins_force_input_forwarding; }
- EditorInspector *get_inspector() { return inspector; }
- VBoxContainer *get_property_editor_vb() { return prop_editor_vb; }
+ EditorInspector *get_inspector() { return inspector_dock->get_inspector(); }
+ Container *get_inspector_dock_addon_area() { return inspector_dock->get_addon_area(); }
ProjectSettingsEditor *get_project_settings() { return project_settings; }
@@ -663,8 +616,8 @@ public:
bool is_addon_plugin_enabled(const String &p_addon) const;
void edit_node(Node *p_node);
- void edit_resource(const Ref<Resource> &p_resource);
- void open_resource(const String &p_type = "");
+ void edit_resource(const Ref<Resource> &p_resource) { inspector_dock->edit_resource(p_resource); };
+ void open_resource(const String &p_type) { inspector_dock->open_resource(p_type); };
void save_resource_in_path(const Ref<Resource> &p_resource, const String &p_path);
void save_resource(const Ref<Resource> &p_resource);
@@ -713,6 +666,7 @@ public:
FileSystemDock *get_filesystem_dock();
ImportDock *get_import_dock();
SceneTreeDock *get_scene_tree_dock();
+ InspectorDock *get_inspector_dock();
static UndoRedo *get_undo_redo() { return &singleton->editor_data.get_undo_redo(); }
EditorSelection *get_editor_selection() { return editor_selection; }
@@ -759,8 +713,6 @@ public:
void save_layout();
- void update_keying();
-
void open_export_template_manager();
void reload_scene(const String &p_path);
@@ -785,6 +737,10 @@ public:
void dim_editor(bool p_dimming);
+ void edit_current() { _edit_current(); };
+
+ void update_keying() const { inspector_dock->update_keying(); };
+
EditorNode();
~EditorNode();
void get_singleton(const char *arg1, bool arg2);
diff --git a/editor/editor_plugin.cpp b/editor/editor_plugin.cpp
index 2e4e887165..24d0592ee7 100644
--- a/editor/editor_plugin.cpp
+++ b/editor/editor_plugin.cpp
@@ -375,7 +375,7 @@ void EditorPlugin::add_control_to_container(CustomControlContainer p_location, C
} break;
case CONTAINER_PROPERTY_EDITOR_BOTTOM: {
- EditorNode::get_singleton()->get_property_editor_vb()->add_child(p_control);
+ EditorNode::get_singleton()->get_inspector_dock_addon_area()->add_child(p_control);
} break;
}
@@ -422,7 +422,7 @@ void EditorPlugin::remove_control_from_container(CustomControlContainer p_locati
} break;
case CONTAINER_PROPERTY_EDITOR_BOTTOM: {
- EditorNode::get_singleton()->get_property_editor_vb()->remove_child(p_control);
+ EditorNode::get_singleton()->get_inspector_dock_addon_area()->remove_child(p_control);
} break;
}
@@ -659,6 +659,14 @@ void EditorPlugin::remove_export_plugin(const Ref<EditorExportPlugin> &p_exporte
EditorExport::get_singleton()->remove_export_plugin(p_exporter);
}
+void EditorPlugin::add_inspector_plugin(const Ref<EditorInspectorPlugin> &p_plugin) {
+ EditorInspector::add_inspector_plugin(p_plugin);
+}
+
+void EditorPlugin::remove_inspector_plugin(const Ref<EditorInspectorPlugin> &p_plugin) {
+ EditorInspector::remove_inspector_plugin(p_plugin);
+}
+
void EditorPlugin::add_scene_import_plugin(const Ref<EditorSceneImporter> &p_importer) {
ResourceImporterScene::get_singleton()->add_importer(p_importer);
}
@@ -728,8 +736,10 @@ void EditorPlugin::_bind_methods() {
ClassDB::bind_method(D_METHOD("remove_import_plugin", "importer"), &EditorPlugin::remove_import_plugin);
ClassDB::bind_method(D_METHOD("add_scene_import_plugin", "scene_importer"), &EditorPlugin::add_scene_import_plugin);
ClassDB::bind_method(D_METHOD("remove_scene_import_plugin", "scene_importer"), &EditorPlugin::remove_scene_import_plugin);
- ClassDB::bind_method(D_METHOD("add_export_plugin", "exporter"), &EditorPlugin::add_export_plugin);
- ClassDB::bind_method(D_METHOD("remove_export_plugin", "exporter"), &EditorPlugin::remove_export_plugin);
+ ClassDB::bind_method(D_METHOD("add_export_plugin", "plugin"), &EditorPlugin::add_export_plugin);
+ ClassDB::bind_method(D_METHOD("remove_export_plugin", "plugin"), &EditorPlugin::remove_export_plugin);
+ ClassDB::bind_method(D_METHOD("add_inspector_plugin", "plugin"), &EditorPlugin::add_inspector_plugin);
+ ClassDB::bind_method(D_METHOD("remove_inspector_plugin", "plugin"), &EditorPlugin::remove_inspector_plugin);
ClassDB::bind_method(D_METHOD("set_input_event_forwarding_always_enabled"), &EditorPlugin::set_input_event_forwarding_always_enabled);
ClassDB::bind_method(D_METHOD("set_force_draw_over_forwarding_enabled"), &EditorPlugin::set_force_draw_over_forwarding_enabled);
diff --git a/editor/editor_plugin.h b/editor/editor_plugin.h
index ebc4afdfeb..8af7f83771 100644
--- a/editor/editor_plugin.h
+++ b/editor/editor_plugin.h
@@ -31,6 +31,7 @@
#ifndef EDITOR_PLUGIN_H
#define EDITOR_PLUGIN_H
+#include "editor/editor_inspector.h"
#include "editor/import/editor_import_plugin.h"
#include "editor/import/resource_importer_scene.h"
#include "io/config_file.h"
@@ -210,6 +211,9 @@ public:
void add_export_plugin(const Ref<EditorExportPlugin> &p_exporter);
void remove_export_plugin(const Ref<EditorExportPlugin> &p_exporter);
+ void add_inspector_plugin(const Ref<EditorInspectorPlugin> &p_plugin);
+ void remove_inspector_plugin(const Ref<EditorInspectorPlugin> &p_plugin);
+
void add_scene_import_plugin(const Ref<EditorSceneImporter> &p_importer);
void remove_scene_import_plugin(const Ref<EditorSceneImporter> &p_importer);
diff --git a/editor/editor_properties.cpp b/editor/editor_properties.cpp
index fb2570d472..c6d3a43f4e 100644
--- a/editor/editor_properties.cpp
+++ b/editor/editor_properties.cpp
@@ -1,7 +1,50 @@
+/*************************************************************************/
+/* editor_properties.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_properties.h"
#include "editor/editor_resource_preview.h"
#include "editor_node.h"
+#include "editor_properties_array_dict.h"
#include "scene/main/viewport.h"
+
+///////////////////// NULL /////////////////////////
+
+void EditorPropertyNil::update_property() {
+}
+
+EditorPropertyNil::EditorPropertyNil() {
+ Label *label = memnew(Label);
+ label->set_text("[null]");
+ add_child(label);
+}
+
///////////////////// TEXT /////////////////////////
void EditorPropertyText::_text_changed(const String &p_string) {
if (updating)
@@ -88,8 +131,8 @@ void EditorPropertyMultilineText::_bind_methods() {
EditorPropertyMultilineText::EditorPropertyMultilineText() {
HBoxContainer *hb = memnew(HBoxContainer);
- set_label_layout(LABEL_LAYOUT_TOP);
add_child(hb);
+ set_bottom_editor(hb);
text = memnew(TextEdit);
text->connect("text_changed", this, "_text_changed");
add_focusable(text);
@@ -457,7 +500,7 @@ public:
virtual String get_tooltip(const Point2 &p_pos) const {
for (int i = 0; i < flag_rects.size(); i++) {
- if (flag_rects[i].has_point(p_pos) && i < names.size()) {
+ if (i < names.size() && flag_rects[i].has_point(p_pos)) {
return names[i];
}
}
@@ -592,6 +635,7 @@ void EditorPropertyLayers::_button_pressed() {
}
Rect2 gp = button->get_global_rect();
+ layers->set_as_minsize();
Vector2 popup_pos = gp.position - Vector2(layers->get_combined_minimum_size().x, 0);
layers->set_global_position(popup_pos);
layers->popup();
@@ -626,7 +670,7 @@ EditorPropertyLayers::EditorPropertyLayers() {
button->set_text("..");
button->connect("pressed", this, "_button_pressed");
hb->add_child(button);
- set_label_layout(LABEL_LAYOUT_TOP);
+ set_bottom_editor(hb);
layers = memnew(PopupMenu);
add_child(layers);
layers->connect("id_pressed", this, "_menu_pressed");
@@ -1237,8 +1281,7 @@ EditorPropertyAABB::EditorPropertyAABB() {
add_focusable(spin[i]);
spin[i]->connect("value_changed", this, "_value_changed");
}
- set_label_reference(spin[0]); //show text and buttons around this
- set_label_layout(LABEL_LAYOUT_TOP);
+ set_bottom_editor(g);
setting = false;
}
@@ -1300,8 +1343,7 @@ EditorPropertyTransform2D::EditorPropertyTransform2D() {
add_focusable(spin[i]);
spin[i]->connect("value_changed", this, "_value_changed");
}
- set_label_reference(spin[0]); //show text and buttons around this
- set_label_layout(LABEL_LAYOUT_TOP);
+ set_bottom_editor(g);
setting = false;
}
@@ -1369,8 +1411,7 @@ EditorPropertyBasis::EditorPropertyBasis() {
add_focusable(spin[i]);
spin[i]->connect("value_changed", this, "_value_changed");
}
- set_label_reference(spin[0]); //show text and buttons around this
- set_label_layout(LABEL_LAYOUT_TOP);
+ set_bottom_editor(g);
setting = false;
}
@@ -1444,8 +1485,7 @@ EditorPropertyTransform::EditorPropertyTransform() {
add_focusable(spin[i]);
spin[i]->connect("value_changed", this, "_value_changed");
}
- set_label_reference(spin[0]); //show text and buttons around this
- set_label_layout(LABEL_LAYOUT_TOP);
+ set_bottom_editor(g);
setting = false;
}
@@ -1482,7 +1522,8 @@ EditorPropertyColor::EditorPropertyColor() {
void EditorPropertyNodePath::_node_selected(const NodePath &p_path) {
- emit_signal("property_changed", get_edited_property(), p_path);
+ Node *base_node = Object::cast_to<Node>(get_edited_object());
+ emit_signal("property_changed", get_edited_property(), base_node->get_path().rel_path_to(p_path));
update_property();
}
@@ -1922,23 +1963,75 @@ void EditorPropertyResource::_update_menu() {
}
}
- Rect2 gt = get_global_rect();
+ Rect2 gt = edit->get_global_rect();
+ menu->set_as_minsize();
int ms = menu->get_combined_minimum_size().width;
Vector2 popup_pos = gt.position + gt.size - Vector2(ms, 0);
- menu->set_position(popup_pos);
+ menu->set_global_position(popup_pos);
menu->popup();
}
+void EditorPropertyResource::_sub_inspector_property_keyed(const String &p_property, const Variant &p_value, bool) {
+
+ emit_signal("property_keyed_with_value", String(get_edited_property()) + ":" + p_property, p_value);
+}
+
+void EditorPropertyResource::_sub_inspector_resource_selected(const RES &p_resource, const String &p_property) {
+
+ emit_signal("resource_selected", String(get_edited_property()) + ":" + p_property, p_resource);
+}
+
+void EditorPropertyResource::_sub_inspector_object_id_selected(int p_id) {
+
+ emit_signal("object_id_selected", get_edited_property(), p_id);
+}
+
void EditorPropertyResource::update_property() {
RES res = get_edited_object()->get(get_edited_property());
+ if (use_sub_inspector) {
+
+ if (res.is_valid() != assign->is_toggle_mode()) {
+ assign->set_toggle_mode(res.is_valid());
+ }
+#ifdef TOOLS_ENABLED
+ if (res.is_valid() && get_edited_object()->editor_is_section_unfolded(get_edited_property())) {
+
+ if (!sub_inspector) {
+ sub_inspector = memnew(EditorInspector);
+ sub_inspector->set_enable_v_scroll(false);
+
+ sub_inspector->connect("property_keyed", this, "_sub_inspector_property_keyed");
+ sub_inspector->connect("resource_selected", this, "_sub_inspector_resource_selected");
+ sub_inspector->connect("object_id_selected", this, "_sub_inspector_object_id_selected");
+ sub_inspector->set_keying(is_keying());
+ sub_inspector->set_read_only(is_read_only());
+ sub_inspector->set_use_folding(is_using_folding());
+
+ add_child(sub_inspector);
+ set_bottom_editor(sub_inspector);
+ assign->set_pressed(true);
+ }
+
+ if (res.ptr() != sub_inspector->get_edited_object()) {
+ sub_inspector->edit(res.ptr());
+ }
+
+ } else {
+ if (sub_inspector) {
+ set_bottom_editor(NULL);
+ memdelete(sub_inspector);
+ sub_inspector = NULL;
+ }
+ }
+#endif
+ }
+
if (res == RES()) {
assign->set_icon(Ref<Texture>());
assign->set_text(TTR("[empty]"));
- assign->set_disabled(true);
} else {
- assign->set_disabled(false);
Ref<Texture> icon;
if (has_icon(res->get_class(), "EditorIcons"))
@@ -1969,7 +2062,16 @@ void EditorPropertyResource::update_property() {
void EditorPropertyResource::_resource_selected() {
RES res = get_edited_object()->get(get_edited_property());
- if (!res.is_null()) {
+ if (res.is_null()) {
+ _update_menu();
+ return;
+ }
+
+ if (use_sub_inspector) {
+
+ get_edited_object()->editor_set_section_unfold(get_edited_property(), assign->is_pressed());
+ update_property();
+ } else {
emit_signal("resource_selected", get_edited_property(), res);
}
@@ -1985,6 +2087,23 @@ void EditorPropertyResource::_notification(int p_what) {
Ref<Texture> t = get_icon("select_arrow", "Tree");
edit->set_icon(t);
}
+
+ if (p_what == NOTIFICATION_DRAG_BEGIN) {
+
+ if (is_visible_in_tree()) {
+ if (_is_drop_valid(get_viewport()->gui_get_drag_data())) {
+ dropping = true;
+ assign->update();
+ }
+ }
+ }
+
+ if (p_what == NOTIFICATION_DRAG_END) {
+ if (dropping) {
+ dropping = false;
+ assign->update();
+ }
+ }
}
void EditorPropertyResource::_viewport_selected(const NodePath &p_path) {
@@ -2003,6 +2122,111 @@ void EditorPropertyResource::_viewport_selected(const NodePath &p_path) {
emit_signal("property_changed", get_edited_property(), vt);
update_property();
}
+
+void EditorPropertyResource::collapse_all_folding() {
+ if (sub_inspector) {
+ sub_inspector->collapse_all_folding();
+ }
+}
+
+void EditorPropertyResource::expand_all_folding() {
+
+ if (sub_inspector) {
+ sub_inspector->expand_all_folding();
+ }
+}
+
+void EditorPropertyResource::_button_draw() {
+
+ if (dropping) {
+ Color color = get_color("accent_color", "Editor");
+ assign->draw_rect(Rect2(Point2(), assign->get_size()), color, false);
+ }
+}
+
+Variant EditorPropertyResource::get_drag_data_fw(const Point2 &p_point, Control *p_from) {
+
+ RES res = get_edited_object()->get(get_edited_property());
+ if (res.is_valid()) {
+
+ return EditorNode::get_singleton()->drag_resource(res, p_from);
+ }
+
+ return Variant();
+}
+
+bool EditorPropertyResource::_is_drop_valid(const Dictionary &p_drag_data) const {
+
+ String allowed_type = base_type;
+
+ Dictionary drag_data = p_drag_data;
+ if (drag_data.has("type") && String(drag_data["type"]) == "resource") {
+ Ref<Resource> res = drag_data["resource"];
+ for (int i = 0; i < allowed_type.get_slice_count(","); i++) {
+ String at = allowed_type.get_slice(",", i).strip_edges();
+ if (res.is_valid() && ClassDB::is_parent_class(res->get_class(), at)) {
+ return true;
+ }
+ }
+ }
+
+ if (drag_data.has("type") && String(drag_data["type"]) == "files") {
+
+ Vector<String> files = drag_data["files"];
+
+ if (files.size() == 1) {
+ String file = files[0];
+ String ftype = EditorFileSystem::get_singleton()->get_file_type(file);
+
+ if (ftype != "") {
+
+ for (int i = 0; i < allowed_type.get_slice_count(","); i++) {
+ String at = allowed_type.get_slice(",", i).strip_edges();
+ if (ClassDB::is_parent_class(ftype, at)) {
+ return true;
+ }
+ }
+ }
+ }
+ }
+
+ return false;
+}
+
+bool EditorPropertyResource::can_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) const {
+
+ return _is_drop_valid(p_data);
+}
+void EditorPropertyResource::drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) {
+
+ ERR_FAIL_COND(!_is_drop_valid(p_data));
+
+ Dictionary drag_data = p_data;
+ if (drag_data.has("type") && String(drag_data["type"]) == "resource") {
+ Ref<Resource> res = drag_data["resource"];
+ if (res.is_valid()) {
+ emit_signal("property_changed", get_edited_property(), res);
+ update_property();
+ return;
+ }
+ }
+
+ if (drag_data.has("type") && String(drag_data["type"]) == "files") {
+
+ Vector<String> files = drag_data["files"];
+
+ if (files.size() == 1) {
+ String file = files[0];
+ RES res = ResourceLoader::load(file);
+ if (res.is_valid()) {
+ emit_signal("property_changed", get_edited_property(), res);
+ update_property();
+ return;
+ }
+ }
+ }
+}
+
void EditorPropertyResource::_bind_methods() {
ClassDB::bind_method(D_METHOD("_file_selected"), &EditorPropertyResource::_file_selected);
@@ -2011,10 +2235,19 @@ void EditorPropertyResource::_bind_methods() {
ClassDB::bind_method(D_METHOD("_resource_preview"), &EditorPropertyResource::_resource_preview);
ClassDB::bind_method(D_METHOD("_resource_selected"), &EditorPropertyResource::_resource_selected);
ClassDB::bind_method(D_METHOD("_viewport_selected"), &EditorPropertyResource::_viewport_selected);
+ ClassDB::bind_method(D_METHOD("_sub_inspector_property_keyed"), &EditorPropertyResource::_sub_inspector_property_keyed);
+ ClassDB::bind_method(D_METHOD("_sub_inspector_resource_selected"), &EditorPropertyResource::_sub_inspector_resource_selected);
+ ClassDB::bind_method(D_METHOD("_sub_inspector_object_id_selected"), &EditorPropertyResource::_sub_inspector_object_id_selected);
+ ClassDB::bind_method(D_METHOD("get_drag_data_fw"), &EditorPropertyResource::get_drag_data_fw);
+ ClassDB::bind_method(D_METHOD("can_drop_data_fw"), &EditorPropertyResource::can_drop_data_fw);
+ ClassDB::bind_method(D_METHOD("drop_data_fw"), &EditorPropertyResource::drop_data_fw);
+ ClassDB::bind_method(D_METHOD("_button_draw"), &EditorPropertyResource::_button_draw);
}
EditorPropertyResource::EditorPropertyResource() {
+ sub_inspector = NULL;
+ use_sub_inspector = !bool(EDITOR_GET("interface/inspector/open_resources_in_new_inspector"));
HBoxContainer *hbc = memnew(HBoxContainer);
add_child(hbc);
assign = memnew(Button);
@@ -2022,6 +2255,8 @@ EditorPropertyResource::EditorPropertyResource() {
assign->set_h_size_flags(SIZE_EXPAND_FILL);
assign->set_clip_text(true);
assign->connect("pressed", this, "_resource_selected");
+ assign->set_drag_forwarding(this);
+ assign->connect("draw", this, "_button_draw");
hbc->add_child(assign);
menu = memnew(PopupMenu);
@@ -2034,6 +2269,7 @@ EditorPropertyResource::EditorPropertyResource() {
file = NULL;
scene_tree = NULL;
+ dropping = false;
}
////////////// DEFAULT PLUGIN //////////////////////
@@ -2051,6 +2287,10 @@ bool EditorInspectorDefaultPlugin::parse_property(Object *p_object, Variant::Typ
switch (p_type) {
// atomic types
+ case Variant::NIL: {
+ EditorPropertyNil *editor = memnew(EditorPropertyNil);
+ add_property_editor(p_path, editor);
+ } break;
case Variant::BOOL: {
EditorPropertyCheck *editor = memnew(EditorPropertyCheck);
add_property_editor(p_path, editor);
@@ -2409,24 +2649,40 @@ bool EditorInspectorDefaultPlugin::parse_property(Object *p_object, Variant::Typ
} break;
case Variant::DICTIONARY: {
+ EditorPropertyDictionary *editor = memnew(EditorPropertyDictionary);
+ add_property_editor(p_path, editor);
} break;
case Variant::ARRAY: {
+ EditorPropertyArray *editor = memnew(EditorPropertyArray);
+ add_property_editor(p_path, editor);
} break;
-
- // arrays
case Variant::POOL_BYTE_ARRAY: {
+ EditorPropertyArray *editor = memnew(EditorPropertyArray);
+ add_property_editor(p_path, editor);
} break; // 20
case Variant::POOL_INT_ARRAY: {
+ EditorPropertyArray *editor = memnew(EditorPropertyArray);
+ add_property_editor(p_path, editor);
} break;
case Variant::POOL_REAL_ARRAY: {
+ EditorPropertyArray *editor = memnew(EditorPropertyArray);
+ add_property_editor(p_path, editor);
} break;
case Variant::POOL_STRING_ARRAY: {
+ EditorPropertyArray *editor = memnew(EditorPropertyArray);
+ add_property_editor(p_path, editor);
} break;
case Variant::POOL_VECTOR2_ARRAY: {
+ EditorPropertyArray *editor = memnew(EditorPropertyArray);
+ add_property_editor(p_path, editor);
} break;
case Variant::POOL_VECTOR3_ARRAY: {
+ EditorPropertyArray *editor = memnew(EditorPropertyArray);
+ add_property_editor(p_path, editor);
} break; // 25
case Variant::POOL_COLOR_ARRAY: {
+ EditorPropertyArray *editor = memnew(EditorPropertyArray);
+ add_property_editor(p_path, editor);
} break;
default: {}
}
diff --git a/editor/editor_properties.h b/editor/editor_properties.h
index 4fcef5fdae..03e72b4ec2 100644
--- a/editor/editor_properties.h
+++ b/editor/editor_properties.h
@@ -1,3 +1,33 @@
+/*************************************************************************/
+/* editor_properties.h */
+/*************************************************************************/
+/* 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. */
+/*************************************************************************/
+
#ifndef EDITOR_PROPERTIES_H
#define EDITOR_PROPERTIES_H
@@ -9,6 +39,15 @@
#include "editor/scene_tree_editor.h"
#include "scene/gui/color_picker.h"
+class EditorPropertyNil : public EditorProperty {
+ GDCLASS(EditorPropertyNil, EditorProperty)
+ LineEdit *text;
+
+public:
+ virtual void update_property();
+ EditorPropertyNil();
+};
+
class EditorPropertyText : public EditorProperty {
GDCLASS(EditorPropertyText, EditorProperty)
LineEdit *text;
@@ -451,7 +490,10 @@ class EditorPropertyResource : public EditorProperty {
PopupMenu *menu;
EditorFileDialog *file;
Vector<String> inheritors_array;
+ EditorInspector *sub_inspector;
+ bool use_sub_inspector;
+ bool dropping;
String base_type;
SceneTreeDialog *scene_tree;
@@ -464,6 +506,16 @@ class EditorPropertyResource : public EditorProperty {
void _update_menu();
+ void _sub_inspector_property_keyed(const String &p_property, const Variant &p_value, bool);
+ void _sub_inspector_resource_selected(const RES &p_resource, const String &p_property);
+ void _sub_inspector_object_id_selected(int p_id);
+
+ void _button_draw();
+ Variant get_drag_data_fw(const Point2 &p_point, Control *p_from);
+ bool _is_drop_valid(const Dictionary &p_drag_data) const;
+ bool can_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) const;
+ void drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from);
+
protected:
static void _bind_methods();
void _notification(int p_what);
@@ -471,6 +523,10 @@ protected:
public:
virtual void update_property();
void setup(const String &p_base_type);
+
+ void collapse_all_folding();
+ void expand_all_folding();
+
EditorPropertyResource();
};
diff --git a/editor/editor_properties_array_dict.cpp b/editor/editor_properties_array_dict.cpp
new file mode 100644
index 0000000000..90f8d0e157
--- /dev/null
+++ b/editor/editor_properties_array_dict.cpp
@@ -0,0 +1,999 @@
+#include "editor_properties_array_dict.h"
+#include "editor/editor_scale.h"
+#include "editor_properties.h"
+
+bool EditorPropertyArrayObject::_set(const StringName &p_name, const Variant &p_value) {
+
+ String pn = p_name;
+
+ if (pn.begins_with("indices")) {
+ int idx = pn.get_slicec('/', 1).to_int();
+ array.set(idx, p_value);
+ return true;
+ }
+
+ return false;
+}
+
+bool EditorPropertyArrayObject::_get(const StringName &p_name, Variant &r_ret) const {
+
+ String pn = p_name;
+
+ if (pn.begins_with("indices")) {
+
+ int idx = pn.get_slicec('/', 1).to_int();
+ bool valid;
+ r_ret = array.get(idx, &valid);
+ return valid;
+ }
+
+ return false;
+}
+
+void EditorPropertyArrayObject::set_array(const Variant &p_array) {
+ array = p_array;
+}
+
+Variant EditorPropertyArrayObject::get_array() {
+ return array;
+}
+
+EditorPropertyArrayObject::EditorPropertyArrayObject() {
+}
+
+///////////////////
+
+bool EditorPropertyDictionaryObject::_set(const StringName &p_name, const Variant &p_value) {
+
+ String pn = p_name;
+
+ if (pn == "new_item_key") {
+
+ new_item_key = p_value;
+ return true;
+ }
+
+ if (pn == "new_item_value") {
+
+ new_item_value = p_value;
+ return true;
+ }
+
+ if (pn.begins_with("indices")) {
+ int idx = pn.get_slicec('/', 1).to_int();
+ Variant key = dict.get_key_at_index(idx);
+ dict[key] = p_value;
+ return true;
+ }
+
+ return false;
+}
+
+bool EditorPropertyDictionaryObject::_get(const StringName &p_name, Variant &r_ret) const {
+
+ String pn = p_name;
+
+ if (pn == "new_item_key") {
+
+ r_ret = new_item_key;
+ return true;
+ }
+
+ if (pn == "new_item_value") {
+
+ r_ret = new_item_value;
+ return true;
+ }
+
+ if (pn.begins_with("indices")) {
+
+ int idx = pn.get_slicec('/', 1).to_int();
+ Variant key = dict.get_key_at_index(idx);
+ r_ret = dict[key];
+ return true;
+ }
+
+ return false;
+}
+
+void EditorPropertyDictionaryObject::set_dict(const Dictionary &p_dict) {
+ dict = p_dict;
+}
+
+Dictionary EditorPropertyDictionaryObject::get_dict() {
+ return dict;
+}
+
+void EditorPropertyDictionaryObject::set_new_item_key(const Variant &p_new_item) {
+ new_item_key = p_new_item;
+}
+
+Variant EditorPropertyDictionaryObject::get_new_item_key() {
+ return new_item_key;
+}
+
+void EditorPropertyDictionaryObject::set_new_item_value(const Variant &p_new_item) {
+ new_item_value = p_new_item;
+}
+
+Variant EditorPropertyDictionaryObject::get_new_item_value() {
+ return new_item_value;
+}
+
+EditorPropertyDictionaryObject::EditorPropertyDictionaryObject() {
+}
+
+///////////////////// ARRAY ///////////////////////////
+
+void EditorPropertyArray::_property_changed(const String &p_prop, Variant p_value) {
+
+ if (p_prop.begins_with("indices")) {
+ int idx = p_prop.get_slice("/", 1).to_int();
+ Variant array = object->get_array();
+ array.set(idx, p_value);
+ emit_signal("property_changed", get_edited_property(), array);
+
+ if (array.get_type() == Variant::ARRAY) {
+ array = array.call("duplicate"); //dupe, so undo/redo works better
+ }
+ object->set_array(array);
+ }
+}
+
+void EditorPropertyArray::_change_type(Object *p_button, int p_index) {
+
+ Button *button = Object::cast_to<Button>(p_button);
+
+ Rect2 rect = button->get_global_rect();
+ change_type->set_as_minsize();
+ change_type->set_global_position(rect.position + rect.size - Vector2(change_type->get_combined_minimum_size().x, 0));
+ change_type->popup();
+ changing_type_idx = p_index;
+}
+
+void EditorPropertyArray::_change_type_menu(int p_index) {
+
+ Variant value;
+ Variant::CallError ce;
+ value = Variant::construct(Variant::Type(p_index), NULL, 0, ce);
+ Variant array = object->get_array();
+ array.set(changing_type_idx, value);
+
+ emit_signal("property_changed", get_edited_property(), array);
+
+ if (array.get_type() == Variant::ARRAY) {
+ array = array.call("duplicate"); //dupe, so undo/redo works better
+ }
+ object->set_array(array);
+ update_property();
+}
+
+void EditorPropertyArray::update_property() {
+
+ Variant array = get_edited_object()->get(get_edited_property());
+
+ if ((!array.is_array()) != edit->is_disabled()) {
+
+ if (array.is_array()) {
+ edit->set_disabled(false);
+ edit->set_pressed(false);
+
+ } else {
+ edit->set_disabled(true);
+ if (vbox) {
+ memdelete(vbox);
+ }
+ }
+ }
+
+ if (!array.is_array()) {
+ return;
+ }
+
+ String arrtype;
+ switch (array.get_type()) {
+ case Variant::ARRAY: {
+
+ arrtype = "Array";
+
+ } break;
+
+ // arrays
+ case Variant::POOL_BYTE_ARRAY: {
+ arrtype = "ByteArray";
+
+ } break;
+ case Variant::POOL_INT_ARRAY: {
+ arrtype = "IntArray";
+
+ } break;
+ case Variant::POOL_REAL_ARRAY: {
+
+ arrtype = "FltArray";
+ } break;
+ case Variant::POOL_STRING_ARRAY: {
+
+ arrtype = "StrArray";
+ } break;
+ case Variant::POOL_VECTOR2_ARRAY: {
+
+ arrtype = "Vec2Array";
+ } break;
+ case Variant::POOL_VECTOR3_ARRAY: {
+ arrtype = "Vec3Array";
+
+ } break;
+ case Variant::POOL_COLOR_ARRAY: {
+ arrtype = "ColArray";
+ } break;
+ default: {}
+ }
+
+ edit->set_text(arrtype + "[" + itos(array.call("size")) + "]");
+
+#ifdef TOOLS_ENABLED
+
+ bool unfolded = get_edited_object()->editor_is_section_unfolded(get_edited_property());
+ if (edit->is_pressed() != unfolded) {
+ edit->set_pressed(unfolded);
+ }
+
+ if (unfolded) {
+
+ updating = true;
+
+ if (!vbox) {
+
+ vbox = memnew(VBoxContainer);
+ add_child(vbox);
+ set_bottom_editor(vbox);
+ HBoxContainer *hbc = memnew(HBoxContainer);
+ vbox->add_child(hbc);
+ Label *label = memnew(Label(TTR("Size: ")));
+ label->set_h_size_flags(SIZE_EXPAND_FILL);
+ hbc->add_child(label);
+ length = memnew(EditorSpinSlider);
+ length->set_step(1);
+ length->set_max(1000000);
+ length->set_h_size_flags(SIZE_EXPAND_FILL);
+ hbc->add_child(length);
+ length->connect("value_changed", this, "_length_changed");
+
+ page_hb = memnew(HBoxContainer);
+ vbox->add_child(page_hb);
+ label = memnew(Label(TTR("Page: ")));
+ label->set_h_size_flags(SIZE_EXPAND_FILL);
+ page_hb->add_child(label);
+ page = memnew(EditorSpinSlider);
+ page->set_step(1);
+ page_hb->add_child(page);
+ page->set_h_size_flags(SIZE_EXPAND_FILL);
+ page->connect("value_changed", this, "_page_changed");
+ } else {
+ //bye bye children of the box
+ while (vbox->get_child_count() > 2) {
+ memdelete(vbox->get_child(2));
+ }
+ }
+
+ int len = array.call("size");
+
+ length->set_value(len);
+
+ int pages = MAX(0, len - 1) / page_len + 1;
+
+ page->set_max(pages);
+ page_idx = MIN(page_idx, pages - 1);
+ page->set_value(page_idx);
+ page_hb->set_visible(pages > 1);
+
+ int offset = page_idx * page_len;
+
+ int amount = MIN(len - offset, page_len);
+
+ if (array.get_type() == Variant::ARRAY) {
+ array = array.call("duplicate");
+ }
+
+ object->set_array(array);
+
+ for (int i = 0; i < amount; i++) {
+ String prop_name = "indices/" + itos(i + offset);
+
+ EditorProperty *prop = NULL;
+ Variant value = array.get(i + offset);
+
+ switch (value.get_type()) {
+ case Variant::NIL: {
+ prop = memnew(EditorPropertyNil);
+
+ } break;
+
+ // atomic types
+ case Variant::BOOL: {
+
+ prop = memnew(EditorPropertyCheck);
+
+ } break;
+ case Variant::INT: {
+ EditorPropertyInteger *ed = memnew(EditorPropertyInteger);
+ ed->setup(-100000, 100000, true, true);
+ prop = ed;
+
+ } break;
+ case Variant::REAL: {
+
+ EditorPropertyFloat *ed = memnew(EditorPropertyFloat);
+ ed->setup(-100000, 100000, 0.001, true, false, true, true);
+ prop = ed;
+ } break;
+ case Variant::STRING: {
+
+ prop = memnew(EditorPropertyText);
+
+ } break;
+
+ // math types
+
+ case Variant::VECTOR2: {
+
+ EditorPropertyVector2 *ed = memnew(EditorPropertyVector2);
+ ed->setup(-100000, 100000, 0.001, true);
+ prop = ed;
+
+ } break;
+ case Variant::RECT2: {
+
+ EditorPropertyRect2 *ed = memnew(EditorPropertyRect2);
+ ed->setup(-100000, 100000, 0.001, true);
+ prop = ed;
+
+ } break;
+ case Variant::VECTOR3: {
+
+ EditorPropertyVector3 *ed = memnew(EditorPropertyVector3);
+ ed->setup(-100000, 100000, 0.001, true);
+ prop = ed;
+
+ } break;
+ case Variant::TRANSFORM2D: {
+
+ EditorPropertyTransform2D *ed = memnew(EditorPropertyTransform2D);
+ ed->setup(-100000, 100000, 0.001, true);
+ prop = ed;
+
+ } break;
+ case Variant::PLANE: {
+
+ EditorPropertyPlane *ed = memnew(EditorPropertyPlane);
+ ed->setup(-100000, 100000, 0.001, true);
+ prop = ed;
+
+ } break;
+ case Variant::QUAT: {
+
+ EditorPropertyQuat *ed = memnew(EditorPropertyQuat);
+ ed->setup(-100000, 100000, 0.001, true);
+ prop = ed;
+
+ } break;
+ case Variant::AABB: {
+
+ EditorPropertyAABB *ed = memnew(EditorPropertyAABB);
+ ed->setup(-100000, 100000, 0.001, true);
+ prop = ed;
+
+ } break;
+ case Variant::BASIS: {
+ EditorPropertyBasis *ed = memnew(EditorPropertyBasis);
+ ed->setup(-100000, 100000, 0.001, true);
+ prop = ed;
+
+ } break;
+ case Variant::TRANSFORM: {
+ EditorPropertyTransform *ed = memnew(EditorPropertyTransform);
+ ed->setup(-100000, 100000, 0.001, true);
+ prop = ed;
+
+ } break;
+
+ // misc types
+ case Variant::COLOR: {
+ prop = memnew(EditorPropertyColor);
+
+ } break;
+ case Variant::NODE_PATH: {
+ prop = memnew(EditorPropertyNodePath);
+
+ } break;
+ case Variant::_RID: {
+ prop = memnew(EditorPropertyNil);
+
+ } break;
+ case Variant::OBJECT: {
+
+ prop = memnew(EditorPropertyResource);
+
+ } break;
+ case Variant::DICTIONARY: {
+ prop = memnew(EditorPropertyDictionary);
+
+ } break;
+ case Variant::ARRAY: {
+
+ prop = memnew(EditorPropertyArray);
+
+ } break;
+
+ // arrays
+ case Variant::POOL_BYTE_ARRAY: {
+ prop = memnew(EditorPropertyArray);
+
+ } break;
+ case Variant::POOL_INT_ARRAY: {
+ prop = memnew(EditorPropertyArray);
+
+ } break;
+ case Variant::POOL_REAL_ARRAY: {
+
+ prop = memnew(EditorPropertyArray);
+ } break;
+ case Variant::POOL_STRING_ARRAY: {
+
+ prop = memnew(EditorPropertyArray);
+ } break;
+ case Variant::POOL_VECTOR2_ARRAY: {
+
+ prop = memnew(EditorPropertyArray);
+ } break;
+ case Variant::POOL_VECTOR3_ARRAY: {
+ prop = memnew(EditorPropertyArray);
+
+ } break;
+ case Variant::POOL_COLOR_ARRAY: {
+ prop = memnew(EditorPropertyArray);
+
+ } break;
+ default: {}
+ }
+
+ prop->set_object_and_property(object.ptr(), prop_name);
+ prop->set_label(itos(i + offset));
+ prop->set_selectable(false);
+ prop->connect("property_changed", this, "_property_changed");
+ if (array.get_type() == Variant::ARRAY) {
+ HBoxContainer *hb = memnew(HBoxContainer);
+ vbox->add_child(hb);
+ hb->add_child(prop);
+ prop->set_h_size_flags(SIZE_EXPAND_FILL);
+ Button *edit = memnew(Button);
+ edit->set_icon(get_icon("Edit", "EditorIcons"));
+ hb->add_child(edit);
+ edit->connect("pressed", this, "_change_type", varray(edit, i + offset));
+ } else {
+ vbox->add_child(prop);
+ }
+
+ prop->update_property();
+ }
+
+ updating = false;
+
+ } else {
+ if (vbox) {
+ set_bottom_editor(NULL);
+ memdelete(vbox);
+ vbox = NULL;
+ }
+ }
+#endif
+}
+
+void EditorPropertyArray::_notification(int p_what) {
+
+ if (p_what == NOTIFICATION_ENTER_TREE || p_what == NOTIFICATION_THEME_CHANGED) {
+ }
+}
+void EditorPropertyArray::_edit_pressed() {
+
+ get_edited_object()->editor_set_section_unfold(get_edited_property(), edit->is_pressed());
+ update_property();
+}
+
+void EditorPropertyArray::_page_changed(double p_page) {
+ if (updating)
+ return;
+ page_idx = p_page;
+ update_property();
+}
+
+void EditorPropertyArray::_length_changed(double p_page) {
+ if (updating)
+ return;
+
+ Variant array = object->get_array();
+ array.call("resize", int(p_page));
+ emit_signal("property_changed", get_edited_property(), array);
+
+ if (array.get_type() == Variant::ARRAY) {
+ array = array.call("duplicate"); //dupe, so undo/redo works better
+ }
+ object->set_array(array);
+ update_property();
+}
+
+void EditorPropertyArray::_bind_methods() {
+ ClassDB::bind_method("_edit_pressed", &EditorPropertyArray::_edit_pressed);
+ ClassDB::bind_method("_page_changed", &EditorPropertyArray::_page_changed);
+ ClassDB::bind_method("_length_changed", &EditorPropertyArray::_length_changed);
+ ClassDB::bind_method("_property_changed", &EditorPropertyArray::_property_changed);
+ ClassDB::bind_method("_change_type", &EditorPropertyArray::_change_type);
+ ClassDB::bind_method("_change_type_menu", &EditorPropertyArray::_change_type_menu);
+}
+
+EditorPropertyArray::EditorPropertyArray() {
+
+ object.instance();
+ page_idx = 0;
+ page_len = 10;
+ edit = memnew(Button);
+ edit->set_flat(true);
+ edit->set_h_size_flags(SIZE_EXPAND_FILL);
+ edit->set_clip_text(true);
+ edit->connect("pressed", this, "_edit_pressed");
+ edit->set_toggle_mode(true);
+ add_child(edit);
+ add_focusable(edit);
+ vbox = NULL;
+ page = NULL;
+ length = NULL;
+ updating = false;
+ change_type = memnew(PopupMenu);
+ add_child(change_type);
+ change_type->connect("id_pressed", this, "_change_type_menu");
+ changing_type_idx = -1;
+ for (int i = 0; i < Variant::VARIANT_MAX; i++) {
+ String type = Variant::get_type_name(Variant::Type(i));
+ change_type->add_item(type, i);
+ }
+ changing_type_idx = -1;
+}
+
+///////////////////// DICTIONARY ///////////////////////////
+
+void EditorPropertyDictionary::_property_changed(const String &p_prop, Variant p_value) {
+
+ if (p_prop == "new_item_key") {
+
+ object->set_new_item_key(p_value);
+ } else if (p_prop == "new_item_value") {
+
+ object->set_new_item_value(p_value);
+ } else if (p_prop.begins_with("indices")) {
+ int idx = p_prop.get_slice("/", 1).to_int();
+ Dictionary dict = object->get_dict();
+ Variant key = dict.get_key_at_index(idx);
+ dict[key] = p_value;
+
+ emit_signal("property_changed", get_edited_property(), dict);
+
+ dict = dict.duplicate(); //dupe, so undo/redo works better
+ object->set_dict(dict);
+ }
+}
+
+void EditorPropertyDictionary::_change_type(Object *p_button, int p_index) {
+
+ Button *button = Object::cast_to<Button>(p_button);
+
+ Rect2 rect = button->get_global_rect();
+ change_type->set_as_minsize();
+ change_type->set_global_position(rect.position + rect.size - Vector2(change_type->get_combined_minimum_size().x, 0));
+ change_type->popup();
+ changing_type_idx = p_index;
+}
+
+void EditorPropertyDictionary::_add_key_value() {
+
+ Dictionary dict = object->get_dict();
+ dict[object->get_new_item_key()] = object->get_new_item_value();
+ object->set_new_item_key(Variant());
+ object->set_new_item_value(Variant());
+
+ emit_signal("property_changed", get_edited_property(), dict);
+
+ dict = dict.duplicate(); //dupe, so undo/redo works better
+ object->set_dict(dict);
+ update_property();
+}
+
+void EditorPropertyDictionary::_change_type_menu(int p_index) {
+
+ if (changing_type_idx < 0) {
+ Variant value;
+ Variant::CallError ce;
+ value = Variant::construct(Variant::Type(p_index), NULL, 0, ce);
+ if (changing_type_idx == -1) {
+ object->set_new_item_key(value);
+ } else {
+ object->set_new_item_value(value);
+ }
+ update_property();
+ return;
+ }
+
+ Dictionary dict = object->get_dict();
+
+ if (p_index < Variant::VARIANT_MAX) {
+
+ Variant value;
+ Variant::CallError ce;
+ value = Variant::construct(Variant::Type(p_index), NULL, 0, ce);
+ Variant key = dict.get_key_at_index(changing_type_idx);
+ dict[key] = value;
+ } else {
+ Variant key = dict.get_key_at_index(changing_type_idx);
+ dict.erase(key);
+ }
+
+ emit_signal("property_changed", get_edited_property(), dict);
+
+ dict = dict.duplicate(); //dupe, so undo/redo works better
+ object->set_dict(dict);
+ update_property();
+}
+
+void EditorPropertyDictionary::update_property() {
+
+ Dictionary dict = get_edited_object()->get(get_edited_property());
+
+ edit->set_text("Dict[" + itos(dict.size()) + "]");
+
+#ifdef TOOLS_ENABLED
+
+ bool unfolded = get_edited_object()->editor_is_section_unfolded(get_edited_property());
+ if (edit->is_pressed() != unfolded) {
+ edit->set_pressed(unfolded);
+ }
+
+ if (unfolded) {
+
+ updating = true;
+
+ if (!vbox) {
+
+ vbox = memnew(VBoxContainer);
+ add_child(vbox);
+ set_bottom_editor(vbox);
+
+ page_hb = memnew(HBoxContainer);
+ vbox->add_child(page_hb);
+ Label *label = memnew(Label(TTR("Page: ")));
+ label->set_h_size_flags(SIZE_EXPAND_FILL);
+ page_hb->add_child(label);
+ page = memnew(EditorSpinSlider);
+ page->set_step(1);
+ page_hb->add_child(page);
+ page->set_h_size_flags(SIZE_EXPAND_FILL);
+ page->connect("value_changed", this, "_page_changed");
+ } else {
+ //bye bye children of the box
+ while (vbox->get_child_count() > 1) {
+ memdelete(vbox->get_child(1));
+ }
+ }
+
+ int len = dict.size();
+
+ int pages = MAX(0, len - 1) / page_len + 1;
+
+ page->set_max(pages);
+ page_idx = MIN(page_idx, pages - 1);
+ page->set_value(page_idx);
+ page_hb->set_visible(pages > 1);
+
+ int offset = page_idx * page_len;
+
+ int amount = MIN(len - offset, page_len);
+
+ dict = dict.duplicate();
+
+ object->set_dict(dict);
+ VBoxContainer *add_vbox = NULL;
+
+ for (int i = 0; i < amount + 2; i++) {
+ String prop_name;
+ Variant key;
+ Variant value;
+
+ if (i < amount) {
+ prop_name = "indices/" + itos(i + offset);
+ key = dict.get_key_at_index(i + offset);
+ value = dict.get_value_at_index(i + offset);
+ } else if (i == amount) {
+ prop_name = "new_item_key";
+ value = object->get_new_item_key();
+ } else if (i == amount + 1) {
+ prop_name = "new_item_value";
+ value = object->get_new_item_value();
+ }
+
+ EditorProperty *prop = NULL;
+
+ switch (value.get_type()) {
+ case Variant::NIL: {
+ prop = memnew(EditorPropertyNil);
+
+ } break;
+
+ // atomic types
+ case Variant::BOOL: {
+
+ prop = memnew(EditorPropertyCheck);
+
+ } break;
+ case Variant::INT: {
+ EditorPropertyInteger *ed = memnew(EditorPropertyInteger);
+ ed->setup(-100000, 100000, true, true);
+ prop = ed;
+
+ } break;
+ case Variant::REAL: {
+
+ EditorPropertyFloat *ed = memnew(EditorPropertyFloat);
+ ed->setup(-100000, 100000, 0.001, true, false, true, true);
+ prop = ed;
+ } break;
+ case Variant::STRING: {
+
+ prop = memnew(EditorPropertyText);
+
+ } break;
+
+ // math types
+
+ case Variant::VECTOR2: {
+
+ EditorPropertyVector2 *ed = memnew(EditorPropertyVector2);
+ ed->setup(-100000, 100000, 0.001, true);
+ prop = ed;
+
+ } break;
+ case Variant::RECT2: {
+
+ EditorPropertyRect2 *ed = memnew(EditorPropertyRect2);
+ ed->setup(-100000, 100000, 0.001, true);
+ prop = ed;
+
+ } break;
+ case Variant::VECTOR3: {
+
+ EditorPropertyVector3 *ed = memnew(EditorPropertyVector3);
+ ed->setup(-100000, 100000, 0.001, true);
+ prop = ed;
+
+ } break;
+ case Variant::TRANSFORM2D: {
+
+ EditorPropertyTransform2D *ed = memnew(EditorPropertyTransform2D);
+ ed->setup(-100000, 100000, 0.001, true);
+ prop = ed;
+
+ } break;
+ case Variant::PLANE: {
+
+ EditorPropertyPlane *ed = memnew(EditorPropertyPlane);
+ ed->setup(-100000, 100000, 0.001, true);
+ prop = ed;
+
+ } break;
+ case Variant::QUAT: {
+
+ EditorPropertyQuat *ed = memnew(EditorPropertyQuat);
+ ed->setup(-100000, 100000, 0.001, true);
+ prop = ed;
+
+ } break;
+ case Variant::AABB: {
+
+ EditorPropertyAABB *ed = memnew(EditorPropertyAABB);
+ ed->setup(-100000, 100000, 0.001, true);
+ prop = ed;
+
+ } break;
+ case Variant::BASIS: {
+ EditorPropertyBasis *ed = memnew(EditorPropertyBasis);
+ ed->setup(-100000, 100000, 0.001, true);
+ prop = ed;
+
+ } break;
+ case Variant::TRANSFORM: {
+ EditorPropertyTransform *ed = memnew(EditorPropertyTransform);
+ ed->setup(-100000, 100000, 0.001, true);
+ prop = ed;
+
+ } break;
+
+ // misc types
+ case Variant::COLOR: {
+ prop = memnew(EditorPropertyColor);
+
+ } break;
+ case Variant::NODE_PATH: {
+ prop = memnew(EditorPropertyNodePath);
+
+ } break;
+ case Variant::_RID: {
+ prop = memnew(EditorPropertyNil);
+
+ } break;
+ case Variant::OBJECT: {
+
+ prop = memnew(EditorPropertyResource);
+
+ } break;
+ case Variant::DICTIONARY: {
+ prop = memnew(EditorPropertyDictionary);
+
+ } break;
+ case Variant::ARRAY: {
+
+ prop = memnew(EditorPropertyArray);
+
+ } break;
+
+ // arrays
+ case Variant::POOL_BYTE_ARRAY: {
+ prop = memnew(EditorPropertyArray);
+
+ } break;
+ case Variant::POOL_INT_ARRAY: {
+ prop = memnew(EditorPropertyArray);
+
+ } break;
+ case Variant::POOL_REAL_ARRAY: {
+
+ prop = memnew(EditorPropertyArray);
+ } break;
+ case Variant::POOL_STRING_ARRAY: {
+
+ prop = memnew(EditorPropertyArray);
+ } break;
+ case Variant::POOL_VECTOR2_ARRAY: {
+
+ prop = memnew(EditorPropertyArray);
+ } break;
+ case Variant::POOL_VECTOR3_ARRAY: {
+ prop = memnew(EditorPropertyArray);
+
+ } break;
+ case Variant::POOL_COLOR_ARRAY: {
+ prop = memnew(EditorPropertyArray);
+
+ } break;
+ default: {}
+ }
+
+ if (i == amount) {
+ PanelContainer *pc = memnew(PanelContainer);
+ vbox->add_child(pc);
+ Ref<StyleBoxFlat> flat;
+ flat.instance();
+ for (int j = 0; j < 4; j++) {
+ flat->set_default_margin(Margin(j), 2 * EDSCALE);
+ }
+ flat->set_bg_color(get_color("prop_subsection", "Editor"));
+
+ pc->add_style_override("panel", flat);
+ add_vbox = memnew(VBoxContainer);
+ pc->add_child(add_vbox);
+ }
+ prop->set_object_and_property(object.ptr(), prop_name);
+ int change_index;
+
+ if (i < amount) {
+ String cs = key.get_construct_string();
+ prop->set_label(key.get_construct_string());
+ prop->set_tooltip(cs);
+ change_index = i + offset;
+ } else if (i == amount) {
+ prop->set_label(TTR("New Key:"));
+ change_index = -1;
+ } else if (i == amount + 1) {
+ prop->set_label(TTR("New Value:"));
+ change_index = -2;
+ }
+
+ prop->set_selectable(false);
+ prop->connect("property_changed", this, "_property_changed");
+
+ HBoxContainer *hb = memnew(HBoxContainer);
+ if (add_vbox) {
+ add_vbox->add_child(hb);
+ } else {
+ vbox->add_child(hb);
+ }
+ hb->add_child(prop);
+ prop->set_h_size_flags(SIZE_EXPAND_FILL);
+ Button *edit = memnew(Button);
+ edit->set_icon(get_icon("Edit", "EditorIcons"));
+ hb->add_child(edit);
+ edit->connect("pressed", this, "_change_type", varray(edit, change_index));
+
+ prop->update_property();
+
+ if (i == amount + 1) {
+ Button *add_item = memnew(Button);
+ add_item->set_text(TTR("Add Key/Value Pair"));
+ add_vbox->add_child(add_item);
+ add_item->connect("pressed", this, "_add_key_value");
+ }
+ }
+
+ updating = false;
+
+ } else {
+ if (vbox) {
+ set_bottom_editor(NULL);
+ memdelete(vbox);
+ vbox = NULL;
+ }
+ }
+#endif
+}
+
+void EditorPropertyDictionary::_notification(int p_what) {
+
+ if (p_what == NOTIFICATION_ENTER_TREE || p_what == NOTIFICATION_THEME_CHANGED) {
+ }
+}
+void EditorPropertyDictionary::_edit_pressed() {
+
+ get_edited_object()->editor_set_section_unfold(get_edited_property(), edit->is_pressed());
+ update_property();
+}
+
+void EditorPropertyDictionary::_page_changed(double p_page) {
+ if (updating)
+ return;
+ page_idx = p_page;
+ update_property();
+}
+
+void EditorPropertyDictionary::_bind_methods() {
+ ClassDB::bind_method("_edit_pressed", &EditorPropertyDictionary::_edit_pressed);
+ ClassDB::bind_method("_page_changed", &EditorPropertyDictionary::_page_changed);
+ ClassDB::bind_method("_property_changed", &EditorPropertyDictionary::_property_changed);
+ ClassDB::bind_method("_change_type", &EditorPropertyDictionary::_change_type);
+ ClassDB::bind_method("_change_type_menu", &EditorPropertyDictionary::_change_type_menu);
+ ClassDB::bind_method("_add_key_value", &EditorPropertyDictionary::_add_key_value);
+}
+
+EditorPropertyDictionary::EditorPropertyDictionary() {
+
+ object.instance();
+ page_idx = 0;
+ page_len = 10;
+ edit = memnew(Button);
+ edit->set_flat(true);
+ edit->set_h_size_flags(SIZE_EXPAND_FILL);
+ edit->set_clip_text(true);
+ edit->connect("pressed", this, "_edit_pressed");
+ edit->set_toggle_mode(true);
+ add_child(edit);
+ add_focusable(edit);
+ vbox = NULL;
+ page = NULL;
+ updating = false;
+ change_type = memnew(PopupMenu);
+ add_child(change_type);
+ change_type->connect("id_pressed", this, "_change_type_menu");
+ changing_type_idx = -1;
+ for (int i = 0; i < Variant::VARIANT_MAX; i++) {
+ String type = Variant::get_type_name(Variant::Type(i));
+ change_type->add_item(type, i);
+ }
+ change_type->add_separator();
+ change_type->add_item(TTR("Remove Item"), Variant::VARIANT_MAX);
+ changing_type_idx = -1;
+}
diff --git a/editor/editor_properties_array_dict.h b/editor/editor_properties_array_dict.h
new file mode 100644
index 0000000000..7f6203ee88
--- /dev/null
+++ b/editor/editor_properties_array_dict.h
@@ -0,0 +1,115 @@
+#ifndef EDITOR_PROPERTIES_ARRAY_DICT_H
+#define EDITOR_PROPERTIES_ARRAY_DICT_H
+
+#include "editor/editor_inspector.h"
+#include "editor/editor_spin_slider.h"
+#include "scene/gui/button.h"
+
+class EditorPropertyArrayObject : public Reference {
+
+ GDCLASS(EditorPropertyArrayObject, Reference);
+
+ Variant array;
+
+protected:
+ bool _set(const StringName &p_name, const Variant &p_value);
+ bool _get(const StringName &p_name, Variant &r_ret) const;
+
+public:
+ void set_array(const Variant &p_array);
+ Variant get_array();
+
+ EditorPropertyArrayObject();
+};
+
+class EditorPropertyDictionaryObject : public Reference {
+
+ GDCLASS(EditorPropertyDictionaryObject, Reference);
+
+ Variant new_item_key;
+ Variant new_item_value;
+ Dictionary dict;
+
+protected:
+ bool _set(const StringName &p_name, const Variant &p_value);
+ bool _get(const StringName &p_name, Variant &r_ret) const;
+
+public:
+ void set_dict(const Dictionary &p_dict);
+ Dictionary get_dict();
+
+ void set_new_item_key(const Variant &p_new_item);
+ Variant get_new_item_key();
+
+ void set_new_item_value(const Variant &p_new_item);
+ Variant get_new_item_value();
+
+ EditorPropertyDictionaryObject();
+};
+
+class EditorPropertyArray : public EditorProperty {
+ GDCLASS(EditorPropertyArray, EditorProperty)
+
+ PopupMenu *change_type;
+ bool updating;
+
+ Ref<EditorPropertyArrayObject> object;
+ int page_len;
+ int page_idx;
+ int changing_type_idx;
+ Button *edit;
+ VBoxContainer *vbox;
+ EditorSpinSlider *length;
+ EditorSpinSlider *page;
+ HBoxContainer *page_hb;
+
+ void _page_changed(double p_page);
+ void _length_changed(double p_page);
+ void _edit_pressed();
+ void _property_changed(const String &p_prop, Variant p_value);
+ void _change_type(Object *p_button, int p_index);
+ void _change_type_menu(int p_index);
+
+protected:
+ static void _bind_methods();
+ void _notification(int p_what);
+
+public:
+ virtual void update_property();
+ EditorPropertyArray();
+};
+
+class EditorPropertyDictionary : public EditorProperty {
+ GDCLASS(EditorPropertyDictionary, EditorProperty)
+
+ PopupMenu *change_type;
+ bool updating;
+
+ Ref<EditorPropertyDictionaryObject> object;
+ int page_len;
+ int page_idx;
+ int changing_type_idx;
+ Button *edit;
+ VBoxContainer *vbox;
+ EditorSpinSlider *length;
+ EditorSpinSlider *page;
+ HBoxContainer *page_hb;
+
+ void _page_changed(double p_page);
+ void _edit_pressed();
+ void _property_changed(const String &p_prop, Variant p_value);
+ void _change_type(Object *p_button, int p_index);
+ void _change_type_menu(int p_index);
+
+ void _add_key_value();
+
+protected:
+ static void _bind_methods();
+ void _notification(int p_what);
+
+public:
+ virtual void update_property();
+ EditorPropertyDictionary();
+};
+
+#endif // EDITOR_PROPERTIES_ARRAY_DICT_H
diff --git a/editor/editor_settings.cpp b/editor/editor_settings.cpp
index fe0392334c..a47605be15 100644
--- a/editor/editor_settings.cpp
+++ b/editor/editor_settings.cpp
@@ -1151,7 +1151,7 @@ void EditorSettings::set_project_metadata(const String &p_section, const String
cf->save(path);
}
-Variant EditorSettings::get_project_metadata(const String &p_section, const String &p_key, Variant p_default) {
+Variant EditorSettings::get_project_metadata(const String &p_section, const String &p_key, Variant p_default) const {
Ref<ConfigFile> cf = memnew(ConfigFile);
String path = get_project_settings_dir().plus_file("project_metadata.cfg");
Error err = cf->load(path);
@@ -1493,6 +1493,9 @@ void EditorSettings::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_settings_dir"), &EditorSettings::get_settings_dir);
ClassDB::bind_method(D_METHOD("get_project_settings_dir"), &EditorSettings::get_project_settings_dir);
+ ClassDB::bind_method(D_METHOD("set_project_metadata", "section", "key", "data"), &EditorSettings::set_project_metadata);
+ ClassDB::bind_method(D_METHOD("get_project_metadata", "section", "key", "default"), &EditorSettings::get_project_metadata, DEFVAL(Variant()));
+
ClassDB::bind_method(D_METHOD("set_favorite_dirs", "dirs"), &EditorSettings::set_favorite_dirs);
ClassDB::bind_method(D_METHOD("get_favorite_dirs"), &EditorSettings::get_favorite_dirs);
ClassDB::bind_method(D_METHOD("set_recent_dirs", "dirs"), &EditorSettings::set_recent_dirs);
diff --git a/editor/editor_settings.h b/editor/editor_settings.h
index e196ca506e..b48aac89c7 100644
--- a/editor/editor_settings.h
+++ b/editor/editor_settings.h
@@ -167,7 +167,7 @@ public:
String get_cache_dir() const;
void set_project_metadata(const String &p_section, const String &p_key, Variant p_data);
- Variant get_project_metadata(const String &p_section, const String &p_key, Variant p_default);
+ Variant get_project_metadata(const String &p_section, const String &p_key, Variant p_default) const;
void set_favorite_dirs(const Vector<String> &p_favorites_dirs);
Vector<String> get_favorite_dirs() const;
diff --git a/editor/editor_spin_slider.cpp b/editor/editor_spin_slider.cpp
index 9764364273..087dcd649f 100644
--- a/editor/editor_spin_slider.cpp
+++ b/editor/editor_spin_slider.cpp
@@ -1,3 +1,33 @@
+/*************************************************************************/
+/* editor_spin_slider.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_spin_slider.h"
#include "editor_scale.h"
#include "os/input.h"
diff --git a/editor/editor_spin_slider.h b/editor/editor_spin_slider.h
index ac8d9e15d6..4956990dc2 100644
--- a/editor/editor_spin_slider.h
+++ b/editor/editor_spin_slider.h
@@ -1,3 +1,33 @@
+/*************************************************************************/
+/* editor_spin_slider.h */
+/*************************************************************************/
+/* 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. */
+/*************************************************************************/
+
#ifndef EDITOR_SPIN_SLIDER_H
#define EDITOR_SPIN_SLIDER_H
diff --git a/editor/filesystem_dock.cpp b/editor/filesystem_dock.cpp
index e7741c7926..297373d299 100644
--- a/editor/filesystem_dock.cpp
+++ b/editor/filesystem_dock.cpp
@@ -383,11 +383,11 @@ void FileSystemDock::_update_file_display_toggle_button() {
if (button_display_mode->is_pressed()) {
display_mode = DISPLAY_LIST;
button_display_mode->set_icon(get_icon("FileThumbnail", "EditorIcons"));
- button_display_mode->set_tooltip(TTR("View items as a grid of thumbnails"));
+ button_display_mode->set_tooltip(TTR("View items as a grid of thumbnails."));
} else {
display_mode = DISPLAY_THUMBNAILS;
button_display_mode->set_icon(get_icon("FileList", "EditorIcons"));
- button_display_mode->set_tooltip(TTR("View items as a list"));
+ button_display_mode->set_tooltip(TTR("View items as a list."));
}
}
@@ -1860,7 +1860,7 @@ FileSystemDock::FileSystemDock(EditorNode *p_editor) {
button_favorite->set_flat(true);
button_favorite->set_toggle_mode(true);
button_favorite->connect("pressed", this, "_favorites_pressed");
- button_favorite->set_tooltip(TTR("Toggle folder status as Favorite"));
+ button_favorite->set_tooltip(TTR("Toggle folder status as Favorite."));
button_favorite->set_focus_mode(FOCUS_NONE);
toolbar_hbc->add_child(button_favorite);
@@ -1916,11 +1916,13 @@ FileSystemDock::FileSystemDock(EditorNode *p_editor) {
file_list_vb->add_child(path_hb);
button_tree = memnew(ToolButton);
+ button_tree->set_tooltip(TTR("Enter tree-view."));
button_tree->hide();
path_hb->add_child(button_tree);
search_box = memnew(LineEdit);
search_box->set_h_size_flags(SIZE_EXPAND_FILL);
+ search_box->set_placeholder(TTR("Search files"));
search_box->connect("text_changed", this, "_search_changed");
path_hb->add_child(search_box);
diff --git a/editor/find_in_files.cpp b/editor/find_in_files.cpp
index 74ea46838b..004a49e2b4 100644
--- a/editor/find_in_files.cpp
+++ b/editor/find_in_files.cpp
@@ -109,6 +109,7 @@ void FindInFiles::start() {
_current_dir = "";
PoolStringArray init_folder;
init_folder.append(_root_dir);
+ _folders_stack.clear();
_folders_stack.push_back(init_folder);
_initial_files_count = 0;
@@ -127,11 +128,12 @@ void FindInFiles::_process() {
// This part can be moved to a thread if needed
OS &os = *OS::get_singleton();
- float duration = 0.0;
- while (duration < 1.0 / 120.0) {
- float time_before = os.get_ticks_msec();
+ float time_before = os.get_ticks_msec();
+ while (is_processing()) {
_iterate();
- duration += (os.get_ticks_msec() - time_before);
+ float elapsed = (os.get_ticks_msec() - time_before);
+ if (elapsed > 1000.0 / 120.0)
+ break;
}
}
@@ -428,6 +430,7 @@ FindInFilesDialog::FindInFilesDialog() {
void FindInFilesDialog::set_search_text(String text) {
_search_text_line_edit->set_text(text);
+ _on_search_text_modified(text);
}
String FindInFilesDialog::get_search_text() const {
diff --git a/editor/groups_editor.cpp b/editor/groups_editor.cpp
index 8443311a54..e42f9780a6 100644
--- a/editor/groups_editor.cpp
+++ b/editor/groups_editor.cpp
@@ -286,6 +286,9 @@ void GroupDialog::_notification(int p_what) {
case NOTIFICATION_ENTER_TREE: {
add_button->set_icon(get_icon("Forward", "EditorIcons"));
remove_button->set_icon(get_icon("Back", "EditorIcons"));
+
+ add_filter->add_icon_override("right_icon", get_icon("Search", "EditorIcons"));
+ remove_filter->add_icon_override("right_icon", get_icon("Search", "EditorIcons"));
} break;
}
}
diff --git a/editor/icons/icon_oriented_path_follow.svg b/editor/icons/icon_oriented_path_follow.svg
new file mode 100644
index 0000000000..bd3f585e54
--- /dev/null
+++ b/editor/icons/icon_oriented_path_follow.svg
@@ -0,0 +1,5 @@
+<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
+<g transform="translate(0 -1036.4)">
+<path transform="translate(0 1036.4)" d="m13 0l-3 4h1.9473c-0.1385 1.3203-0.5583 1.9074-1.084 2.2754-0.64426 0.451-1.7129 0.60547-2.9629 0.73047s-2.6814 0.22053-3.9121 1.082c-0.89278 0.62493-1.5321 1.6522-1.8184 3.0957a2 2 0 0 0 -1.1699 1.8164 2 2 0 0 0 2 2 2 2 0 0 0 2 -2 2 2 0 0 0 -0.84961 -1.6328c0.19235-0.88496 0.55306-1.3373 0.98633-1.6406 0.64426-0.451 1.7129-0.60547 2.9629-0.73047s2.6814-0.22053 3.9121-1.082c1.0528-0.73697 1.7552-2.032 1.9375-3.9141h2.0508l-3-4z" fill="#fc9c9c" fill-opacity=".99608"/>
+</g>
+</svg>
diff --git a/editor/import/editor_import_collada.cpp b/editor/import/editor_import_collada.cpp
index 1d7545f182..2fb3bf7b1e 100644
--- a/editor/import/editor_import_collada.cpp
+++ b/editor/import/editor_import_collada.cpp
@@ -339,7 +339,7 @@ Error ColladaImport::_create_scene(Collada::Node *p_node, Spatial *p_parent) {
NodeMap nm;
nm.node = node;
node_map[p_node->id] = nm;
- node_name_map[p_node->name] = p_node->id;
+ node_name_map[node->get_name()] = p_node->id;
Transform xf = p_node->default_transform;
xf = collada.fix_transform(xf) * p_node->post_transform;
diff --git a/editor/import/resource_importer_bitmask.cpp b/editor/import/resource_importer_bitmask.cpp
index a5d3959952..7b330936f6 100644
--- a/editor/import/resource_importer_bitmask.cpp
+++ b/editor/import/resource_importer_bitmask.cpp
@@ -1,3 +1,33 @@
+/*************************************************************************/
+/* resource_importer_bitmask.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 "resource_importer_bitmask.h"
#include "core/image.h"
#include "editor/editor_file_system.h"
diff --git a/editor/import/resource_importer_bitmask.h b/editor/import/resource_importer_bitmask.h
index 8a3cafa7ce..f3537df819 100644
--- a/editor/import/resource_importer_bitmask.h
+++ b/editor/import/resource_importer_bitmask.h
@@ -1,3 +1,33 @@
+/*************************************************************************/
+/* resource_importer_bitmask.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. */
+/*************************************************************************/
+
#ifndef RESOURCE_IMPORTER_BITMASK_H
#define RESOURCE_IMPORTER_BITMASK_H
diff --git a/editor/import_dock.cpp b/editor/import_dock.cpp
index 128196be5a..f91802b352 100644
--- a/editor/import_dock.cpp
+++ b/editor/import_dock.cpp
@@ -407,6 +407,7 @@ ImportDock::ImportDock() {
set_name("Import");
imported = memnew(Label);
imported->add_style_override("normal", EditorNode::get_singleton()->get_gui_base()->get_stylebox("normal", "LineEdit"));
+ imported->set_clip_text(true);
add_child(imported);
HBoxContainer *hb = memnew(HBoxContainer);
add_margin_child(TTR("Import As:"), hb);
diff --git a/editor/inspector_dock.cpp b/editor/inspector_dock.cpp
new file mode 100644
index 0000000000..4159a3658e
--- /dev/null
+++ b/editor/inspector_dock.cpp
@@ -0,0 +1,564 @@
+/*************************************************************************/
+/* inspector_dock.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 "inspector_dock.h"
+
+#include "editor/editor_node.h"
+#include "editor/editor_settings.h"
+#include "editor/plugins/animation_player_editor_plugin.h"
+
+void InspectorDock::_menu_option(int p_option) {
+ switch (p_option) {
+ case RESOURCE_SAVE: {
+ _save_resource(false);
+ } break;
+ case RESOURCE_SAVE_AS: {
+ _save_resource(true);
+ } break;
+
+ case OBJECT_REQUEST_HELP: {
+ if (current) {
+ editor->set_visible_editor(EditorNode::EDITOR_SCRIPT);
+ emit_signal("request_help", current->get_class());
+ }
+ } break;
+
+ case OBJECT_COPY_PARAMS: {
+ editor_data->apply_changes_in_editors();
+ if (current)
+ editor_data->copy_object_params(current);
+ } break;
+
+ case OBJECT_PASTE_PARAMS: {
+ editor_data->apply_changes_in_editors();
+ if (current)
+ editor_data->paste_object_params(current);
+ editor_data->get_undo_redo().clear_history();
+ } break;
+
+ case OBJECT_UNIQUE_RESOURCES: {
+ editor_data->apply_changes_in_editors();
+ if (current) {
+ List<PropertyInfo> props;
+ current->get_property_list(&props);
+ Map<RES, RES> duplicates;
+ for (List<PropertyInfo>::Element *E = props.front(); E; E = E->next()) {
+
+ if (!(E->get().usage & PROPERTY_USAGE_STORAGE))
+ continue;
+
+ Variant v = current->get(E->get().name);
+ if (v.is_ref()) {
+ REF ref = v;
+ if (ref.is_valid()) {
+
+ RES res = ref;
+ if (res.is_valid()) {
+
+ if (!duplicates.has(res)) {
+ duplicates[res] = res->duplicate();
+ }
+ res = duplicates[res];
+
+ current->set(E->get().name, res);
+ }
+ }
+ }
+ }
+ }
+
+ editor_data->get_undo_redo().clear_history();
+
+ editor->get_editor_plugins_over()->edit(NULL);
+ editor->get_editor_plugins_over()->edit(current);
+
+ } break;
+
+ default: {
+ if (p_option >= OBJECT_METHOD_BASE) {
+ ERR_FAIL_COND(!current);
+
+ int idx = p_option - OBJECT_METHOD_BASE;
+
+ List<MethodInfo> methods;
+ current->get_method_list(&methods);
+
+ ERR_FAIL_INDEX(idx, methods.size());
+ String name = methods[idx].name;
+
+ if (current)
+ current->call(name);
+ }
+ }
+ }
+}
+
+void InspectorDock::_new_resource() {
+ new_resource_dialog->popup_create(true);
+}
+
+void InspectorDock::_load_resource(const String &p_type) {
+ load_resource_dialog->set_mode(EditorFileDialog::MODE_OPEN_FILE);
+
+ List<String> extensions;
+ ResourceLoader::get_recognized_extensions_for_type(p_type, &extensions);
+
+ load_resource_dialog->clear_filters();
+ for (int i = 0; i < extensions.size(); i++) {
+ load_resource_dialog->add_filter("*." + extensions[i] + " ; " + extensions[i].to_upper());
+ }
+
+ load_resource_dialog->popup_centered_ratio();
+}
+
+void InspectorDock::_resource_file_selected(String p_file) {
+ RES res = ResourceLoader::load(p_file);
+ if (res.is_null()) {
+ warning_dialog->get_ok()->set_text("Ugh");
+ warning_dialog->set_text(TTR("Failed to load resource."));
+ return;
+ };
+
+ editor->push_item(res.operator->());
+}
+
+void InspectorDock::_save_resource(bool save_as) const {
+ uint32_t current = EditorNode::get_singleton()->get_editor_history()->get_current();
+ Object *current_obj = current > 0 ? ObjectDB::get_instance(current) : NULL;
+
+ ERR_FAIL_COND(!Object::cast_to<Resource>(current_obj))
+
+ RES current_res = RES(Object::cast_to<Resource>(current_obj));
+
+ if (save_as)
+ editor->save_resource_as(current_res);
+ else
+ editor->save_resource(current_res);
+}
+
+void InspectorDock::_unref_resource() const {
+ uint32_t current = EditorNode::get_singleton()->get_editor_history()->get_current();
+ Object *current_obj = current > 0 ? ObjectDB::get_instance(current) : NULL;
+
+ ERR_FAIL_COND(!Object::cast_to<Resource>(current_obj))
+
+ RES current_res = RES(Object::cast_to<Resource>(current_obj));
+ current_res->set_path("");
+ editor->edit_current();
+}
+
+void InspectorDock::_copy_resource() const {
+ uint32_t current = EditorNode::get_singleton()->get_editor_history()->get_current();
+ Object *current_obj = current > 0 ? ObjectDB::get_instance(current) : NULL;
+
+ ERR_FAIL_COND(!Object::cast_to<Resource>(current_obj))
+
+ RES current_res = RES(Object::cast_to<Resource>(current_obj));
+
+ EditorSettings::get_singleton()->set_resource_clipboard(current_res);
+}
+
+void InspectorDock::_paste_resource() const {
+ RES r = EditorSettings::get_singleton()->get_resource_clipboard();
+ if (r.is_valid()) {
+ editor->push_item(EditorSettings::get_singleton()->get_resource_clipboard().ptr(), String());
+ }
+}
+
+void InspectorDock::_prepare_history() {
+ EditorHistory *editor_history = EditorNode::get_singleton()->get_editor_history();
+
+ int history_to = MAX(0, editor_history->get_history_len() - 25);
+
+ history_menu->get_popup()->clear();
+
+ Ref<Texture> base_icon = get_icon("Object", "EditorIcons");
+ Set<ObjectID> already;
+ for (int i = editor_history->get_history_len() - 1; i >= history_to; i--) {
+
+ ObjectID id = editor_history->get_history_obj(i);
+ Object *obj = ObjectDB::get_instance(id);
+ if (!obj || already.has(id)) {
+ if (history_to > 0) {
+ history_to--;
+ }
+ continue;
+ }
+
+ already.insert(id);
+
+ Ref<Texture> icon = get_icon("Object", "EditorIcons");
+ if (has_icon(obj->get_class(), "EditorIcons"))
+ icon = get_icon(obj->get_class(), "EditorIcons");
+ else
+ icon = base_icon;
+
+ String text;
+ if (Object::cast_to<Resource>(obj)) {
+ Resource *r = Object::cast_to<Resource>(obj);
+ if (r->get_path().is_resource_file())
+ text = r->get_path().get_file();
+ else if (r->get_name() != String()) {
+ text = r->get_name();
+ } else {
+ text = r->get_class();
+ }
+ } else if (Object::cast_to<Node>(obj)) {
+ text = Object::cast_to<Node>(obj)->get_name();
+ } else if (obj->is_class("ScriptEditorDebuggerInspectedObject")) {
+ text = obj->call("get_title");
+ } else {
+ text = obj->get_class();
+ }
+
+ if (i == editor_history->get_history_pos()) {
+ text = "[" + text + "]";
+ }
+ history_menu->get_popup()->add_icon_item(icon, text, i);
+ }
+}
+
+void InspectorDock::_select_history(int p_idx) const {
+ //push it to the top, it is not correct, but it's more useful
+ ObjectID id = EditorNode::get_singleton()->get_editor_history()->get_history_obj(p_idx);
+ Object *obj = ObjectDB::get_instance(id);
+ if (!obj)
+ return;
+ editor->push_item(obj);
+}
+
+void InspectorDock::_resource_created() const {
+ Object *c = new_resource_dialog->instance_selected();
+
+ ERR_FAIL_COND(!c);
+ Resource *r = Object::cast_to<Resource>(c);
+ ERR_FAIL_COND(!r);
+
+ REF res(r);
+ editor->push_item(c);
+}
+
+void InspectorDock::_resource_selected(const RES &p_res, const String &p_property) const {
+ if (p_res.is_null())
+ return;
+
+ RES r = p_res;
+ editor->push_item(r.operator->(), p_property);
+}
+
+void InspectorDock::_edit_forward() {
+ if (EditorNode::get_singleton()->get_editor_history()->next())
+ editor->edit_current();
+}
+void InspectorDock::_edit_back() {
+ EditorHistory *editor_history = EditorNode::get_singleton()->get_editor_history();
+ if (editor_history->previous() || editor_history->get_path_size() == 1)
+ editor->edit_current();
+}
+
+void InspectorDock::_menu_collapseall() {
+ inspector->collapse_all_folding();
+}
+
+void InspectorDock::_menu_expandall() {
+ inspector->expand_all_folding();
+}
+
+void InspectorDock::_property_keyed(const String &p_keyed, const Variant &p_value, bool p_advance) {
+ AnimationPlayerEditor::singleton->get_key_editor()->insert_value_key(p_keyed, p_value, p_advance);
+}
+
+void InspectorDock::_transform_keyed(Object *sp, const String &p_sub, const Transform &p_key) {
+ Spatial *s = Object::cast_to<Spatial>(sp);
+ if (!s)
+ return;
+ AnimationPlayerEditor::singleton->get_key_editor()->insert_transform_key(s, p_sub, p_key);
+}
+
+void InspectorDock::_warning_pressed() {
+ warning_dialog->get_ok()->set_text(TTR("Ok"));
+ warning_dialog->popup_centered_minsize();
+}
+
+Container *InspectorDock::get_addon_area() {
+ return this;
+}
+
+void InspectorDock::_bind_methods() {
+ ClassDB::bind_method("_menu_option", &InspectorDock::_menu_option);
+
+ ClassDB::bind_method("update_keying", &InspectorDock::update_keying);
+ ClassDB::bind_method("_property_keyed", &InspectorDock::_property_keyed);
+ ClassDB::bind_method("_transform_keyed", &InspectorDock::_transform_keyed);
+
+ ClassDB::bind_method("_new_resource", &InspectorDock::_new_resource);
+ ClassDB::bind_method("_resource_file_selected", &InspectorDock::_resource_file_selected);
+ ClassDB::bind_method("_open_resource_selector", &InspectorDock::_open_resource_selector);
+ ClassDB::bind_method("_unref_resource", &InspectorDock::_unref_resource);
+ ClassDB::bind_method("_paste_resource", &InspectorDock::_paste_resource);
+ ClassDB::bind_method("_copy_resource", &InspectorDock::_copy_resource);
+
+ ClassDB::bind_method("_select_history", &InspectorDock::_select_history);
+ ClassDB::bind_method("_prepare_history", &InspectorDock::_prepare_history);
+ ClassDB::bind_method("_resource_created", &InspectorDock::_resource_created);
+ ClassDB::bind_method("_resource_selected", &InspectorDock::_resource_selected, DEFVAL(""));
+ ClassDB::bind_method("_menu_collapseall", &InspectorDock::_menu_collapseall);
+ ClassDB::bind_method("_menu_expandall", &InspectorDock::_menu_expandall);
+ ClassDB::bind_method("_warning_pressed", &InspectorDock::_warning_pressed);
+ ClassDB::bind_method("_edit_forward", &InspectorDock::_edit_forward);
+ ClassDB::bind_method("_edit_back", &InspectorDock::_edit_back);
+
+ ADD_SIGNAL(MethodInfo("request_help"));
+}
+
+void InspectorDock::edit_resource(const Ref<Resource> &p_resource) {
+ _resource_selected(p_resource, "");
+}
+
+void InspectorDock::open_resource(const String &p_type) {
+ _load_resource(p_type);
+}
+
+void InspectorDock::set_warning(const String &p_message) {
+ warning->hide();
+ if (p_message != String()) {
+ warning->show();
+ warning_dialog->set_text(p_message);
+ }
+}
+
+void InspectorDock::clear() {
+}
+
+void InspectorDock::update(Object *p_object) {
+
+ EditorHistory *editor_history = EditorNode::get_singleton()->get_editor_history();
+ backward_button->set_disabled(editor_history->is_at_beginning());
+ forward_button->set_disabled(editor_history->is_at_end());
+
+ history_menu->set_disabled(true);
+ if (editor_history->get_history_len() > 0) {
+ history_menu->set_disabled(false);
+ }
+ editor_path->update_path();
+
+ current = p_object;
+
+ if (!p_object) {
+ object_menu->set_disabled(true);
+ warning->hide();
+ search->set_editable(false);
+
+ return;
+ }
+
+ bool is_resource = p_object->is_class("Resource");
+ bool is_node = p_object->is_class("Node");
+
+ object_menu->set_disabled(false);
+ search->set_editable(true);
+
+ PopupMenu *p = object_menu->get_popup();
+
+ p->clear();
+ p->add_shortcut(ED_SHORTCUT("property_editor/expand_all", TTR("Expand all properties")), EXPAND_ALL);
+ p->add_shortcut(ED_SHORTCUT("property_editor/collapse_all", TTR("Collapse all properties")), COLLAPSE_ALL);
+ p->add_separator();
+ if (is_resource) {
+ p->add_item(TTR("Save"), RESOURCE_SAVE);
+ p->add_item(TTR("Save As..."), RESOURCE_SAVE_AS);
+ p->add_separator();
+ }
+ p->add_shortcut(ED_SHORTCUT("property_editor/copy_params", TTR("Copy Params")), OBJECT_COPY_PARAMS);
+ p->add_shortcut(ED_SHORTCUT("property_editor/paste_params", TTR("Paste Params")), OBJECT_PASTE_PARAMS);
+ p->add_separator();
+ p->add_shortcut(ED_SHORTCUT("property_editor/paste_resource", TTR("Paste Resource")), RESOURCE_PASTE);
+ if (is_resource) {
+ p->add_shortcut(ED_SHORTCUT("property_editor/copy_resource", TTR("Copy Resource")), RESOURCE_COPY);
+ p->add_shortcut(ED_SHORTCUT("property_editor/unref_resource", TTR("Make Built-In")), RESOURCE_UNREF);
+ }
+
+ if (is_resource || is_node) {
+ p->add_separator();
+ p->add_shortcut(ED_SHORTCUT("property_editor/make_subresources_unique", TTR("Make Sub-Resources Unique")), OBJECT_UNIQUE_RESOURCES);
+ p->add_separator();
+ p->add_icon_shortcut(get_icon("HelpSearch", "EditorIcons"), ED_SHORTCUT("property_editor/open_help", TTR("Open in Help")), OBJECT_REQUEST_HELP);
+ }
+
+ List<MethodInfo> methods;
+ p_object->get_method_list(&methods);
+
+ if (!methods.empty()) {
+
+ bool found = false;
+ List<MethodInfo>::Element *I = methods.front();
+ int i = 0;
+ while (I) {
+
+ if (I->get().flags & METHOD_FLAG_EDITOR) {
+ if (!found) {
+ p->add_separator();
+ found = true;
+ }
+ p->add_item(I->get().name.capitalize(), OBJECT_METHOD_BASE + i);
+ }
+ i++;
+ I = I->next();
+ }
+ }
+}
+
+void InspectorDock::update_keying() {
+ bool valid = false;
+
+ if (AnimationPlayerEditor::singleton->get_key_editor()->has_keying()) {
+
+ EditorHistory *editor_history = EditorNode::get_singleton()->get_editor_history();
+ if (editor_history->get_path_size() >= 1) {
+
+ Object *obj = ObjectDB::get_instance(editor_history->get_path_object(0));
+ if (Object::cast_to<Node>(obj)) {
+
+ valid = true;
+ }
+ }
+ }
+
+ inspector->set_keying(valid);
+}
+
+InspectorDock::InspectorDock(EditorNode *p_editor, EditorData &p_editor_data) {
+ set_name("Inspector");
+ set_theme(p_editor->get_gui_base()->get_theme());
+
+ editor = p_editor;
+ editor_data = &p_editor_data;
+
+ HBoxContainer *general_options_hb = memnew(HBoxContainer);
+ add_child(general_options_hb);
+
+ resource_new_button = memnew(ToolButton);
+ resource_new_button->set_tooltip(TTR("Create a new resource in memory and edit it."));
+ resource_new_button->set_icon(get_icon("New", "EditorIcons"));
+ general_options_hb->add_child(resource_new_button);
+ resource_new_button->connect("pressed", this, "_new_resource");
+ resource_new_button->set_focus_mode(Control::FOCUS_NONE);
+
+ resource_load_button = memnew(ToolButton);
+ resource_load_button->set_tooltip(TTR("Load an existing resource from disk and edit it."));
+ resource_load_button->set_icon(get_icon("Load", "EditorIcons"));
+ general_options_hb->add_child(resource_load_button);
+ resource_load_button->connect("pressed", this, "_open_resource_selector");
+ resource_load_button->set_focus_mode(Control::FOCUS_NONE);
+
+ general_options_hb->add_spacer();
+
+ backward_button = memnew(ToolButton);
+ general_options_hb->add_child(backward_button);
+ backward_button->set_icon(get_icon("Back", "EditorIcons"));
+ backward_button->set_flat(true);
+ backward_button->set_tooltip(TTR("Go to the previous edited object in history."));
+ backward_button->set_disabled(true);
+ backward_button->connect("pressed", this, "_edit_back");
+
+ forward_button = memnew(ToolButton);
+ general_options_hb->add_child(forward_button);
+ forward_button->set_icon(get_icon("Forward", "EditorIcons"));
+ forward_button->set_flat(true);
+ forward_button->set_tooltip(TTR("Go to the next edited object in history."));
+ forward_button->set_disabled(true);
+ forward_button->connect("pressed", this, "_edit_forward");
+
+ history_menu = memnew(MenuButton);
+ history_menu->set_tooltip(TTR("History of recently edited objects."));
+ history_menu->set_icon(get_icon("History", "EditorIcons"));
+ general_options_hb->add_child(history_menu);
+ history_menu->connect("about_to_show", this, "_prepare_history");
+ history_menu->get_popup()->connect("id_pressed", this, "_select_history");
+
+ HBoxContainer *node_info_hb = memnew(HBoxContainer);
+ add_child(node_info_hb);
+
+ editor_path = memnew(EditorPath(editor->get_editor_history()));
+ editor_path->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+ node_info_hb->add_child(editor_path);
+
+ object_menu = memnew(MenuButton);
+ object_menu->set_icon(get_icon("Tools", "EditorIcons"));
+ node_info_hb->add_child(object_menu);
+ object_menu->set_tooltip(TTR("Object properties."));
+ object_menu->get_popup()->connect("id_pressed", this, "_menu_option");
+
+ new_resource_dialog = memnew(CreateDialog);
+ editor->get_gui_base()->add_child(new_resource_dialog);
+ new_resource_dialog->set_base_type("Resource");
+ new_resource_dialog->connect("create", this, "_resource_created");
+
+ search = memnew(LineEdit);
+ search->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+ search->set_placeholder(TTR("Filter properties"));
+ search->add_icon_override("right_icon", get_icon("Search", "EditorIcons"));
+ add_child(search);
+
+ warning = memnew(Button);
+ add_child(warning);
+ warning->set_text(TTR("Changes may be lost!"));
+ warning->set_icon(get_icon("NodeWarning", "EditorIcons"));
+ warning->hide();
+ warning->connect("pressed", this, "_warning_pressed");
+
+ warning_dialog = memnew(AcceptDialog);
+ editor->get_gui_base()->add_child(warning_dialog);
+
+ load_resource_dialog = memnew(EditorFileDialog);
+ add_child(load_resource_dialog);
+ load_resource_dialog->set_current_dir("res://");
+ load_resource_dialog->connect("file_selected", this, "_resource_file_selected");
+
+ inspector = memnew(EditorInspector);
+ add_child(inspector);
+ inspector->set_autoclear(true);
+ inspector->set_show_categories(true);
+ inspector->set_v_size_flags(Control::SIZE_EXPAND_FILL);
+ inspector->set_use_doc_hints(true);
+ inspector->set_hide_script(false);
+ inspector->set_enable_capitalize_paths(bool(EDITOR_DEF("interface/editor/capitalize_properties", true)));
+ inspector->set_use_folding(!bool(EDITOR_DEF("interface/editor/disable_inspector_folding", false)));
+ inspector->register_text_enter(search);
+ inspector->set_undo_redo(&editor_data->get_undo_redo());
+
+ inspector->set_use_filter(true); // TODO: check me
+
+ inspector->connect("resource_selected", this, "_resource_selected");
+ inspector->connect("property_keyed", this, "_property_keyed");
+}
+
+InspectorDock::~InspectorDock() {
+}
diff --git a/editor/inspector_dock.h b/editor/inspector_dock.h
new file mode 100644
index 0000000000..688c8beed7
--- /dev/null
+++ b/editor/inspector_dock.h
@@ -0,0 +1,137 @@
+/*************************************************************************/
+/* inspector_dock.h */
+/*************************************************************************/
+/* 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. */
+/*************************************************************************/
+
+#ifndef INSPECTOR_DOCK_H
+#define INSPECTOR_DOCK_H
+
+#include "editor/animation_editor.h"
+#include "editor/connections_dialog.h"
+#include "editor/create_dialog.h"
+#include "editor/editor_data.h"
+#include "editor/editor_inspector.h"
+#include "editor/editor_path.h"
+#include "scene/gui/box_container.h"
+#include "scene/gui/button.h"
+#include "scene/gui/control.h"
+#include "scene/gui/label.h"
+#include "scene/gui/popup_menu.h"
+#include "scene/gui/tool_button.h"
+
+class EditorNode;
+
+class InspectorDock : public VBoxContainer {
+
+ GDCLASS(InspectorDock, VBoxContainer);
+
+ enum MenuOptions {
+ RESOURCE_NEW,
+ RESOURCE_LOAD,
+ RESOURCE_SAVE,
+ RESOURCE_SAVE_AS,
+ RESOURCE_UNREF,
+ RESOURCE_COPY,
+ RESOURCE_PASTE,
+ OBJECT_COPY_PARAMS,
+ OBJECT_PASTE_PARAMS,
+ OBJECT_UNIQUE_RESOURCES,
+ OBJECT_REQUEST_HELP,
+
+ COLLAPSE_ALL,
+ EXPAND_ALL,
+
+ OBJECT_METHOD_BASE = 500
+ };
+
+ EditorNode *editor;
+ EditorData *editor_data;
+
+ EditorInspector *inspector;
+
+ Object *current;
+
+ ToolButton *backward_button;
+ ToolButton *forward_button;
+
+ EditorFileDialog *load_resource_dialog;
+ CreateDialog *new_resource_dialog;
+ ToolButton *resource_new_button;
+ ToolButton *resource_load_button;
+ MenuButton *resource_save_button;
+ MenuButton *history_menu;
+ LineEdit *search;
+
+ MenuButton *object_menu;
+ EditorPath *editor_path;
+
+ Button *warning;
+ AcceptDialog *warning_dialog;
+
+ void _menu_option(int p_option);
+
+ void _new_resource();
+ void _load_resource(const String &p_type = "");
+ void _open_resource_selector() { _load_resource(); }; // just used to call from arg-less signal
+ void _resource_file_selected(String p_file);
+ void _save_resource(bool save_as) const;
+ void _unref_resource() const;
+ void _copy_resource() const;
+ void _paste_resource() const;
+
+ void _warning_pressed();
+ void _resource_created() const;
+ void _resource_selected(const RES &p_res, const String &p_property = "") const;
+ void _edit_forward();
+ void _edit_back();
+ void _menu_collapseall();
+ void _menu_expandall();
+ void _select_history(int p_idx) const;
+ void _prepare_history();
+
+ void _property_keyed(const String &p_keyed, const Variant &p_value, bool p_advance);
+ void _transform_keyed(Object *sp, const String &p_sub, const Transform &p_key);
+
+protected:
+ static void _bind_methods();
+
+public:
+ void update_keying();
+ void edit_resource(const Ref<Resource> &p_resource);
+ void open_resource(const String &p_type);
+ void clear();
+ void set_warning(const String &p_message);
+ void update(Object *p_object);
+ Container *get_addon_area();
+ EditorInspector *get_inspector() { return inspector; }
+
+ InspectorDock(EditorNode *p_editor, EditorData &p_editor_data);
+ ~InspectorDock();
+};
+
+#endif
diff --git a/editor/plugins/asset_library_editor_plugin.cpp b/editor/plugins/asset_library_editor_plugin.cpp
index 0ff316a286..d595d4dd98 100644
--- a/editor/plugins/asset_library_editor_plugin.cpp
+++ b/editor/plugins/asset_library_editor_plugin.cpp
@@ -705,7 +705,18 @@ void EditorAssetLibrary::_image_update(bool use_cache, bool final, const PoolByt
int len = image_data.size();
PoolByteArray::Read r = image_data.read();
- Ref<Image> image = Ref<Image>(memnew(Image(r.ptr(), len)));
+ Ref<Image> image = Ref<Image>(memnew(Image));
+
+ uint8_t png_signature[8] = { 137, 80, 78, 71, 13, 10, 26, 10 };
+ uint8_t jpg_signature[3] = { 255, 216, 255 };
+
+ if (r.ptr()) {
+ if (memcmp(&r[0], &png_signature[0], 8) == 0) {
+ image->copy_internals_from(Image::_png_mem_loader_func(r.ptr(), len));
+ } else if (memcmp(&r[0], &jpg_signature[0], 3) == 0) {
+ image->copy_internals_from(Image::_jpg_mem_loader_func(r.ptr(), len));
+ }
+ }
if (!image->empty()) {
switch (image_queue[p_queue_id].image_type) {
@@ -750,7 +761,7 @@ void EditorAssetLibrary::_image_request_completed(int p_status, int p_code, cons
ERR_FAIL_COND(!image_queue.has(p_queue_id));
- if (p_status == HTTPRequest::RESULT_SUCCESS) {
+ if (p_status == HTTPRequest::RESULT_SUCCESS && p_code < HTTPClient::RESPONSE_BAD_REQUEST) {
if (p_code != HTTPClient::RESPONSE_NOT_MODIFIED) {
for (int i = 0; i < headers.size(); i++) {
@@ -781,7 +792,7 @@ void EditorAssetLibrary::_image_request_completed(int p_status, int p_code, cons
_image_update(p_code == HTTPClient::RESPONSE_NOT_MODIFIED, true, p_data, p_queue_id);
} else {
- WARN_PRINTS("Error getting PNG file from URL: " + image_queue[p_queue_id].image_url);
+ // WARN_PRINTS("Error getting image file from URL: " + image_queue[p_queue_id].image_url);
Object *obj = ObjectDB::get_instance(image_queue[p_queue_id].target);
if (obj) {
obj->call("set_image", image_queue[p_queue_id].image_type, image_queue[p_queue_id].image_index, get_icon("DefaultProjectIcon", "EditorIcons"));
@@ -936,41 +947,43 @@ HBoxContainer *EditorAssetLibrary::_make_pages(int p_page, int p_page_count, int
if (to > p_page_count)
to = p_page_count;
- Color gray = Color(0.65, 0.65, 0.65);
-
hbc->add_spacer();
- hbc->add_constant_override("separation", 10);
+ hbc->add_constant_override("separation", 5);
+ Button *first = memnew(Button);
+ first->set_text(TTR("First"));
if (p_page != 0) {
- LinkButton *first = memnew(LinkButton);
- first->set_text(TTR("first"));
- first->add_color_override("font_color", gray);
- first->set_underline_mode(LinkButton::UNDERLINE_MODE_ON_HOVER);
first->connect("pressed", this, "_search", varray(0));
- hbc->add_child(first);
+ } else {
+ first->set_disabled(true);
+ first->set_focus_mode(Control::FOCUS_NONE);
}
+ hbc->add_child(first);
+ Button *prev = memnew(Button);
+ prev->set_text(TTR("Previous"));
if (p_page > 0) {
- LinkButton *prev = memnew(LinkButton);
- prev->set_text(TTR("prev"));
- prev->add_color_override("font_color", gray);
- prev->set_underline_mode(LinkButton::UNDERLINE_MODE_ON_HOVER);
prev->connect("pressed", this, "_search", varray(p_page - 1));
- hbc->add_child(prev);
+ } else {
+ prev->set_disabled(true);
+ prev->set_focus_mode(Control::FOCUS_NONE);
}
+ hbc->add_child(prev);
+ hbc->add_child(memnew(VSeparator));
for (int i = from; i < to; i++) {
if (i == p_page) {
- Label *current = memnew(Label);
+ Button *current = memnew(Button);
current->set_text(itos(i + 1));
+ current->set_disabled(true);
+ current->set_focus_mode(Control::FOCUS_NONE);
+
hbc->add_child(current);
} else {
- LinkButton *current = memnew(LinkButton);
- current->add_color_override("font_color", gray);
- current->set_underline_mode(LinkButton::UNDERLINE_MODE_ON_HOVER);
+ Button *current = memnew(Button);
current->set_text(itos(i + 1));
current->connect("pressed", this, "_search", varray(i));
@@ -978,28 +991,26 @@ HBoxContainer *EditorAssetLibrary::_make_pages(int p_page, int p_page_count, int
}
}
+ Button *next = memnew(Button);
+ next->set_text(TTR("Next"));
if (p_page < p_page_count - 1) {
- LinkButton *next = memnew(LinkButton);
- next->set_text(TTR("next"));
- next->add_color_override("font_color", gray);
- next->set_underline_mode(LinkButton::UNDERLINE_MODE_ON_HOVER);
next->connect("pressed", this, "_search", varray(p_page + 1));
-
- hbc->add_child(next);
+ } else {
+ next->set_disabled(true);
+ next->set_focus_mode(Control::FOCUS_NONE);
}
+ hbc->add_child(memnew(VSeparator));
+ hbc->add_child(next);
+ Button *last = memnew(Button);
+ last->set_text(TTR("Last"));
if (p_page != p_page_count - 1) {
- LinkButton *last = memnew(LinkButton);
- last->set_text(TTR("last"));
- last->add_color_override("font_color", gray);
- last->set_underline_mode(LinkButton::UNDERLINE_MODE_ON_HOVER);
- hbc->add_child(last);
last->connect("pressed", this, "_search", varray(p_page_count - 1));
+ } else {
+ last->set_disabled(true);
+ last->set_focus_mode(Control::FOCUS_NONE);
}
-
- Label *totals = memnew(Label);
- totals->set_text("( " + itos(from * p_page_len) + " - " + itos(from * p_page_len + p_current_items - 1) + " / " + itos(p_total_items) + " )");
- hbc->add_child(totals);
+ hbc->add_child(last);
hbc->add_spacer();
diff --git a/editor/plugins/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp
index f27796db5e..ca5aa7039d 100644
--- a/editor/plugins/canvas_item_editor_plugin.cpp
+++ b/editor/plugins/canvas_item_editor_plugin.cpp
@@ -539,6 +539,88 @@ void CanvasItemEditor::_get_canvas_items_at_pos(const Point2 &p_pos, Vector<_Sel
}
}
+void CanvasItemEditor::_get_bones_at_pos(const Point2 &p_pos, Vector<_SelectResult> &r_items) {
+ Point2 screen_pos = transform.xform(p_pos);
+
+ for (Map<BoneKey, BoneList>::Element *E = bone_list.front(); E; E = E->next()) {
+ Node2D *from_node = Object::cast_to<Node2D>(ObjectDB::get_instance(E->key().from));
+ Node2D *to_node = Object::cast_to<Node2D>(ObjectDB::get_instance(E->key().to));
+
+ Vector<Vector2> bone_shape;
+ if (!_get_bone_shape(&bone_shape, NULL, E))
+ continue;
+
+ // Check if the point is inside the Polygon2D
+ if (Geometry::is_point_in_polygon(screen_pos, bone_shape)) {
+ // Check if the item is already in the list
+ bool duplicate = false;
+ for (int i = 0; i < r_items.size(); i++) {
+ if (r_items[i].item == from_node) {
+ duplicate = true;
+ break;
+ }
+ }
+ if (duplicate)
+ continue;
+
+ // Else, add it
+ _SelectResult res;
+ res.item = from_node;
+ res.z_index = from_node ? from_node->get_z_index() : 0;
+ res.has_z = from_node;
+ r_items.push_back(res);
+ }
+ }
+}
+
+bool CanvasItemEditor::_get_bone_shape(Vector<Vector2> *shape, Vector<Vector2> *outline_shape, Map<BoneKey, BoneList>::Element *bone) {
+ int bone_width = EditorSettings::get_singleton()->get("editors/2d/bone_width");
+ int bone_outline_width = EditorSettings::get_singleton()->get("editors/2d/bone_outline_size");
+
+ Node2D *from_node = Object::cast_to<Node2D>(ObjectDB::get_instance(bone->key().from));
+ Node2D *to_node = Object::cast_to<Node2D>(ObjectDB::get_instance(bone->key().to));
+
+ if (!from_node->is_inside_tree())
+ return false; //may have been removed
+ if (!from_node)
+ return false;
+
+ if (!to_node && bone->get().length == 0)
+ return false;
+
+ Vector2 from = transform.xform(from_node->get_global_position());
+ Vector2 to;
+
+ if (to_node)
+ to = transform.xform(to_node->get_global_position());
+ else
+ to = transform.xform(from_node->get_global_transform().xform(Vector2(bone->get().length, 0)));
+
+ Vector2 rel = to - from;
+ Vector2 relt = rel.tangent().normalized() * bone_width;
+ Vector2 reln = rel.normalized();
+ Vector2 reltn = relt.normalized();
+
+ if (shape) {
+ shape->clear();
+ shape->push_back(from);
+ shape->push_back(from + rel * 0.2 + relt);
+ shape->push_back(to);
+ shape->push_back(from + rel * 0.2 - relt);
+ }
+
+ if (outline_shape) {
+ outline_shape->clear();
+ outline_shape->push_back(from + (-reln - reltn) * bone_outline_width);
+ outline_shape->push_back(from + (-reln + reltn) * bone_outline_width);
+ outline_shape->push_back(from + rel * 0.2 + relt + reltn * bone_outline_width);
+ outline_shape->push_back(to + (reln + reltn) * bone_outline_width);
+ outline_shape->push_back(to + (reln - reltn) * bone_outline_width);
+ outline_shape->push_back(from + rel * 0.2 - relt - reltn * bone_outline_width);
+ }
+ return true;
+}
+
void CanvasItemEditor::_find_canvas_items_in_rect(const Rect2 &p_rect, Node *p_node, List<CanvasItem *> *r_items, const Transform2D &p_parent_xform, const Transform2D &p_canvas_xform) {
if (!p_node)
return;
@@ -1796,8 +1878,13 @@ bool CanvasItemEditor::_gui_input_select(const Ref<InputEvent> &p_event) {
// Find the item to select
CanvasItem *canvas_item = NULL;
Vector<_SelectResult> selection;
+
+ // Retrieve the items
_get_canvas_items_at_pos(click, selection, editor_selection->get_selection().empty() ? 1 : 0);
+ // Retrieve the bones
+ _get_bones_at_pos(click, selection);
+
for (int i = 0; i < selection.size(); i++) {
if (editor_selection->is_selected(selection[i].item)) {
// Drag the node(s) if requested
@@ -2588,57 +2675,25 @@ void CanvasItemEditor::_draw_bones() {
RID ci = viewport->get_canvas_item();
if (skeleton_show_bones) {
- int bone_width = EditorSettings::get_singleton()->get("editors/2d/bone_width");
Color bone_color1 = EditorSettings::get_singleton()->get("editors/2d/bone_color1");
Color bone_color2 = EditorSettings::get_singleton()->get("editors/2d/bone_color2");
Color bone_ik_color = EditorSettings::get_singleton()->get("editors/2d/bone_ik_color");
Color bone_outline_color = EditorSettings::get_singleton()->get("editors/2d/bone_outline_color");
Color bone_selected_color = EditorSettings::get_singleton()->get("editors/2d/bone_selected_color");
- int bone_outline_size = EditorSettings::get_singleton()->get("editors/2d/bone_outline_size");
for (Map<BoneKey, BoneList>::Element *E = bone_list.front(); E; E = E->next()) {
- Node2D *from_node = Object::cast_to<Node2D>(ObjectDB::get_instance(E->key().from));
- Node2D *to_node = Object::cast_to<Node2D>(ObjectDB::get_instance(E->key().to));
-
- if (!from_node->is_inside_tree())
- continue; //may have been removed
- if (!from_node)
+ Vector<Vector2> bone_shape;
+ Vector<Vector2> bone_shape_outline;
+ if (!_get_bone_shape(&bone_shape, &bone_shape_outline, E))
continue;
- if (!to_node && E->get().length == 0)
+ Node2D *from_node = Object::cast_to<Node2D>(ObjectDB::get_instance(E->key().from));
+ if (!from_node->is_visible_in_tree())
continue;
- Vector2 from = transform.xform(from_node->get_global_position());
- Vector2 to;
-
- if (to_node)
- to = transform.xform(to_node->get_global_position());
- else
- to = transform.xform(from_node->get_global_transform().xform(Vector2(E->get().length, 0)));
-
- Vector2 rel = to - from;
- Vector2 relt = rel.tangent().normalized() * bone_width;
- Vector2 reln = rel.normalized();
- Vector2 reltn = relt.normalized();
-
- Vector<Vector2> bone_shape;
- bone_shape.push_back(from);
- bone_shape.push_back(from + rel * 0.2 + relt);
- bone_shape.push_back(to);
- bone_shape.push_back(from + rel * 0.2 - relt);
-
- Vector<Vector2> bone_shape_outline;
- bone_shape_outline.push_back(from + (-reln - reltn) * bone_outline_size);
- bone_shape_outline.push_back(from + (-reln + reltn) * bone_outline_size);
- bone_shape_outline.push_back(from + rel * 0.2 + relt + reltn * bone_outline_size);
- bone_shape_outline.push_back(to + (reln + reltn) * bone_outline_size);
- bone_shape_outline.push_back(to + (reln - reltn) * bone_outline_size);
- bone_shape_outline.push_back(from + rel * 0.2 - relt - reltn * bone_outline_size);
-
Vector<Color> colors;
if (from_node->has_meta("_edit_ik_")) {
-
colors.push_back(bone_ik_color);
colors.push_back(bone_ik_color);
colors.push_back(bone_ik_color);
diff --git a/editor/plugins/canvas_item_editor_plugin.h b/editor/plugins/canvas_item_editor_plugin.h
index a1957b892e..4d2af11303 100644
--- a/editor/plugins/canvas_item_editor_plugin.h
+++ b/editor/plugins/canvas_item_editor_plugin.h
@@ -351,6 +351,7 @@ class CanvasItemEditor : public VBoxContainer {
void _find_canvas_items_at_pos(const Point2 &p_pos, Node *p_node, Vector<_SelectResult> &r_items, int p_limit = 0, const Transform2D &p_parent_xform = Transform2D(), const Transform2D &p_canvas_xform = Transform2D());
void _get_canvas_items_at_pos(const Point2 &p_pos, Vector<_SelectResult> &r_items, int p_limit = 0);
+ void _get_bones_at_pos(const Point2 &p_pos, Vector<_SelectResult> &r_items);
void _find_canvas_items_in_rect(const Rect2 &p_rect, Node *p_node, List<CanvasItem *> *r_items, const Transform2D &p_parent_xform = Transform2D(), const Transform2D &p_canvas_xform = Transform2D());
bool _select_click_on_item(CanvasItem *item, Point2 p_click_pos, bool p_append);
@@ -379,6 +380,7 @@ class CanvasItemEditor : public VBoxContainer {
UndoRedo *undo_redo;
bool _build_bones_list(Node *p_node);
+ bool _get_bone_shape(Vector<Vector2> *shape, Vector<Vector2> *outline_shape, Map<BoneKey, BoneList>::Element *bone);
List<CanvasItem *> _get_edited_canvas_items(bool retreive_locked = false, bool remove_canvas_item_if_parent_in_selection = true);
Rect2 _get_encompassing_rect_from_list(List<CanvasItem *> p_list);
diff --git a/editor/plugins/collision_polygon_2d_editor_plugin.cpp b/editor/plugins/collision_polygon_2d_editor_plugin.cpp
index b624d69810..672337ba2f 100644
--- a/editor/plugins/collision_polygon_2d_editor_plugin.cpp
+++ b/editor/plugins/collision_polygon_2d_editor_plugin.cpp
@@ -42,6 +42,7 @@ void CollisionPolygon2DEditor::_set_node(Node *p_polygon) {
CollisionPolygon2DEditor::CollisionPolygon2DEditor(EditorNode *p_editor) :
AbstractPolygon2DEditor(p_editor) {
+ node = NULL;
}
CollisionPolygon2DEditorPlugin::CollisionPolygon2DEditorPlugin(EditorNode *p_node) :
diff --git a/editor/plugins/curve_editor_plugin.cpp b/editor/plugins/curve_editor_plugin.cpp
index 7c49408c35..49c54ad67d 100644
--- a/editor/plugins/curve_editor_plugin.cpp
+++ b/editor/plugins/curve_editor_plugin.cpp
@@ -91,7 +91,7 @@ void CurveEditor::set_curve(Ref<Curve> curve) {
}
Size2 CurveEditor::get_minimum_size() const {
- return Vector2(64, 64);
+ return Vector2(64, 150) * EDSCALE;
}
void CurveEditor::_notification(int p_what) {
@@ -639,7 +639,7 @@ void CurveEditor::_draw() {
Ref<Font> font = get_font("font", "Label");
float font_height = font->get_height();
- const Color text_color = get_color("font_color", "Editor");
+ Color text_color = get_color("font_color", "Editor");
{
// X axis
@@ -720,6 +720,7 @@ void CurveEditor::_draw() {
// Help text
if (_selected_point > 0 && _selected_point + 1 < curve.get_point_count()) {
+ text_color.a *= 0.4;
draw_string(font, Vector2(50, font_height), TTR("Hold Shift to edit tangents individually"), text_color);
}
}
@@ -750,87 +751,28 @@ void CurveEditor::_bind_methods() {
//---------------
-CurveEditorPlugin::CurveEditorPlugin(EditorNode *p_node) {
- _editor_node = p_node;
-
- _view = memnew(CurveEditor);
- _view->set_custom_minimum_size(Size2(100, 128 * EDSCALE));
- _view->hide();
-
- _toggle_button = _editor_node->add_bottom_panel_item(get_name(), _view);
- _toggle_button->hide();
-
- get_editor_interface()->get_resource_previewer()->add_preview_generator(memnew(CurvePreviewGenerator));
-}
-
-CurveEditorPlugin::~CurveEditorPlugin() {
-}
-
-void CurveEditorPlugin::edit(Object *p_object) {
-
- Ref<Curve> curve_ref;
-
- if (_current_ref.is_valid()) {
- CurveTexture *ct = Object::cast_to<CurveTexture>(*_current_ref);
- if (ct)
- ct->disconnect(CoreStringNames::get_singleton()->changed, this, "_curve_texture_changed");
- }
-
- if (p_object) {
- Resource *res = Object::cast_to<Resource>(p_object);
- ERR_FAIL_COND(res == NULL);
- ERR_FAIL_COND(!handles(p_object));
-
- _current_ref = Ref<Resource>(Object::cast_to<Resource>(p_object));
-
- if (_current_ref.is_valid()) {
- Curve *curve = Object::cast_to<Curve>(*_current_ref);
- if (curve)
- curve_ref = Ref<Curve>(curve);
- else {
- CurveTexture *ct = Object::cast_to<CurveTexture>(*_current_ref);
- if (ct) {
- ct->connect(CoreStringNames::get_singleton()->changed, this, "_curve_texture_changed");
- curve_ref = ct->get_curve();
- }
- }
- }
+bool EditorInspectorPluginCurve::can_handle(Object *p_object) {
- } else {
- _current_ref = Ref<Resource>();
- }
-
- _view->set_curve(curve_ref);
+ return Object::cast_to<Curve>(p_object) != NULL;
}
-bool CurveEditorPlugin::handles(Object *p_object) const {
- // Both handled so that we can keep the curve editor open
- return Object::cast_to<Curve>(p_object) || Object::cast_to<CurveTexture>(p_object);
-}
+void EditorInspectorPluginCurve::parse_begin(Object *p_object) {
-void CurveEditorPlugin::make_visible(bool p_visible) {
- if (p_visible) {
- _toggle_button->show();
- _editor_node->make_bottom_panel_item_visible(_view);
- } else {
- _toggle_button->hide();
- if (_view->is_visible_in_tree())
- _editor_node->hide_bottom_panel();
- }
-}
+ Curve *curve = Object::cast_to<Curve>(p_object);
+ ERR_FAIL_COND(!curve);
+ Ref<Curve> c(curve);
-void CurveEditorPlugin::_curve_texture_changed() {
- // If the curve is shown indirectly as a CurveTexture is edited,
- // we need to monitor when the curve property gets assigned
- CurveTexture *ct = Object::cast_to<CurveTexture>(*_current_ref);
- if (ct) {
- _view->set_curve(ct->get_curve());
- }
+ CurveEditor *editor = memnew(CurveEditor);
+ editor->set_curve(curve);
+ add_custom_control(editor);
}
-void CurveEditorPlugin::_bind_methods() {
+CurveEditorPlugin::CurveEditorPlugin(EditorNode *p_node) {
+ Ref<EditorInspectorPluginCurve> curve_plugin;
+ curve_plugin.instance();
+ EditorInspector::add_inspector_plugin(curve_plugin);
- ClassDB::bind_method(D_METHOD("_curve_texture_changed"), &CurveEditorPlugin::_curve_texture_changed);
+ get_editor_interface()->get_resource_previewer()->add_preview_generator(memnew(CurvePreviewGenerator));
}
//-----------------------------------
@@ -852,13 +794,13 @@ Ref<Texture> CurvePreviewGenerator::generate(const Ref<Resource> &p_from) {
img_ref.instance();
Image &im = **img_ref;
- im.create(thumbnail_size, thumbnail_size, 0, Image::FORMAT_RGBA8);
+ im.create(thumbnail_size, thumbnail_size / 2, 0, Image::FORMAT_RGBA8);
im.lock();
Color bg_color(0.1, 0.1, 0.1, 1.0);
for (int i = 0; i < thumbnail_size; i++) {
- for (int j = 0; j < thumbnail_size; j++) {
+ for (int j = 0; j < thumbnail_size / 2; j++) {
im.set_pixel(i, j, bg_color);
}
}
diff --git a/editor/plugins/curve_editor_plugin.h b/editor/plugins/curve_editor_plugin.h
index 97f1ba2fa1..255f359ed2 100644
--- a/editor/plugins/curve_editor_plugin.h
+++ b/editor/plugins/curve_editor_plugin.h
@@ -119,28 +119,19 @@ private:
float _tangents_length;
};
+class EditorInspectorPluginCurve : public EditorInspectorPlugin {
+ GDCLASS(EditorInspectorPluginCurve, EditorInspectorPlugin)
+public:
+ virtual bool can_handle(Object *p_object);
+ virtual void parse_begin(Object *p_object);
+};
+
class CurveEditorPlugin : public EditorPlugin {
GDCLASS(CurveEditorPlugin, EditorPlugin)
public:
CurveEditorPlugin(EditorNode *p_node);
- ~CurveEditorPlugin();
String get_name() const { return "Curve"; }
- bool has_main_screen() const { return false; }
- void edit(Object *p_object);
- bool handles(Object *p_object) const;
- void make_visible(bool p_visible);
-
-private:
- static void _bind_methods();
-
- void _curve_texture_changed();
-
-private:
- CurveEditor *_view;
- Ref<Resource> _current_ref;
- EditorNode *_editor_node;
- ToolButton *_toggle_button;
};
class CurvePreviewGenerator : public EditorResourcePreviewGenerator {
diff --git a/editor/plugins/gradient_editor_plugin.cpp b/editor/plugins/gradient_editor_plugin.cpp
index e89cb68935..442bd52ea7 100644
--- a/editor/plugins/gradient_editor_plugin.cpp
+++ b/editor/plugins/gradient_editor_plugin.cpp
@@ -33,77 +33,70 @@
#include "canvas_item_editor_plugin.h"
#include "spatial_editor_plugin.h"
-GradientEditorPlugin::GradientEditorPlugin(EditorNode *p_node) {
-
- editor = p_node;
- ramp_editor = memnew(GradientEdit);
-
- add_control_to_container(CONTAINER_PROPERTY_EDITOR_BOTTOM, ramp_editor);
-
- ramp_editor->set_custom_minimum_size(Size2(100, 48));
- ramp_editor->hide();
- ramp_editor->connect("ramp_changed", this, "ramp_changed");
+Size2 GradientEditor::get_minimum_size() const {
+ return Size2(0, 60) * EDSCALE;
}
+void GradientEditor::_gradient_changed() {
-void GradientEditorPlugin::edit(Object *p_object) {
-
- Gradient *gradient = Object::cast_to<Gradient>(p_object);
- if (!gradient)
+ if (editing)
return;
- gradient_ref = Ref<Gradient>(gradient);
- ramp_editor->set_points(gradient_ref->get_points());
-}
-bool GradientEditorPlugin::handles(Object *p_object) const {
+ editing = true;
+ Vector<Gradient::Point> points = gradient->get_points();
+ set_points(points);
+ editing = false;
+}
- return p_object->is_class("Gradient");
+void GradientEditor::_ramp_changed() {
+
+ editing = true;
+ UndoRedo *undo_redo = EditorNode::get_singleton()->get_undo_redo();
+ undo_redo->create_action("Gradient Edited");
+ undo_redo->add_do_method(gradient.ptr(), "set_offsets", get_offsets());
+ undo_redo->add_do_method(gradient.ptr(), "set_colors", get_colors());
+ undo_redo->add_undo_method(gradient.ptr(), "set_offsets", gradient->get_offsets());
+ undo_redo->add_undo_method(gradient.ptr(), "set_colors", gradient->get_colors());
+ undo_redo->commit_action();
+ editing = false;
}
-void GradientEditorPlugin::make_visible(bool p_visible) {
+void GradientEditor::_bind_methods() {
- if (p_visible) {
- ramp_editor->show();
- } else {
- ramp_editor->hide();
- }
+ ClassDB::bind_method("_gradient_changed", &GradientEditor::_gradient_changed);
+ ClassDB::bind_method("_ramp_changed", &GradientEditor::_ramp_changed);
}
-void GradientEditorPlugin::_ramp_changed() {
-
- if (gradient_ref.is_valid()) {
+void GradientEditor::set_gradient(const Ref<Gradient> &p_gradient) {
+ gradient = p_gradient;
+ connect("ramp_changed", this, "_ramp_changed");
+ gradient->connect("changed", this, "_gradient_changed");
+ set_points(gradient->get_points());
+}
- UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
+GradientEditor::GradientEditor() {
+ editing = false;
+}
- //Not sure if I should convert this data to PoolVector
- Vector<float> new_offsets = ramp_editor->get_offsets();
- Vector<Color> new_colors = ramp_editor->get_colors();
- Vector<float> old_offsets = gradient_ref->get_offsets();
- Vector<Color> old_colors = gradient_ref->get_colors();
+///////////////////////
- if (old_offsets.size() != new_offsets.size())
- ur->create_action(TTR("Add/Remove Color Ramp Point"));
- else
- ur->create_action(TTR("Modify Color Ramp"), UndoRedo::MERGE_ENDS);
- ur->add_do_method(this, "undo_redo_gradient", new_offsets, new_colors);
- ur->add_undo_method(this, "undo_redo_gradient", old_offsets, old_colors);
- ur->commit_action();
+bool EditorInspectorPluginGradient::can_handle(Object *p_object) {
- //color_ramp_ref->set_points(ramp_editor->get_points());
- }
+ return Object::cast_to<Gradient>(p_object) != NULL;
}
-void GradientEditorPlugin::_undo_redo_gradient(const Vector<float> &offsets, const Vector<Color> &colors) {
+void EditorInspectorPluginGradient::parse_begin(Object *p_object) {
- gradient_ref->set_offsets(offsets);
- gradient_ref->set_colors(colors);
- ramp_editor->set_points(gradient_ref->get_points());
- ramp_editor->update();
-}
+ Gradient *gradient = Object::cast_to<Gradient>(p_object);
+ Ref<Gradient> g(gradient);
-GradientEditorPlugin::~GradientEditorPlugin() {
+ GradientEditor *editor = memnew(GradientEditor);
+ editor->set_gradient(g);
+ add_custom_control(editor);
}
-void GradientEditorPlugin::_bind_methods() {
- ClassDB::bind_method(D_METHOD("ramp_changed"), &GradientEditorPlugin::_ramp_changed);
- ClassDB::bind_method(D_METHOD("undo_redo_gradient", "offsets", "colors"), &GradientEditorPlugin::_undo_redo_gradient);
+GradientEditorPlugin::GradientEditorPlugin(EditorNode *p_node) {
+
+ Ref<EditorInspectorPluginGradient> plugin;
+ plugin.instance();
+ add_inspector_plugin(plugin);
}
diff --git a/editor/plugins/gradient_editor_plugin.h b/editor/plugins/gradient_editor_plugin.h
index 52f4c59575..0c878b168f 100644
--- a/editor/plugins/gradient_editor_plugin.h
+++ b/editor/plugins/gradient_editor_plugin.h
@@ -35,28 +35,39 @@
#include "editor/editor_plugin.h"
#include "scene/gui/gradient_edit.h"
-class GradientEditorPlugin : public EditorPlugin {
+class GradientEditor : public GradientEdit {
+ GDCLASS(GradientEditor, GradientEdit)
- GDCLASS(GradientEditorPlugin, EditorPlugin);
+ bool editing;
+ Ref<Gradient> gradient;
- Ref<Gradient> gradient_ref;
- GradientEdit *ramp_editor;
- EditorNode *editor;
+ void _gradient_changed();
+ void _ramp_changed();
protected:
static void _bind_methods();
- void _ramp_changed();
- void _undo_redo_gradient(const Vector<float> &offsets, const Vector<Color> &colors);
+
+public:
+ virtual Size2 get_minimum_size() const;
+ void set_gradient(const Ref<Gradient> &p_gradient);
+ GradientEditor();
+};
+
+class EditorInspectorPluginGradient : public EditorInspectorPlugin {
+ GDCLASS(EditorInspectorPluginGradient, EditorInspectorPlugin)
+public:
+ virtual bool can_handle(Object *p_object);
+ virtual void parse_begin(Object *p_object);
+};
+
+class GradientEditorPlugin : public EditorPlugin {
+
+ GDCLASS(GradientEditorPlugin, EditorPlugin);
public:
virtual String get_name() const { return "ColorRamp"; }
- bool has_main_screen() const { return false; }
- virtual void edit(Object *p_object);
- virtual bool handles(Object *p_object) const;
- virtual void make_visible(bool p_visible);
GradientEditorPlugin(EditorNode *p_node);
- ~GradientEditorPlugin();
};
#endif /* TOOLS_EDITOR_PLUGINS_COLOR_RAMP_EDITOR_PLUGIN_H_ */
diff --git a/editor/plugins/line_2d_editor_plugin.cpp b/editor/plugins/line_2d_editor_plugin.cpp
index 47d5a73078..ba6452c1d1 100644
--- a/editor/plugins/line_2d_editor_plugin.cpp
+++ b/editor/plugins/line_2d_editor_plugin.cpp
@@ -64,6 +64,7 @@ void Line2DEditor::_action_set_polygon(int p_idx, const Variant &p_previous, con
Line2DEditor::Line2DEditor(EditorNode *p_editor) :
AbstractPolygon2DEditor(p_editor) {
+ node = NULL;
}
Line2DEditorPlugin::Line2DEditorPlugin(EditorNode *p_node) :
diff --git a/editor/plugins/navigation_polygon_editor_plugin.cpp b/editor/plugins/navigation_polygon_editor_plugin.cpp
index d1edf1ae10..0332e15b0e 100644
--- a/editor/plugins/navigation_polygon_editor_plugin.cpp
+++ b/editor/plugins/navigation_polygon_editor_plugin.cpp
@@ -123,6 +123,7 @@ void NavigationPolygonEditor::_create_resource() {
NavigationPolygonEditor::NavigationPolygonEditor(EditorNode *p_editor) :
AbstractPolygon2DEditor(p_editor) {
+ node = NULL;
}
NavigationPolygonEditorPlugin::NavigationPolygonEditorPlugin(EditorNode *p_node) :
diff --git a/editor/plugins/polygon_2d_editor_plugin.cpp b/editor/plugins/polygon_2d_editor_plugin.cpp
index f04e0a801c..ed41e1931e 100644
--- a/editor/plugins/polygon_2d_editor_plugin.cpp
+++ b/editor/plugins/polygon_2d_editor_plugin.cpp
@@ -1035,6 +1035,7 @@ Vector2 Polygon2DEditor::snap_point(Vector2 p_target) const {
Polygon2DEditor::Polygon2DEditor(EditorNode *p_editor) :
AbstractPolygon2DEditor(p_editor) {
+ node = NULL;
snap_step = Vector2(10, 10);
use_snap = false;
snap_show_grid = false;
diff --git a/editor/plugins/script_editor_plugin.cpp b/editor/plugins/script_editor_plugin.cpp
index ac250f085d..94dcbd8e18 100644
--- a/editor/plugins/script_editor_plugin.cpp
+++ b/editor/plugins/script_editor_plugin.cpp
@@ -1188,7 +1188,7 @@ void ScriptEditor::_notification(int p_what) {
case NOTIFICATION_READY: {
get_tree()->connect("tree_changed", this, "_tree_changed");
- editor->connect("request_help", this, "_request_help");
+ editor->get_inspector_dock()->connect("request_help", this, "_request_help");
editor->connect("request_help_search", this, "_help_search");
editor->connect("request_help_index", this, "_help_index");
} break;
@@ -1404,6 +1404,7 @@ void ScriptEditor::_update_members_overview_visibility() {
ScriptEditorBase *se = _get_current_editor();
if (!se) {
+ members_overview_buttons_hbox->set_visible(false);
members_overview->set_visible(false);
return;
}
@@ -1549,9 +1550,10 @@ void ScriptEditor::_update_script_names() {
ScriptEditorBase *se = Object::cast_to<ScriptEditorBase>(tab_container->get_child(i));
if (se) {
- String name = se->get_name();
Ref<Texture> icon = se->get_icon();
String path = se->get_edited_script()->get_path();
+ bool built_in = !path.is_resource_file();
+ String name = built_in ? path.get_file() : se->get_name();
_ScriptEditorItemData sd;
sd.icon = icon;
@@ -2680,7 +2682,7 @@ ScriptEditor::ScriptEditor(EditorNode *p_editor) {
members_overview_vbox->add_child(members_overview_buttons_hbox);
members_overview_alphabeta_sort_button = memnew(ToolButton);
- members_overview_alphabeta_sort_button->set_tooltip(TTR("Sort alphabetically"));
+ members_overview_alphabeta_sort_button->set_tooltip(TTR("Toggle alphabetical sorting of the method list."));
members_overview_alphabeta_sort_button->set_toggle_mode(true);
members_overview_alphabeta_sort_button->set_pressed(EditorSettings::get_singleton()->get("text_editor/tools/sort_members_outline_alphabetically"));
members_overview_alphabeta_sort_button->connect("toggled", this, "_toggle_members_overview_alpha_sort");
diff --git a/editor/plugins/skeleton_2d_editor_plugin.cpp b/editor/plugins/skeleton_2d_editor_plugin.cpp
index e372f792d6..08bfebefbd 100644
--- a/editor/plugins/skeleton_2d_editor_plugin.cpp
+++ b/editor/plugins/skeleton_2d_editor_plugin.cpp
@@ -1,3 +1,33 @@
+/*************************************************************************/
+/* skeleton_2d_editor_plugin.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 "skeleton_2d_editor_plugin.h"
#include "canvas_item_editor_plugin.h"
diff --git a/editor/plugins/skeleton_2d_editor_plugin.h b/editor/plugins/skeleton_2d_editor_plugin.h
index bbe2a3a6f2..26ab4328b0 100644
--- a/editor/plugins/skeleton_2d_editor_plugin.h
+++ b/editor/plugins/skeleton_2d_editor_plugin.h
@@ -1,3 +1,33 @@
+/*************************************************************************/
+/* skeleton_2d_editor_plugin.h */
+/*************************************************************************/
+/* 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. */
+/*************************************************************************/
+
#ifndef SKELETON_2D_EDITOR_PLUGIN_H
#define SKELETON_2D_EDITOR_PLUGIN_H
diff --git a/editor/plugins/sprite_editor_plugin.cpp b/editor/plugins/sprite_editor_plugin.cpp
index 49816fe2ae..66673cca00 100644
--- a/editor/plugins/sprite_editor_plugin.cpp
+++ b/editor/plugins/sprite_editor_plugin.cpp
@@ -1,3 +1,33 @@
+/*************************************************************************/
+/* sprite_editor_plugin.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 "sprite_editor_plugin.h"
#include "canvas_item_editor_plugin.h"
diff --git a/editor/plugins/sprite_editor_plugin.h b/editor/plugins/sprite_editor_plugin.h
index 17aa3eb1f9..238227e4a0 100644
--- a/editor/plugins/sprite_editor_plugin.h
+++ b/editor/plugins/sprite_editor_plugin.h
@@ -1,3 +1,33 @@
+/*************************************************************************/
+/* sprite_editor_plugin.h */
+/*************************************************************************/
+/* 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. */
+/*************************************************************************/
+
#ifndef SPRITE_EDITOR_PLUGIN_H
#define SPRITE_EDITOR_PLUGIN_H
diff --git a/editor/plugins/style_box_editor_plugin.cpp b/editor/plugins/style_box_editor_plugin.cpp
index f4faab69ed..f6d98cb4c7 100644
--- a/editor/plugins/style_box_editor_plugin.cpp
+++ b/editor/plugins/style_box_editor_plugin.cpp
@@ -30,7 +30,26 @@
#include "style_box_editor_plugin.h"
-void StyleBoxEditor::edit(const Ref<StyleBox> &p_stylebox) {
+bool EditorInspectorPluginStyleBox::can_handle(Object *p_object) {
+
+ return Object::cast_to<StyleBox>(p_object) != NULL;
+}
+
+void EditorInspectorPluginStyleBox::parse_begin(Object *p_object) {
+
+ Ref<StyleBox> sb = Ref<StyleBox>(Object::cast_to<StyleBox>(p_object));
+
+ StyleBoxPreview *preview = memnew(StyleBoxPreview);
+ preview->edit(sb);
+ add_custom_control(preview);
+}
+bool EditorInspectorPluginStyleBox::parse_property(Object *p_object, Variant::Type p_type, const String &p_path, PropertyHint p_hint, const String &p_hint_text, int p_usage) {
+ return false; //do not want
+}
+void EditorInspectorPluginStyleBox::parse_end() {
+}
+
+void StyleBoxPreview::edit(const Ref<StyleBox> &p_stylebox) {
if (stylebox.is_valid())
stylebox->disconnect("changed", this, "_sb_changed");
@@ -39,71 +58,33 @@ void StyleBoxEditor::edit(const Ref<StyleBox> &p_stylebox) {
preview->add_style_override("panel", stylebox);
stylebox->connect("changed", this, "_sb_changed");
}
+ _sb_changed();
}
-void StyleBoxEditor::_sb_changed() {
+void StyleBoxPreview::_sb_changed() {
preview->update();
+ if (stylebox.is_valid()) {
+ Size2 ms = stylebox->get_minimum_size() * 4 / 3;
+ ms.height = MAX(ms.height, 150 * EDSCALE);
+ preview->set_custom_minimum_size(ms);
+ }
}
-void StyleBoxEditor::_bind_methods() {
+void StyleBoxPreview::_bind_methods() {
- ClassDB::bind_method("_sb_changed", &StyleBoxEditor::_sb_changed);
- //ClassDB::bind_method("_import",&StyleBoxEditor::_import);
- //ClassDB::bind_method("_import_accept",&StyleBoxEditor::_import_accept);
- //ClassDB::bind_method("_preview_text_changed",&StyleBoxEditor::_preview_text_changed);
+ ClassDB::bind_method("_sb_changed", &StyleBoxPreview::_sb_changed);
}
-StyleBoxEditor::StyleBoxEditor() {
-
- panel = memnew(Panel);
- add_child(panel);
- panel->set_anchors_and_margins_preset(Control::PRESET_WIDE);
-
- Label *l = memnew(Label);
- l->set_text(TTR("StyleBox Preview:"));
- l->set_position(Point2(5, 5));
- panel->add_child(l);
+StyleBoxPreview::StyleBoxPreview() {
preview = memnew(Panel);
- panel->add_child(preview);
- preview->set_position(Point2(50, 50));
- preview->set_size(Size2(200, 100));
-}
-
-void StyleBoxEditorPlugin::edit(Object *p_node) {
-
- if (Object::cast_to<StyleBox>(p_node)) {
- stylebox_editor->edit(Object::cast_to<StyleBox>(p_node));
- stylebox_editor->show();
- } else
- stylebox_editor->hide();
-}
-
-bool StyleBoxEditorPlugin::handles(Object *p_node) const {
-
- return p_node->is_class("StyleBox");
-}
-
-void StyleBoxEditorPlugin::make_visible(bool p_visible) {
-
- if (p_visible) {
- button->show();
- EditorNode::get_singleton()->make_bottom_panel_item_visible(stylebox_editor);
-
- } else {
- if (stylebox_editor->is_visible_in_tree())
- EditorNode::get_singleton()->hide_bottom_panel();
- button->hide();
- }
+ add_margin_child(TTR("Preview:"), preview);
}
StyleBoxEditorPlugin::StyleBoxEditorPlugin(EditorNode *p_node) {
- stylebox_editor = memnew(StyleBoxEditor);
- stylebox_editor->set_custom_minimum_size(Size2(0, 250));
-
- //p_node->get_viewport()->add_child(stylebox_editor);
- button = p_node->add_bottom_panel_item(TTR("StyleBox"), stylebox_editor);
- button->hide();
+ Ref<EditorInspectorPluginStyleBox> inspector_plugin;
+ inspector_plugin.instance();
+ add_inspector_plugin(inspector_plugin);
}
diff --git a/editor/plugins/style_box_editor_plugin.h b/editor/plugins/style_box_editor_plugin.h
index 34d8caaeb6..6b0d7e57a8 100644
--- a/editor/plugins/style_box_editor_plugin.h
+++ b/editor/plugins/style_box_editor_plugin.h
@@ -31,18 +31,17 @@
#ifndef STYLE_BOX_EDITOR_PLUGIN_H
#define STYLE_BOX_EDITOR_PLUGIN_H
+#include "editor/editor_inspector.h"
#include "editor/editor_node.h"
#include "scene/gui/option_button.h"
#include "scene/gui/texture_rect.h"
#include "scene/resources/style_box.h"
-class StyleBoxEditor : public Control {
+class StyleBoxPreview : public VBoxContainer {
- GDCLASS(StyleBoxEditor, Control);
+ GDCLASS(StyleBoxPreview, VBoxContainer);
- Panel *panel;
Panel *preview;
-
Ref<StyleBox> stylebox;
void _sb_changed();
@@ -53,23 +52,24 @@ protected:
public:
void edit(const Ref<StyleBox> &p_stylebox);
- StyleBoxEditor();
+ StyleBoxPreview();
+};
+
+class EditorInspectorPluginStyleBox : public EditorInspectorPlugin {
+ GDCLASS(EditorInspectorPluginStyleBox, EditorInspectorPlugin)
+public:
+ virtual bool can_handle(Object *p_object);
+ virtual void parse_begin(Object *p_object);
+ virtual bool parse_property(Object *p_object, Variant::Type p_type, const String &p_path, PropertyHint p_hint, const String &p_hint_text, int p_usage);
+ virtual void parse_end();
};
class StyleBoxEditorPlugin : public EditorPlugin {
GDCLASS(StyleBoxEditorPlugin, EditorPlugin);
- StyleBoxEditor *stylebox_editor;
- EditorNode *editor;
- Button *button;
-
public:
virtual String get_name() const { return "StyleBox"; }
- bool has_main_screen() const { return false; }
- virtual void edit(Object *p_node);
- virtual bool handles(Object *p_node) const;
- virtual void make_visible(bool p_visible);
StyleBoxEditorPlugin(EditorNode *p_node);
};
diff --git a/editor/plugins/texture_region_editor_plugin.cpp b/editor/plugins/texture_region_editor_plugin.cpp
index 5ba3931689..e4fdd1f251 100644
--- a/editor/plugins/texture_region_editor_plugin.cpp
+++ b/editor/plugins/texture_region_editor_plugin.cpp
@@ -601,6 +601,17 @@ void TextureRegionEditor::apply_rect(const Rect2 &rect) {
void TextureRegionEditor::_notification(int p_what) {
switch (p_what) {
+ case NOTIFICATION_PROCESS: {
+ if (node_sprite) {
+ if (node_sprite->is_region()) {
+
+ set_process(false);
+ EditorNode::get_singleton()->make_bottom_panel_item_visible(this);
+ }
+ } else {
+ set_process(false);
+ }
+ } break;
case NOTIFICATION_THEME_CHANGED:
case NOTIFICATION_READY: {
zoom_out->set_icon(get_icon("ZoomLess", "EditorIcons"));
@@ -640,6 +651,23 @@ void TextureRegionEditor::_bind_methods() {
ClassDB::bind_method(D_METHOD("_zoom_out"), &TextureRegionEditor::_zoom_out);
}
+bool TextureRegionEditor::is_stylebox() {
+ return obj_styleBox.is_valid();
+}
+
+bool TextureRegionEditor::is_atlas_texture() {
+
+ return atlas_tex.is_valid();
+}
+
+bool TextureRegionEditor::is_ninepatch() {
+ return node_ninepatch != NULL;
+}
+
+Sprite *TextureRegionEditor::get_sprite() {
+ return node_sprite;
+}
+
void TextureRegionEditor::edit(Object *p_obj) {
if (node_sprite)
node_sprite->remove_change_receptor(this);
@@ -670,6 +698,12 @@ void TextureRegionEditor::edit(Object *p_obj) {
tile_set = Ref<TileSet>(NULL);
}
edit_draw->update();
+ if (node_sprite && !node_sprite->is_region()) {
+ set_process(true);
+ }
+ if (!p_obj) {
+ set_process(false);
+ }
}
void TextureRegionEditor::_changed_callback(Object *p_changed, const char *p_prop) {
@@ -932,8 +966,12 @@ bool TextureRegionEditorPlugin::handles(Object *p_object) const {
void TextureRegionEditorPlugin::make_visible(bool p_visible) {
if (p_visible) {
texture_region_button->show();
- if (texture_region_button->is_pressed())
- region_editor->show();
+ if (region_editor->is_stylebox() || region_editor->is_atlas_texture() || region_editor->is_ninepatch() || (region_editor->get_sprite() && region_editor->get_sprite()->is_region())) {
+ editor->make_bottom_panel_item_visible(region_editor);
+ } else {
+ if (texture_region_button->is_pressed())
+ region_editor->show();
+ }
} else {
texture_region_button->hide();
region_editor->edit(NULL);
@@ -989,10 +1027,10 @@ TextureRegionEditorPlugin::TextureRegionEditorPlugin(EditorNode *p_node) {
editor = p_node;
region_editor = memnew(TextureRegionEditor(p_node));
- texture_region_button = p_node->add_bottom_panel_item(TTR("Texture Region"), region_editor);
+ texture_region_button = p_node->add_bottom_panel_item(TTR("TextureRegion"), region_editor);
texture_region_button->set_tooltip(TTR("Texture Region Editor"));
- region_editor->set_custom_minimum_size(Size2(0, 200));
+ region_editor->set_custom_minimum_size(Size2(0, 200) * EDSCALE);
region_editor->hide();
texture_region_button->hide();
}
diff --git a/editor/plugins/texture_region_editor_plugin.h b/editor/plugins/texture_region_editor_plugin.h
index 1244953a3f..eeba1987a6 100644
--- a/editor/plugins/texture_region_editor_plugin.h
+++ b/editor/plugins/texture_region_editor_plugin.h
@@ -131,6 +131,10 @@ public:
void _region_draw();
void _region_input(const Ref<InputEvent> &p_input);
void _scroll_changed(float);
+ bool is_stylebox();
+ bool is_atlas_texture();
+ bool is_ninepatch();
+ Sprite *get_sprite();
void edit(Object *p_obj);
TextureRegionEditor(EditorNode *p_editor);
diff --git a/editor/plugins/tile_set_editor_plugin.cpp b/editor/plugins/tile_set_editor_plugin.cpp
index 385fa24ad8..c79cf02062 100644
--- a/editor/plugins/tile_set_editor_plugin.cpp
+++ b/editor/plugins/tile_set_editor_plugin.cpp
@@ -126,7 +126,7 @@ void TileSetEditor::_import_node(Node *p_node, Ref<TileSet> p_library) {
Transform2D shape_transform = sb->shape_owner_get_transform(E->get());
bool one_way = sb->is_shape_owner_one_way_collision_enabled(E->get());
- shape_transform.set_origin(shape_transform.get_origin() - phys_offset);
+ shape_transform[2] -= phys_offset - sb->get_transform().xform(shape_transform[2]);
for (int k = 0; k < sb->shape_owner_get_shape_count(E->get()); k++) {
@@ -667,7 +667,7 @@ void TileSetEditor::_on_workspace_draw() {
if (mask & TileSet::BIND_BOTTOMRIGHT) {
workspace->draw_rect(Rect2(anchor + size / 2, size / 2), c);
}
- } else if (tileset->autotile_get_bitmask_mode(get_current_tile()) == TileSet::BITMASK_3X3) {
+ } else {
if (mask & TileSet::BIND_TOPLEFT) {
workspace->draw_rect(Rect2(anchor, size / 3), c);
}
@@ -821,7 +821,7 @@ void TileSetEditor::_on_workspace_input(const Ref<InputEvent> &p_ie) {
bit = TileSet::BIND_BOTTOMRIGHT;
}
}
- } else if (tileset->autotile_get_bitmask_mode(get_current_tile()) == TileSet::BITMASK_3X3) {
+ } else {
if (pos.x < size.x / 3) {
if (pos.y < size.y / 3) {
bit = TileSet::BIND_TOPLEFT;
@@ -884,7 +884,7 @@ void TileSetEditor::_on_workspace_input(const Ref<InputEvent> &p_ie) {
bit = TileSet::BIND_BOTTOMRIGHT;
}
}
- } else if (tileset->autotile_get_bitmask_mode(get_current_tile()) == TileSet::BITMASK_3X3) {
+ } else {
if (pos.x < size.x / 3) {
if (pos.y < size.y / 3) {
bit = TileSet::BIND_TOPLEFT;
@@ -1849,7 +1849,7 @@ void TileSetEditorHelper::_get_property_list(List<PropertyInfo> *p_list) const {
if (selected_tile < 0 || tileset.is_null())
return;
- p_list->push_back(PropertyInfo(Variant::INT, "bitmask_mode", PROPERTY_HINT_ENUM, "2x2,3x3"));
+ p_list->push_back(PropertyInfo(Variant::INT, "bitmask_mode", PROPERTY_HINT_ENUM, "2x2,3x3 (minimal),3x3"));
p_list->push_back(PropertyInfo(Variant::VECTOR2, "layout/tile_size"));
p_list->push_back(PropertyInfo(Variant::INT, "layout/spacing", PROPERTY_HINT_RANGE, "0,256,1"));
}
diff --git a/editor/project_manager.cpp b/editor/project_manager.cpp
index 97d3a070ab..0d06b71420 100644
--- a/editor/project_manager.cpp
+++ b/editor/project_manager.cpp
@@ -199,6 +199,7 @@ private:
sp = TTR("Imported Project");
project_name->set_text(sp);
+ _text_changed(sp);
}
}
@@ -222,6 +223,7 @@ private:
}
String sp = p.simplify_path();
project_path->set_text(sp);
+ _path_text_changed(sp);
get_ok()->call_deferred("grab_focus");
}
@@ -230,6 +232,7 @@ private:
String p = p_path;
String sp = p.simplify_path();
project_path->set_text(sp);
+ _path_text_changed(sp);
get_ok()->call_deferred("grab_focus");
}
@@ -263,7 +266,9 @@ private:
if (d->make_dir(project_name->get_text()) == OK) {
d->change_dir(project_name->get_text());
- project_path->set_text(d->get_current_dir());
+ String dir_str = d->get_current_dir();
+ project_path->set_text(dir_str);
+ _path_text_changed(dir_str);
created_folder_path = d->get_current_dir();
create_dir->set_disabled(true);
} else {
@@ -475,7 +480,9 @@ private:
_remove_created_folder();
project_path->clear();
+ _path_text_changed("");
project_name->clear();
+ _text_changed("");
if (status_rect->get_texture() == get_icon("StatusError", "EditorIcons"))
msg->show();
@@ -540,7 +547,9 @@ public:
msg->show();
get_ok()->set_disabled(true);
} else if (current->has_setting("application/config/name")) {
- project_name->set_text(current->get("application/config/name"));
+ String proj = current->get("application/config/name");
+ project_name->set_text(proj);
+ _text_changed(proj);
}
project_name->call_deferred("grab_focus");
@@ -559,7 +568,9 @@ public:
fdialog->set_current_dir(d->get_current_dir());
memdelete(d);
}
- project_name->set_text(TTR("New Game Project"));
+ String proj = TTR("New Game Project");
+ project_name->set_text(proj);
+ _text_changed(proj);
project_path->set_editable(true);
browse->set_disabled(false);
diff --git a/editor/scene_tree_dock.cpp b/editor/scene_tree_dock.cpp
index f5cee4cd65..b82a036130 100644
--- a/editor/scene_tree_dock.cpp
+++ b/editor/scene_tree_dock.cpp
@@ -75,6 +75,8 @@ void SceneTreeDock::_unhandled_key_input(Ref<InputEvent> p_event) {
if (ED_IS_SHORTCUT("scene_tree/batch_rename", p_event)) {
_tool_selected(TOOL_BATCH_RENAME);
+ } else if (ED_IS_SHORTCUT("scene_tree/rename", p_event)) {
+ _tool_selected(TOOL_RENAME);
} else if (ED_IS_SHORTCUT("scene_tree/add_child_node", p_event)) {
_tool_selected(TOOL_NEW);
} else if (ED_IS_SHORTCUT("scene_tree/instance_scene", p_event)) {
@@ -293,6 +295,13 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) {
rename_dialog->popup_centered();
}
} break;
+ case TOOL_RENAME: {
+ Tree *tree = scene_tree->get_scene_tree();
+ if (tree->is_anything_selected()) {
+ tree->grab_focus();
+ tree->edit_selected();
+ }
+ } break;
case TOOL_NEW: {
String preferred = "";
@@ -1870,7 +1879,6 @@ void SceneTreeDock::_tree_rmb(const Vector2 &p_menu_pos) {
menu->clear();
- menu->add_icon_shortcut(get_icon("Rename", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/batch_rename"), TOOL_BATCH_RENAME);
if (selection.size() == 1) {
subresources.clear();
@@ -1886,6 +1894,9 @@ void SceneTreeDock::_tree_rmb(const Vector2 &p_menu_pos) {
menu->add_icon_shortcut(get_icon("ScriptCreate", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/attach_script"), TOOL_ATTACH_SCRIPT);
menu->add_icon_shortcut(get_icon("ScriptRemove", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/clear_script"), TOOL_CLEAR_SCRIPT);
menu->add_separator();
+ menu->add_icon_shortcut(get_icon("Rename", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/rename"), TOOL_RENAME);
+ } else { // multi select
+ menu->add_icon_shortcut(get_icon("Rename", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/batch_rename"), TOOL_BATCH_RENAME);
}
menu->add_icon_shortcut(get_icon("Reload", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/change_node_type"), TOOL_REPLACE);
menu->add_separator();
@@ -1925,6 +1936,12 @@ void SceneTreeDock::_tree_rmb(const Vector2 &p_menu_pos) {
menu->add_icon_shortcut(get_icon("ScriptCreate", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/attach_script"), TOOL_ATTACH_SCRIPT);
menu->add_icon_shortcut(get_icon("ScriptRemove", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/clear_script"), TOOL_CLEAR_SCRIPT);
}
+
+ if (selection.size() > 1) {
+ //this is not a commonly used action, it makes no sense for it to be where it was nor always present.
+ menu->add_separator();
+ menu->add_icon_shortcut(get_icon("Rename", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/batch_rename"), TOOL_BATCH_RENAME);
+ }
menu->add_separator();
menu->add_icon_shortcut(get_icon("Remove", "EditorIcons"), ED_SHORTCUT("scene_tree/delete", TTR("Delete Node(s)"), KEY_DELETE), TOOL_ERASE);
menu->set_size(Size2(1, 1));
@@ -2064,6 +2081,7 @@ SceneTreeDock::SceneTreeDock(EditorNode *p_editor, Node *p_scene_root, EditorSel
filter_hbc->add_constant_override("separate", 0);
ToolButton *tb;
+ ED_SHORTCUT("scene_tree/rename", TTR("Rename"));
ED_SHORTCUT("scene_tree/batch_rename", TTR("Batch Rename"), KEY_MASK_CMD | KEY_F2);
ED_SHORTCUT("scene_tree/add_child_node", TTR("Add Child Node"), KEY_MASK_CMD | KEY_A);
ED_SHORTCUT("scene_tree/instance_scene", TTR("Instance Child Scene"));
diff --git a/editor/scene_tree_dock.h b/editor/scene_tree_dock.h
index fd7d616a80..ed13e063bb 100644
--- a/editor/scene_tree_dock.h
+++ b/editor/scene_tree_dock.h
@@ -59,6 +59,7 @@ class SceneTreeDock : public VBoxContainer {
TOOL_NEW,
TOOL_INSTANCE,
+ TOOL_RENAME,
TOOL_BATCH_RENAME,
TOOL_REPLACE,
TOOL_ATTACH_SCRIPT,
diff --git a/editor/translations/editor.pot b/editor/translations/editor.pot
index 61d67d7089..687c517180 100644
--- a/editor/translations/editor.pot
+++ b/editor/translations/editor.pot
@@ -3261,19 +3261,19 @@ msgid "Download for this asset is already in progress!"
msgstr ""
#: editor/plugins/asset_library_editor_plugin.cpp
-msgid "first"
+msgid "First"
msgstr ""
#: editor/plugins/asset_library_editor_plugin.cpp
-msgid "prev"
+msgid "Previous"
msgstr ""
#: editor/plugins/asset_library_editor_plugin.cpp
-msgid "next"
+msgid "Next"
msgstr ""
#: editor/plugins/asset_library_editor_plugin.cpp
-msgid "last"
+msgid "Last"
msgstr ""
#: editor/plugins/asset_library_editor_plugin.cpp