Skip to content

Commit

Permalink
Merge pull request #18545 from vnen/editor-autoload
Browse files Browse the repository at this point in the history
Enable autoload in editor
  • Loading branch information
reduz authored May 14, 2018
2 parents 92f1deb + decf178 commit 47d4a01
Show file tree
Hide file tree
Showing 10 changed files with 329 additions and 100 deletions.
2 changes: 2 additions & 0 deletions core/script_language.h
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,8 @@ class ScriptLanguage {

virtual void auto_indent_code(String &p_code, int p_from_line, int p_to_line) const = 0;
virtual void add_global_constant(const StringName &p_variable, const Variant &p_value) = 0;
virtual void add_named_global_constant(const StringName &p_name, const Variant &p_value) {}
virtual void remove_named_global_constant(const StringName &p_name) {}

/* MULTITHREAD FUNCTIONS */

Expand Down
164 changes: 152 additions & 12 deletions editor/editor_autoload_settings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@
#include "editor_node.h"
#include "global_constants.h"
#include "project_settings.h"
#include "scene/main/viewport.h"
#include "scene/resources/packed_scene.h"

#define PREVIEW_LIST_MAX_SIZE 10

Expand Down Expand Up @@ -155,8 +157,8 @@ void EditorAutoloadSettings::_autoload_edited() {
undo_redo->add_undo_method(ProjectSettings::get_singleton(), "set_order", selected_autoload, order);
undo_redo->add_undo_method(ProjectSettings::get_singleton(), "clear", name);

undo_redo->add_do_method(this, "update_autoload");
undo_redo->add_undo_method(this, "update_autoload");
undo_redo->add_do_method(this, "call_deferred", "update_autoload");
undo_redo->add_undo_method(this, "call_deferred", "update_autoload");

undo_redo->add_do_method(this, "emit_signal", autoload_changed);
undo_redo->add_undo_method(this, "emit_signal", autoload_changed);
Expand Down Expand Up @@ -187,8 +189,8 @@ void EditorAutoloadSettings::_autoload_edited() {
undo_redo->add_do_method(ProjectSettings::get_singleton(), "set_order", base, order);
undo_redo->add_undo_method(ProjectSettings::get_singleton(), "set_order", base, order);

undo_redo->add_do_method(this, "update_autoload");
undo_redo->add_undo_method(this, "update_autoload");
undo_redo->add_do_method(this, "call_deferred", "update_autoload");
undo_redo->add_undo_method(this, "call_deferred", "update_autoload");

undo_redo->add_do_method(this, "emit_signal", autoload_changed);
undo_redo->add_undo_method(this, "emit_signal", autoload_changed);
Expand Down Expand Up @@ -296,6 +298,18 @@ 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

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());
}
}

autoload_cache.clear();

tree->clear();
Expand All @@ -317,19 +331,44 @@ void EditorAutoloadSettings::update_autoload() {
if (name.empty())
continue;

AutoLoadInfo old_info;
if (to_remove.has(name)) {
old_info = to_remove[name];
}

AutoLoadInfo info;
info.name = pi.name;
info.order = ProjectSettings::get_singleton()->get_order(pi.name);
info.is_singleton = path.begins_with("*");

autoload_cache.push_back(info);
if (info.is_singleton) {
path = path.substr(1, path.length());
}

bool global = false;
info.name = name;
info.path = path;
info.order = ProjectSettings::get_singleton()->get_order(pi.name);

if (path.begins_with("*")) {
global = true;
path = path.substr(1, path.length());
if (old_info.name == info.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);
} else {
to_add_singleton.push_back(name);
}
}
} else {
// Resource changed
to_add.push_back(info);
}
} else {
// New autoload
to_add.push_back(info);
}

autoload_cache.push_back(info);

TreeItem *item = tree->create_item(root);
item->set_text(0, name);
item->set_editable(0, true);
Expand All @@ -340,14 +379,85 @@ void EditorAutoloadSettings::update_autoload() {
item->set_cell_mode(2, TreeItem::CELL_MODE_CHECK);
item->set_editable(2, true);
item->set_text(2, TTR("Enable"));
item->set_checked(2, global);
item->set_checked(2, info.is_singleton);
item->add_button(3, get_icon("FileList", "EditorIcons"), BUTTON_OPEN);
item->add_button(3, get_icon("MoveUp", "EditorIcons"), BUTTON_MOVE_UP);
item->add_button(3, get_icon("MoveDown", "EditorIcons"), BUTTON_MOVE_DOWN);
item->add_button(3, get_icon("Remove", "EditorIcons"), BUTTON_DELETE);
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
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);
}

// 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);
}
}

// Add new nodes to the tree
List<Node *> nodes_to_add;
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());
}

ERR_EXPLAIN("Path in autoload not a node or script: " + info.path);
ERR_CONTINUE(!n);
n->set_name(info.name);

//defer so references are all valid on _ready()
nodes_to_add.push_back(n);

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);
}
}
}

for (List<Node *>::Element *E = nodes_to_add.front(); E; E = E->next()) {
get_tree()->get_root()->add_child(E->get());
}

updating_autoload = false;
}

Expand Down Expand Up @@ -592,6 +702,36 @@ void EditorAutoloadSettings::_bind_methods() {

EditorAutoloadSettings::EditorAutoloadSettings() {

// Make first cache
List<PropertyInfo> props;
ProjectSettings::get_singleton()->get_property_list(&props);
for (List<PropertyInfo>::Element *E = props.front(); E; E = E->next()) {

const PropertyInfo &pi = E->get();

if (!pi.name.begins_with("autoload/"))
continue;

String name = pi.name.get_slice("/", 1);
String path = ProjectSettings::get_singleton()->get(pi.name);

if (name.empty())
continue;

AutoLoadInfo info;
info.is_singleton = path.begins_with("*");

if (info.is_singleton) {
path = path.substr(1, path.length());
}

info.name = name;
info.path = path;
info.order = ProjectSettings::get_singleton()->get_order(pi.name);

autoload_cache.push_back(info);
}

autoload_changed = "autoload_changed";

updating_autoload = false;
Expand Down
2 changes: 2 additions & 0 deletions editor/editor_autoload_settings.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ class EditorAutoloadSettings : public VBoxContainer {

struct AutoLoadInfo {
String name;
String path;
bool is_singleton;
int order;

bool operator==(const AutoLoadInfo &p_info) {
Expand Down
Loading

0 comments on commit 47d4a01

Please sign in to comment.