You've already forked godot
mirror of
https://github.com/godotengine/godot.git
synced 2025-11-10 13:00:37 +00:00
Rewrite code for unfolding and make it automatic on scene load, which works better.
This commit is contained in:
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#include "core/os/file_access.h"
|
#include "core/os/file_access.h"
|
||||||
#include "editor_settings.h"
|
#include "editor_settings.h"
|
||||||
|
#include "editor_inspector.h"
|
||||||
|
|
||||||
PoolVector<String> EditorFolding::_get_unfolds(const Object *p_object) {
|
PoolVector<String> EditorFolding::_get_unfolds(const Object *p_object) {
|
||||||
|
|
||||||
@@ -171,5 +172,89 @@ bool EditorFolding::has_folding_data(const String &p_path) {
|
|||||||
return FileAccess::exists(file);
|
return FileAccess::exists(file);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void EditorFolding::_do_object_unfolds(Object *p_object, Set<RES> &resources) {
|
||||||
|
|
||||||
|
List<PropertyInfo> plist;
|
||||||
|
p_object->get_property_list(&plist);
|
||||||
|
String group_base;
|
||||||
|
String group;
|
||||||
|
|
||||||
|
Set<String> unfold_group;
|
||||||
|
|
||||||
|
for (List<PropertyInfo>::Element *E = plist.front(); E; E = E->next()) {
|
||||||
|
|
||||||
|
if (E->get().usage & PROPERTY_USAGE_CATEGORY) {
|
||||||
|
group="";
|
||||||
|
group_base="";
|
||||||
|
}
|
||||||
|
if (E->get().usage & PROPERTY_USAGE_GROUP) {
|
||||||
|
group = E->get().name;
|
||||||
|
group_base = E->get().hint_string;
|
||||||
|
if (group_base.ends_with("_")) {
|
||||||
|
group_base=group_base.substr(0,group_base.length()-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//can unfold
|
||||||
|
if (E->get().usage & PROPERTY_USAGE_EDITOR) {
|
||||||
|
|
||||||
|
|
||||||
|
if (group != "") { //group
|
||||||
|
if (group_base==String() || E->get().name.begins_with(group_base)) {
|
||||||
|
bool can_revert = EditorPropertyRevert::can_property_revert(p_object,E->get().name);
|
||||||
|
if (can_revert) {
|
||||||
|
unfold_group.insert(group);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else { //path
|
||||||
|
int last = E->get().name.find_last("/");
|
||||||
|
if (last!=-1) {
|
||||||
|
bool can_revert = EditorPropertyRevert::can_property_revert(p_object,E->get().name);
|
||||||
|
if (can_revert) {
|
||||||
|
unfold_group.insert(E->get().name.substr(0,last));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (E->get().type == Variant::OBJECT) {
|
||||||
|
RES res = p_object->get(E->get().name);
|
||||||
|
if (res.is_valid() && !resources.has(res) && res->get_path() != String() && !res->get_path().is_resource_file()) {
|
||||||
|
|
||||||
|
resources.insert(res);
|
||||||
|
_do_object_unfolds(res.ptr(),resources);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Set<String>::Element *E=unfold_group.front();E;E=E->next()) {
|
||||||
|
p_object->editor_set_section_unfold(E->get(),true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void EditorFolding::_do_node_unfolds(Node *p_root, Node *p_node, Set<RES> &resources) {
|
||||||
|
if (p_root != p_node) {
|
||||||
|
if (!p_node->get_owner()) {
|
||||||
|
return; //not owned, bye
|
||||||
|
}
|
||||||
|
if (p_node->get_owner() != p_root && !p_root->is_editable_instance(p_node)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_do_object_unfolds(p_node,resources);
|
||||||
|
|
||||||
|
for (int i = 0; i < p_node->get_child_count(); i++) {
|
||||||
|
_do_node_unfolds(p_root, p_node->get_child(i), resources);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void EditorFolding::unfold_scene(Node *p_scene) {
|
||||||
|
|
||||||
|
Set<RES> resources;
|
||||||
|
_do_node_unfolds(p_scene,p_scene,resources);
|
||||||
|
}
|
||||||
|
|
||||||
EditorFolding::EditorFolding() {
|
EditorFolding::EditorFolding() {
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,9 @@ class EditorFolding {
|
|||||||
|
|
||||||
void _fill_folds(const Node *p_root, const Node *p_node, Array &p_folds, Array &resource_folds, Set<RES> &resources);
|
void _fill_folds(const Node *p_root, const Node *p_node, Array &p_folds, Array &resource_folds, Set<RES> &resources);
|
||||||
|
|
||||||
|
void _do_object_unfolds(Object *p_object, Set<RES> &resources);
|
||||||
|
void _do_node_unfolds(Node *p_root, Node *p_node, Set<RES> &resources);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void save_resource_folding(const RES &p_resource, const String &p_path);
|
void save_resource_folding(const RES &p_resource, const String &p_path);
|
||||||
void load_resource_folding(RES p_resource, const String &p_path);
|
void load_resource_folding(RES p_resource, const String &p_path);
|
||||||
@@ -17,6 +20,8 @@ public:
|
|||||||
void save_scene_folding(const Node *p_scene, const String &p_path);
|
void save_scene_folding(const Node *p_scene, const String &p_path);
|
||||||
void load_scene_folding(Node *p_scene, const String &p_path);
|
void load_scene_folding(Node *p_scene, const String &p_path);
|
||||||
|
|
||||||
|
void unfold_scene(Node *p_scene);
|
||||||
|
|
||||||
bool has_folding_data(const String &p_path);
|
bool has_folding_data(const String &p_path);
|
||||||
|
|
||||||
EditorFolding();
|
EditorFolding();
|
||||||
|
|||||||
@@ -297,16 +297,12 @@ bool EditorProperty::is_read_only() const {
|
|||||||
return read_only;
|
return read_only;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool EditorProperty::_might_be_in_instance() {
|
bool EditorPropertyRevert::may_node_be_in_instance(Node *p_node) {
|
||||||
|
|
||||||
if (!object)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
Node *node = Object::cast_to<Node>(object);
|
|
||||||
|
|
||||||
Node *edited_scene = EditorNode::get_singleton()->get_edited_scene();
|
Node *edited_scene = EditorNode::get_singleton()->get_edited_scene();
|
||||||
|
|
||||||
bool might_be = false;
|
bool might_be = false;
|
||||||
|
Node *node = p_node;
|
||||||
|
|
||||||
while (node) {
|
while (node) {
|
||||||
|
|
||||||
@@ -328,13 +324,9 @@ bool EditorProperty::_might_be_in_instance() {
|
|||||||
return might_be; // or might not be
|
return might_be; // or might not be
|
||||||
}
|
}
|
||||||
|
|
||||||
bool EditorProperty::_get_instanced_node_original_property(const StringName &p_prop, Variant &value) {
|
bool EditorPropertyRevert::get_instanced_node_original_property(Node *p_node, const StringName &p_prop, Variant &value) {
|
||||||
|
|
||||||
Node *node = Object::cast_to<Node>(object);
|
|
||||||
|
|
||||||
if (!node)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
|
Node *node = p_node;
|
||||||
Node *orig = node;
|
Node *orig = node;
|
||||||
|
|
||||||
Node *edited_scene = EditorNode::get_singleton()->get_edited_scene();
|
Node *edited_scene = EditorNode::get_singleton()->get_edited_scene();
|
||||||
@@ -376,7 +368,7 @@ bool EditorProperty::_get_instanced_node_original_property(const StringName &p_p
|
|||||||
|
|
||||||
if (!found) {
|
if (!found) {
|
||||||
//if not found, try default class value
|
//if not found, try default class value
|
||||||
Variant attempt = ClassDB::class_get_default_property_value(object->get_class_name(), property);
|
Variant attempt = ClassDB::class_get_default_property_value(node->get_class_name(), p_prop);
|
||||||
if (attempt.get_type() != Variant::NIL) {
|
if (attempt.get_type() != Variant::NIL) {
|
||||||
found = true;
|
found = true;
|
||||||
value = attempt;
|
value = attempt;
|
||||||
@@ -386,14 +378,14 @@ bool EditorProperty::_get_instanced_node_original_property(const StringName &p_p
|
|||||||
return found;
|
return found;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool EditorProperty::_is_property_different(const Variant &p_current, const Variant &p_orig) {
|
bool EditorPropertyRevert::is_node_property_different(Node *p_node, const Variant &p_current, const Variant &p_orig) {
|
||||||
|
|
||||||
// this is a pretty difficult function, because a property may not be saved but may have
|
// this is a pretty difficult function, because a property may not be saved but may have
|
||||||
// the flag to not save if one or if zero
|
// the flag to not save if one or if zero
|
||||||
|
|
||||||
//make sure there is an actual state
|
//make sure there is an actual state
|
||||||
{
|
{
|
||||||
Node *node = Object::cast_to<Node>(object);
|
Node *node = p_node;
|
||||||
if (!node)
|
if (!node)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@@ -435,45 +427,54 @@ bool EditorProperty::_is_property_different(const Variant &p_current, const Vari
|
|||||||
return bool(Variant::evaluate(Variant::OP_NOT_EQUAL, p_current, p_orig));
|
return bool(Variant::evaluate(Variant::OP_NOT_EQUAL, p_current, p_orig));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool EditorPropertyRevert::can_property_revert(Object *p_object, const StringName &p_property) {
|
||||||
|
|
||||||
|
bool has_revert = false;
|
||||||
|
|
||||||
|
Node *node = Object::cast_to<Node>(p_object);
|
||||||
|
|
||||||
|
if (node && EditorPropertyRevert::may_node_be_in_instance(node)) {
|
||||||
|
//check for difference including instantiation
|
||||||
|
Variant vorig;
|
||||||
|
if (EditorPropertyRevert::get_instanced_node_original_property(node, p_property, vorig)) {
|
||||||
|
Variant v = p_object->get(p_property);
|
||||||
|
|
||||||
|
if (EditorPropertyRevert::is_node_property_different(node, v, vorig)) {
|
||||||
|
has_revert = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
//check for difference against default class value instead
|
||||||
|
Variant default_value = ClassDB::class_get_default_property_value(p_object->get_class_name(), p_property);
|
||||||
|
if (default_value != Variant() && default_value != p_object->get(p_property)) {
|
||||||
|
has_revert = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (p_object->call("property_can_revert", p_property).operator bool()) {
|
||||||
|
|
||||||
|
has_revert = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!has_revert && !p_object->get_script().is_null()) {
|
||||||
|
Ref<Script> scr = p_object->get_script();
|
||||||
|
Variant orig_value;
|
||||||
|
if (scr->get_property_default_value(p_property, orig_value)) {
|
||||||
|
if (orig_value != p_object->get(p_property)) {
|
||||||
|
has_revert = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return has_revert;
|
||||||
|
}
|
||||||
|
|
||||||
void EditorProperty::update_reload_status() {
|
void EditorProperty::update_reload_status() {
|
||||||
|
|
||||||
if (property == StringName())
|
if (property == StringName())
|
||||||
return; //no property, so nothing to do
|
return; //no property, so nothing to do
|
||||||
|
|
||||||
bool has_reload = false;
|
bool has_reload = EditorPropertyRevert::can_property_revert(object, property);
|
||||||
|
|
||||||
if (_might_be_in_instance()) {
|
|
||||||
//check for difference including instantiation
|
|
||||||
Variant vorig;
|
|
||||||
if (_get_instanced_node_original_property(property, vorig)) {
|
|
||||||
Variant v = object->get(property);
|
|
||||||
|
|
||||||
if (_is_property_different(v, vorig)) {
|
|
||||||
has_reload = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
//check for difference against default class value instead
|
|
||||||
Variant default_value = ClassDB::class_get_default_property_value(object->get_class_name(), property);
|
|
||||||
if (default_value != Variant() && default_value != object->get(property)) {
|
|
||||||
has_reload = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (object->call("property_can_revert", property).operator bool()) {
|
|
||||||
|
|
||||||
has_reload = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!has_reload && !object->get_script().is_null()) {
|
|
||||||
Ref<Script> scr = object->get_script();
|
|
||||||
Variant orig_value;
|
|
||||||
if (scr->get_property_default_value(property, orig_value)) {
|
|
||||||
if (orig_value != object->get(property)) {
|
|
||||||
has_reload = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (has_reload != can_revert) {
|
if (has_reload != can_revert) {
|
||||||
can_revert = has_reload;
|
can_revert = has_reload;
|
||||||
@@ -638,7 +639,8 @@ void EditorProperty::_gui_input(const Ref<InputEvent> &p_event) {
|
|||||||
|
|
||||||
Variant vorig;
|
Variant vorig;
|
||||||
|
|
||||||
if (_might_be_in_instance() && _get_instanced_node_original_property(property, vorig)) {
|
Node *node = Object::cast_to<Node>(object);
|
||||||
|
if (node && EditorPropertyRevert::may_node_be_in_instance(node) && EditorPropertyRevert::get_instanced_node_original_property(node, property, vorig)) {
|
||||||
|
|
||||||
emit_signal("property_changed", property, vorig.duplicate(true));
|
emit_signal("property_changed", property, vorig.duplicate(true));
|
||||||
update_property();
|
update_property();
|
||||||
@@ -1380,28 +1382,6 @@ void EditorInspector::update_tree() {
|
|||||||
|
|
||||||
// TreeItem *current_category = NULL;
|
// TreeItem *current_category = NULL;
|
||||||
|
|
||||||
bool unfold_if_edited = false;
|
|
||||||
|
|
||||||
if (use_folding && auto_unfold_edited && get_tree()->get_edited_scene_root()) {
|
|
||||||
String path;
|
|
||||||
Node *node = Object::cast_to<Node>(object);
|
|
||||||
if (node) {
|
|
||||||
path = get_tree()->get_edited_scene_root()->get_filename();
|
|
||||||
}
|
|
||||||
Resource *res = Object::cast_to<Resource>(object);
|
|
||||||
if (res) {
|
|
||||||
if (res->get_path().is_resource_file()) {
|
|
||||||
path = res->get_path();
|
|
||||||
} else if (res->get_path().begins_with("res://")) { //internal resource
|
|
||||||
path = get_tree()->get_edited_scene_root()->get_filename();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!EditorNode::get_singleton()->get_editor_folding().has_folding_data(path)) {
|
|
||||||
unfold_if_edited = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
String filter = search_box ? search_box->get_text() : "";
|
String filter = search_box ? search_box->get_text() : "";
|
||||||
String group;
|
String group;
|
||||||
String group_base;
|
String group_base;
|
||||||
@@ -1721,13 +1701,6 @@ void EditorInspector::update_tree() {
|
|||||||
if (current_selected && ep->property == current_selected) {
|
if (current_selected && ep->property == current_selected) {
|
||||||
ep->select(current_focusable);
|
ep->select(current_focusable);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (unfold_if_edited && ep->can_revert_to_default()) {
|
|
||||||
//if edited and there is a parent section, unfold it.
|
|
||||||
if (current_vbox && section_map.has(current_vbox)) {
|
|
||||||
section_map[current_vbox]->unfold();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2224,10 +2197,6 @@ String EditorInspector::get_object_class() const {
|
|||||||
return object_class;
|
return object_class;
|
||||||
}
|
}
|
||||||
|
|
||||||
void EditorInspector::set_auto_unfold_edited(bool p_enable) {
|
|
||||||
auto_unfold_edited = p_enable;
|
|
||||||
}
|
|
||||||
|
|
||||||
void EditorInspector::_bind_methods() {
|
void EditorInspector::_bind_methods() {
|
||||||
|
|
||||||
ClassDB::bind_method("_property_changed", &EditorInspector::_property_changed, DEFVAL(false));
|
ClassDB::bind_method("_property_changed", &EditorInspector::_property_changed, DEFVAL(false));
|
||||||
@@ -2284,7 +2253,6 @@ EditorInspector::EditorInspector() {
|
|||||||
set_process(true);
|
set_process(true);
|
||||||
property_focusable = -1;
|
property_focusable = -1;
|
||||||
use_sub_inspector_bg = false;
|
use_sub_inspector_bg = false;
|
||||||
auto_unfold_edited = false;
|
|
||||||
|
|
||||||
get_v_scrollbar()->connect("value_changed", this, "_vscroll_changed");
|
get_v_scrollbar()->connect("value_changed", this, "_vscroll_changed");
|
||||||
update_scroll_request = -1;
|
update_scroll_request = -1;
|
||||||
|
|||||||
@@ -37,6 +37,15 @@
|
|||||||
|
|
||||||
class UndoRedo;
|
class UndoRedo;
|
||||||
|
|
||||||
|
class EditorPropertyRevert {
|
||||||
|
public:
|
||||||
|
static bool may_node_be_in_instance(Node *p_node);
|
||||||
|
static bool get_instanced_node_original_property(Node *p_node, const StringName &p_prop, Variant &value);
|
||||||
|
static bool is_node_property_different(Node *p_node, const Variant &p_current, const Variant &p_orig);
|
||||||
|
|
||||||
|
static bool can_property_revert(Object *p_object, const StringName &p_property);
|
||||||
|
};
|
||||||
|
|
||||||
class EditorProperty : public Container {
|
class EditorProperty : public Container {
|
||||||
|
|
||||||
GDCLASS(EditorProperty, Container)
|
GDCLASS(EditorProperty, Container)
|
||||||
@@ -70,7 +79,6 @@ private:
|
|||||||
bool use_folding;
|
bool use_folding;
|
||||||
bool draw_top_bg;
|
bool draw_top_bg;
|
||||||
|
|
||||||
bool _might_be_in_instance();
|
|
||||||
bool _is_property_different(const Variant &p_current, const Variant &p_orig);
|
bool _is_property_different(const Variant &p_current, const Variant &p_orig);
|
||||||
bool _get_instanced_node_original_property(const StringName &p_prop, Variant &value);
|
bool _get_instanced_node_original_property(const StringName &p_prop, Variant &value);
|
||||||
void _focusable_focused(int p_index);
|
void _focusable_focused(int p_index);
|
||||||
@@ -272,7 +280,6 @@ class EditorInspector : public ScrollContainer {
|
|||||||
bool read_only;
|
bool read_only;
|
||||||
bool keying;
|
bool keying;
|
||||||
bool use_sub_inspector_bg;
|
bool use_sub_inspector_bg;
|
||||||
bool auto_unfold_edited;
|
|
||||||
|
|
||||||
float refresh_countdown;
|
float refresh_countdown;
|
||||||
bool update_tree_pending;
|
bool update_tree_pending;
|
||||||
@@ -367,7 +374,6 @@ public:
|
|||||||
String get_object_class() const;
|
String get_object_class() const;
|
||||||
|
|
||||||
void set_use_sub_inspector_bg(bool p_enable);
|
void set_use_sub_inspector_bg(bool p_enable);
|
||||||
void set_auto_unfold_edited(bool p_enable);
|
|
||||||
|
|
||||||
EditorInspector();
|
EditorInspector();
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -2926,7 +2926,12 @@ Error EditorNode::load_scene(const String &p_scene, bool p_ignore_broken_deps, b
|
|||||||
_update_scene_tabs();
|
_update_scene_tabs();
|
||||||
_add_to_recent_scenes(lpath);
|
_add_to_recent_scenes(lpath);
|
||||||
|
|
||||||
editor_folding.load_scene_folding(new_scene, lpath);
|
if (editor_folding.has_folding_data(lpath)) {
|
||||||
|
editor_folding.load_scene_folding(new_scene, lpath);
|
||||||
|
} else if (EDITOR_GET("interface/inspector/auto_unfold_foreign_scenes")) {
|
||||||
|
editor_folding.unfold_scene(new_scene);
|
||||||
|
editor_folding.save_scene_folding(new_scene, lpath);
|
||||||
|
}
|
||||||
|
|
||||||
prev_scene->set_disabled(previous_scenes.size() == 0);
|
prev_scene->set_disabled(previous_scenes.size() == 0);
|
||||||
opening_prev = false;
|
opening_prev = false;
|
||||||
@@ -4878,7 +4883,7 @@ EditorNode::EditorNode() {
|
|||||||
EDITOR_DEF_RST("interface/scene_tabs/show_thumbnail_on_hover", true);
|
EDITOR_DEF_RST("interface/scene_tabs/show_thumbnail_on_hover", true);
|
||||||
EDITOR_DEF_RST("interface/inspector/capitalize_properties", true);
|
EDITOR_DEF_RST("interface/inspector/capitalize_properties", true);
|
||||||
EDITOR_DEF_RST("interface/inspector/disable_folding", false);
|
EDITOR_DEF_RST("interface/inspector/disable_folding", false);
|
||||||
EDITOR_DEF_RST("interface/inspector/auto_unfold_edited", true);
|
EDITOR_DEF_RST("interface/inspector/auto_unfold_foreign_scenes", true);
|
||||||
EDITOR_DEF("interface/inspector/horizontal_vector2_editing", false);
|
EDITOR_DEF("interface/inspector/horizontal_vector2_editing", false);
|
||||||
EDITOR_DEF("interface/inspector/horizontal_vector_types_editing", true);
|
EDITOR_DEF("interface/inspector/horizontal_vector_types_editing", true);
|
||||||
EDITOR_DEF("interface/inspector/open_resources_in_current_inspector", true);
|
EDITOR_DEF("interface/inspector/open_resources_in_current_inspector", true);
|
||||||
|
|||||||
@@ -593,7 +593,6 @@ InspectorDock::InspectorDock(EditorNode *p_editor, EditorData &p_editor_data) {
|
|||||||
inspector->set_undo_redo(&editor_data->get_undo_redo());
|
inspector->set_undo_redo(&editor_data->get_undo_redo());
|
||||||
|
|
||||||
inspector->set_use_filter(true); // TODO: check me
|
inspector->set_use_filter(true); // TODO: check me
|
||||||
inspector->set_auto_unfold_edited(bool(EDITOR_GET("interface/inspector/auto_unfold_edited")));
|
|
||||||
|
|
||||||
inspector->connect("resource_selected", this, "_resource_selected");
|
inspector->connect("resource_selected", this, "_resource_selected");
|
||||||
inspector->connect("property_keyed", this, "_property_keyed");
|
inspector->connect("property_keyed", this, "_property_keyed");
|
||||||
|
|||||||
Reference in New Issue
Block a user