Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enable autoload in editor #18545

Merged
merged 1 commit into from
May 14, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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