Cleanup EditorNode and EditorData
Co-authored-by: Eric M <itsjusteza@gmail.com>
This commit is contained in:
+137
-178
@@ -38,12 +38,13 @@
|
||||
#include "editor/plugins/script_editor_plugin.h"
|
||||
#include "scene/resources/packed_scene.h"
|
||||
|
||||
void EditorHistory::cleanup_history() {
|
||||
void EditorSelectionHistory::cleanup_history() {
|
||||
for (int i = 0; i < history.size(); i++) {
|
||||
bool fail = false;
|
||||
|
||||
for (int j = 0; j < history[i].path.size(); j++) {
|
||||
if (!history[i].path[j].ref.is_null()) {
|
||||
// Reference is not null - object still alive.
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -51,21 +52,16 @@ void EditorHistory::cleanup_history() {
|
||||
if (obj) {
|
||||
Node *n = Object::cast_to<Node>(obj);
|
||||
if (n && n->is_inside_tree()) {
|
||||
// Node valid and inside tree - object still alive.
|
||||
continue;
|
||||
}
|
||||
if (!n) { // Possibly still alive
|
||||
if (!n) {
|
||||
// Node possibly still alive.
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (j <= history[i].level) {
|
||||
//before or equal level, complete fail
|
||||
fail = true;
|
||||
} else {
|
||||
//after level, clip
|
||||
history.write[i].path.resize(j);
|
||||
}
|
||||
} // Else: object not valid - not alive.
|
||||
|
||||
fail = true;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -75,16 +71,16 @@ void EditorHistory::cleanup_history() {
|
||||
}
|
||||
}
|
||||
|
||||
if (current >= history.size()) {
|
||||
current = history.size() - 1;
|
||||
if (current_elem_idx >= history.size()) {
|
||||
current_elem_idx = history.size() - 1;
|
||||
}
|
||||
}
|
||||
|
||||
void EditorHistory::_add_object(ObjectID p_object, const String &p_property, int p_level_change, bool p_inspector_only) {
|
||||
void EditorSelectionHistory::add_object(ObjectID p_object, const String &p_property, bool p_inspector_only) {
|
||||
Object *obj = ObjectDB::get_instance(p_object);
|
||||
ERR_FAIL_COND(!obj);
|
||||
RefCounted *r = Object::cast_to<RefCounted>(obj);
|
||||
Obj o;
|
||||
_Object o;
|
||||
if (r) {
|
||||
o.ref = REF(r);
|
||||
}
|
||||
@@ -92,86 +88,64 @@ void EditorHistory::_add_object(ObjectID p_object, const String &p_property, int
|
||||
o.property = p_property;
|
||||
o.inspector_only = p_inspector_only;
|
||||
|
||||
History h;
|
||||
|
||||
bool has_prev = current >= 0 && current < history.size();
|
||||
bool has_prev = current_elem_idx >= 0 && current_elem_idx < history.size();
|
||||
|
||||
if (has_prev) {
|
||||
history.resize(current + 1); //clip history to next
|
||||
history.resize(current_elem_idx + 1); // Clip history to next.
|
||||
}
|
||||
|
||||
HistoryElement h;
|
||||
if (!p_property.is_empty() && has_prev) {
|
||||
//add a sub property
|
||||
History &pr = history.write[current];
|
||||
h = pr;
|
||||
// Add a sub property.
|
||||
HistoryElement &prev_element = history.write[current_elem_idx];
|
||||
h = prev_element;
|
||||
h.path.resize(h.level + 1);
|
||||
h.path.push_back(o);
|
||||
h.level++;
|
||||
} else if (p_level_change != -1 && has_prev) {
|
||||
//add a sub property
|
||||
History &pr = history.write[current];
|
||||
h = pr;
|
||||
ERR_FAIL_INDEX(p_level_change, h.path.size());
|
||||
h.level = p_level_change;
|
||||
|
||||
} else {
|
||||
//add a new node
|
||||
// Create a new history item.
|
||||
h.path.push_back(o);
|
||||
h.level = 0;
|
||||
}
|
||||
|
||||
history.push_back(h);
|
||||
current++;
|
||||
current_elem_idx++;
|
||||
}
|
||||
|
||||
void EditorHistory::add_object_inspector_only(ObjectID p_object) {
|
||||
_add_object(p_object, "", -1, true);
|
||||
}
|
||||
|
||||
void EditorHistory::add_object(ObjectID p_object) {
|
||||
_add_object(p_object, "", -1);
|
||||
}
|
||||
|
||||
void EditorHistory::add_object(ObjectID p_object, const String &p_subprop) {
|
||||
_add_object(p_object, p_subprop, -1);
|
||||
}
|
||||
|
||||
void EditorHistory::add_object(ObjectID p_object, int p_relevel) {
|
||||
_add_object(p_object, "", p_relevel);
|
||||
}
|
||||
|
||||
int EditorHistory::get_history_len() {
|
||||
int EditorSelectionHistory::get_history_len() {
|
||||
return history.size();
|
||||
}
|
||||
|
||||
int EditorHistory::get_history_pos() {
|
||||
return current;
|
||||
int EditorSelectionHistory::get_history_pos() {
|
||||
return current_elem_idx;
|
||||
}
|
||||
|
||||
bool EditorHistory::is_history_obj_inspector_only(int p_obj) const {
|
||||
bool EditorSelectionHistory::is_history_obj_inspector_only(int p_obj) const {
|
||||
ERR_FAIL_INDEX_V(p_obj, history.size(), false);
|
||||
ERR_FAIL_INDEX_V(history[p_obj].level, history[p_obj].path.size(), false);
|
||||
return history[p_obj].path[history[p_obj].level].inspector_only;
|
||||
}
|
||||
|
||||
ObjectID EditorHistory::get_history_obj(int p_obj) const {
|
||||
ObjectID EditorSelectionHistory::get_history_obj(int p_obj) const {
|
||||
ERR_FAIL_INDEX_V(p_obj, history.size(), ObjectID());
|
||||
ERR_FAIL_INDEX_V(history[p_obj].level, history[p_obj].path.size(), ObjectID());
|
||||
return history[p_obj].path[history[p_obj].level].object;
|
||||
}
|
||||
|
||||
bool EditorHistory::is_at_beginning() const {
|
||||
return current <= 0;
|
||||
bool EditorSelectionHistory::is_at_beginning() const {
|
||||
return current_elem_idx <= 0;
|
||||
}
|
||||
|
||||
bool EditorHistory::is_at_end() const {
|
||||
return ((current + 1) >= history.size());
|
||||
bool EditorSelectionHistory::is_at_end() const {
|
||||
return ((current_elem_idx + 1) >= history.size());
|
||||
}
|
||||
|
||||
bool EditorHistory::next() {
|
||||
bool EditorSelectionHistory::next() {
|
||||
cleanup_history();
|
||||
|
||||
if ((current + 1) < history.size()) {
|
||||
current++;
|
||||
if ((current_elem_idx + 1) < history.size()) {
|
||||
current_elem_idx++;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
@@ -179,11 +153,11 @@ bool EditorHistory::next() {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool EditorHistory::previous() {
|
||||
bool EditorSelectionHistory::previous() {
|
||||
cleanup_history();
|
||||
|
||||
if (current > 0) {
|
||||
current--;
|
||||
if (current_elem_idx > 0) {
|
||||
current_elem_idx--;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
@@ -191,76 +165,63 @@ bool EditorHistory::previous() {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool EditorHistory::is_current_inspector_only() const {
|
||||
if (current < 0 || current >= history.size()) {
|
||||
bool EditorSelectionHistory::is_current_inspector_only() const {
|
||||
if (current_elem_idx < 0 || current_elem_idx >= history.size()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const History &h = history[current];
|
||||
const HistoryElement &h = history[current_elem_idx];
|
||||
return h.path[h.level].inspector_only;
|
||||
}
|
||||
|
||||
ObjectID EditorHistory::get_current() {
|
||||
if (current < 0 || current >= history.size()) {
|
||||
ObjectID EditorSelectionHistory::get_current() {
|
||||
if (current_elem_idx < 0 || current_elem_idx >= history.size()) {
|
||||
return ObjectID();
|
||||
}
|
||||
|
||||
History &h = history.write[current];
|
||||
Object *obj = ObjectDB::get_instance(h.path[h.level].object);
|
||||
if (!obj) {
|
||||
return ObjectID();
|
||||
}
|
||||
|
||||
return obj->get_instance_id();
|
||||
Object *obj = ObjectDB::get_instance(get_history_obj(current_elem_idx));
|
||||
return obj ? obj->get_instance_id() : ObjectID();
|
||||
}
|
||||
|
||||
int EditorHistory::get_path_size() const {
|
||||
if (current < 0 || current >= history.size()) {
|
||||
int EditorSelectionHistory::get_path_size() const {
|
||||
if (current_elem_idx < 0 || current_elem_idx >= history.size()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
const History &h = history[current];
|
||||
return h.path.size();
|
||||
return history[current_elem_idx].path.size();
|
||||
}
|
||||
|
||||
ObjectID EditorHistory::get_path_object(int p_index) const {
|
||||
if (current < 0 || current >= history.size()) {
|
||||
ObjectID EditorSelectionHistory::get_path_object(int p_index) const {
|
||||
if (current_elem_idx < 0 || current_elem_idx >= history.size()) {
|
||||
return ObjectID();
|
||||
}
|
||||
|
||||
const History &h = history[current];
|
||||
ERR_FAIL_INDEX_V(p_index, history[current_elem_idx].path.size(), ObjectID());
|
||||
|
||||
ERR_FAIL_INDEX_V(p_index, h.path.size(), ObjectID());
|
||||
|
||||
Object *obj = ObjectDB::get_instance(h.path[p_index].object);
|
||||
if (!obj) {
|
||||
return ObjectID();
|
||||
}
|
||||
|
||||
return obj->get_instance_id();
|
||||
Object *obj = ObjectDB::get_instance(history[current_elem_idx].path[p_index].object);
|
||||
return obj ? obj->get_instance_id() : ObjectID();
|
||||
}
|
||||
|
||||
String EditorHistory::get_path_property(int p_index) const {
|
||||
if (current < 0 || current >= history.size()) {
|
||||
String EditorSelectionHistory::get_path_property(int p_index) const {
|
||||
if (current_elem_idx < 0 || current_elem_idx >= history.size()) {
|
||||
return "";
|
||||
}
|
||||
|
||||
const History &h = history[current];
|
||||
|
||||
ERR_FAIL_INDEX_V(p_index, h.path.size(), "");
|
||||
|
||||
return h.path[p_index].property;
|
||||
ERR_FAIL_INDEX_V(p_index, history[current_elem_idx].path.size(), "");
|
||||
return history[current_elem_idx].path[p_index].property;
|
||||
}
|
||||
|
||||
void EditorHistory::clear() {
|
||||
void EditorSelectionHistory::clear() {
|
||||
history.clear();
|
||||
current = -1;
|
||||
current_elem_idx = -1;
|
||||
}
|
||||
|
||||
EditorHistory::EditorHistory() {
|
||||
current = -1;
|
||||
EditorSelectionHistory::EditorSelectionHistory() {
|
||||
current_elem_idx = -1;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
EditorPlugin *EditorData::get_editor(Object *p_object) {
|
||||
// We need to iterate backwards so that we can check user-created plugins first.
|
||||
// Otherwise, it would not be possible for plugins to handle CanvasItem and Spatial nodes.
|
||||
@@ -636,14 +597,14 @@ bool EditorData::check_and_update_scene(int p_idx) {
|
||||
|
||||
EditorProgress ep("update_scene", TTR("Updating Scene"), 2);
|
||||
ep.step(TTR("Storing local changes..."), 0);
|
||||
//pack first, so it stores diffs to previous version of saved scene
|
||||
// Pack first, so it stores diffs to previous version of saved scene.
|
||||
Error err = pscene->pack(edited_scene[p_idx].root);
|
||||
ERR_FAIL_COND_V(err != OK, false);
|
||||
ep.step(TTR("Updating scene..."), 1);
|
||||
Node *new_scene = pscene->instantiate(PackedScene::GEN_EDIT_STATE_MAIN);
|
||||
ERR_FAIL_COND_V(!new_scene, false);
|
||||
|
||||
//transfer selection
|
||||
// Transfer selection.
|
||||
List<Node *> new_selection;
|
||||
for (const Node *E : edited_scene.write[p_idx].selection) {
|
||||
NodePath p = edited_scene[p_idx].root->get_path_to(E);
|
||||
@@ -675,7 +636,6 @@ int EditorData::get_edited_scene() const {
|
||||
void EditorData::set_edited_scene(int p_idx) {
|
||||
ERR_FAIL_INDEX(p_idx, edited_scene.size());
|
||||
current_edited_scene = p_idx;
|
||||
//swap
|
||||
}
|
||||
|
||||
Node *EditorData::get_edited_scene_root(int p_idx) {
|
||||
@@ -850,23 +810,23 @@ NodePath EditorData::get_edited_scene_live_edit_root() {
|
||||
return edited_scene[current_edited_scene].live_edit_root;
|
||||
}
|
||||
|
||||
void EditorData::save_edited_scene_state(EditorSelection *p_selection, EditorHistory *p_history, const Dictionary &p_custom) {
|
||||
void EditorData::save_edited_scene_state(EditorSelection *p_selection, EditorSelectionHistory *p_history, const Dictionary &p_custom) {
|
||||
ERR_FAIL_INDEX(current_edited_scene, edited_scene.size());
|
||||
|
||||
EditedScene &es = edited_scene.write[current_edited_scene];
|
||||
es.selection = p_selection->get_full_selected_node_list();
|
||||
es.history_current = p_history->current;
|
||||
es.history_current = p_history->current_elem_idx;
|
||||
es.history_stored = p_history->history;
|
||||
es.editor_states = get_editor_states();
|
||||
es.custom_state = p_custom;
|
||||
}
|
||||
|
||||
Dictionary EditorData::restore_edited_scene_state(EditorSelection *p_selection, EditorHistory *p_history) {
|
||||
Dictionary EditorData::restore_edited_scene_state(EditorSelection *p_selection, EditorSelectionHistory *p_history) {
|
||||
ERR_FAIL_INDEX_V(current_edited_scene, edited_scene.size(), Dictionary());
|
||||
|
||||
EditedScene &es = edited_scene.write[current_edited_scene];
|
||||
|
||||
p_history->current = es.history_current;
|
||||
p_history->current_elem_idx = es.history_current;
|
||||
p_history->history = es.history_stored;
|
||||
|
||||
p_selection->clear();
|
||||
@@ -1033,12 +993,11 @@ void EditorData::script_class_load_icon_paths() {
|
||||
|
||||
EditorData::EditorData() {
|
||||
current_edited_scene = -1;
|
||||
|
||||
//load_imported_scenes_from_globals();
|
||||
script_class_load_icon_paths();
|
||||
}
|
||||
|
||||
///////////
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void EditorSelection::_node_removed(Node *p_node) {
|
||||
if (!selection.has(p_node)) {
|
||||
return;
|
||||
@@ -1050,7 +1009,7 @@ void EditorSelection::_node_removed(Node *p_node) {
|
||||
}
|
||||
selection.erase(p_node);
|
||||
changed = true;
|
||||
nl_changed = true;
|
||||
node_list_changed = true;
|
||||
}
|
||||
|
||||
void EditorSelection::add_node(Node *p_node) {
|
||||
@@ -1061,7 +1020,7 @@ void EditorSelection::add_node(Node *p_node) {
|
||||
}
|
||||
|
||||
changed = true;
|
||||
nl_changed = true;
|
||||
node_list_changed = true;
|
||||
Object *meta = nullptr;
|
||||
for (Object *E : editor_plugins) {
|
||||
meta = E->call("_get_editor_data", p_node);
|
||||
@@ -1072,32 +1031,92 @@ void EditorSelection::add_node(Node *p_node) {
|
||||
selection[p_node] = meta;
|
||||
|
||||
p_node->connect("tree_exiting", callable_mp(this, &EditorSelection::_node_removed), varray(p_node), CONNECT_ONESHOT);
|
||||
|
||||
//emit_signal(SNAME("selection_changed"));
|
||||
}
|
||||
|
||||
void EditorSelection::remove_node(Node *p_node) {
|
||||
ERR_FAIL_NULL(p_node);
|
||||
|
||||
if (!selection.has(p_node)) {
|
||||
return;
|
||||
}
|
||||
|
||||
changed = true;
|
||||
nl_changed = true;
|
||||
node_list_changed = true;
|
||||
Object *meta = selection[p_node];
|
||||
if (meta) {
|
||||
memdelete(meta);
|
||||
}
|
||||
selection.erase(p_node);
|
||||
|
||||
p_node->disconnect("tree_exiting", callable_mp(this, &EditorSelection::_node_removed));
|
||||
//emit_signal(SNAME("selection_changed"));
|
||||
}
|
||||
|
||||
bool EditorSelection::is_selected(Node *p_node) const {
|
||||
return selection.has(p_node);
|
||||
}
|
||||
|
||||
void EditorSelection::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("clear"), &EditorSelection::clear);
|
||||
ClassDB::bind_method(D_METHOD("add_node", "node"), &EditorSelection::add_node);
|
||||
ClassDB::bind_method(D_METHOD("remove_node", "node"), &EditorSelection::remove_node);
|
||||
ClassDB::bind_method(D_METHOD("get_selected_nodes"), &EditorSelection::get_selected_nodes);
|
||||
ClassDB::bind_method(D_METHOD("get_transformable_selected_nodes"), &EditorSelection::_get_transformable_selected_nodes);
|
||||
ClassDB::bind_method(D_METHOD("_emit_change"), &EditorSelection::_emit_change);
|
||||
ADD_SIGNAL(MethodInfo("selection_changed"));
|
||||
}
|
||||
|
||||
void EditorSelection::add_editor_plugin(Object *p_object) {
|
||||
editor_plugins.push_back(p_object);
|
||||
}
|
||||
|
||||
void EditorSelection::_update_node_list() {
|
||||
if (!node_list_changed) {
|
||||
return;
|
||||
}
|
||||
|
||||
selected_node_list.clear();
|
||||
|
||||
// If the selection does not have the parent of the selected node, then add the node to the node list.
|
||||
// However, if the parent is already selected, then adding this node is redundant as
|
||||
// it is included with the parent, so skip it.
|
||||
for (const KeyValue<Node *, Object *> &E : selection) {
|
||||
Node *parent = E.key;
|
||||
parent = parent->get_parent();
|
||||
bool skip = false;
|
||||
while (parent) {
|
||||
if (selection.has(parent)) {
|
||||
skip = true;
|
||||
break;
|
||||
}
|
||||
parent = parent->get_parent();
|
||||
}
|
||||
|
||||
if (skip) {
|
||||
continue;
|
||||
}
|
||||
selected_node_list.push_back(E.key);
|
||||
}
|
||||
|
||||
node_list_changed = true;
|
||||
}
|
||||
|
||||
void EditorSelection::update() {
|
||||
_update_node_list();
|
||||
|
||||
if (!changed) {
|
||||
return;
|
||||
}
|
||||
changed = false;
|
||||
if (!emitted) {
|
||||
emitted = true;
|
||||
call_deferred(SNAME("_emit_change"));
|
||||
}
|
||||
}
|
||||
|
||||
void EditorSelection::_emit_change() {
|
||||
emit_signal(SNAME("selection_changed"));
|
||||
emitted = false;
|
||||
}
|
||||
|
||||
Array EditorSelection::_get_transformable_selected_nodes() {
|
||||
Array ret;
|
||||
|
||||
@@ -1118,71 +1137,11 @@ TypedArray<Node> EditorSelection::get_selected_nodes() {
|
||||
return ret;
|
||||
}
|
||||
|
||||
void EditorSelection::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("clear"), &EditorSelection::clear);
|
||||
ClassDB::bind_method(D_METHOD("add_node", "node"), &EditorSelection::add_node);
|
||||
ClassDB::bind_method(D_METHOD("remove_node", "node"), &EditorSelection::remove_node);
|
||||
ClassDB::bind_method(D_METHOD("get_selected_nodes"), &EditorSelection::get_selected_nodes);
|
||||
ClassDB::bind_method(D_METHOD("get_transformable_selected_nodes"), &EditorSelection::_get_transformable_selected_nodes);
|
||||
ClassDB::bind_method(D_METHOD("_emit_change"), &EditorSelection::_emit_change);
|
||||
ADD_SIGNAL(MethodInfo("selection_changed"));
|
||||
}
|
||||
|
||||
void EditorSelection::add_editor_plugin(Object *p_object) {
|
||||
editor_plugins.push_back(p_object);
|
||||
}
|
||||
|
||||
void EditorSelection::_update_nl() {
|
||||
if (!nl_changed) {
|
||||
return;
|
||||
}
|
||||
|
||||
selected_node_list.clear();
|
||||
|
||||
for (const KeyValue<Node *, Object *> &E : selection) {
|
||||
Node *parent = E.key;
|
||||
parent = parent->get_parent();
|
||||
bool skip = false;
|
||||
while (parent) {
|
||||
if (selection.has(parent)) {
|
||||
skip = true;
|
||||
break;
|
||||
}
|
||||
parent = parent->get_parent();
|
||||
}
|
||||
|
||||
if (skip) {
|
||||
continue;
|
||||
}
|
||||
selected_node_list.push_back(E.key);
|
||||
}
|
||||
|
||||
nl_changed = true;
|
||||
}
|
||||
|
||||
void EditorSelection::update() {
|
||||
_update_nl();
|
||||
|
||||
if (!changed) {
|
||||
return;
|
||||
}
|
||||
changed = false;
|
||||
if (!emitted) {
|
||||
emitted = true;
|
||||
call_deferred(SNAME("_emit_change"));
|
||||
}
|
||||
}
|
||||
|
||||
void EditorSelection::_emit_change() {
|
||||
emit_signal(SNAME("selection_changed"));
|
||||
emitted = false;
|
||||
}
|
||||
|
||||
List<Node *> &EditorSelection::get_selected_node_list() {
|
||||
if (changed) {
|
||||
update();
|
||||
} else {
|
||||
_update_nl();
|
||||
_update_node_list();
|
||||
}
|
||||
return selected_node_list;
|
||||
}
|
||||
@@ -1202,7 +1161,7 @@ void EditorSelection::clear() {
|
||||
}
|
||||
|
||||
changed = true;
|
||||
nl_changed = true;
|
||||
node_list_changed = true;
|
||||
}
|
||||
|
||||
EditorSelection::EditorSelection() {
|
||||
|
||||
Reference in New Issue
Block a user