Better supported for remote object editing with the inspector with a simple dictionary editor implement
This commit is contained in:
parent
ccf76798d5
commit
c655fc7cd8
5 changed files with 298 additions and 14 deletions
189
editor/dictionary_property_edit.cpp
Normal file
189
editor/dictionary_property_edit.cpp
Normal file
|
@ -0,0 +1,189 @@
|
|||
/*************************************************************************/
|
||||
/* dictionary_property_edit.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2017 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 "dictionary_property_edit.h"
|
||||
#include "editor_node.h"
|
||||
|
||||
void DictionaryPropertyEdit::_notif_change() {
|
||||
_change_notify();
|
||||
}
|
||||
|
||||
void DictionaryPropertyEdit::_notif_changev(const String &p_v) {
|
||||
_change_notify(p_v.utf8().get_data());
|
||||
}
|
||||
|
||||
void DictionaryPropertyEdit::_set_key(const Variant &p_old_key, const Variant &p_new_key) {
|
||||
|
||||
// TODO: Set key of a dictionary is not allowd yet
|
||||
return;
|
||||
}
|
||||
|
||||
void DictionaryPropertyEdit::_set_value(const Variant &p_key, const Variant &p_value) {
|
||||
|
||||
Dictionary dict = get_dictionary();
|
||||
dict[p_key] = p_value;
|
||||
Object *o = ObjectDB::get_instance(obj);
|
||||
if (!o)
|
||||
return;
|
||||
|
||||
o->set(property, dict);
|
||||
}
|
||||
|
||||
Variant DictionaryPropertyEdit::get_dictionary() const {
|
||||
|
||||
Object *o = ObjectDB::get_instance(obj);
|
||||
if (!o)
|
||||
return Dictionary();
|
||||
Variant dict = o->get(property);
|
||||
if (dict.get_type() != Variant::DICTIONARY)
|
||||
return Dictionary();
|
||||
return dict;
|
||||
}
|
||||
|
||||
void DictionaryPropertyEdit::_get_property_list(List<PropertyInfo> *p_list) const {
|
||||
|
||||
Dictionary dict = get_dictionary();
|
||||
|
||||
Array keys = dict.keys();
|
||||
keys.sort();
|
||||
|
||||
for (int i = 0; i < keys.size(); i++) {
|
||||
String index = itos(i);
|
||||
|
||||
const Variant &key = keys[i];
|
||||
PropertyInfo pi(key.get_type(), index + ": key");
|
||||
p_list->push_back(pi);
|
||||
|
||||
const Variant &value = dict[key];
|
||||
pi = PropertyInfo(value.get_type(), index + ": value");
|
||||
p_list->push_back(pi);
|
||||
}
|
||||
}
|
||||
|
||||
void DictionaryPropertyEdit::edit(Object *p_obj, const StringName &p_prop) {
|
||||
|
||||
property = p_prop;
|
||||
obj = p_obj->get_instance_id();
|
||||
}
|
||||
|
||||
Node *DictionaryPropertyEdit::get_node() {
|
||||
|
||||
Object *o = ObjectDB::get_instance(obj);
|
||||
if (!o)
|
||||
return NULL;
|
||||
|
||||
return cast_to<Node>(o);
|
||||
}
|
||||
|
||||
void DictionaryPropertyEdit::_bind_methods() {
|
||||
|
||||
ClassDB::bind_method(D_METHOD("_set_key"), &DictionaryPropertyEdit::_set_key);
|
||||
ClassDB::bind_method(D_METHOD("_set_value"), &DictionaryPropertyEdit::_set_value);
|
||||
ClassDB::bind_method(D_METHOD("_notif_change"), &DictionaryPropertyEdit::_notif_change);
|
||||
ClassDB::bind_method(D_METHOD("_notif_changev"), &DictionaryPropertyEdit::_notif_changev);
|
||||
}
|
||||
|
||||
bool DictionaryPropertyEdit::_set(const StringName &p_name, const Variant &p_value) {
|
||||
|
||||
Dictionary dict = get_dictionary();
|
||||
Array keys = dict.keys();
|
||||
keys.sort();
|
||||
|
||||
String pn = p_name;
|
||||
int slash = pn.find(": ");
|
||||
if (slash != -1 && pn.length() > slash) {
|
||||
String type = pn.substr(slash + 2, pn.length());
|
||||
int index = pn.substr(0, slash).to_int();
|
||||
if (type == "key" && index < keys.size()) {
|
||||
|
||||
const Variant &key = keys[index];
|
||||
UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
|
||||
|
||||
ur->create_action(TTR("Change Dictionary Key"));
|
||||
ur->add_do_method(this, "_set_key", key, p_value);
|
||||
ur->add_undo_method(this, "_set_key", p_value, key);
|
||||
ur->add_do_method(this, "_notif_changev", p_name);
|
||||
ur->add_undo_method(this, "_notif_changev", p_name);
|
||||
ur->commit_action();
|
||||
|
||||
return true;
|
||||
} else if (type == "value" && index < keys.size()) {
|
||||
const Variant &key = keys[index];
|
||||
if (dict.has(key)) {
|
||||
|
||||
Variant value = dict[key];
|
||||
UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
|
||||
|
||||
ur->create_action(TTR("Change Dictionary Value"));
|
||||
ur->add_do_method(this, "_set_value", key, p_value);
|
||||
ur->add_undo_method(this, "_set_value", key, value);
|
||||
ur->add_do_method(this, "_notif_changev", p_name);
|
||||
ur->add_undo_method(this, "_notif_changev", p_name);
|
||||
ur->commit_action();
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool DictionaryPropertyEdit::_get(const StringName &p_name, Variant &r_ret) const {
|
||||
|
||||
Dictionary dict = get_dictionary();
|
||||
Array keys = dict.keys();
|
||||
keys.sort();
|
||||
|
||||
String pn = p_name;
|
||||
int slash = pn.find(": ");
|
||||
|
||||
if (slash != -1 && pn.length() > slash) {
|
||||
|
||||
String type = pn.substr(slash + 2, pn.length());
|
||||
int index = pn.substr(0, slash).to_int();
|
||||
|
||||
if (type == "key" && index < keys.size()) {
|
||||
r_ret = keys[index];
|
||||
return true;
|
||||
} else if (type == "value" && index < keys.size()) {
|
||||
const Variant &key = keys[index];
|
||||
if (dict.has(key)) {
|
||||
r_ret = dict[key];
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
DictionaryPropertyEdit::DictionaryPropertyEdit() {
|
||||
obj = 0;
|
||||
}
|
62
editor/dictionary_property_edit.h
Normal file
62
editor/dictionary_property_edit.h
Normal file
|
@ -0,0 +1,62 @@
|
|||
/*************************************************************************/
|
||||
/* dictionary_property_edit.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2017 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 DICTIONARY_PROPERTY_EDIT_H
|
||||
#define DICTIONARY_PROPERTY_EDIT_H
|
||||
|
||||
#include "scene/main/node.h"
|
||||
|
||||
class DictionaryPropertyEdit : public Reference {
|
||||
GDCLASS(DictionaryPropertyEdit, Reference);
|
||||
|
||||
ObjectID obj;
|
||||
StringName property;
|
||||
|
||||
void _notif_change();
|
||||
void _notif_changev(const String &p_v);
|
||||
void _set_key(const Variant &p_old_key, const Variant &p_new_key);
|
||||
void _set_value(const Variant &p_key, const Variant &p_value);
|
||||
|
||||
Variant get_dictionary() const;
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
bool _set(const StringName &p_name, const Variant &p_value);
|
||||
bool _get(const StringName &p_name, Variant &r_ret) const;
|
||||
void _get_property_list(List<PropertyInfo> *p_list) const;
|
||||
|
||||
public:
|
||||
void edit(Object *p_obj, const StringName &p_prop);
|
||||
|
||||
Node *get_node();
|
||||
|
||||
DictionaryPropertyEdit();
|
||||
};
|
||||
|
||||
#endif // DICTIONARY_PROPERTY_EDIT_H
|
|
@ -283,8 +283,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/editor/always_show_close_button_in_scene_tabs", false)) ? Tabs::CLOSE_BUTTON_SHOW_ALWAYS : Tabs::CLOSE_BUTTON_SHOW_ACTIVE_ONLY));
|
||||
property_editor->set_enable_capitalize_paths(bool(EDITOR_DEF("interface/editor/capitalize_properties", true)));
|
||||
Ref<Theme> theme = create_custom_theme(theme_base->get_theme());
|
||||
Ref<Theme> theme = create_editor_theme(theme_base->get_theme());
|
||||
|
||||
theme_base->set_theme(theme);
|
||||
gui_base->set_theme(theme);
|
||||
|
@ -1330,6 +1329,8 @@ void EditorNode::_prepare_history() {
|
|||
}
|
||||
} 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();
|
||||
}
|
||||
|
@ -1425,6 +1426,7 @@ void EditorNode::_edit_current() {
|
|||
|
||||
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);
|
||||
|
@ -1478,6 +1480,11 @@ void EditorNode::_edit_current() {
|
|||
|
||||
} else {
|
||||
|
||||
if (current_obj->is_class("ScriptEditorDebuggerInspectedObject")) {
|
||||
editable_warning = TTR("This is a remote object so changes to it will not be kept.\nPlease read the documentation relevant to debugging to better understand this workflow.");
|
||||
capitalize = false;
|
||||
}
|
||||
|
||||
property_editor->edit(current_obj);
|
||||
node_dock->set_node(NULL);
|
||||
}
|
||||
|
@ -1487,6 +1494,10 @@ void EditorNode::_edit_current() {
|
|||
property_editable_warning_dialog->set_text(editable_warning);
|
||||
}
|
||||
|
||||
if (property_editor->is_capitalize_paths_enabled() != capitalize) {
|
||||
property_editor->set_enable_capitalize_paths(capitalize);
|
||||
}
|
||||
|
||||
/* Take care of PLUGIN EDITOR */
|
||||
|
||||
EditorPlugin *main_plugin = editor_data.get_editor(current_obj);
|
||||
|
|
|
@ -149,14 +149,14 @@ void EditorPath::_notification(int p_what) {
|
|||
|
||||
if (name == "")
|
||||
name = r->get_class();
|
||||
} else if (Object::cast_to<Node>(obj)) {
|
||||
|
||||
} else if (obj->is_class("ScriptEditorDebuggerInspectedObject"))
|
||||
name = obj->call("get_title");
|
||||
else if (Object::cast_to<Node>(obj))
|
||||
name = Object::cast_to<Node>(obj)->get_name();
|
||||
} else if (Object::cast_to<Resource>(obj) && Object::cast_to<Resource>(obj)->get_name() != "") {
|
||||
else if (Object::cast_to<Resource>(obj) && Object::cast_to<Resource>(obj)->get_name() != "")
|
||||
name = Object::cast_to<Resource>(obj)->get_name();
|
||||
} else {
|
||||
else
|
||||
name = obj->get_class();
|
||||
}
|
||||
|
||||
set_tooltip(obj->get_class());
|
||||
|
||||
|
|
|
@ -40,6 +40,7 @@
|
|||
#include "core/project_settings.h"
|
||||
#include "editor/array_property_edit.h"
|
||||
#include "editor/create_dialog.h"
|
||||
#include "editor/dictionary_property_edit.h"
|
||||
#include "editor/editor_export.h"
|
||||
#include "editor/editor_file_system.h"
|
||||
#include "editor/editor_help.h"
|
||||
|
@ -1153,7 +1154,8 @@ void CustomPropertyEditor::_node_path_selected(NodePath p_path) {
|
|||
node = Object::cast_to<Node>(owner);
|
||||
else if (owner->is_class("ArrayPropertyEdit"))
|
||||
node = Object::cast_to<ArrayPropertyEdit>(owner)->get_node();
|
||||
|
||||
else if (owner->is_class("DictionaryPropertyEdit"))
|
||||
node = Object::cast_to<DictionaryPropertyEdit>(owner)->get_node();
|
||||
if (!node) {
|
||||
v = p_path;
|
||||
emit_signal("variant_changed");
|
||||
|
@ -3211,9 +3213,14 @@ void PropertyEditor::update_tree() {
|
|||
} break;
|
||||
case Variant::DICTIONARY: {
|
||||
|
||||
Variant v = obj->get(p.name);
|
||||
|
||||
item->set_cell_mode(1, TreeItem::CELL_MODE_STRING);
|
||||
item->set_editable(1, false);
|
||||
item->set_text(1, obj->get(p.name).operator String());
|
||||
item->set_text(1, String("Dictionary{") + itos(v.call("size")) + "}");
|
||||
item->add_button(1, get_icon("EditResource", "EditorIcons"));
|
||||
|
||||
if (show_type_icons)
|
||||
item->set_icon(0, get_icon("DictionaryData", "EditorIcons"));
|
||||
|
||||
} break;
|
||||
|
||||
|
@ -3412,7 +3419,9 @@ void PropertyEditor::update_tree() {
|
|||
type = p.hint_string;
|
||||
|
||||
RES res = obj->get(p.name).operator RefPtr();
|
||||
|
||||
if (type.begins_with("RES:") && type != "RES:") { // Remote resources
|
||||
res = ResourceLoader::load(type.substr(4, type.length()));
|
||||
}
|
||||
Ref<EncodedObjectAsID> encoded = obj->get(p.name); //for debugger and remote tools
|
||||
|
||||
if (encoded.is_valid()) {
|
||||
|
@ -3423,6 +3432,7 @@ void PropertyEditor::update_tree() {
|
|||
item->set_editable(1, true);
|
||||
|
||||
} else if (obj->get(p.name).get_type() == Variant::NIL || res.is_null()) {
|
||||
|
||||
item->set_text(1, "<null>");
|
||||
item->set_icon(1, Ref<Texture>());
|
||||
item->set_custom_as_button(1, false);
|
||||
|
@ -3581,7 +3591,7 @@ void PropertyEditor::_edit_set(const String &p_name, const Variant &p_value, boo
|
|||
}
|
||||
}
|
||||
|
||||
if (!undo_redo || Object::cast_to<ArrayPropertyEdit>(obj)) { //kind of hacky
|
||||
if (!undo_redo || Object::cast_to<ArrayPropertyEdit>(obj) || Object::cast_to<DictionaryPropertyEdit>(obj)) { //kind of hacky
|
||||
|
||||
obj->set(p_name, p_value);
|
||||
if (p_refresh_all)
|
||||
|
@ -3714,7 +3724,7 @@ void PropertyEditor::_item_edited() {
|
|||
_edit_set(name, item->get_text(1), refresh_all);
|
||||
}
|
||||
} break;
|
||||
// math types
|
||||
// math types
|
||||
|
||||
case Variant::VECTOR3: {
|
||||
|
||||
|
@ -3979,8 +3989,20 @@ void PropertyEditor::_edit_button(Object *p_item, int p_column, int p_button) {
|
|||
|
||||
Ref<ArrayPropertyEdit> ape = memnew(ArrayPropertyEdit);
|
||||
ape->edit(obj, n, ht, Variant::Type(t));
|
||||
|
||||
EditorNode::get_singleton()->push_item(ape.ptr());
|
||||
|
||||
} else if (t == Variant::DICTIONARY) {
|
||||
|
||||
Variant v = obj->get(n);
|
||||
|
||||
if (v.get_type() != t) {
|
||||
Variant::CallError ce;
|
||||
v = Variant::construct(Variant::Type(t), NULL, 0, ce);
|
||||
}
|
||||
|
||||
Ref<DictionaryPropertyEdit> dpe = memnew(DictionaryPropertyEdit);
|
||||
dpe->edit(obj, n);
|
||||
EditorNode::get_singleton()->push_item(dpe.ptr());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue