Merge pull request #18545 from vnen/editor-autoload
Enable autoload in editor
This commit is contained in:
commit
47d4a011d8
|
@ -236,6 +236,8 @@ public:
|
||||||
|
|
||||||
virtual void auto_indent_code(String &p_code, int p_from_line, int p_to_line) const = 0;
|
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_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 */
|
/* MULTITHREAD FUNCTIONS */
|
||||||
|
|
||||||
|
|
|
@ -33,6 +33,8 @@
|
||||||
#include "editor_node.h"
|
#include "editor_node.h"
|
||||||
#include "global_constants.h"
|
#include "global_constants.h"
|
||||||
#include "project_settings.h"
|
#include "project_settings.h"
|
||||||
|
#include "scene/main/viewport.h"
|
||||||
|
#include "scene/resources/packed_scene.h"
|
||||||
|
|
||||||
#define PREVIEW_LIST_MAX_SIZE 10
|
#define PREVIEW_LIST_MAX_SIZE 10
|
||||||
|
|
||||||
|
@ -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(), "set_order", selected_autoload, order);
|
||||||
undo_redo->add_undo_method(ProjectSettings::get_singleton(), "clear", name);
|
undo_redo->add_undo_method(ProjectSettings::get_singleton(), "clear", name);
|
||||||
|
|
||||||
undo_redo->add_do_method(this, "update_autoload");
|
undo_redo->add_do_method(this, "call_deferred", "update_autoload");
|
||||||
undo_redo->add_undo_method(this, "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_do_method(this, "emit_signal", autoload_changed);
|
||||||
undo_redo->add_undo_method(this, "emit_signal", autoload_changed);
|
undo_redo->add_undo_method(this, "emit_signal", autoload_changed);
|
||||||
|
@ -187,8 +189,8 @@ void EditorAutoloadSettings::_autoload_edited() {
|
||||||
undo_redo->add_do_method(ProjectSettings::get_singleton(), "set_order", base, order);
|
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_undo_method(ProjectSettings::get_singleton(), "set_order", base, order);
|
||||||
|
|
||||||
undo_redo->add_do_method(this, "update_autoload");
|
undo_redo->add_do_method(this, "call_deferred", "update_autoload");
|
||||||
undo_redo->add_undo_method(this, "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_do_method(this, "emit_signal", autoload_changed);
|
||||||
undo_redo->add_undo_method(this, "emit_signal", autoload_changed);
|
undo_redo->add_undo_method(this, "emit_signal", autoload_changed);
|
||||||
|
@ -296,6 +298,18 @@ void EditorAutoloadSettings::update_autoload() {
|
||||||
|
|
||||||
updating_autoload = true;
|
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();
|
autoload_cache.clear();
|
||||||
|
|
||||||
tree->clear();
|
tree->clear();
|
||||||
|
@ -317,19 +331,44 @@ void EditorAutoloadSettings::update_autoload() {
|
||||||
if (name.empty())
|
if (name.empty())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
AutoLoadInfo old_info;
|
||||||
|
if (to_remove.has(name)) {
|
||||||
|
old_info = to_remove[name];
|
||||||
|
}
|
||||||
|
|
||||||
AutoLoadInfo info;
|
AutoLoadInfo info;
|
||||||
info.name = pi.name;
|
info.is_singleton = path.begins_with("*");
|
||||||
info.order = ProjectSettings::get_singleton()->get_order(pi.name);
|
|
||||||
|
|
||||||
autoload_cache.push_back(info);
|
if (info.is_singleton) {
|
||||||
|
|
||||||
bool global = false;
|
|
||||||
|
|
||||||
if (path.begins_with("*")) {
|
|
||||||
global = true;
|
|
||||||
path = path.substr(1, path.length());
|
path = path.substr(1, path.length());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
info.name = name;
|
||||||
|
info.path = path;
|
||||||
|
info.order = ProjectSettings::get_singleton()->get_order(pi.name);
|
||||||
|
|
||||||
|
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);
|
TreeItem *item = tree->create_item(root);
|
||||||
item->set_text(0, name);
|
item->set_text(0, name);
|
||||||
item->set_editable(0, true);
|
item->set_editable(0, true);
|
||||||
|
@ -340,7 +379,7 @@ void EditorAutoloadSettings::update_autoload() {
|
||||||
item->set_cell_mode(2, TreeItem::CELL_MODE_CHECK);
|
item->set_cell_mode(2, TreeItem::CELL_MODE_CHECK);
|
||||||
item->set_editable(2, true);
|
item->set_editable(2, true);
|
||||||
item->set_text(2, TTR("Enable"));
|
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("FileList", "EditorIcons"), BUTTON_OPEN);
|
||||||
item->add_button(3, get_icon("MoveUp", "EditorIcons"), BUTTON_MOVE_UP);
|
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("MoveDown", "EditorIcons"), BUTTON_MOVE_DOWN);
|
||||||
|
@ -348,6 +387,77 @@ void EditorAutoloadSettings::update_autoload() {
|
||||||
item->set_selectable(3, false);
|
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;
|
updating_autoload = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -592,6 +702,36 @@ void EditorAutoloadSettings::_bind_methods() {
|
||||||
|
|
||||||
EditorAutoloadSettings::EditorAutoloadSettings() {
|
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";
|
autoload_changed = "autoload_changed";
|
||||||
|
|
||||||
updating_autoload = false;
|
updating_autoload = false;
|
||||||
|
|
|
@ -50,6 +50,8 @@ class EditorAutoloadSettings : public VBoxContainer {
|
||||||
|
|
||||||
struct AutoLoadInfo {
|
struct AutoLoadInfo {
|
||||||
String name;
|
String name;
|
||||||
|
String path;
|
||||||
|
bool is_singleton;
|
||||||
int order;
|
int order;
|
||||||
|
|
||||||
bool operator==(const AutoLoadInfo &p_info) {
|
bool operator==(const AutoLoadInfo &p_info) {
|
||||||
|
|
194
main/main.cpp
194
main/main.cpp
|
@ -1661,6 +1661,114 @@ bool Main::start() {
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if (!project_manager) { // game or editor
|
||||||
|
if (game_path != "" || script != "") {
|
||||||
|
//autoload
|
||||||
|
List<PropertyInfo> props;
|
||||||
|
ProjectSettings::get_singleton()->get_property_list(&props);
|
||||||
|
|
||||||
|
//first pass, add the constants so they exist before any script is loaded
|
||||||
|
for (List<PropertyInfo>::Element *E = props.front(); E; E = E->next()) {
|
||||||
|
|
||||||
|
String s = E->get().name;
|
||||||
|
if (!s.begins_with("autoload/"))
|
||||||
|
continue;
|
||||||
|
String name = s.get_slicec('/', 1);
|
||||||
|
String path = ProjectSettings::get_singleton()->get(s);
|
||||||
|
bool global_var = false;
|
||||||
|
if (path.begins_with("*")) {
|
||||||
|
global_var = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (global_var) {
|
||||||
|
for (int i = 0; i < ScriptServer::get_language_count(); i++) {
|
||||||
|
#ifdef TOOLS_ENABLED
|
||||||
|
if (editor) {
|
||||||
|
ScriptServer::get_language(i)->add_named_global_constant(name, Variant());
|
||||||
|
} else {
|
||||||
|
ScriptServer::get_language(i)->add_global_constant(name, Variant());
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
ScriptServer::get_language(i)->add_global_constant(name, Variant());
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//second pass, load into global constants
|
||||||
|
List<Node *> to_add;
|
||||||
|
#ifdef TOOLS_ENABLED
|
||||||
|
ResourceLoader::set_timestamp_on_load(editor); // Avoid problems when editing
|
||||||
|
#endif
|
||||||
|
for (List<PropertyInfo>::Element *E = props.front(); E; E = E->next()) {
|
||||||
|
|
||||||
|
String s = E->get().name;
|
||||||
|
if (!s.begins_with("autoload/"))
|
||||||
|
continue;
|
||||||
|
String name = s.get_slicec('/', 1);
|
||||||
|
String path = ProjectSettings::get_singleton()->get(s);
|
||||||
|
bool global_var = false;
|
||||||
|
if (path.begins_with("*")) {
|
||||||
|
global_var = true;
|
||||||
|
path = path.substr(1, path.length() - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
RES res = ResourceLoader::load(path);
|
||||||
|
ERR_EXPLAIN("Can't autoload: " + 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: " + 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: " + path);
|
||||||
|
ERR_CONTINUE(!n);
|
||||||
|
n->set_name(name);
|
||||||
|
|
||||||
|
//defer so references are all valid on _ready()
|
||||||
|
to_add.push_back(n);
|
||||||
|
|
||||||
|
if (global_var) {
|
||||||
|
for (int i = 0; i < ScriptServer::get_language_count(); i++) {
|
||||||
|
#ifdef TOOLS_ENABLED
|
||||||
|
if (editor) {
|
||||||
|
ScriptServer::get_language(i)->add_named_global_constant(name, n);
|
||||||
|
} else {
|
||||||
|
ScriptServer::get_language(i)->add_global_constant(name, n);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
ScriptServer::get_language(i)->add_global_constant(name, n);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef TOOLS_ENABLED
|
||||||
|
ResourceLoader::set_timestamp_on_load(false);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
for (List<Node *>::Element *E = to_add.front(); E; E = E->next()) {
|
||||||
|
|
||||||
|
sml->get_root()->add_child(E->get());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef TOOLS_ENABLED
|
#ifdef TOOLS_ENABLED
|
||||||
|
|
||||||
EditorNode *editor_node = NULL;
|
EditorNode *editor_node = NULL;
|
||||||
|
@ -1680,9 +1788,6 @@ bool Main::start() {
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!editor && !project_manager) {
|
if (!editor && !project_manager) {
|
||||||
//standard helpers that can be changed from main config
|
//standard helpers that can be changed from main config
|
||||||
|
|
||||||
|
@ -1795,89 +1900,6 @@ bool Main::start() {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!project_manager && !editor) { // game
|
if (!project_manager && !editor) { // game
|
||||||
if (game_path != "" || script != "") {
|
|
||||||
//autoload
|
|
||||||
List<PropertyInfo> props;
|
|
||||||
ProjectSettings::get_singleton()->get_property_list(&props);
|
|
||||||
|
|
||||||
//first pass, add the constants so they exist before any script is loaded
|
|
||||||
for (List<PropertyInfo>::Element *E = props.front(); E; E = E->next()) {
|
|
||||||
|
|
||||||
String s = E->get().name;
|
|
||||||
if (!s.begins_with("autoload/"))
|
|
||||||
continue;
|
|
||||||
String name = s.get_slicec('/', 1);
|
|
||||||
String path = ProjectSettings::get_singleton()->get(s);
|
|
||||||
bool global_var = false;
|
|
||||||
if (path.begins_with("*")) {
|
|
||||||
global_var = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (global_var) {
|
|
||||||
for (int i = 0; i < ScriptServer::get_language_count(); i++) {
|
|
||||||
ScriptServer::get_language(i)->add_global_constant(name, Variant());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//second pass, load into global constants
|
|
||||||
List<Node *> to_add;
|
|
||||||
for (List<PropertyInfo>::Element *E = props.front(); E; E = E->next()) {
|
|
||||||
|
|
||||||
String s = E->get().name;
|
|
||||||
if (!s.begins_with("autoload/"))
|
|
||||||
continue;
|
|
||||||
String name = s.get_slicec('/', 1);
|
|
||||||
String path = ProjectSettings::get_singleton()->get(s);
|
|
||||||
bool global_var = false;
|
|
||||||
if (path.begins_with("*")) {
|
|
||||||
global_var = true;
|
|
||||||
path = path.substr(1, path.length() - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
RES res = ResourceLoader::load(path);
|
|
||||||
ERR_EXPLAIN("Can't autoload: " + 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: " + 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: " + path);
|
|
||||||
ERR_CONTINUE(!n);
|
|
||||||
n->set_name(name);
|
|
||||||
|
|
||||||
//defer so references are all valid on _ready()
|
|
||||||
to_add.push_back(n);
|
|
||||||
|
|
||||||
if (global_var) {
|
|
||||||
for (int i = 0; i < ScriptServer::get_language_count(); i++) {
|
|
||||||
ScriptServer::get_language(i)->add_global_constant(name, n);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (List<Node *>::Element *E = to_add.front(); E; E = E->next()) {
|
|
||||||
|
|
||||||
sml->get_root()->add_child(E->get());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (game_path != "") {
|
if (game_path != "") {
|
||||||
Node *scene = NULL;
|
Node *scene = NULL;
|
||||||
Ref<PackedScene> scenedata = ResourceLoader::load(local_game_path);
|
Ref<PackedScene> scenedata = ResourceLoader::load(local_game_path);
|
||||||
|
|
|
@ -1333,6 +1333,15 @@ void GDScriptLanguage::add_global_constant(const StringName &p_variable, const V
|
||||||
_add_global(p_variable, p_value);
|
_add_global(p_variable, p_value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GDScriptLanguage::add_named_global_constant(const StringName &p_name, const Variant &p_value) {
|
||||||
|
named_globals[p_name] = p_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GDScriptLanguage::remove_named_global_constant(const StringName &p_name) {
|
||||||
|
ERR_FAIL_COND(!named_globals.has(p_name));
|
||||||
|
named_globals.erase(p_name);
|
||||||
|
}
|
||||||
|
|
||||||
void GDScriptLanguage::init() {
|
void GDScriptLanguage::init() {
|
||||||
|
|
||||||
//populate global constants
|
//populate global constants
|
||||||
|
|
|
@ -262,6 +262,7 @@ class GDScriptLanguage : public ScriptLanguage {
|
||||||
Variant *_global_array;
|
Variant *_global_array;
|
||||||
Vector<Variant> global_array;
|
Vector<Variant> global_array;
|
||||||
Map<StringName, int> globals;
|
Map<StringName, int> globals;
|
||||||
|
Map<StringName, Variant> named_globals;
|
||||||
|
|
||||||
struct CallLevel {
|
struct CallLevel {
|
||||||
|
|
||||||
|
@ -369,7 +370,8 @@ public:
|
||||||
|
|
||||||
_FORCE_INLINE_ int get_global_array_size() const { return global_array.size(); }
|
_FORCE_INLINE_ int get_global_array_size() const { return global_array.size(); }
|
||||||
_FORCE_INLINE_ Variant *get_global_array() { return _global_array; }
|
_FORCE_INLINE_ Variant *get_global_array() { return _global_array; }
|
||||||
_FORCE_INLINE_ const Map<StringName, int> &get_global_map() { return globals; }
|
_FORCE_INLINE_ const Map<StringName, int> &get_global_map() const { return globals; }
|
||||||
|
_FORCE_INLINE_ const Map<StringName, Variant> &get_named_globals_map() const { return named_globals; }
|
||||||
|
|
||||||
_FORCE_INLINE_ static GDScriptLanguage *get_singleton() { return singleton; }
|
_FORCE_INLINE_ static GDScriptLanguage *get_singleton() { return singleton; }
|
||||||
|
|
||||||
|
@ -403,6 +405,8 @@ public:
|
||||||
virtual String _get_indentation() const;
|
virtual String _get_indentation() const;
|
||||||
virtual void auto_indent_code(String &p_code, int p_from_line, int p_to_line) const;
|
virtual void auto_indent_code(String &p_code, int p_from_line, int p_to_line) const;
|
||||||
virtual void add_global_constant(const StringName &p_variable, const Variant &p_value);
|
virtual void add_global_constant(const StringName &p_variable, const Variant &p_value);
|
||||||
|
virtual void add_named_global_constant(const StringName &p_name, const Variant &p_value);
|
||||||
|
virtual void remove_named_global_constant(const StringName &p_name);
|
||||||
|
|
||||||
/* DEBUGGER FUNCTIONS */
|
/* DEBUGGER FUNCTIONS */
|
||||||
|
|
||||||
|
|
|
@ -278,6 +278,18 @@ int GDScriptCompiler::_parse_expression(CodeGen &codegen, const GDScriptParser::
|
||||||
return idx | (GDScriptFunction::ADDR_TYPE_GLOBAL << GDScriptFunction::ADDR_BITS); //argument (stack root)
|
return idx | (GDScriptFunction::ADDR_TYPE_GLOBAL << GDScriptFunction::ADDR_BITS); //argument (stack root)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef TOOLS_ENABLED
|
||||||
|
if (GDScriptLanguage::get_singleton()->get_named_globals_map().has(identifier)) {
|
||||||
|
|
||||||
|
int idx = codegen.named_globals.find(identifier);
|
||||||
|
if (idx == -1) {
|
||||||
|
idx = codegen.named_globals.size();
|
||||||
|
codegen.named_globals.push_back(identifier);
|
||||||
|
}
|
||||||
|
return idx | (GDScriptFunction::ADDR_TYPE_NAMED_GLOBAL << GDScriptFunction::ADDR_BITS);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
//not found, error
|
//not found, error
|
||||||
|
|
||||||
_set_error("Identifier not found: " + String(identifier), p_expression);
|
_set_error("Identifier not found: " + String(identifier), p_expression);
|
||||||
|
@ -1511,6 +1523,18 @@ Error GDScriptCompiler::_parse_function(GDScript *p_script, const GDScriptParser
|
||||||
gdfunc->_global_names_count = 0;
|
gdfunc->_global_names_count = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef TOOLS_ENABLED
|
||||||
|
// Named globals
|
||||||
|
if (codegen.named_globals.size()) {
|
||||||
|
gdfunc->named_globals.resize(codegen.named_globals.size());
|
||||||
|
gdfunc->_named_globals_ptr = gdfunc->named_globals.ptr();
|
||||||
|
for (int i = 0; i < codegen.named_globals.size(); i++) {
|
||||||
|
gdfunc->named_globals[i] = codegen.named_globals[i];
|
||||||
|
}
|
||||||
|
gdfunc->_named_globals_count = gdfunc->named_globals.size();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if (codegen.opcodes.size()) {
|
if (codegen.opcodes.size()) {
|
||||||
|
|
||||||
gdfunc->code = codegen.opcodes;
|
gdfunc->code = codegen.opcodes;
|
||||||
|
|
|
@ -94,6 +94,9 @@ class GDScriptCompiler {
|
||||||
|
|
||||||
HashMap<Variant, int, VariantHasher, VariantComparator> constant_map;
|
HashMap<Variant, int, VariantHasher, VariantComparator> constant_map;
|
||||||
Map<StringName, int> name_map;
|
Map<StringName, int> name_map;
|
||||||
|
#ifdef TOOLS_ENABLED
|
||||||
|
Vector<StringName> named_globals;
|
||||||
|
#endif
|
||||||
|
|
||||||
int get_name_map_pos(const StringName &p_identifier) {
|
int get_name_map_pos(const StringName &p_identifier) {
|
||||||
int ret;
|
int ret;
|
||||||
|
|
|
@ -108,6 +108,21 @@ Variant *GDScriptFunction::_get_variant(int p_address, GDScriptInstance *p_insta
|
||||||
#endif
|
#endif
|
||||||
return &GDScriptLanguage::get_singleton()->get_global_array()[address];
|
return &GDScriptLanguage::get_singleton()->get_global_array()[address];
|
||||||
} break;
|
} break;
|
||||||
|
#ifdef TOOLS_ENABLED
|
||||||
|
case ADDR_TYPE_NAMED_GLOBAL: {
|
||||||
|
#ifdef DEBUG_ENABLED
|
||||||
|
ERR_FAIL_INDEX_V(address, _named_globals_count, NULL);
|
||||||
|
#endif
|
||||||
|
StringName id = _named_globals_ptr[address];
|
||||||
|
|
||||||
|
if (GDScriptLanguage::get_singleton()->get_named_globals_map().has(id)) {
|
||||||
|
return (Variant *)&GDScriptLanguage::get_singleton()->get_named_globals_map()[id];
|
||||||
|
} else {
|
||||||
|
r_error = "Autoload singleton '" + String(id) + "' has been removed.";
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
#endif
|
||||||
case ADDR_TYPE_NIL: {
|
case ADDR_TYPE_NIL: {
|
||||||
return &nil;
|
return &nil;
|
||||||
} break;
|
} break;
|
||||||
|
|
|
@ -92,7 +92,8 @@ public:
|
||||||
ADDR_TYPE_STACK = 5,
|
ADDR_TYPE_STACK = 5,
|
||||||
ADDR_TYPE_STACK_VARIABLE = 6,
|
ADDR_TYPE_STACK_VARIABLE = 6,
|
||||||
ADDR_TYPE_GLOBAL = 7,
|
ADDR_TYPE_GLOBAL = 7,
|
||||||
ADDR_TYPE_NIL = 8
|
ADDR_TYPE_NAMED_GLOBAL = 8,
|
||||||
|
ADDR_TYPE_NIL = 9
|
||||||
};
|
};
|
||||||
|
|
||||||
enum RPCMode {
|
enum RPCMode {
|
||||||
|
@ -121,6 +122,10 @@ private:
|
||||||
int _constant_count;
|
int _constant_count;
|
||||||
const StringName *_global_names_ptr;
|
const StringName *_global_names_ptr;
|
||||||
int _global_names_count;
|
int _global_names_count;
|
||||||
|
#ifdef TOOLS_ENABLED
|
||||||
|
const StringName *_named_globals_ptr;
|
||||||
|
int _named_globals_count;
|
||||||
|
#endif
|
||||||
const int *_default_arg_ptr;
|
const int *_default_arg_ptr;
|
||||||
int _default_arg_count;
|
int _default_arg_count;
|
||||||
const int *_code_ptr;
|
const int *_code_ptr;
|
||||||
|
@ -137,6 +142,9 @@ private:
|
||||||
StringName name;
|
StringName name;
|
||||||
Vector<Variant> constants;
|
Vector<Variant> constants;
|
||||||
Vector<StringName> global_names;
|
Vector<StringName> global_names;
|
||||||
|
#ifdef TOOLS_ENABLED
|
||||||
|
Vector<StringName> named_globals;
|
||||||
|
#endif
|
||||||
Vector<int> default_arguments;
|
Vector<int> default_arguments;
|
||||||
Vector<int> code;
|
Vector<int> code;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue