diff options
Diffstat (limited to 'modules/gdscript')
19 files changed, 299 insertions, 58 deletions
diff --git a/modules/gdscript/SCsub b/modules/gdscript/SCsub index 13870170a5..73f09f1659 100644 --- a/modules/gdscript/SCsub +++ b/modules/gdscript/SCsub @@ -7,4 +7,7 @@ env_gdscript = env_modules.Clone() env_gdscript.add_source_files(env.modules_sources, "*.cpp") +if env['tools']: + env_gdscript.add_source_files(env.modules_sources, "./editor/*.cpp") + Export('env') diff --git a/modules/gdscript/config.py b/modules/gdscript/config.py index 6496b59d75..95b40d90af 100644 --- a/modules/gdscript/config.py +++ b/modules/gdscript/config.py @@ -1,4 +1,4 @@ -def can_build(platform): +def can_build(env, platform): return True def configure(env): diff --git a/modules/gdscript/doc_classes/GDScript.xml b/modules/gdscript/doc_classes/GDScript.xml index 40a435f459..632970f8c0 100644 --- a/modules/gdscript/doc_classes/GDScript.xml +++ b/modules/gdscript/doc_classes/GDScript.xml @@ -8,7 +8,7 @@ [method new] creates a new instance of the script. [method Object.set_script] extends an existing object, if that object's class matches one of the script's base classes. </description> <tutorials> - http://docs.godotengine.org/en/3.0/getting_started/scripting/gdscript/index.html + <link>http://docs.godotengine.org/en/3.0/getting_started/scripting/gdscript/index.html</link> </tutorials> <demos> </demos> diff --git a/modules/gdscript/gdscript_highlighter.cpp b/modules/gdscript/editor/gdscript_highlighter.cpp index 4e89851bf2..fedc510f01 100644 --- a/modules/gdscript/gdscript_highlighter.cpp +++ b/modules/gdscript/editor/gdscript_highlighter.cpp @@ -29,6 +29,8 @@ /*************************************************************************/ #include "gdscript_highlighter.h" +#include "../gdscript_tokenizer.h" +#include "editor/editor_settings.h" #include "scene/gui/text_edit.h" inline bool _is_symbol(CharType c) { @@ -61,12 +63,20 @@ static bool _is_hex_symbol(CharType c) { Map<int, TextEdit::HighlighterInfo> GDScriptSyntaxHighlighter::_get_line_syntax_highlighting(int p_line) { Map<int, TextEdit::HighlighterInfo> color_map; + Type next_type = NONE; + Type current_type = NONE; + Type previous_type = NONE; + + String previous_text = ""; + int previous_column = 0; + bool prev_is_char = false; bool prev_is_number = false; bool in_keyword = false; bool in_word = false; bool in_function_name = false; bool in_member_variable = false; + bool in_node_path = false; bool is_hex_notation = false; Color keyword_color; Color color; @@ -214,18 +224,64 @@ Map<int, TextEdit::HighlighterInfo> GDScriptSyntaxHighlighter::_get_line_syntax_ in_member_variable = false; } - if (in_region >= 0) + if (!in_node_path && in_region == -1 && str[j] == '$') { + in_node_path = true; + } else if (in_region != -1 || (is_symbol && str[j] != '/')) { + in_node_path = false; + } + + if (in_region >= 0) { + next_type = REGION; color = text_editor->_get_color_region(in_region).color; - else if (in_keyword) + } else if (in_node_path) { + next_type = NODE_PATH; + color = node_path_color; + } else if (in_keyword) { + next_type = KEYWORD; color = keyword_color; - else if (in_member_variable) + } else if (in_member_variable) { + next_type = MEMBER; color = member_color; - else if (in_function_name) - color = function_color; - else if (is_symbol) + } else if (in_function_name) { + next_type = FUNCTION; + + if (previous_text == GDScriptTokenizer::get_token_name(GDScriptTokenizer::TK_PR_FUNCTION)) { + color = function_definition_color; + } else { + color = function_color; + } + } else if (is_symbol) { + next_type = SYMBOL; color = symbol_color; - else if (is_number) + } else if (is_number) { + next_type = NUMBER; color = number_color; + } else { + next_type = IDENTIFIER; + } + + if (next_type != current_type) { + if (current_type == NONE) { + current_type = next_type; + } else { + previous_type = current_type; + current_type = next_type; + + // no need to store regions... + if (previous_type == REGION) { + previous_text = ""; + previous_column = j; + } else { + String text = str.substr(previous_column, j - previous_column).strip_edges(); + previous_column = j; + + // ignore if just whitespace + if (text != "") { + previous_text = text; + } + } + } + } prev_is_char = is_char; prev_is_number = is_number; @@ -255,6 +311,25 @@ void GDScriptSyntaxHighlighter::_update_cache() { function_color = text_editor->get_color("function_color"); number_color = text_editor->get_color("number_color"); member_color = text_editor->get_color("member_variable_color"); + + EditorSettings *settings = EditorSettings::get_singleton(); + String text_editor_color_theme = settings->get("text_editor/theme/color_theme"); + + bool default_theme = text_editor_color_theme == "Default"; + bool dark_theme = settings->is_dark_theme(); + + function_definition_color = Color::html(default_theme ? "#01e1ff" : dark_theme ? "#01e1ff" : "#00a5ba"); + node_path_color = Color::html(default_theme ? "#64c15a" : dark_theme ? "64c15a" : "#518b4b"); + + EDITOR_DEF("text_editor/highlighting/gdscript/function_definition_color", function_definition_color); + EDITOR_DEF("text_editor/highlighting/gdscript/node_path_color", node_path_color); + if (text_editor_color_theme == "Adaptive" || default_theme) { + settings->set_initial_value("text_editor/highlighting/gdscript/function_definition_color", function_definition_color, true); + settings->set_initial_value("text_editor/highlighting/gdscript/node_path_color", node_path_color, true); + } + + function_definition_color = EDITOR_GET("text_editor/highlighting/gdscript/function_definition_color"); + node_path_color = EDITOR_GET("text_editor/highlighting/gdscript/node_path_color"); } SyntaxHighlighter *GDScriptSyntaxHighlighter::create() { diff --git a/modules/gdscript/gdscript_highlighter.h b/modules/gdscript/editor/gdscript_highlighter.h index ef1bdd4103..0296ab7652 100644 --- a/modules/gdscript/gdscript_highlighter.h +++ b/modules/gdscript/editor/gdscript_highlighter.h @@ -35,13 +35,27 @@ class GDScriptSyntaxHighlighter : public SyntaxHighlighter { private: + enum Type { + NONE, + REGION, + NODE_PATH, + SYMBOL, + NUMBER, + FUNCTION, + KEYWORD, + MEMBER, + IDENTIFIER + }; + // colours Color font_color; Color symbol_color; Color function_color; + Color function_definition_color; Color built_in_type_color; Color number_color; Color member_color; + Color node_path_color; public: static SyntaxHighlighter *create(); diff --git a/modules/gdscript/gdscript.cpp b/modules/gdscript/gdscript.cpp index 4e3ee4d22c..f23e7854a5 100644 --- a/modules/gdscript/gdscript.cpp +++ b/modules/gdscript/gdscript.cpp @@ -1220,7 +1220,7 @@ ScriptLanguage *GDScriptInstance::get_language() { return GDScriptLanguage::get_singleton(); } -GDScriptInstance::RPCMode GDScriptInstance::get_rpc_mode(const StringName &p_method) const { +MultiplayerAPI::RPCMode GDScriptInstance::get_rpc_mode(const StringName &p_method) const { const GDScript *cscript = script.ptr(); @@ -1228,17 +1228,17 @@ GDScriptInstance::RPCMode GDScriptInstance::get_rpc_mode(const StringName &p_met const Map<StringName, GDScriptFunction *>::Element *E = cscript->member_functions.find(p_method); if (E) { - if (E->get()->get_rpc_mode() != RPC_MODE_DISABLED) { + if (E->get()->get_rpc_mode() != MultiplayerAPI::RPC_MODE_DISABLED) { return E->get()->get_rpc_mode(); } } cscript = cscript->_base; } - return RPC_MODE_DISABLED; + return MultiplayerAPI::RPC_MODE_DISABLED; } -GDScriptInstance::RPCMode GDScriptInstance::get_rset_mode(const StringName &p_variable) const { +MultiplayerAPI::RPCMode GDScriptInstance::get_rset_mode(const StringName &p_variable) const { const GDScript *cscript = script.ptr(); @@ -1253,7 +1253,7 @@ GDScriptInstance::RPCMode GDScriptInstance::get_rset_mode(const StringName &p_va cscript = cscript->_base; } - return RPC_MODE_DISABLED; + return MultiplayerAPI::RPC_MODE_DISABLED; } void GDScriptInstance::reload_members() { @@ -1333,6 +1333,15 @@ void GDScriptLanguage::add_global_constant(const StringName &p_variable, const V _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() { //populate global constants @@ -1760,6 +1769,9 @@ void GDScriptLanguage::get_reserved_words(List<String> *p_words) const { "sync", "master", "slave", + "remotesync", + "mastersync", + "slavesync", 0 }; diff --git a/modules/gdscript/gdscript.h b/modules/gdscript/gdscript.h index 9566e3b32e..a35b0a10d5 100644 --- a/modules/gdscript/gdscript.h +++ b/modules/gdscript/gdscript.h @@ -63,7 +63,7 @@ class GDScript : public Script { int index; StringName setter; StringName getter; - ScriptInstance::RPCMode rpc_mode; + MultiplayerAPI::RPCMode rpc_mode; }; friend class GDScriptInstance; @@ -248,8 +248,8 @@ public: void reload_members(); - virtual RPCMode get_rpc_mode(const StringName &p_method) const; - virtual RPCMode get_rset_mode(const StringName &p_variable) const; + virtual MultiplayerAPI::RPCMode get_rpc_mode(const StringName &p_method) const; + virtual MultiplayerAPI::RPCMode get_rset_mode(const StringName &p_variable) const; GDScriptInstance(); ~GDScriptInstance(); @@ -262,6 +262,7 @@ class GDScriptLanguage : public ScriptLanguage { Variant *_global_array; Vector<Variant> global_array; Map<StringName, int> globals; + Map<StringName, Variant> named_globals; struct CallLevel { @@ -369,7 +370,8 @@ public: _FORCE_INLINE_ int get_global_array_size() const { return global_array.size(); } _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; } @@ -403,6 +405,8 @@ public: virtual String _get_indentation() 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_named_global_constant(const StringName &p_name, const Variant &p_value); + virtual void remove_named_global_constant(const StringName &p_name); /* DEBUGGER FUNCTIONS */ diff --git a/modules/gdscript/gdscript_compiler.cpp b/modules/gdscript/gdscript_compiler.cpp index 048948dada..5c834966c5 100644 --- a/modules/gdscript/gdscript_compiler.cpp +++ b/modules/gdscript/gdscript_compiler.cpp @@ -278,6 +278,18 @@ int GDScriptCompiler::_parse_expression(CodeGen &codegen, const GDScriptParser:: 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 _set_error("Identifier not found: " + String(identifier), p_expression); @@ -726,6 +738,9 @@ int GDScriptCompiler::_parse_expression(CodeGen &codegen, const GDScriptParser:: case GDScriptParser::OperatorNode::OP_NEG: { if (!_create_unary_operator(codegen, on, Variant::OP_NEGATE, p_stack_level)) return -1; } break; + case GDScriptParser::OperatorNode::OP_POS: { + if (!_create_unary_operator(codegen, on, Variant::OP_POSITIVE, p_stack_level)) return -1; + } break; case GDScriptParser::OperatorNode::OP_NOT: { if (!_create_unary_operator(codegen, on, Variant::OP_NOT, p_stack_level)) return -1; } break; @@ -1511,6 +1526,18 @@ Error GDScriptCompiler::_parse_function(GDScript *p_script, const GDScriptParser 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()) { gdfunc->code = codegen.opcodes; diff --git a/modules/gdscript/gdscript_compiler.h b/modules/gdscript/gdscript_compiler.h index 62aafdbe01..237b0de9e7 100644 --- a/modules/gdscript/gdscript_compiler.h +++ b/modules/gdscript/gdscript_compiler.h @@ -94,6 +94,9 @@ class GDScriptCompiler { HashMap<Variant, int, VariantHasher, VariantComparator> constant_map; Map<StringName, int> name_map; +#ifdef TOOLS_ENABLED + Vector<StringName> named_globals; +#endif int get_name_map_pos(const StringName &p_identifier) { int ret; diff --git a/modules/gdscript/gdscript_editor.cpp b/modules/gdscript/gdscript_editor.cpp index 87e1276492..c0c3bd7b06 100644 --- a/modules/gdscript/gdscript_editor.cpp +++ b/modules/gdscript/gdscript_editor.cpp @@ -54,18 +54,18 @@ void GDScriptLanguage::get_string_delimiters(List<String> *p_delimiters) const { } Ref<Script> GDScriptLanguage::get_template(const String &p_class_name, const String &p_base_class_name) const { - String _template = String() + - "extends %BASE%\n\n" + - "# class member variables go here, for example:\n" + - "# var a = 2\n" + - "# var b = \"textvar\"\n\n" + - "func _ready():\n" + - "%TS%# Called when the node is added to the scene for the first time.\n" + - "%TS%# Initialization here.\n" + - "%TS%pass\n\n" + - "#func _process(delta):\n" + - "#%TS%# Called every frame. Delta is time since last frame.\n" + - "#%TS%# Update game logic here.\n" + + String _template = "extends %BASE%\n" + "\n" + "# Declare member variables here. Examples:\n" + "# var a = 2\n" + "# var b = \"text\"\n" + "\n" + "# Called when the node enters the scene tree for the first time.\n" + "func _ready():\n" + "%TS%pass # Replace with function body.\n" + "\n" + "# Called every frame. 'delta' is the elapsed time since the previous frame.\n" + "#func _process(delta):\n" "#%TS%pass\n"; _template = _template.replace("%BASE%", p_base_class_name); @@ -118,6 +118,13 @@ bool GDScriptLanguage::validate(const String &p_script, int &r_line_error, int & funcs[cl->static_functions[i]->line] = cl->static_functions[i]->name; } + for (int i = 0; i < cl->subclasses.size(); i++) { + for (int j = 0; j < cl->subclasses[i]->functions.size(); j++) { + + funcs[cl->subclasses[i]->functions[j]->line] = String(cl->subclasses[i]->name) + "." + String(cl->subclasses[i]->functions[j]->name); + } + } + for (Map<int, String>::Element *E = funcs.front(); E; E = E->next()) { r_functions->push_back(E->get() + ":" + itos(E->key())); @@ -416,7 +423,7 @@ String GDScriptLanguage::make_function(const String &p_class, const String &p_na s += p_args[i].get_slice(":", 0); } } - s += "):\n" + _get_indentation() + "pass # replace with function body\n"; + s += "):\n" + _get_indentation() + "pass # Replace with function body.\n"; return s; } @@ -2636,6 +2643,13 @@ Error GDScriptLanguage::lookup_code(const String &p_code, const String &p_symbol } } + if ("PI" == p_symbol || "TAU" == p_symbol || "INF" == p_symbol || "NAN" == p_symbol) { + r_result.type = ScriptLanguage::LookupResult::RESULT_CLASS_CONSTANT; + r_result.class_name = "@GDScript"; + r_result.class_member = p_symbol; + return OK; + } + GDScriptParser p; p.parse(p_code, p_base_path, false, "", true); diff --git a/modules/gdscript/gdscript_function.cpp b/modules/gdscript/gdscript_function.cpp index 1c5b8187ca..61130cb58f 100644 --- a/modules/gdscript/gdscript_function.cpp +++ b/modules/gdscript/gdscript_function.cpp @@ -108,6 +108,21 @@ Variant *GDScriptFunction::_get_variant(int p_address, GDScriptInstance *p_insta #endif return &GDScriptLanguage::get_singleton()->get_global_array()[address]; } 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: { return &nil; } break; @@ -1440,7 +1455,7 @@ GDScriptFunction::GDScriptFunction() : _stack_size = 0; _call_size = 0; - rpc_mode = ScriptInstance::RPC_MODE_DISABLED; + rpc_mode = MultiplayerAPI::RPC_MODE_DISABLED; name = "<anonymous>"; #ifdef DEBUG_ENABLED _func_cname = NULL; diff --git a/modules/gdscript/gdscript_function.h b/modules/gdscript/gdscript_function.h index dff4bdfaf2..836325f0fe 100644 --- a/modules/gdscript/gdscript_function.h +++ b/modules/gdscript/gdscript_function.h @@ -92,15 +92,8 @@ public: ADDR_TYPE_STACK = 5, ADDR_TYPE_STACK_VARIABLE = 6, ADDR_TYPE_GLOBAL = 7, - ADDR_TYPE_NIL = 8 - }; - - enum RPCMode { - RPC_DISABLED, - RPC_ENABLED, - RPC_SYNC, - RPC_SYNC_MASTER, - RPC_SYNC_SLAVE + ADDR_TYPE_NAMED_GLOBAL = 8, + ADDR_TYPE_NIL = 9 }; struct StackDebug { @@ -121,6 +114,10 @@ private: int _constant_count; const StringName *_global_names_ptr; int _global_names_count; +#ifdef TOOLS_ENABLED + const StringName *_named_globals_ptr; + int _named_globals_count; +#endif const int *_default_arg_ptr; int _default_arg_count; const int *_code_ptr; @@ -130,13 +127,16 @@ private: int _call_size; int _initial_line; bool _static; - ScriptInstance::RPCMode rpc_mode; + MultiplayerAPI::RPCMode rpc_mode; GDScript *_script; StringName name; Vector<Variant> constants; Vector<StringName> global_names; +#ifdef TOOLS_ENABLED + Vector<StringName> named_globals; +#endif Vector<int> default_arguments; Vector<int> code; @@ -222,7 +222,7 @@ public: Variant call(GDScriptInstance *p_instance, const Variant **p_args, int p_argcount, Variant::CallError &r_err, CallState *p_state = NULL); - _FORCE_INLINE_ ScriptInstance::RPCMode get_rpc_mode() const { return rpc_mode; } + _FORCE_INLINE_ MultiplayerAPI::RPCMode get_rpc_mode() const { return rpc_mode; } GDScriptFunction(); ~GDScriptFunction(); }; diff --git a/modules/gdscript/gdscript_functions.cpp b/modules/gdscript/gdscript_functions.cpp index a88ba477c6..cccf09c58e 100644 --- a/modules/gdscript/gdscript_functions.cpp +++ b/modules/gdscript/gdscript_functions.cpp @@ -120,6 +120,7 @@ const char *GDScriptFunctions::get_func_name(Function p_func) { "Color8", "ColorN", "print_stack", + "get_stack", "instance_from_id", "len", "is_instance_valid", @@ -1213,6 +1214,22 @@ void GDScriptFunctions::call(Function p_func, const Variant **p_args, int p_arg_ }; } break; + case GET_STACK: { + VALIDATE_ARG_COUNT(0); + + ScriptLanguage *script = GDScriptLanguage::get_singleton(); + Array ret; + for (int i = 0; i < script->debug_get_stack_level_count(); i++) { + + Dictionary frame; + frame["source"] = script->debug_get_stack_level_source(i); + frame["function"] = script->debug_get_stack_level_function(i); + frame["line"] = script->debug_get_stack_level_line(i); + ret.push_back(frame); + }; + r_ret = ret; + } break; + case INSTANCE_FROM_ID: { VALIDATE_ARG_COUNT(1); @@ -1813,6 +1830,11 @@ MethodInfo GDScriptFunctions::get_info(Function p_func) { mi.return_val.type = Variant::NIL; return mi; } break; + case GET_STACK: { + MethodInfo mi("get_stack"); + mi.return_val.type = Variant::NIL; + return mi; + } break; case INSTANCE_FROM_ID: { MethodInfo mi("instance_from_id", PropertyInfo(Variant::INT, "instance_id")); diff --git a/modules/gdscript/gdscript_functions.h b/modules/gdscript/gdscript_functions.h index c4731d17a4..899a7ebd25 100644 --- a/modules/gdscript/gdscript_functions.h +++ b/modules/gdscript/gdscript_functions.h @@ -111,6 +111,7 @@ public: COLOR8, COLORN, PRINT_STACK, + GET_STACK, INSTANCE_FROM_ID, LEN, IS_INSTANCE_VALID, diff --git a/modules/gdscript/gdscript_parser.cpp b/modules/gdscript/gdscript_parser.cpp index e7b0700e76..9650563ee6 100644 --- a/modules/gdscript/gdscript_parser.cpp +++ b/modules/gdscript/gdscript_parser.cpp @@ -716,6 +716,14 @@ GDScriptParser::Node *GDScriptParser::_parse_expression(Node *p_parent, bool p_s expr = constant; bfn = true; } + + if (!bfn && GDScriptLanguage::get_singleton()->get_named_globals_map().has(identifier)) { + //check from singletons + ConstantNode *constant = alloc_node<ConstantNode>(); + constant->value = GDScriptLanguage::get_singleton()->get_named_globals_map()[identifier]; + expr = constant; + bfn = true; + } } if (!bfn) { @@ -3365,7 +3373,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) { function->line = fnline; function->rpc_mode = rpc_mode; - rpc_mode = ScriptInstance::RPC_MODE_DISABLED; + rpc_mode = MultiplayerAPI::RPC_MODE_DISABLED; if (_static) p_class->static_functions.push_back(function); @@ -3923,10 +3931,10 @@ void GDScriptParser::_parse_class(ClassNode *p_class) { tokenizer->advance(); } - if (tokenizer->get_token() != GDScriptTokenizer::TK_PR_VAR && tokenizer->get_token() != GDScriptTokenizer::TK_PR_ONREADY && tokenizer->get_token() != GDScriptTokenizer::TK_PR_REMOTE && tokenizer->get_token() != GDScriptTokenizer::TK_PR_MASTER && tokenizer->get_token() != GDScriptTokenizer::TK_PR_SLAVE && tokenizer->get_token() != GDScriptTokenizer::TK_PR_SYNC) { + if (tokenizer->get_token() != GDScriptTokenizer::TK_PR_VAR && tokenizer->get_token() != GDScriptTokenizer::TK_PR_ONREADY && tokenizer->get_token() != GDScriptTokenizer::TK_PR_REMOTE && tokenizer->get_token() != GDScriptTokenizer::TK_PR_MASTER && tokenizer->get_token() != GDScriptTokenizer::TK_PR_SLAVE && tokenizer->get_token() != GDScriptTokenizer::TK_PR_SYNC && tokenizer->get_token() != GDScriptTokenizer::TK_PR_REMOTESYNC && tokenizer->get_token() != GDScriptTokenizer::TK_PR_MASTERSYNC && tokenizer->get_token() != GDScriptTokenizer::TK_PR_SLAVESYNC) { current_export = PropertyInfo(); - _set_error("Expected 'var', 'onready', 'remote', 'master', 'slave' or 'sync'."); + _set_error("Expected 'var', 'onready', 'remote', 'master', 'slave', 'sync', 'remotesync', 'mastersync', 'slavesync'."); return; } @@ -3959,7 +3967,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) { return; } } - rpc_mode = ScriptInstance::RPC_MODE_REMOTE; + rpc_mode = MultiplayerAPI::RPC_MODE_REMOTE; continue; } break; @@ -3980,7 +3988,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) { } } - rpc_mode = ScriptInstance::RPC_MODE_MASTER; + rpc_mode = MultiplayerAPI::RPC_MODE_MASTER; continue; } break; case GDScriptTokenizer::TK_PR_SLAVE: { @@ -4000,9 +4008,10 @@ void GDScriptParser::_parse_class(ClassNode *p_class) { } } - rpc_mode = ScriptInstance::RPC_MODE_SLAVE; + rpc_mode = MultiplayerAPI::RPC_MODE_SLAVE; continue; } break; + case GDScriptTokenizer::TK_PR_REMOTESYNC: case GDScriptTokenizer::TK_PR_SYNC: { //may be fallthrough from export, ignore if so @@ -4015,7 +4024,37 @@ void GDScriptParser::_parse_class(ClassNode *p_class) { return; } - rpc_mode = ScriptInstance::RPC_MODE_SYNC; + rpc_mode = MultiplayerAPI::RPC_MODE_SYNC; + continue; + } break; + case GDScriptTokenizer::TK_PR_MASTERSYNC: { + + //may be fallthrough from export, ignore if so + tokenizer->advance(); + if (tokenizer->get_token() != GDScriptTokenizer::TK_PR_VAR && tokenizer->get_token() != GDScriptTokenizer::TK_PR_FUNCTION) { + if (current_export.type) + _set_error("Expected 'var'."); + else + _set_error("Expected 'var' or 'func'."); + return; + } + + rpc_mode = MultiplayerAPI::RPC_MODE_MASTERSYNC; + continue; + } break; + case GDScriptTokenizer::TK_PR_SLAVESYNC: { + + //may be fallthrough from export, ignore if so + tokenizer->advance(); + if (tokenizer->get_token() != GDScriptTokenizer::TK_PR_VAR && tokenizer->get_token() != GDScriptTokenizer::TK_PR_FUNCTION) { + if (current_export.type) + _set_error("Expected 'var'."); + else + _set_error("Expected 'var' or 'func'."); + return; + } + + rpc_mode = MultiplayerAPI::RPC_MODE_SLAVESYNC; continue; } break; case GDScriptTokenizer::TK_PR_VAR: { @@ -4045,7 +4084,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) { tokenizer->advance(); - rpc_mode = ScriptInstance::RPC_MODE_DISABLED; + rpc_mode = MultiplayerAPI::RPC_MODE_DISABLED; if (tokenizer->get_token() == GDScriptTokenizer::TK_OP_ASSIGN) { @@ -4054,7 +4093,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) { #endif tokenizer->advance(); - Node *subexpr = _parse_and_reduce_expression(p_class, false, autoexport); + Node *subexpr = _parse_and_reduce_expression(p_class, false, autoexport || member._export.type != Variant::NIL); if (!subexpr) { if (_recover_from_completion()) { break; @@ -4470,7 +4509,7 @@ void GDScriptParser::clear() { current_class = NULL; completion_found = false; - rpc_mode = ScriptInstance::RPC_MODE_DISABLED; + rpc_mode = MultiplayerAPI::RPC_MODE_DISABLED; current_function = NULL; diff --git a/modules/gdscript/gdscript_parser.h b/modules/gdscript/gdscript_parser.h index 485ba1263d..b88a59537c 100644 --- a/modules/gdscript/gdscript_parser.h +++ b/modules/gdscript/gdscript_parser.h @@ -89,7 +89,7 @@ public: StringName getter; int line; Node *expression; - ScriptInstance::RPCMode rpc_mode; + MultiplayerAPI::RPCMode rpc_mode; }; struct Constant { StringName identifier; @@ -125,7 +125,7 @@ public: struct FunctionNode : public Node { bool _static; - ScriptInstance::RPCMode rpc_mode; + MultiplayerAPI::RPCMode rpc_mode; StringName name; Vector<StringName> arguments; Vector<Node *> default_values; @@ -134,7 +134,7 @@ public: FunctionNode() { type = TYPE_FUNCTION; _static = false; - rpc_mode = ScriptInstance::RPC_MODE_DISABLED; + rpc_mode = MultiplayerAPI::RPC_MODE_DISABLED; } }; @@ -493,7 +493,7 @@ private: PropertyInfo current_export; - ScriptInstance::RPCMode rpc_mode; + MultiplayerAPI::RPCMode rpc_mode; void _set_error(const String &p_error, int p_line = -1, int p_column = -1); bool _recover_from_completion(); diff --git a/modules/gdscript/gdscript_tokenizer.cpp b/modules/gdscript/gdscript_tokenizer.cpp index 6a844cd651..3c8e1ddbe4 100644 --- a/modules/gdscript/gdscript_tokenizer.cpp +++ b/modules/gdscript/gdscript_tokenizer.cpp @@ -110,6 +110,9 @@ const char *GDScriptTokenizer::token_names[TK_MAX] = { "sync", "master", "slave", + "remotesync", + "mastersync", + "slavesync", "'['", "']'", "'{'", @@ -201,6 +204,9 @@ static const _kws _keyword_list[] = { { GDScriptTokenizer::TK_PR_MASTER, "master" }, { GDScriptTokenizer::TK_PR_SLAVE, "slave" }, { GDScriptTokenizer::TK_PR_SYNC, "sync" }, + { GDScriptTokenizer::TK_PR_REMOTESYNC, "remotesync" }, + { GDScriptTokenizer::TK_PR_MASTERSYNC, "mastersync" }, + { GDScriptTokenizer::TK_PR_SLAVESYNC, "slavesync" }, { GDScriptTokenizer::TK_PR_CONST, "const" }, { GDScriptTokenizer::TK_PR_ENUM, "enum" }, //controlflow @@ -247,6 +253,9 @@ bool GDScriptTokenizer::is_token_literal(int p_offset, bool variable_safe) const case TK_PR_MASTER: case TK_PR_SLAVE: case TK_PR_SYNC: + case TK_PR_REMOTESYNC: + case TK_PR_MASTERSYNC: + case TK_PR_SLAVESYNC: return true; // Literal for non-variables only: diff --git a/modules/gdscript/gdscript_tokenizer.h b/modules/gdscript/gdscript_tokenizer.h index b020c85199..c4f1f9fd94 100644 --- a/modules/gdscript/gdscript_tokenizer.h +++ b/modules/gdscript/gdscript_tokenizer.h @@ -115,6 +115,9 @@ public: TK_PR_SYNC, TK_PR_MASTER, TK_PR_SLAVE, + TK_PR_REMOTESYNC, + TK_PR_MASTERSYNC, + TK_PR_SLAVESYNC, TK_BRACKET_OPEN, TK_BRACKET_CLOSE, TK_CURLY_BRACKET_OPEN, diff --git a/modules/gdscript/register_types.cpp b/modules/gdscript/register_types.cpp index 85c94c3596..422223370b 100644 --- a/modules/gdscript/register_types.cpp +++ b/modules/gdscript/register_types.cpp @@ -30,8 +30,8 @@ #include "register_types.h" +#include "editor/gdscript_highlighter.h" #include "gdscript.h" -#include "gdscript_highlighter.h" #include "gdscript_tokenizer.h" #include "io/file_access_encrypted.h" #include "io/resource_loader.h" |