parent
199ad16bbc
commit
48f1d02da4
12 changed files with 271 additions and 65 deletions
|
@ -1302,6 +1302,10 @@ Array Object::_get_signal_connection_list(const String& p_signal) const{
|
||||||
|
|
||||||
void Object::get_signal_list(List<MethodInfo> *p_signals ) const {
|
void Object::get_signal_list(List<MethodInfo> *p_signals ) const {
|
||||||
|
|
||||||
|
if (!script.is_null()) {
|
||||||
|
Ref<Script>(script)->get_script_signal_list(p_signals);
|
||||||
|
}
|
||||||
|
|
||||||
ObjectTypeDB::get_signal_list(get_type_name(),p_signals);
|
ObjectTypeDB::get_signal_list(get_type_name(),p_signals);
|
||||||
//find maybe usersignals?
|
//find maybe usersignals?
|
||||||
const StringName *S=NULL;
|
const StringName *S=NULL;
|
||||||
|
@ -1313,6 +1317,7 @@ void Object::get_signal_list(List<MethodInfo> *p_signals ) const {
|
||||||
p_signals->push_back(signal_map[*S].user);
|
p_signals->push_back(signal_map[*S].user);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1351,6 +1356,10 @@ Error Object::connect(const StringName& p_signal, Object *p_to_object, const Str
|
||||||
Signal *s = signal_map.getptr(p_signal);
|
Signal *s = signal_map.getptr(p_signal);
|
||||||
if (!s) {
|
if (!s) {
|
||||||
bool signal_is_valid = ObjectTypeDB::has_signal(get_type_name(),p_signal);
|
bool signal_is_valid = ObjectTypeDB::has_signal(get_type_name(),p_signal);
|
||||||
|
//check in script
|
||||||
|
if (!signal_is_valid && !script.is_null() && Ref<Script>(script)->has_script_signal(p_signal))
|
||||||
|
signal_is_valid=true;
|
||||||
|
|
||||||
if (!signal_is_valid) {
|
if (!signal_is_valid) {
|
||||||
ERR_EXPLAIN("Attempt to connect nonexistent signal '"+p_signal+"' to method '"+p_to_method+"'");
|
ERR_EXPLAIN("Attempt to connect nonexistent signal '"+p_signal+"' to method '"+p_to_method+"'");
|
||||||
ERR_FAIL_COND_V(!signal_is_valid,ERR_INVALID_PARAMETER);
|
ERR_FAIL_COND_V(!signal_is_valid,ERR_INVALID_PARAMETER);
|
||||||
|
|
|
@ -94,6 +94,10 @@ public:
|
||||||
|
|
||||||
virtual ScriptLanguage *get_language() const=0;
|
virtual ScriptLanguage *get_language() const=0;
|
||||||
|
|
||||||
|
virtual bool has_script_signal(const StringName& p_signal) const=0;
|
||||||
|
virtual void get_script_signal_list(List<MethodInfo> *r_signals) const=0;
|
||||||
|
|
||||||
|
|
||||||
virtual void update_exports() {} //editor tool
|
virtual void update_exports() {} //editor tool
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -45,3 +45,4 @@ func _on_shot_body_enter( body ):
|
||||||
#hit the tilemap
|
#hit the tilemap
|
||||||
_hit_something()
|
_hit_something()
|
||||||
pass # replace with function body
|
pass # replace with function body
|
||||||
|
|
||||||
|
|
Binary file not shown.
|
@ -28,15 +28,6 @@
|
||||||
/*************************************************************************/
|
/*************************************************************************/
|
||||||
#include "gd_compiler.h"
|
#include "gd_compiler.h"
|
||||||
#include "gd_script.h"
|
#include "gd_script.h"
|
||||||
/* TODO:
|
|
||||||
|
|
||||||
*AND and OR need early abort
|
|
||||||
-Inheritance properly process (done?)
|
|
||||||
*create built in initializer and constructor
|
|
||||||
*assign operators
|
|
||||||
*build arrays and dictionaries
|
|
||||||
*call parent constructor
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
void GDCompiler::_set_error(const String& p_error,const GDParser::Node *p_node) {
|
void GDCompiler::_set_error(const String& p_error,const GDParser::Node *p_node) {
|
||||||
|
@ -1397,13 +1388,14 @@ Error GDCompiler::_parse_class(GDScript *p_script,GDScript *p_owner,const GDPars
|
||||||
|
|
||||||
|
|
||||||
int index_from=0;
|
int index_from=0;
|
||||||
|
Ref<GDNativeClass> native;
|
||||||
|
|
||||||
if (p_class->extends_used) {
|
if (p_class->extends_used) {
|
||||||
//do inheritance
|
//do inheritance
|
||||||
String path = p_class->extends_file;
|
String path = p_class->extends_file;
|
||||||
|
|
||||||
Ref<GDScript> script;
|
Ref<GDScript> script;
|
||||||
Ref<GDNativeClass> native;
|
|
||||||
|
|
||||||
if (path!="") {
|
if (path!="") {
|
||||||
//path (and optionally subclasses)
|
//path (and optionally subclasses)
|
||||||
|
@ -1573,7 +1565,35 @@ Error GDCompiler::_parse_class(GDScript *p_script,GDScript *p_owner,const GDPars
|
||||||
//p_script->constants[constant->value].make_const();
|
//p_script->constants[constant->value].make_const();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for(int i=0;i<p_class->_signals.size();i++) {
|
||||||
|
|
||||||
|
StringName name = p_class->_signals[i].name;
|
||||||
|
|
||||||
|
GDScript *c = p_script;
|
||||||
|
|
||||||
|
while(c) {
|
||||||
|
|
||||||
|
if (c->_signals.has(name)) {
|
||||||
|
_set_error("Signal '"+name+"' redefined (in current or parent class)",p_class);
|
||||||
|
return ERR_ALREADY_EXISTS;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (c->base.is_valid()) {
|
||||||
|
c=c->base.ptr();
|
||||||
|
} else {
|
||||||
|
c=NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (native.is_valid()) {
|
||||||
|
if (ObjectTypeDB::has_signal(native->get_name(),name)) {
|
||||||
|
_set_error("Signal '"+name+"' redefined (original in native class '"+String(native->get_name())+"')",p_class);
|
||||||
|
return ERR_ALREADY_EXISTS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
p_script->_signals[name]=p_class->_signals[i].arguments;
|
||||||
|
}
|
||||||
//parse sub-classes
|
//parse sub-classes
|
||||||
|
|
||||||
for(int i=0;i<p_class->subclasses.size();i++) {
|
for(int i=0;i<p_class->subclasses.size();i++) {
|
||||||
|
|
|
@ -1520,8 +1520,10 @@ void GDParser::_parse_block(BlockNode *p_block,bool p_static) {
|
||||||
op->arguments.push_back(assigned);
|
op->arguments.push_back(assigned);
|
||||||
p_block->statements.push_back(op);
|
p_block->statements.push_back(op);
|
||||||
|
|
||||||
_end_statement();
|
if (!_end_statement()) {
|
||||||
|
_set_error("Expected end of statement (var)");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
} break;
|
} break;
|
||||||
case GDTokenizer::TK_CF_IF: {
|
case GDTokenizer::TK_CF_IF: {
|
||||||
|
@ -1946,8 +1948,10 @@ void GDParser::_parse_class(ClassNode *p_class) {
|
||||||
_parse_extends(p_class);
|
_parse_extends(p_class);
|
||||||
if (error_set)
|
if (error_set)
|
||||||
return;
|
return;
|
||||||
_end_statement();
|
if (!_end_statement()) {
|
||||||
|
_set_error("Expected end of statement after extends");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
} break;
|
} break;
|
||||||
case GDTokenizer::TK_PR_TOOL: {
|
case GDTokenizer::TK_PR_TOOL: {
|
||||||
|
@ -2227,6 +2231,53 @@ void GDParser::_parse_class(ClassNode *p_class) {
|
||||||
|
|
||||||
//arguments
|
//arguments
|
||||||
} break;
|
} break;
|
||||||
|
case GDTokenizer::TK_PR_SIGNAL: {
|
||||||
|
tokenizer->advance();
|
||||||
|
|
||||||
|
if (tokenizer->get_token()!=GDTokenizer::TK_IDENTIFIER) {
|
||||||
|
_set_error("Expected identifier after 'signal'.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ClassNode::Signal sig;
|
||||||
|
sig.name = tokenizer->get_token_identifier();
|
||||||
|
tokenizer->advance();
|
||||||
|
|
||||||
|
|
||||||
|
if (tokenizer->get_token()==GDTokenizer::TK_PARENTHESIS_OPEN) {
|
||||||
|
tokenizer->advance();
|
||||||
|
while(true) {
|
||||||
|
|
||||||
|
|
||||||
|
if (tokenizer->get_token()==GDTokenizer::TK_PARENTHESIS_CLOSE) {
|
||||||
|
tokenizer->advance();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tokenizer->get_token()!=GDTokenizer::TK_IDENTIFIER) {
|
||||||
|
_set_error("Expected identifier in signal argument.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
sig.arguments.push_back(tokenizer->get_token_identifier());
|
||||||
|
tokenizer->advance();
|
||||||
|
|
||||||
|
if (tokenizer->get_token()==GDTokenizer::TK_COMMA) {
|
||||||
|
tokenizer->advance();
|
||||||
|
} else if (tokenizer->get_token()!=GDTokenizer::TK_PARENTHESIS_CLOSE) {
|
||||||
|
_set_error("Expected ',' or ')' after signal parameter identifier.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
p_class->_signals.push_back(sig);
|
||||||
|
|
||||||
|
if (!_end_statement()) {
|
||||||
|
_set_error("Expected end of statement (signal)");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} break;
|
||||||
case GDTokenizer::TK_PR_EXPORT: {
|
case GDTokenizer::TK_PR_EXPORT: {
|
||||||
|
|
||||||
tokenizer->advance();
|
tokenizer->advance();
|
||||||
|
@ -2644,8 +2695,10 @@ void GDParser::_parse_class(ClassNode *p_class) {
|
||||||
|
|
||||||
p_class->variables.push_back(member);
|
p_class->variables.push_back(member);
|
||||||
|
|
||||||
_end_statement();
|
if (!_end_statement()) {
|
||||||
|
_set_error("Expected end of statement (continue)");
|
||||||
|
return;
|
||||||
|
}
|
||||||
} break;
|
} break;
|
||||||
case GDTokenizer::TK_PR_CONST: {
|
case GDTokenizer::TK_PR_CONST: {
|
||||||
//variale declaration and (eventual) initialization
|
//variale declaration and (eventual) initialization
|
||||||
|
@ -2682,8 +2735,10 @@ void GDParser::_parse_class(ClassNode *p_class) {
|
||||||
|
|
||||||
p_class->constant_expressions.push_back(constant);
|
p_class->constant_expressions.push_back(constant);
|
||||||
|
|
||||||
_end_statement();
|
if (!_end_statement()) {
|
||||||
|
_set_error("Expected end of statement (constant)");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
|
|
|
@ -76,6 +76,7 @@ public:
|
||||||
StringName extends_file;
|
StringName extends_file;
|
||||||
Vector<StringName> extends_class;
|
Vector<StringName> extends_class;
|
||||||
|
|
||||||
|
|
||||||
struct Member {
|
struct Member {
|
||||||
PropertyInfo _export;
|
PropertyInfo _export;
|
||||||
#ifdef TOOLS_ENABLED
|
#ifdef TOOLS_ENABLED
|
||||||
|
@ -92,11 +93,17 @@ public:
|
||||||
Node *expression;
|
Node *expression;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct Signal {
|
||||||
|
StringName name;
|
||||||
|
Vector<StringName> arguments;
|
||||||
|
};
|
||||||
|
|
||||||
Vector<ClassNode*> subclasses;
|
Vector<ClassNode*> subclasses;
|
||||||
Vector<Member> variables;
|
Vector<Member> variables;
|
||||||
Vector<Constant> constant_expressions;
|
Vector<Constant> constant_expressions;
|
||||||
Vector<FunctionNode*> functions;
|
Vector<FunctionNode*> functions;
|
||||||
Vector<FunctionNode*> static_functions;
|
Vector<FunctionNode*> static_functions;
|
||||||
|
Vector<Signal> _signals;
|
||||||
BlockNode *initializer;
|
BlockNode *initializer;
|
||||||
ClassNode *owner;
|
ClassNode *owner;
|
||||||
//Vector<Node*> initializers;
|
//Vector<Node*> initializers;
|
||||||
|
|
|
@ -1756,6 +1756,12 @@ bool GDScript::_update_exports() {
|
||||||
//print_line("found "+c->variables[i]._export.name);
|
//print_line("found "+c->variables[i]._export.name);
|
||||||
member_default_values_cache[c->variables[i].identifier]=c->variables[i].default_value;
|
member_default_values_cache[c->variables[i].identifier]=c->variables[i].default_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_signals.clear();
|
||||||
|
|
||||||
|
for(int i=0;i<c->_signals.size();i++) {
|
||||||
|
_signals[c->_signals[i].name]=c->_signals[i].arguments;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
//print_line("unchaged is "+get_path());
|
//print_line("unchaged is "+get_path());
|
||||||
|
@ -2100,6 +2106,47 @@ Ref<GDScript> GDScript::get_base() const {
|
||||||
return base;
|
return base;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool GDScript::has_script_signal(const StringName& p_signal) const {
|
||||||
|
if (_signals.has(p_signal))
|
||||||
|
return true;
|
||||||
|
if (base.is_valid()) {
|
||||||
|
return base->has_script_signal(p_signal);
|
||||||
|
}
|
||||||
|
#ifdef TOOLS_ENABLED
|
||||||
|
else if (base_cache.is_valid()){
|
||||||
|
return base_cache->has_script_signal(p_signal);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
void GDScript::get_script_signal_list(List<MethodInfo> *r_signals) const {
|
||||||
|
|
||||||
|
for(const Map<StringName,Vector<StringName> >::Element *E=_signals.front();E;E=E->next()) {
|
||||||
|
|
||||||
|
MethodInfo mi;
|
||||||
|
mi.name=E->key();
|
||||||
|
for(int i=0;i<E->get().size();i++) {
|
||||||
|
PropertyInfo arg;
|
||||||
|
arg.name=E->get()[i];
|
||||||
|
mi.arguments.push_back(arg);
|
||||||
|
}
|
||||||
|
r_signals->push_back(mi);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (base.is_valid()) {
|
||||||
|
base->get_script_signal_list(r_signals);
|
||||||
|
}
|
||||||
|
#ifdef TOOLS_ENABLED
|
||||||
|
else if (base_cache.is_valid()){
|
||||||
|
base_cache->get_script_signal_list(r_signals);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
GDScript::GDScript() {
|
GDScript::GDScript() {
|
||||||
|
|
||||||
|
|
||||||
|
@ -2594,6 +2641,7 @@ void GDScriptLanguage::get_reserved_words(List<String> *p_words) const {
|
||||||
"static",
|
"static",
|
||||||
"float",
|
"float",
|
||||||
"int",
|
"int",
|
||||||
|
"signal",
|
||||||
0};
|
0};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -260,6 +260,7 @@ friend class GDScriptLanguage;
|
||||||
Map<StringName,GDFunction> member_functions;
|
Map<StringName,GDFunction> member_functions;
|
||||||
Map<StringName,MemberInfo> member_indices; //members are just indices to the instanced script.
|
Map<StringName,MemberInfo> member_indices; //members are just indices to the instanced script.
|
||||||
Map<StringName,Ref<GDScript> > subclasses;
|
Map<StringName,Ref<GDScript> > subclasses;
|
||||||
|
Map<StringName,Vector<StringName> > _signals;
|
||||||
|
|
||||||
#ifdef TOOLS_ENABLED
|
#ifdef TOOLS_ENABLED
|
||||||
|
|
||||||
|
@ -318,6 +319,9 @@ public:
|
||||||
const Map<StringName,GDFunction>& get_member_functions() const { return member_functions; }
|
const Map<StringName,GDFunction>& get_member_functions() const { return member_functions; }
|
||||||
const Ref<GDNativeClass>& get_native() const { return native; }
|
const Ref<GDNativeClass>& get_native() const { return native; }
|
||||||
|
|
||||||
|
virtual bool has_script_signal(const StringName& p_signal) const;
|
||||||
|
virtual void get_script_signal_list(List<MethodInfo> *r_signals) const;
|
||||||
|
|
||||||
|
|
||||||
bool is_tool() const { return tool; }
|
bool is_tool() const { return tool; }
|
||||||
Ref<GDScript> get_base() const;
|
Ref<GDScript> get_base() const;
|
||||||
|
|
|
@ -856,6 +856,7 @@ void GDTokenizerText::_advance() {
|
||||||
{TK_PR_PRELOAD,"preload"},
|
{TK_PR_PRELOAD,"preload"},
|
||||||
{TK_PR_ASSERT,"assert"},
|
{TK_PR_ASSERT,"assert"},
|
||||||
{TK_PR_YIELD,"yield"},
|
{TK_PR_YIELD,"yield"},
|
||||||
|
{TK_PR_SIGNAL,"signal"},
|
||||||
{TK_PR_CONST,"const"},
|
{TK_PR_CONST,"const"},
|
||||||
//controlflow
|
//controlflow
|
||||||
{TK_CF_IF,"if"},
|
{TK_CF_IF,"if"},
|
||||||
|
|
|
@ -104,6 +104,7 @@ public:
|
||||||
TK_PR_PRELOAD,
|
TK_PR_PRELOAD,
|
||||||
TK_PR_ASSERT,
|
TK_PR_ASSERT,
|
||||||
TK_PR_YIELD,
|
TK_PR_YIELD,
|
||||||
|
TK_PR_SIGNAL,
|
||||||
TK_BRACKET_OPEN,
|
TK_BRACKET_OPEN,
|
||||||
TK_BRACKET_CLOSE,
|
TK_BRACKET_CLOSE,
|
||||||
TK_CURLY_BRACKET_OPEN,
|
TK_CURLY_BRACKET_OPEN,
|
||||||
|
|
|
@ -632,6 +632,51 @@ void ConnectionsDialog::update_tree() {
|
||||||
node->get_signal_list(&node_signals);
|
node->get_signal_list(&node_signals);
|
||||||
|
|
||||||
//node_signals.sort_custom<_ConnectionsDialogMethodInfoSort>();
|
//node_signals.sort_custom<_ConnectionsDialogMethodInfoSort>();
|
||||||
|
bool did_script=false;
|
||||||
|
StringName base = node->get_type();
|
||||||
|
|
||||||
|
while(base) {
|
||||||
|
|
||||||
|
List<MethodInfo> node_signals;
|
||||||
|
Ref<Texture> icon;
|
||||||
|
String name;
|
||||||
|
|
||||||
|
if (!did_script) {
|
||||||
|
|
||||||
|
Ref<Script> scr = node->get_script();
|
||||||
|
if (scr.is_valid()) {
|
||||||
|
scr->get_script_signal_list(&node_signals);
|
||||||
|
if (scr->get_path().is_resource_file())
|
||||||
|
name=scr->get_path().get_file();
|
||||||
|
else
|
||||||
|
name=scr->get_type();
|
||||||
|
|
||||||
|
if (has_icon(scr->get_type(),"EditorIcons")) {
|
||||||
|
icon=get_icon(scr->get_type(),"EditorIcons");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
ObjectTypeDB::get_signal_list(base,&node_signals,true);
|
||||||
|
if (has_icon(base,"EditorIcons")) {
|
||||||
|
icon=get_icon(base,"EditorIcons");
|
||||||
|
}
|
||||||
|
name=base;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TreeItem *pitem = NULL;
|
||||||
|
|
||||||
|
if (node_signals.size()) {
|
||||||
|
pitem=tree->create_item(root);
|
||||||
|
pitem->set_text(0,name);
|
||||||
|
pitem->set_icon(0,icon);
|
||||||
|
pitem->set_selectable(0,false);
|
||||||
|
pitem->set_editable(0,false);
|
||||||
|
pitem->set_custom_bg_color(0,get_color("prop_subsection","Editor"));
|
||||||
|
node_signals.sort();
|
||||||
|
}
|
||||||
|
|
||||||
for(List<MethodInfo>::Element *E=node_signals.front();E;E=E->next()) {
|
for(List<MethodInfo>::Element *E=node_signals.front();E;E=E->next()) {
|
||||||
|
|
||||||
|
@ -649,7 +694,11 @@ void ConnectionsDialog::update_tree() {
|
||||||
|
|
||||||
if (i>0)
|
if (i>0)
|
||||||
signaldesc+=", ";
|
signaldesc+=", ";
|
||||||
signaldesc+=Variant::get_type_name(pi.type)+" "+(pi.name==""?String("arg "+itos(i)):pi.name);
|
String tname="var";
|
||||||
|
if (pi.type!=Variant::NIL) {
|
||||||
|
tname=Variant::get_type_name(pi.type);
|
||||||
|
}
|
||||||
|
signaldesc+=tname+" "+(pi.name==""?String("arg "+itos(i)):pi.name);
|
||||||
argnames.push_back(pi.name);
|
argnames.push_back(pi.name);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -658,7 +707,7 @@ void ConnectionsDialog::update_tree() {
|
||||||
|
|
||||||
signaldesc+=")";
|
signaldesc+=")";
|
||||||
|
|
||||||
TreeItem *item=tree->create_item(root);
|
TreeItem *item=tree->create_item(pitem);
|
||||||
item->set_text(0,signaldesc);
|
item->set_text(0,signaldesc);
|
||||||
Dictionary sinfo;
|
Dictionary sinfo;
|
||||||
sinfo["name"]=mi.name;
|
sinfo["name"]=mi.name;
|
||||||
|
@ -703,6 +752,13 @@ void ConnectionsDialog::update_tree() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!did_script) {
|
||||||
|
did_script=true;
|
||||||
|
} else {
|
||||||
|
base=ObjectTypeDB::type_inherits_from(base);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
get_ok()->set_text("Connect");
|
get_ok()->set_text("Connect");
|
||||||
get_ok()->set_disabled(true);
|
get_ok()->set_disabled(true);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue