You've already forked godot
mirror of
https://github.com/godotengine/godot.git
synced 2025-11-22 15:06:45 +00:00
New Code Completion
-=-=-=-=-=-=-=-=-=- -Massive improvement to code completion -Argument hinting for functions If you manage to out-smart the code-completion in a situation where completion should be possible to guess, let me know. Please enter the commit message for your changes. Lines starting
This commit is contained in:
@@ -87,7 +87,9 @@ Vector<StringName> MethodBind::get_argument_names() const {
|
|||||||
|
|
||||||
|
|
||||||
void MethodBind::set_default_arguments(const Vector<Variant>& p_defargs) {
|
void MethodBind::set_default_arguments(const Vector<Variant>& p_defargs) {
|
||||||
default_arguments=p_defargs; default_argument_count=default_arguments.size();
|
default_arguments=p_defargs;
|
||||||
|
default_argument_count=default_arguments.size();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef DEBUG_METHODS_ENABLED
|
#ifdef DEBUG_METHODS_ENABLED
|
||||||
|
|||||||
@@ -1694,6 +1694,11 @@ void ObjectDB::debug_objects(DebugFunc p_func) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Object::get_argument_options(const StringName& p_function,int p_idx,List<String>*r_options) const {
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
int ObjectDB::get_object_count() {
|
int ObjectDB::get_object_count() {
|
||||||
|
|
||||||
GLOBAL_LOCK_FUNCTION;
|
GLOBAL_LOCK_FUNCTION;
|
||||||
|
|||||||
@@ -583,6 +583,7 @@ public:
|
|||||||
|
|
||||||
virtual void get_translatable_strings(List<String> *p_strings) const;
|
virtual void get_translatable_strings(List<String> *p_strings) const;
|
||||||
|
|
||||||
|
virtual void get_argument_options(const StringName& p_function,int p_idx,List<String>*r_options) const;
|
||||||
|
|
||||||
StringName XL_MESSAGE(const StringName& p_message) const; //translate message (internationalization)
|
StringName XL_MESSAGE(const StringName& p_message) const; //translate message (internationalization)
|
||||||
StringName tr(const StringName& p_message) const; //translate message (alternative)
|
StringName tr(const StringName& p_message) const; //translate message (alternative)
|
||||||
|
|||||||
@@ -144,7 +144,7 @@ public:
|
|||||||
virtual bool has_named_classes() const=0;
|
virtual bool has_named_classes() const=0;
|
||||||
virtual int find_function(const String& p_function,const String& p_code) const=0;
|
virtual int find_function(const String& p_function,const String& p_code) const=0;
|
||||||
virtual String make_function(const String& p_class,const String& p_name,const StringArray& p_args) const=0;
|
virtual String make_function(const String& p_class,const String& p_name,const StringArray& p_args) const=0;
|
||||||
virtual Error complete_keyword(const String& p_code, int p_line, const String& p_base_path, const String& p_keyword, List<String>* r_options) { return ERR_UNAVAILABLE; }
|
virtual Error complete_code(const String& p_code, const String& p_base_path, Object*p_owner,List<String>* r_options,String& r_call_hint) { return ERR_UNAVAILABLE; }
|
||||||
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;
|
||||||
|
|
||||||
/* DEBUGGER FUNCTIONS */
|
/* DEBUGGER FUNCTIONS */
|
||||||
|
|||||||
126
core/variant.cpp
126
core/variant.cpp
@@ -2631,3 +2631,129 @@ Variant Variant::call(const StringName& p_method,VARIANT_ARG_DECLARE) {
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
String Variant::get_construct_string() const {
|
||||||
|
|
||||||
|
switch( type ) {
|
||||||
|
|
||||||
|
case NIL: return "null";
|
||||||
|
case BOOL: return _data._bool ? "true" : "false";
|
||||||
|
case INT: return String::num(_data._int);
|
||||||
|
case REAL: return String::num(_data._real);
|
||||||
|
case STRING: return "\""+*reinterpret_cast<const String*>(_data._mem)+"\"";
|
||||||
|
case VECTOR2: return "Vector2("+operator Vector2()+")";
|
||||||
|
case RECT2: return "Rect2("+operator Rect2()+")";
|
||||||
|
case MATRIX32: return "Matrix32("+operator Matrix32()+")";
|
||||||
|
case VECTOR3: return "Vector3("+operator Vector3()+")";
|
||||||
|
case PLANE: return "Plane("+operator Plane()+")";
|
||||||
|
//case QUAT:
|
||||||
|
case _AABB: return "AABB("+operator AABB()+")";
|
||||||
|
case QUAT: return "Quat("+operator Quat()+")";
|
||||||
|
case MATRIX3: return "Matrix3("+operator Matrix3()+")";
|
||||||
|
case TRANSFORM: return "Transform("+operator Transform()+")";
|
||||||
|
case NODE_PATH: return "@\""+operator NodePath()+"\"";
|
||||||
|
case INPUT_EVENT: return "InputEvent()";
|
||||||
|
case COLOR: return "Color("+String::num( operator Color().r)+","+String::num( operator Color().g)+","+String::num( operator Color().b)+","+String::num( operator Color().a)+")" ;
|
||||||
|
case DICTIONARY: {
|
||||||
|
|
||||||
|
const Dictionary &d =*reinterpret_cast<const Dictionary*>(_data._mem);
|
||||||
|
//const String *K=NULL;
|
||||||
|
String str="{";
|
||||||
|
List<Variant> keys;
|
||||||
|
d.get_key_list(&keys);
|
||||||
|
|
||||||
|
Vector<_VariantStrPair> pairs;
|
||||||
|
|
||||||
|
for(List<Variant>::Element *E=keys.front();E;E=E->next()) {
|
||||||
|
|
||||||
|
_VariantStrPair sp;
|
||||||
|
sp.key=E->get().get_construct_string();
|
||||||
|
sp.value=d[E->get()].get_construct_string();
|
||||||
|
pairs.push_back(sp);
|
||||||
|
}
|
||||||
|
|
||||||
|
pairs.sort();
|
||||||
|
|
||||||
|
for(int i=0;i<pairs.size();i++) {
|
||||||
|
if (i>0)
|
||||||
|
str+=", ";
|
||||||
|
str+="("+pairs[i].key+":"+pairs[i].value+")";
|
||||||
|
}
|
||||||
|
str+="}";
|
||||||
|
|
||||||
|
return str;
|
||||||
|
} break;
|
||||||
|
case VECTOR3_ARRAY: {
|
||||||
|
|
||||||
|
DVector<Vector3> vec = operator DVector<Vector3>();
|
||||||
|
String str="[";
|
||||||
|
for(int i=0;i<vec.size();i++) {
|
||||||
|
|
||||||
|
if (i>0)
|
||||||
|
str+=", ";
|
||||||
|
str+=Variant( vec[i] ).get_construct_string();
|
||||||
|
}
|
||||||
|
return str+"]";
|
||||||
|
} break;
|
||||||
|
case STRING_ARRAY: {
|
||||||
|
|
||||||
|
DVector<String> vec = operator DVector<String>();
|
||||||
|
String str="[";
|
||||||
|
for(int i=0;i<vec.size();i++) {
|
||||||
|
|
||||||
|
if (i>0)
|
||||||
|
str+=", ";
|
||||||
|
str=str+=Variant( vec[i] ).get_construct_string();
|
||||||
|
}
|
||||||
|
return str+"]";
|
||||||
|
} break;
|
||||||
|
case INT_ARRAY: {
|
||||||
|
|
||||||
|
DVector<int> vec = operator DVector<int>();
|
||||||
|
String str="[";
|
||||||
|
for(int i=0;i<vec.size();i++) {
|
||||||
|
|
||||||
|
if (i>0)
|
||||||
|
str+=", ";
|
||||||
|
str=str+itos(vec[i]);
|
||||||
|
}
|
||||||
|
return str+"]";
|
||||||
|
} break;
|
||||||
|
case REAL_ARRAY: {
|
||||||
|
|
||||||
|
DVector<real_t> vec = operator DVector<real_t>();
|
||||||
|
String str="[";
|
||||||
|
for(int i=0;i<vec.size();i++) {
|
||||||
|
|
||||||
|
if (i>0)
|
||||||
|
str+=", ";
|
||||||
|
str=str+rtos(vec[i]);
|
||||||
|
}
|
||||||
|
return str+"]";
|
||||||
|
} break;
|
||||||
|
case ARRAY: {
|
||||||
|
|
||||||
|
Array arr = operator Array();
|
||||||
|
String str="[";
|
||||||
|
for (int i=0; i<arr.size(); i++) {
|
||||||
|
if (i)
|
||||||
|
str+=", ";
|
||||||
|
str += arr[i].get_construct_string();
|
||||||
|
};
|
||||||
|
return str+"]";
|
||||||
|
|
||||||
|
} break;
|
||||||
|
case OBJECT: {
|
||||||
|
|
||||||
|
if (_get_obj().obj)
|
||||||
|
return _get_obj().obj->get_type()+".new()";
|
||||||
|
else
|
||||||
|
return "null";
|
||||||
|
|
||||||
|
} break;
|
||||||
|
default: {
|
||||||
|
return "["+get_type_name(type)+"]";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|||||||
@@ -415,6 +415,8 @@ public:
|
|||||||
static bool has_numeric_constant(Variant::Type p_type, const StringName& p_value);
|
static bool has_numeric_constant(Variant::Type p_type, const StringName& p_value);
|
||||||
static int get_numeric_constant_value(Variant::Type p_type, const StringName& p_value);
|
static int get_numeric_constant_value(Variant::Type p_type, const StringName& p_value);
|
||||||
|
|
||||||
|
String get_construct_string() const;
|
||||||
|
|
||||||
void operator=(const Variant& p_variant); // only this is enough for all the other types
|
void operator=(const Variant& p_variant); // only this is enough for all the other types
|
||||||
Variant(const Variant& p_variant);
|
Variant(const Variant& p_variant);
|
||||||
_FORCE_INLINE_ Variant() { type=NIL; }
|
_FORCE_INLINE_ Variant() { type=NIL; }
|
||||||
|
|||||||
@@ -332,6 +332,12 @@ Error OS_Unix::execute(const String& p_path, const List<String>& p_arguments,boo
|
|||||||
Error OS_Unix::kill(const ProcessID& p_pid) {
|
Error OS_Unix::kill(const ProcessID& p_pid) {
|
||||||
|
|
||||||
int ret = ::kill(p_pid,SIGKILL);
|
int ret = ::kill(p_pid,SIGKILL);
|
||||||
|
if (!ret) {
|
||||||
|
//avoid zombie process
|
||||||
|
int st;
|
||||||
|
::waitpid(p_pid,&st,0);
|
||||||
|
|
||||||
|
}
|
||||||
return ret?ERR_INVALID_PARAMETER:OK;
|
return ret?ERR_INVALID_PARAMETER:OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
30
makefile
30
makefile
@@ -1,30 +0,0 @@
|
|||||||
#*************************************************************************/
|
|
||||||
#* This file is part of: */
|
|
||||||
#* GODOT ENGINE */
|
|
||||||
#* http://www.godotengine.org */
|
|
||||||
#*************************************************************************/
|
|
||||||
# Simple makefile to give support for external C/C++ IDEs */
|
|
||||||
#*************************************************************************/
|
|
||||||
|
|
||||||
# Default build
|
|
||||||
all: debug
|
|
||||||
|
|
||||||
# Release Build
|
|
||||||
release:
|
|
||||||
scons target="release" bin/godot
|
|
||||||
|
|
||||||
# Profile Build
|
|
||||||
profile:
|
|
||||||
scons target="profile" bin/godot
|
|
||||||
|
|
||||||
# Debug Build
|
|
||||||
debug:
|
|
||||||
# Debug information (code size gets severely affected):
|
|
||||||
# g: Default (same as g2)
|
|
||||||
# g0: no debug info
|
|
||||||
# g1: minimal info
|
|
||||||
# g3: maximal info
|
|
||||||
scons target="debug" CCFLAGS="-g" bin/godot
|
|
||||||
|
|
||||||
clean:
|
|
||||||
scons -c bin/godot
|
|
||||||
@@ -1168,6 +1168,7 @@ Error GDCompiler::_parse_function(GDScript *p_script,const GDParser::ClassNode *
|
|||||||
codegen.current_line=0;
|
codegen.current_line=0;
|
||||||
codegen.call_max=0;
|
codegen.call_max=0;
|
||||||
codegen.debug_stack=ScriptDebugger::get_singleton()!=NULL;
|
codegen.debug_stack=ScriptDebugger::get_singleton()!=NULL;
|
||||||
|
Vector<StringName> argnames;
|
||||||
|
|
||||||
int stack_level=0;
|
int stack_level=0;
|
||||||
|
|
||||||
@@ -1175,6 +1176,9 @@ Error GDCompiler::_parse_function(GDScript *p_script,const GDParser::ClassNode *
|
|||||||
for(int i=0;i<p_func->arguments.size();i++) {
|
for(int i=0;i<p_func->arguments.size();i++) {
|
||||||
int idx = i;
|
int idx = i;
|
||||||
codegen.add_stack_identifier(p_func->arguments[i],i);
|
codegen.add_stack_identifier(p_func->arguments[i],i);
|
||||||
|
#ifdef TOOLS_ENABLED
|
||||||
|
argnames.push_back(p_func->arguments[i]);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
stack_level=p_func->arguments.size();
|
stack_level=p_func->arguments.size();
|
||||||
}
|
}
|
||||||
@@ -1249,6 +1253,9 @@ Error GDCompiler::_parse_function(GDScript *p_script,const GDParser::ClassNode *
|
|||||||
if (p_func)
|
if (p_func)
|
||||||
gdfunc->_static=p_func->_static;
|
gdfunc->_static=p_func->_static;
|
||||||
|
|
||||||
|
#ifdef TOOLS_ENABLED
|
||||||
|
gdfunc->arg_names=argnames;
|
||||||
|
#endif
|
||||||
//constants
|
//constants
|
||||||
if (codegen.constant_map.size()) {
|
if (codegen.constant_map.size()) {
|
||||||
gdfunc->_constant_count=codegen.constant_map.size();
|
gdfunc->_constant_count=codegen.constant_map.size();
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -30,19 +30,6 @@
|
|||||||
#include "print_string.h"
|
#include "print_string.h"
|
||||||
#include "io/resource_loader.h"
|
#include "io/resource_loader.h"
|
||||||
#include "os/file_access.h"
|
#include "os/file_access.h"
|
||||||
/* TODO:
|
|
||||||
|
|
||||||
*Property reduce constant expressions
|
|
||||||
*Implement missing operators in variant?
|
|
||||||
*constructor
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
todo:
|
|
||||||
fix post ++,--
|
|
||||||
make sure ++,-- don't work on constant expressions
|
|
||||||
seems passing parent node as param is not needed
|
|
||||||
*/
|
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
T* GDParser::alloc_node() {
|
T* GDParser::alloc_node() {
|
||||||
@@ -116,14 +103,20 @@ bool GDParser::_enter_indent_block(BlockNode* p_block) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GDParser::_parse_arguments(Node* p_parent,Vector<Node*>& p_args,bool p_static) {
|
bool GDParser::_parse_arguments(Node* p_parent,Vector<Node*>& p_args,bool p_static,bool p_can_codecomplete) {
|
||||||
|
|
||||||
if (tokenizer->get_token()==GDTokenizer::TK_PARENTHESIS_CLOSE) {
|
if (tokenizer->get_token()==GDTokenizer::TK_PARENTHESIS_CLOSE) {
|
||||||
tokenizer->advance();
|
tokenizer->advance();
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
|
int argidx=0;
|
||||||
|
|
||||||
while(true) {
|
while(true) {
|
||||||
|
|
||||||
|
if (tokenizer->get_token()==GDTokenizer::TK_CURSOR) {
|
||||||
|
_make_completable_call(argidx);
|
||||||
|
completion_node=p_parent;
|
||||||
|
}
|
||||||
|
|
||||||
Node*arg = _parse_expression(p_parent,p_static);
|
Node*arg = _parse_expression(p_parent,p_static);
|
||||||
if (!arg)
|
if (!arg)
|
||||||
@@ -144,6 +137,7 @@ bool GDParser::_parse_arguments(Node* p_parent,Vector<Node*>& p_args,bool p_stat
|
|||||||
}
|
}
|
||||||
|
|
||||||
tokenizer->advance();
|
tokenizer->advance();
|
||||||
|
argidx++;
|
||||||
} else {
|
} else {
|
||||||
// something is broken
|
// something is broken
|
||||||
_set_error("Expected ',' or ')'");
|
_set_error("Expected ',' or ')'");
|
||||||
@@ -158,6 +152,48 @@ bool GDParser::_parse_arguments(Node* p_parent,Vector<Node*>& p_args,bool p_stat
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void GDParser::_make_completable_call(int p_arg) {
|
||||||
|
|
||||||
|
completion_cursor=StringName();
|
||||||
|
completion_type=COMPLETION_CALL_ARGUMENTS;
|
||||||
|
completion_class=current_class;
|
||||||
|
completion_function=current_function;
|
||||||
|
completion_line=tokenizer->get_token_line();
|
||||||
|
completion_argument=p_arg;
|
||||||
|
completion_block=current_block;
|
||||||
|
tokenizer->advance();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool GDParser::_get_completable_identifier(CompletionType p_type,StringName& identifier) {
|
||||||
|
|
||||||
|
identifier=StringName();
|
||||||
|
if (tokenizer->get_token()==GDTokenizer::TK_IDENTIFIER) {
|
||||||
|
identifier=tokenizer->get_token_identifier();
|
||||||
|
tokenizer->advance();
|
||||||
|
}
|
||||||
|
if (tokenizer->get_token()==GDTokenizer::TK_CURSOR) {
|
||||||
|
|
||||||
|
completion_cursor=identifier;
|
||||||
|
completion_type=p_type;
|
||||||
|
completion_class=current_class;
|
||||||
|
completion_function=current_function;
|
||||||
|
completion_line=tokenizer->get_token_line();
|
||||||
|
completion_block=current_block;
|
||||||
|
tokenizer->advance();
|
||||||
|
|
||||||
|
if (tokenizer->get_token()==GDTokenizer::TK_IDENTIFIER) {
|
||||||
|
identifier=identifier.operator String() + tokenizer->get_token_identifier().operator String();
|
||||||
|
tokenizer->advance();
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
GDParser::Node* GDParser::_parse_expression(Node *p_parent,bool p_static,bool p_allow_assign) {
|
GDParser::Node* GDParser::_parse_expression(Node *p_parent,bool p_static,bool p_allow_assign) {
|
||||||
|
|
||||||
@@ -199,6 +235,9 @@ GDParser::Node* GDParser::_parse_expression(Node *p_parent,bool p_static,bool p_
|
|||||||
|
|
||||||
tokenizer->advance();
|
tokenizer->advance();
|
||||||
expr=subexpr;
|
expr=subexpr;
|
||||||
|
} else if (tokenizer->get_token()==GDTokenizer::TK_CURSOR) {
|
||||||
|
tokenizer->advance();
|
||||||
|
continue; //no point in cursor in the middle of expression
|
||||||
|
|
||||||
} else if (tokenizer->get_token()==GDTokenizer::TK_CONSTANT) {
|
} else if (tokenizer->get_token()==GDTokenizer::TK_CONSTANT) {
|
||||||
|
|
||||||
@@ -327,12 +366,19 @@ GDParser::Node* GDParser::_parse_expression(Node *p_parent,bool p_static,bool p_
|
|||||||
|
|
||||||
Variant::Type bi_type = tokenizer->get_token_type();
|
Variant::Type bi_type = tokenizer->get_token_type();
|
||||||
tokenizer->advance(2);
|
tokenizer->advance(2);
|
||||||
if (tokenizer->get_token()!=GDTokenizer::TK_IDENTIFIER) {
|
|
||||||
|
StringName identifier;
|
||||||
|
|
||||||
|
if (_get_completable_identifier(COMPLETION_BUILT_IN_TYPE_CONSTANT,identifier)) {
|
||||||
|
|
||||||
|
completion_built_in_constant=bi_type;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (identifier!=StringName()) {
|
||||||
|
|
||||||
_set_error("Built-in type constant expected after '.'");
|
_set_error("Built-in type constant expected after '.'");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
StringName identifier = tokenizer->get_token_identifier();
|
|
||||||
if (!Variant::has_numeric_constant(bi_type,identifier)) {
|
if (!Variant::has_numeric_constant(bi_type,identifier)) {
|
||||||
|
|
||||||
_set_error("Static constant '"+identifier.operator String()+"' not present in built-in type "+Variant::get_type_name(bi_type)+".");
|
_set_error("Static constant '"+identifier.operator String()+"' not present in built-in type "+Variant::get_type_name(bi_type)+".");
|
||||||
@@ -342,7 +388,7 @@ GDParser::Node* GDParser::_parse_expression(Node *p_parent,bool p_static,bool p_
|
|||||||
ConstantNode *cn = alloc_node<ConstantNode>();
|
ConstantNode *cn = alloc_node<ConstantNode>();
|
||||||
cn->value=Variant::get_numeric_constant_value(bi_type,identifier);
|
cn->value=Variant::get_numeric_constant_value(bi_type,identifier);
|
||||||
expr=cn;
|
expr=cn;
|
||||||
tokenizer->advance();
|
|
||||||
|
|
||||||
} else if (tokenizer->get_token(1)==GDTokenizer::TK_PARENTHESIS_OPEN && (tokenizer->get_token()==GDTokenizer::TK_BUILT_IN_TYPE || tokenizer->get_token()==GDTokenizer::TK_IDENTIFIER || tokenizer->get_token()==GDTokenizer::TK_BUILT_IN_FUNC)) {
|
} else if (tokenizer->get_token(1)==GDTokenizer::TK_PARENTHESIS_OPEN && (tokenizer->get_token()==GDTokenizer::TK_BUILT_IN_TYPE || tokenizer->get_token()==GDTokenizer::TK_IDENTIFIER || tokenizer->get_token()==GDTokenizer::TK_BUILT_IN_FUNC)) {
|
||||||
//function or constructor
|
//function or constructor
|
||||||
@@ -355,23 +401,35 @@ GDParser::Node* GDParser::_parse_expression(Node *p_parent,bool p_static,bool p_
|
|||||||
TypeNode *tn = alloc_node<TypeNode>();
|
TypeNode *tn = alloc_node<TypeNode>();
|
||||||
tn->vtype=tokenizer->get_token_type();
|
tn->vtype=tokenizer->get_token_type();
|
||||||
op->arguments.push_back(tn);
|
op->arguments.push_back(tn);
|
||||||
|
tokenizer->advance(2);
|
||||||
} else if (tokenizer->get_token()==GDTokenizer::TK_BUILT_IN_FUNC) {
|
} else if (tokenizer->get_token()==GDTokenizer::TK_BUILT_IN_FUNC) {
|
||||||
|
|
||||||
BuiltInFunctionNode *bn = alloc_node<BuiltInFunctionNode>();
|
BuiltInFunctionNode *bn = alloc_node<BuiltInFunctionNode>();
|
||||||
bn->function=tokenizer->get_token_built_in_func();
|
bn->function=tokenizer->get_token_built_in_func();
|
||||||
op->arguments.push_back(bn);
|
op->arguments.push_back(bn);
|
||||||
|
tokenizer->advance(2);
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
SelfNode *self = alloc_node<SelfNode>();
|
SelfNode *self = alloc_node<SelfNode>();
|
||||||
op->arguments.push_back(self);
|
op->arguments.push_back(self);
|
||||||
|
|
||||||
IdentifierNode* id = alloc_node<IdentifierNode>();
|
StringName identifier;
|
||||||
id->name=tokenizer->get_token_identifier();
|
if (_get_completable_identifier(COMPLETION_FUNCTION,identifier)) {
|
||||||
op->arguments.push_back(id);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
tokenizer->advance(2);
|
IdentifierNode* id = alloc_node<IdentifierNode>();
|
||||||
if (!_parse_arguments(op,op->arguments,p_static))
|
id->name=identifier;
|
||||||
|
op->arguments.push_back(id);
|
||||||
|
tokenizer->advance(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tokenizer->get_token()==GDTokenizer::TK_CURSOR) {
|
||||||
|
_make_completable_call(0);
|
||||||
|
completion_node=op;
|
||||||
|
|
||||||
|
}
|
||||||
|
if (!_parse_arguments(op,op->arguments,p_static,true))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
expr=op;
|
expr=op;
|
||||||
@@ -381,12 +439,15 @@ GDParser::Node* GDParser::_parse_expression(Node *p_parent,bool p_static,bool p_
|
|||||||
|
|
||||||
const ClassNode* cln = static_cast<const ClassNode*>(get_parse_tree());
|
const ClassNode* cln = static_cast<const ClassNode*>(get_parse_tree());
|
||||||
bool bfn = false;
|
bool bfn = false;
|
||||||
StringName idn( tokenizer->get_token_identifier() );
|
StringName identifier;
|
||||||
|
if (_get_completable_identifier(COMPLETION_IDENTIFIER,identifier)) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
for( int i=0; i<cln->constant_expressions.size(); ++i ) {
|
for( int i=0; i<cln->constant_expressions.size(); ++i ) {
|
||||||
|
|
||||||
if( cln->constant_expressions[i].identifier == idn ) {
|
if( cln->constant_expressions[i].identifier == identifier ) {
|
||||||
tokenizer->advance();
|
|
||||||
expr = cln->constant_expressions[i].expression;
|
expr = cln->constant_expressions[i].expression;
|
||||||
bfn = true;
|
bfn = true;
|
||||||
break;
|
break;
|
||||||
@@ -395,8 +456,7 @@ GDParser::Node* GDParser::_parse_expression(Node *p_parent,bool p_static,bool p_
|
|||||||
|
|
||||||
if ( !bfn ) {
|
if ( !bfn ) {
|
||||||
IdentifierNode *id = alloc_node<IdentifierNode>();
|
IdentifierNode *id = alloc_node<IdentifierNode>();
|
||||||
id->name = idn;
|
id->name = identifier;
|
||||||
tokenizer->advance();
|
|
||||||
expr = id;
|
expr = id;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -600,7 +660,7 @@ GDParser::Node* GDParser::_parse_expression(Node *p_parent,bool p_static,bool p_
|
|||||||
|
|
||||||
expr=dict;
|
expr=dict;
|
||||||
|
|
||||||
} else if (tokenizer->get_token()==GDTokenizer::TK_PERIOD && tokenizer->get_token(1)==GDTokenizer::TK_IDENTIFIER && tokenizer->get_token(2)==GDTokenizer::TK_PARENTHESIS_OPEN) {
|
} else if (tokenizer->get_token()==GDTokenizer::TK_PERIOD && (tokenizer->get_token(1)==GDTokenizer::TK_IDENTIFIER || tokenizer->get_token(1)==GDTokenizer::TK_CURSOR) && tokenizer->get_token(2)==GDTokenizer::TK_PARENTHESIS_OPEN) {
|
||||||
// parent call
|
// parent call
|
||||||
|
|
||||||
tokenizer->advance(); //goto identifier
|
tokenizer->advance(); //goto identifier
|
||||||
@@ -611,12 +671,16 @@ GDParser::Node* GDParser::_parse_expression(Node *p_parent,bool p_static,bool p_
|
|||||||
/*SelfNode *self = alloc_node<SelfNode>();
|
/*SelfNode *self = alloc_node<SelfNode>();
|
||||||
op->arguments.push_back(self);
|
op->arguments.push_back(self);
|
||||||
forbidden for now */
|
forbidden for now */
|
||||||
|
StringName identifier;
|
||||||
|
if (_get_completable_identifier(COMPLETION_PARENT_FUNCTION,identifier)) {
|
||||||
|
//indexing stuff
|
||||||
|
}
|
||||||
|
|
||||||
IdentifierNode *id = alloc_node<IdentifierNode>();
|
IdentifierNode *id = alloc_node<IdentifierNode>();
|
||||||
id->name=tokenizer->get_token_identifier();
|
id->name=identifier;
|
||||||
op->arguments.push_back(id);
|
op->arguments.push_back(id);
|
||||||
|
|
||||||
tokenizer->advance(2);
|
tokenizer->advance(1);
|
||||||
if (!_parse_arguments(op,op->arguments,p_static))
|
if (!_parse_arguments(op,op->arguments,p_static))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
@@ -651,7 +715,7 @@ GDParser::Node* GDParser::_parse_expression(Node *p_parent,bool p_static,bool p_
|
|||||||
|
|
||||||
//indexing using "."
|
//indexing using "."
|
||||||
|
|
||||||
if (tokenizer->get_token(1)!=GDTokenizer::TK_IDENTIFIER && tokenizer->get_token(1)!=GDTokenizer::TK_BUILT_IN_FUNC ) {
|
if (tokenizer->get_token(1)!=GDTokenizer::TK_CURSOR && tokenizer->get_token(1)!=GDTokenizer::TK_IDENTIFIER && tokenizer->get_token(1)!=GDTokenizer::TK_BUILT_IN_FUNC ) {
|
||||||
_set_error("Expected identifier as member");
|
_set_error("Expected identifier as member");
|
||||||
return NULL;
|
return NULL;
|
||||||
} else if (tokenizer->get_token(2)==GDTokenizer::TK_PARENTHESIS_OPEN) {
|
} else if (tokenizer->get_token(2)==GDTokenizer::TK_PARENTHESIS_OPEN) {
|
||||||
@@ -659,37 +723,67 @@ GDParser::Node* GDParser::_parse_expression(Node *p_parent,bool p_static,bool p_
|
|||||||
OperatorNode * op = alloc_node<OperatorNode>();
|
OperatorNode * op = alloc_node<OperatorNode>();
|
||||||
op->op=OperatorNode::OP_CALL;
|
op->op=OperatorNode::OP_CALL;
|
||||||
|
|
||||||
|
tokenizer->advance();
|
||||||
|
|
||||||
IdentifierNode * id = alloc_node<IdentifierNode>();
|
IdentifierNode * id = alloc_node<IdentifierNode>();
|
||||||
if (tokenizer->get_token(1)==GDTokenizer::TK_BUILT_IN_FUNC ) {
|
if (tokenizer->get_token()==GDTokenizer::TK_BUILT_IN_FUNC ) {
|
||||||
//small hack so built in funcs don't obfuscate methods
|
//small hack so built in funcs don't obfuscate methods
|
||||||
|
|
||||||
id->name=GDFunctions::get_func_name(tokenizer->get_token_built_in_func(1));
|
id->name=GDFunctions::get_func_name(tokenizer->get_token_built_in_func());
|
||||||
|
tokenizer->advance();
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
id->name=tokenizer->get_token_identifier(1);
|
StringName identifier;
|
||||||
|
if (_get_completable_identifier(COMPLETION_METHOD,identifier)) {
|
||||||
|
completion_node=op;
|
||||||
|
//indexing stuff
|
||||||
|
}
|
||||||
|
|
||||||
|
id->name=identifier;
|
||||||
}
|
}
|
||||||
|
|
||||||
op->arguments.push_back(expr); // call what
|
op->arguments.push_back(expr); // call what
|
||||||
op->arguments.push_back(id); // call func
|
op->arguments.push_back(id); // call func
|
||||||
//get arguments
|
//get arguments
|
||||||
tokenizer->advance(3);
|
tokenizer->advance(1);
|
||||||
if (!_parse_arguments(op,op->arguments,p_static))
|
if (tokenizer->get_token()==GDTokenizer::TK_CURSOR) {
|
||||||
|
_make_completable_call(0);
|
||||||
|
completion_node=op;
|
||||||
|
|
||||||
|
}
|
||||||
|
if (!_parse_arguments(op,op->arguments,p_static,true))
|
||||||
return NULL;
|
return NULL;
|
||||||
expr=op;
|
expr=op;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
//simple indexing!
|
//simple indexing!
|
||||||
|
|
||||||
|
|
||||||
OperatorNode * op = alloc_node<OperatorNode>();
|
OperatorNode * op = alloc_node<OperatorNode>();
|
||||||
op->op=OperatorNode::OP_INDEX_NAMED;
|
op->op=OperatorNode::OP_INDEX_NAMED;
|
||||||
|
tokenizer->advance();
|
||||||
|
|
||||||
|
|
||||||
|
StringName identifier;
|
||||||
|
if (_get_completable_identifier(COMPLETION_INDEX,identifier)) {
|
||||||
|
|
||||||
|
if (identifier==StringName()) {
|
||||||
|
identifier="@temp"; //so it parses allright
|
||||||
|
}
|
||||||
|
completion_node=op;
|
||||||
|
|
||||||
|
//indexing stuff
|
||||||
|
}
|
||||||
|
|
||||||
IdentifierNode * id = alloc_node<IdentifierNode>();
|
IdentifierNode * id = alloc_node<IdentifierNode>();
|
||||||
id->name=tokenizer->get_token_identifier(1);
|
id->name=identifier;
|
||||||
|
|
||||||
op->arguments.push_back(expr);
|
op->arguments.push_back(expr);
|
||||||
op->arguments.push_back(id);
|
op->arguments.push_back(id);
|
||||||
|
|
||||||
expr=op;
|
expr=op;
|
||||||
|
|
||||||
tokenizer->advance(2);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if (tokenizer->get_token()==GDTokenizer::TK_BRACKET_OPEN) {
|
} else if (tokenizer->get_token()==GDTokenizer::TK_BRACKET_OPEN) {
|
||||||
@@ -1442,6 +1536,7 @@ void GDParser::_parse_block(BlockNode *p_block,bool p_static) {
|
|||||||
cf_if->arguments.push_back(condition);
|
cf_if->arguments.push_back(condition);
|
||||||
|
|
||||||
cf_if->body = alloc_node<BlockNode>();
|
cf_if->body = alloc_node<BlockNode>();
|
||||||
|
cf_if->body->parent_block=p_block;
|
||||||
p_block->sub_blocks.push_back(cf_if->body);
|
p_block->sub_blocks.push_back(cf_if->body);
|
||||||
|
|
||||||
if (!_enter_indent_block(cf_if->body)) {
|
if (!_enter_indent_block(cf_if->body)) {
|
||||||
@@ -1449,7 +1544,10 @@ void GDParser::_parse_block(BlockNode *p_block,bool p_static) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
current_block=cf_if->body;
|
||||||
_parse_block(cf_if->body,p_static);
|
_parse_block(cf_if->body,p_static);
|
||||||
|
current_block=p_block;
|
||||||
|
|
||||||
if (error_set)
|
if (error_set)
|
||||||
return;
|
return;
|
||||||
p_block->statements.push_back(cf_if);
|
p_block->statements.push_back(cf_if);
|
||||||
@@ -1476,6 +1574,7 @@ void GDParser::_parse_block(BlockNode *p_block,bool p_static) {
|
|||||||
tokenizer->advance();
|
tokenizer->advance();
|
||||||
|
|
||||||
cf_if->body_else=alloc_node<BlockNode>();
|
cf_if->body_else=alloc_node<BlockNode>();
|
||||||
|
cf_if->body_else->parent_block=p_block;
|
||||||
p_block->sub_blocks.push_back(cf_if->body_else);
|
p_block->sub_blocks.push_back(cf_if->body_else);
|
||||||
|
|
||||||
ControlFlowNode *cf_else = alloc_node<ControlFlowNode>();
|
ControlFlowNode *cf_else = alloc_node<ControlFlowNode>();
|
||||||
@@ -1491,6 +1590,7 @@ void GDParser::_parse_block(BlockNode *p_block,bool p_static) {
|
|||||||
cf_if->body_else->statements.push_back(cf_else);
|
cf_if->body_else->statements.push_back(cf_else);
|
||||||
cf_if=cf_else;
|
cf_if=cf_else;
|
||||||
cf_if->body=alloc_node<BlockNode>();
|
cf_if->body=alloc_node<BlockNode>();
|
||||||
|
cf_if->body->parent_block=p_block;
|
||||||
p_block->sub_blocks.push_back(cf_if->body);
|
p_block->sub_blocks.push_back(cf_if->body);
|
||||||
|
|
||||||
|
|
||||||
@@ -1499,7 +1599,9 @@ void GDParser::_parse_block(BlockNode *p_block,bool p_static) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
current_block=cf_else->body;
|
||||||
_parse_block(cf_else->body,p_static);
|
_parse_block(cf_else->body,p_static);
|
||||||
|
current_block=p_block;
|
||||||
if (error_set)
|
if (error_set)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -1515,13 +1617,16 @@ void GDParser::_parse_block(BlockNode *p_block,bool p_static) {
|
|||||||
|
|
||||||
tokenizer->advance();
|
tokenizer->advance();
|
||||||
cf_if->body_else=alloc_node<BlockNode>();
|
cf_if->body_else=alloc_node<BlockNode>();
|
||||||
|
cf_if->body_else->parent_block=p_block;
|
||||||
p_block->sub_blocks.push_back(cf_if->body_else);
|
p_block->sub_blocks.push_back(cf_if->body_else);
|
||||||
|
|
||||||
if (!_enter_indent_block(cf_if->body_else)) {
|
if (!_enter_indent_block(cf_if->body_else)) {
|
||||||
p_block->end_line=tokenizer->get_token_line();
|
p_block->end_line=tokenizer->get_token_line();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
current_block=cf_if->body_else;
|
||||||
_parse_block(cf_if->body_else,p_static);
|
_parse_block(cf_if->body_else,p_static);
|
||||||
|
current_block=p_block;
|
||||||
if (error_set)
|
if (error_set)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -1548,6 +1653,7 @@ void GDParser::_parse_block(BlockNode *p_block,bool p_static) {
|
|||||||
cf_while->arguments.push_back(condition);
|
cf_while->arguments.push_back(condition);
|
||||||
|
|
||||||
cf_while->body = alloc_node<BlockNode>();
|
cf_while->body = alloc_node<BlockNode>();
|
||||||
|
cf_while->body->parent_block=p_block;
|
||||||
p_block->sub_blocks.push_back(cf_while->body);
|
p_block->sub_blocks.push_back(cf_while->body);
|
||||||
|
|
||||||
if (!_enter_indent_block(cf_while->body)) {
|
if (!_enter_indent_block(cf_while->body)) {
|
||||||
@@ -1555,7 +1661,9 @@ void GDParser::_parse_block(BlockNode *p_block,bool p_static) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
current_block=cf_while->body;
|
||||||
_parse_block(cf_while->body,p_static);
|
_parse_block(cf_while->body,p_static);
|
||||||
|
current_block=p_block;
|
||||||
if (error_set)
|
if (error_set)
|
||||||
return;
|
return;
|
||||||
p_block->statements.push_back(cf_while);
|
p_block->statements.push_back(cf_while);
|
||||||
@@ -1592,6 +1700,7 @@ void GDParser::_parse_block(BlockNode *p_block,bool p_static) {
|
|||||||
cf_for->arguments.push_back(container);
|
cf_for->arguments.push_back(container);
|
||||||
|
|
||||||
cf_for->body = alloc_node<BlockNode>();
|
cf_for->body = alloc_node<BlockNode>();
|
||||||
|
cf_for->body->parent_block=p_block;
|
||||||
p_block->sub_blocks.push_back(cf_for->body);
|
p_block->sub_blocks.push_back(cf_for->body);
|
||||||
|
|
||||||
if (!_enter_indent_block(cf_for->body)) {
|
if (!_enter_indent_block(cf_for->body)) {
|
||||||
@@ -1599,7 +1708,10 @@ void GDParser::_parse_block(BlockNode *p_block,bool p_static) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
current_block=cf_for->body;
|
||||||
_parse_block(cf_for->body,p_static);
|
_parse_block(cf_for->body,p_static);
|
||||||
|
current_block=p_block;
|
||||||
|
|
||||||
if (error_set)
|
if (error_set)
|
||||||
return;
|
return;
|
||||||
p_block->statements.push_back(cf_for);
|
p_block->statements.push_back(cf_for);
|
||||||
@@ -1865,7 +1977,9 @@ void GDParser::_parse_class(ClassNode *p_class) {
|
|||||||
|
|
||||||
ClassNode *newclass = alloc_node<ClassNode>();
|
ClassNode *newclass = alloc_node<ClassNode>();
|
||||||
newclass->initializer = alloc_node<BlockNode>();
|
newclass->initializer = alloc_node<BlockNode>();
|
||||||
|
newclass->initializer->parent_class=newclass;
|
||||||
newclass->name=name;
|
newclass->name=name;
|
||||||
|
newclass->owner=p_class;
|
||||||
|
|
||||||
p_class->subclasses.push_back(newclass);
|
p_class->subclasses.push_back(newclass);
|
||||||
|
|
||||||
@@ -1882,7 +1996,9 @@ void GDParser::_parse_class(ClassNode *p_class) {
|
|||||||
_set_error("Indented block expected.");
|
_set_error("Indented block expected.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
current_class=newclass;
|
||||||
_parse_class(newclass);
|
_parse_class(newclass);
|
||||||
|
current_class=p_class;
|
||||||
|
|
||||||
} break;
|
} break;
|
||||||
/* this is for functions....
|
/* this is for functions....
|
||||||
@@ -2020,6 +2136,7 @@ void GDParser::_parse_class(ClassNode *p_class) {
|
|||||||
tokenizer->advance();
|
tokenizer->advance();
|
||||||
|
|
||||||
BlockNode *block = alloc_node<BlockNode>();
|
BlockNode *block = alloc_node<BlockNode>();
|
||||||
|
block->parent_class=p_class;
|
||||||
|
|
||||||
if (name=="_init") {
|
if (name=="_init") {
|
||||||
|
|
||||||
@@ -2095,8 +2212,12 @@ void GDParser::_parse_class(ClassNode *p_class) {
|
|||||||
p_class->functions.push_back(function);
|
p_class->functions.push_back(function);
|
||||||
|
|
||||||
|
|
||||||
_parse_block(block,_static);
|
current_function=function;
|
||||||
function->body=block;
|
function->body=block;
|
||||||
|
current_block=block;
|
||||||
|
_parse_block(block,_static);
|
||||||
|
current_block=NULL;
|
||||||
|
|
||||||
//arguments
|
//arguments
|
||||||
} break;
|
} break;
|
||||||
case GDTokenizer::TK_PR_EXPORT: {
|
case GDTokenizer::TK_PR_EXPORT: {
|
||||||
@@ -2401,7 +2522,9 @@ void GDParser::_parse_class(ClassNode *p_class) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
member.identifier=tokenizer->get_token_identifier();
|
member.identifier=tokenizer->get_token_identifier();
|
||||||
|
member.expression=NULL;
|
||||||
member._export.name=member.identifier;
|
member._export.name=member.identifier;
|
||||||
|
member.line=tokenizer->get_token_line();
|
||||||
tokenizer->advance();
|
tokenizer->advance();
|
||||||
|
|
||||||
if (tokenizer->get_token()==GDTokenizer::TK_OP_ASSIGN) {
|
if (tokenizer->get_token()==GDTokenizer::TK_OP_ASSIGN) {
|
||||||
@@ -2417,6 +2540,8 @@ void GDParser::_parse_class(ClassNode *p_class) {
|
|||||||
if (!subexpr)
|
if (!subexpr)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
member.expression=subexpr;
|
||||||
|
|
||||||
if (autoexport) {
|
if (autoexport) {
|
||||||
if (subexpr->type==Node::TYPE_ARRAY) {
|
if (subexpr->type==Node::TYPE_ARRAY) {
|
||||||
|
|
||||||
@@ -2608,6 +2733,8 @@ Error GDParser::_parse(const String& p_base_path) {
|
|||||||
//assume class
|
//assume class
|
||||||
ClassNode *main_class = alloc_node<ClassNode>();
|
ClassNode *main_class = alloc_node<ClassNode>();
|
||||||
main_class->initializer = alloc_node<BlockNode>();
|
main_class->initializer = alloc_node<BlockNode>();
|
||||||
|
main_class->initializer->parent_class=main_class;
|
||||||
|
current_class=main_class;
|
||||||
|
|
||||||
_parse_class(main_class);
|
_parse_class(main_class);
|
||||||
|
|
||||||
@@ -2625,6 +2752,12 @@ Error GDParser::_parse(const String& p_base_path) {
|
|||||||
|
|
||||||
Error GDParser::parse_bytecode(const Vector<uint8_t> &p_bytecode,const String& p_base_path, const String &p_self_path) {
|
Error GDParser::parse_bytecode(const Vector<uint8_t> &p_bytecode,const String& p_base_path, const String &p_self_path) {
|
||||||
|
|
||||||
|
completion_type=COMPLETION_NONE;
|
||||||
|
completion_node=NULL;
|
||||||
|
completion_class=NULL;
|
||||||
|
completion_function=NULL;
|
||||||
|
completion_block=NULL;
|
||||||
|
|
||||||
self_path=p_self_path;
|
self_path=p_self_path;
|
||||||
GDTokenizerBuffer *tb = memnew( GDTokenizerBuffer );
|
GDTokenizerBuffer *tb = memnew( GDTokenizerBuffer );
|
||||||
tb->set_code_buffer(p_bytecode);
|
tb->set_code_buffer(p_bytecode);
|
||||||
@@ -2638,6 +2771,12 @@ Error GDParser::parse_bytecode(const Vector<uint8_t> &p_bytecode,const String& p
|
|||||||
|
|
||||||
Error GDParser::parse(const String& p_code, const String& p_base_path, bool p_just_validate, const String &p_self_path) {
|
Error GDParser::parse(const String& p_code, const String& p_base_path, bool p_just_validate, const String &p_self_path) {
|
||||||
|
|
||||||
|
completion_type=COMPLETION_NONE;
|
||||||
|
completion_node=NULL;
|
||||||
|
completion_class=NULL;
|
||||||
|
completion_function=NULL;
|
||||||
|
completion_block=NULL;
|
||||||
|
|
||||||
self_path=p_self_path;
|
self_path=p_self_path;
|
||||||
GDTokenizerText *tt = memnew( GDTokenizerText );
|
GDTokenizerText *tt = memnew( GDTokenizerText );
|
||||||
tt->set_code(p_code);
|
tt->set_code(p_code);
|
||||||
@@ -2667,6 +2806,12 @@ void GDParser::clear() {
|
|||||||
head=NULL;
|
head=NULL;
|
||||||
list=NULL;
|
list=NULL;
|
||||||
|
|
||||||
|
completion_type=COMPLETION_NONE;
|
||||||
|
completion_node=NULL;
|
||||||
|
completion_class=NULL;
|
||||||
|
completion_function=NULL;
|
||||||
|
completion_block=NULL;
|
||||||
|
|
||||||
validating=false;
|
validating=false;
|
||||||
error_set=false;
|
error_set=false;
|
||||||
tab_level.clear();
|
tab_level.clear();
|
||||||
@@ -2680,6 +2825,52 @@ void GDParser::clear() {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
GDParser::CompletionType GDParser::get_completion_type() {
|
||||||
|
|
||||||
|
return completion_type;
|
||||||
|
}
|
||||||
|
|
||||||
|
StringName GDParser::get_completion_cursor() {
|
||||||
|
|
||||||
|
return completion_cursor;
|
||||||
|
}
|
||||||
|
|
||||||
|
int GDParser::get_completion_line() {
|
||||||
|
|
||||||
|
return completion_line;
|
||||||
|
}
|
||||||
|
|
||||||
|
Variant::Type GDParser::get_completion_built_in_constant(){
|
||||||
|
|
||||||
|
return completion_built_in_constant;
|
||||||
|
}
|
||||||
|
|
||||||
|
GDParser::Node *GDParser::get_completion_node(){
|
||||||
|
|
||||||
|
return completion_node;
|
||||||
|
}
|
||||||
|
|
||||||
|
GDParser::BlockNode *GDParser::get_completion_block() {
|
||||||
|
|
||||||
|
return completion_block;
|
||||||
|
}
|
||||||
|
|
||||||
|
GDParser::ClassNode *GDParser::get_completion_class(){
|
||||||
|
|
||||||
|
return completion_class;
|
||||||
|
}
|
||||||
|
|
||||||
|
GDParser::FunctionNode *GDParser::get_completion_function(){
|
||||||
|
|
||||||
|
return completion_function;
|
||||||
|
}
|
||||||
|
|
||||||
|
int GDParser::get_completion_argument_index() {
|
||||||
|
|
||||||
|
return completion_argument;
|
||||||
|
}
|
||||||
|
|
||||||
GDParser::GDParser() {
|
GDParser::GDParser() {
|
||||||
|
|
||||||
head=NULL;
|
head=NULL;
|
||||||
|
|||||||
@@ -84,6 +84,8 @@ public:
|
|||||||
StringName identifier;
|
StringName identifier;
|
||||||
StringName setter;
|
StringName setter;
|
||||||
StringName getter;
|
StringName getter;
|
||||||
|
int line;
|
||||||
|
Node *expression;
|
||||||
};
|
};
|
||||||
struct Constant {
|
struct Constant {
|
||||||
StringName identifier;
|
StringName identifier;
|
||||||
@@ -96,10 +98,11 @@ public:
|
|||||||
Vector<FunctionNode*> functions;
|
Vector<FunctionNode*> functions;
|
||||||
Vector<FunctionNode*> static_functions;
|
Vector<FunctionNode*> static_functions;
|
||||||
BlockNode *initializer;
|
BlockNode *initializer;
|
||||||
|
ClassNode *owner;
|
||||||
//Vector<Node*> initializers;
|
//Vector<Node*> initializers;
|
||||||
int end_line;
|
int end_line;
|
||||||
|
|
||||||
ClassNode() { tool=false; type=TYPE_CLASS; extends_used=false; end_line=-1;}
|
ClassNode() { tool=false; type=TYPE_CLASS; extends_used=false; end_line=-1; owner=NULL;}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -118,6 +121,8 @@ public:
|
|||||||
|
|
||||||
struct BlockNode : public Node {
|
struct BlockNode : public Node {
|
||||||
|
|
||||||
|
ClassNode *parent_class=NULL;
|
||||||
|
BlockNode *parent_block=NULL;
|
||||||
Map<StringName,int> locals;
|
Map<StringName,int> locals;
|
||||||
List<Node*> statements;
|
List<Node*> statements;
|
||||||
Vector<StringName> variables;
|
Vector<StringName> variables;
|
||||||
@@ -126,7 +131,7 @@ public:
|
|||||||
//the following is useful for code completion
|
//the following is useful for code completion
|
||||||
List<BlockNode*> sub_blocks;
|
List<BlockNode*> sub_blocks;
|
||||||
int end_line;
|
int end_line;
|
||||||
BlockNode() { type=TYPE_BLOCK; end_line=-1;}
|
BlockNode() { type=TYPE_BLOCK; end_line=-1; parent_block=NULL; parent_class=NULL; }
|
||||||
};
|
};
|
||||||
|
|
||||||
struct TypeNode : public Node {
|
struct TypeNode : public Node {
|
||||||
@@ -349,6 +354,18 @@ public:
|
|||||||
};
|
};
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
enum CompletionType {
|
||||||
|
COMPLETION_NONE,
|
||||||
|
COMPLETION_BUILT_IN_TYPE_CONSTANT,
|
||||||
|
COMPLETION_FUNCTION,
|
||||||
|
COMPLETION_IDENTIFIER,
|
||||||
|
COMPLETION_PARENT_FUNCTION,
|
||||||
|
COMPLETION_METHOD,
|
||||||
|
COMPLETION_CALL_ARGUMENTS,
|
||||||
|
COMPLETION_INDEX,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
@@ -375,12 +392,31 @@ private:
|
|||||||
String base_path;
|
String base_path;
|
||||||
String self_path;
|
String self_path;
|
||||||
|
|
||||||
|
|
||||||
|
ClassNode *current_class;
|
||||||
|
FunctionNode *current_function;
|
||||||
|
BlockNode *current_block;
|
||||||
|
|
||||||
|
bool _get_completable_identifier(CompletionType p_type,StringName& identifier);
|
||||||
|
void _make_completable_call(int p_arg);
|
||||||
|
|
||||||
|
CompletionType completion_type;
|
||||||
|
StringName completion_cursor;
|
||||||
|
bool completion_static;
|
||||||
|
Variant::Type completion_built_in_constant;
|
||||||
|
Node *completion_node;
|
||||||
|
ClassNode *completion_class;
|
||||||
|
FunctionNode *completion_function;
|
||||||
|
BlockNode *completion_block;
|
||||||
|
int completion_line;
|
||||||
|
int completion_argument;
|
||||||
|
|
||||||
PropertyInfo current_export;
|
PropertyInfo current_export;
|
||||||
|
|
||||||
void _set_error(const String& p_error, int p_line=-1, int p_column=-1);
|
void _set_error(const String& p_error, int p_line=-1, int p_column=-1);
|
||||||
|
|
||||||
|
|
||||||
bool _parse_arguments(Node* p_parent,Vector<Node*>& p_args,bool p_static);
|
bool _parse_arguments(Node* p_parent, Vector<Node*>& p_args, bool p_static, bool p_can_codecomplete=false);
|
||||||
bool _enter_indent_block(BlockNode *p_block=NULL);
|
bool _enter_indent_block(BlockNode *p_block=NULL);
|
||||||
bool _parse_newline();
|
bool _parse_newline();
|
||||||
Node* _parse_expression(Node *p_parent,bool p_static,bool p_allow_assign=false);
|
Node* _parse_expression(Node *p_parent,bool p_static,bool p_allow_assign=false);
|
||||||
@@ -404,6 +440,19 @@ public:
|
|||||||
|
|
||||||
const Node *get_parse_tree() const;
|
const Node *get_parse_tree() const;
|
||||||
|
|
||||||
|
//completion info
|
||||||
|
|
||||||
|
CompletionType get_completion_type();
|
||||||
|
StringName get_completion_cursor();
|
||||||
|
int get_completion_line();
|
||||||
|
Variant::Type get_completion_built_in_constant();
|
||||||
|
Node *get_completion_node();
|
||||||
|
ClassNode *get_completion_class();
|
||||||
|
BlockNode *get_completion_block();
|
||||||
|
FunctionNode *get_completion_function();
|
||||||
|
int get_completion_argument_index();
|
||||||
|
|
||||||
|
|
||||||
void clear();
|
void clear();
|
||||||
GDParser();
|
GDParser();
|
||||||
~GDParser();
|
~GDParser();
|
||||||
|
|||||||
@@ -129,6 +129,10 @@ friend class GDCompiler;
|
|||||||
const char*_func_cname;
|
const char*_func_cname;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef TOOLS_ENABLED
|
||||||
|
Vector<StringName> arg_names;
|
||||||
|
#endif
|
||||||
|
|
||||||
List<StackDebug> stack_debug;
|
List<StackDebug> stack_debug;
|
||||||
|
|
||||||
_FORCE_INLINE_ Variant *_get_variant(int p_address,GDInstance *p_instance,GDScript *p_script,Variant &self,Variant *p_stack,String& r_error) const;
|
_FORCE_INLINE_ Variant *_get_variant(int p_address,GDInstance *p_instance,GDScript *p_script,Variant &self,Variant *p_stack,String& r_error) const;
|
||||||
@@ -169,6 +173,19 @@ public:
|
|||||||
_FORCE_INLINE_ bool is_empty() const { return _code_size==0; }
|
_FORCE_INLINE_ bool is_empty() const { return _code_size==0; }
|
||||||
|
|
||||||
int get_argument_count() const { return _argument_count; }
|
int get_argument_count() const { return _argument_count; }
|
||||||
|
StringName get_argument_name(int p_idx) const {
|
||||||
|
#ifdef TOOLS_ENABLED
|
||||||
|
ERR_FAIL_INDEX_V(p_idx,arg_names.size(),StringName());
|
||||||
|
return arg_names[p_idx];
|
||||||
|
#endif
|
||||||
|
return StringName();
|
||||||
|
|
||||||
|
}
|
||||||
|
Variant get_default_argument(int p_idx) const {
|
||||||
|
ERR_FAIL_INDEX_V(p_idx,default_arguments.size(),Variant());
|
||||||
|
return default_arguments[p_idx];
|
||||||
|
}
|
||||||
|
|
||||||
Variant call(GDInstance *p_instance,const Variant **p_args, int p_argcount,Variant::CallError& r_err,CallState *p_state=NULL);
|
Variant call(GDInstance *p_instance,const Variant **p_args, int p_argcount,Variant::CallError& r_err,CallState *p_state=NULL);
|
||||||
|
|
||||||
GDFunction();
|
GDFunction();
|
||||||
@@ -293,6 +310,7 @@ protected:
|
|||||||
static void _bind_methods();
|
static void _bind_methods();
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
bool is_valid() const { return valid; }
|
||||||
|
|
||||||
const Map<StringName,Ref<GDScript> >& get_subclasses() const { return subclasses; }
|
const Map<StringName,Ref<GDScript> >& get_subclasses() const { return subclasses; }
|
||||||
const Map<StringName,Variant >& get_constants() const { return constants; }
|
const Map<StringName,Variant >& get_constants() const { return constants; }
|
||||||
@@ -488,7 +506,7 @@ public:
|
|||||||
virtual bool has_named_classes() const;
|
virtual bool has_named_classes() const;
|
||||||
virtual int find_function(const String& p_function,const String& p_code) const;
|
virtual int find_function(const String& p_function,const String& p_code) const;
|
||||||
virtual String make_function(const String& p_class,const String& p_name,const StringArray& p_args) const;
|
virtual String make_function(const String& p_class,const String& p_name,const StringArray& p_args) const;
|
||||||
virtual Error complete_keyword(const String& p_code, int p_line, const String& p_base_path,const String& p_keyword, List<String>* r_options);
|
virtual Error complete_code(const String& p_code, const String& p_base_path, Object*p_owner,List<String>* r_options,String& r_call_hint);
|
||||||
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;
|
||||||
|
|
||||||
/* DEBUGGER FUNCTIONS */
|
/* DEBUGGER FUNCTIONS */
|
||||||
|
|||||||
@@ -110,7 +110,8 @@ const char* GDTokenizer::token_names[TK_MAX]={
|
|||||||
"':'",
|
"':'",
|
||||||
"'\\n'",
|
"'\\n'",
|
||||||
"Error",
|
"Error",
|
||||||
"EOF"};
|
"EOF",
|
||||||
|
"Cursor"};
|
||||||
|
|
||||||
const char *GDTokenizer::get_token_name(Token p_token) {
|
const char *GDTokenizer::get_token_name(Token p_token) {
|
||||||
|
|
||||||
@@ -648,6 +649,9 @@ void GDTokenizerText::_advance() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
} break;
|
} break;
|
||||||
|
case 0xFFFF: {
|
||||||
|
_make_token(TK_CURSOR);
|
||||||
|
} break;
|
||||||
default: {
|
default: {
|
||||||
|
|
||||||
if (_is_number(GETCHAR(0)) || (GETCHAR(0)=='.' && _is_number(GETCHAR(1)))) {
|
if (_is_number(GETCHAR(0)) || (GETCHAR(0)=='.' && _is_number(GETCHAR(1)))) {
|
||||||
|
|||||||
@@ -118,6 +118,7 @@ public:
|
|||||||
TK_NEWLINE,
|
TK_NEWLINE,
|
||||||
TK_ERROR,
|
TK_ERROR,
|
||||||
TK_EOF,
|
TK_EOF,
|
||||||
|
TK_CURSOR, //used for code completion
|
||||||
TK_MAX
|
TK_MAX
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1398,6 +1398,7 @@ void OS_Windows::set_video_mode(const VideoMode& p_video_mode,int p_screen) {
|
|||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
OS::VideoMode OS_Windows::get_video_mode(int p_screen) const {
|
OS::VideoMode OS_Windows::get_video_mode(int p_screen) const {
|
||||||
|
|
||||||
return video_mode;
|
return video_mode;
|
||||||
|
|||||||
@@ -1178,6 +1178,19 @@ NodePath AnimationPlayer::get_root() const {
|
|||||||
return root;
|
return root;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AnimationPlayer::get_argument_options(const StringName& p_function,int p_idx,List<String>*r_options) const {
|
||||||
|
|
||||||
|
String pf = p_function;
|
||||||
|
if (p_function=="play" || p_function=="remove_animation" || p_function=="has_animation" || p_function=="queue") {
|
||||||
|
List<StringName> al;
|
||||||
|
get_animation_list(&al);
|
||||||
|
for (List<StringName>::Element *E=al.front();E;E=E->next()) {
|
||||||
|
|
||||||
|
r_options->push_back("\""+String(E->get())+"\"");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Node::get_argument_options(p_function,p_idx,r_options);
|
||||||
|
}
|
||||||
|
|
||||||
void AnimationPlayer::_bind_methods() {
|
void AnimationPlayer::_bind_methods() {
|
||||||
|
|
||||||
|
|||||||
@@ -290,6 +290,9 @@ public:
|
|||||||
|
|
||||||
void clear_caches(); ///< must be called by hand if an animation was modified after added
|
void clear_caches(); ///< must be called by hand if an animation was modified after added
|
||||||
|
|
||||||
|
void get_argument_options(const StringName& p_function,int p_idx,List<String>*r_options) const;
|
||||||
|
|
||||||
|
|
||||||
AnimationPlayer();
|
AnimationPlayer();
|
||||||
~AnimationPlayer();
|
~AnimationPlayer();
|
||||||
|
|
||||||
|
|||||||
@@ -1325,9 +1325,12 @@ Size2 Control::get_minimum_size() const {
|
|||||||
|
|
||||||
Ref<Texture> Control::get_icon(const StringName& p_name,const StringName& p_type) const {
|
Ref<Texture> Control::get_icon(const StringName& p_name,const StringName& p_type) const {
|
||||||
|
|
||||||
|
if (p_type==StringName()) {
|
||||||
|
|
||||||
const Ref<Texture>* tex = data.icon_override.getptr(p_name);
|
const Ref<Texture>* tex = data.icon_override.getptr(p_name);
|
||||||
if (tex)
|
if (tex)
|
||||||
return *tex;
|
return *tex;
|
||||||
|
}
|
||||||
|
|
||||||
StringName type = p_type?p_type:get_type_name();
|
StringName type = p_type?p_type:get_type_name();
|
||||||
|
|
||||||
@@ -1353,12 +1356,11 @@ Ref<Texture> Control::get_icon(const StringName& p_name,const StringName& p_type
|
|||||||
|
|
||||||
Ref<StyleBox> Control::get_stylebox(const StringName& p_name,const StringName& p_type) const {
|
Ref<StyleBox> Control::get_stylebox(const StringName& p_name,const StringName& p_type) const {
|
||||||
|
|
||||||
|
if (p_type==StringName()) {
|
||||||
const Ref<StyleBox>* style = data.style_override.getptr(p_name);
|
const Ref<StyleBox>* style = data.style_override.getptr(p_name);
|
||||||
|
|
||||||
|
|
||||||
if (style)
|
if (style)
|
||||||
return *style;
|
return *style;
|
||||||
|
}
|
||||||
|
|
||||||
StringName type = p_type?p_type:get_type_name();
|
StringName type = p_type?p_type:get_type_name();
|
||||||
|
|
||||||
@@ -1382,9 +1384,11 @@ Ref<StyleBox> Control::get_stylebox(const StringName& p_name,const StringName& p
|
|||||||
}
|
}
|
||||||
Ref<Font> Control::get_font(const StringName& p_name,const StringName& p_type) const {
|
Ref<Font> Control::get_font(const StringName& p_name,const StringName& p_type) const {
|
||||||
|
|
||||||
|
if (p_type==StringName()) {
|
||||||
const Ref<Font>* font = data.font_override.getptr(p_name);
|
const Ref<Font>* font = data.font_override.getptr(p_name);
|
||||||
if (font)
|
if (font)
|
||||||
return *font;
|
return *font;
|
||||||
|
}
|
||||||
|
|
||||||
StringName type = p_type?p_type:get_type_name();
|
StringName type = p_type?p_type:get_type_name();
|
||||||
|
|
||||||
@@ -1411,9 +1415,11 @@ Ref<Font> Control::get_font(const StringName& p_name,const StringName& p_type) c
|
|||||||
}
|
}
|
||||||
Color Control::get_color(const StringName& p_name,const StringName& p_type) const {
|
Color Control::get_color(const StringName& p_name,const StringName& p_type) const {
|
||||||
|
|
||||||
|
if (p_type==StringName()) {
|
||||||
const Color* color = data.color_override.getptr(p_name);
|
const Color* color = data.color_override.getptr(p_name);
|
||||||
if (color)
|
if (color)
|
||||||
return *color;
|
return *color;
|
||||||
|
}
|
||||||
|
|
||||||
StringName type = p_type?p_type:get_type_name();
|
StringName type = p_type?p_type:get_type_name();
|
||||||
// try with custom themes
|
// try with custom themes
|
||||||
@@ -1438,9 +1444,11 @@ Color Control::get_color(const StringName& p_name,const StringName& p_type) cons
|
|||||||
|
|
||||||
int Control::get_constant(const StringName& p_name,const StringName& p_type) const {
|
int Control::get_constant(const StringName& p_name,const StringName& p_type) const {
|
||||||
|
|
||||||
|
if (p_type==StringName()) {
|
||||||
const int* constant = data.constant_override.getptr(p_name);
|
const int* constant = data.constant_override.getptr(p_name);
|
||||||
if (constant)
|
if (constant)
|
||||||
return *constant;
|
return *constant;
|
||||||
|
}
|
||||||
|
|
||||||
StringName type = p_type?p_type:get_type_name();
|
StringName type = p_type?p_type:get_type_name();
|
||||||
// try with custom themes
|
// try with custom themes
|
||||||
@@ -1467,9 +1475,11 @@ int Control::get_constant(const StringName& p_name,const StringName& p_type) con
|
|||||||
|
|
||||||
bool Control::has_icon(const StringName& p_name,const StringName& p_type) const {
|
bool Control::has_icon(const StringName& p_name,const StringName& p_type) const {
|
||||||
|
|
||||||
|
if (p_type==StringName()) {
|
||||||
const Ref<Texture>* tex = data.icon_override.getptr(p_name);
|
const Ref<Texture>* tex = data.icon_override.getptr(p_name);
|
||||||
if (tex)
|
if (tex)
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
StringName type = p_type?p_type:get_type_name();
|
StringName type = p_type?p_type:get_type_name();
|
||||||
|
|
||||||
@@ -1494,11 +1504,12 @@ bool Control::has_icon(const StringName& p_name,const StringName& p_type) const
|
|||||||
}
|
}
|
||||||
bool Control::has_stylebox(const StringName& p_name,const StringName& p_type) const {
|
bool Control::has_stylebox(const StringName& p_name,const StringName& p_type) const {
|
||||||
|
|
||||||
|
if (p_type==StringName()) {
|
||||||
const Ref<StyleBox>* style = data.style_override.getptr(p_name);
|
const Ref<StyleBox>* style = data.style_override.getptr(p_name);
|
||||||
|
|
||||||
if (style)
|
if (style)
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
StringName type = p_type?p_type:get_type_name();
|
StringName type = p_type?p_type:get_type_name();
|
||||||
|
|
||||||
@@ -1523,9 +1534,11 @@ bool Control::has_stylebox(const StringName& p_name,const StringName& p_type) co
|
|||||||
}
|
}
|
||||||
bool Control::has_font(const StringName& p_name,const StringName& p_type) const {
|
bool Control::has_font(const StringName& p_name,const StringName& p_type) const {
|
||||||
|
|
||||||
|
if (p_type==StringName()) {
|
||||||
const Ref<Font>* font = data.font_override.getptr(p_name);
|
const Ref<Font>* font = data.font_override.getptr(p_name);
|
||||||
if (font)
|
if (font)
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
StringName type = p_type?p_type:get_type_name();
|
StringName type = p_type?p_type:get_type_name();
|
||||||
@@ -1551,9 +1564,11 @@ bool Control::has_font(const StringName& p_name,const StringName& p_type) const
|
|||||||
}
|
}
|
||||||
bool Control::has_color(const StringName& p_name,const StringName& p_type) const {
|
bool Control::has_color(const StringName& p_name,const StringName& p_type) const {
|
||||||
|
|
||||||
|
if (p_type==StringName()) {
|
||||||
const Color* color = data.color_override.getptr(p_name);
|
const Color* color = data.color_override.getptr(p_name);
|
||||||
if (color)
|
if (color)
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
StringName type = p_type?p_type:get_type_name();
|
StringName type = p_type?p_type:get_type_name();
|
||||||
|
|
||||||
@@ -1579,9 +1594,12 @@ bool Control::has_color(const StringName& p_name,const StringName& p_type) const
|
|||||||
|
|
||||||
bool Control::has_constant(const StringName& p_name,const StringName& p_type) const {
|
bool Control::has_constant(const StringName& p_name,const StringName& p_type) const {
|
||||||
|
|
||||||
|
if (p_type==StringName()) {
|
||||||
|
|
||||||
const int* constant = data.constant_override.getptr(p_name);
|
const int* constant = data.constant_override.getptr(p_name);
|
||||||
if (constant)
|
if (constant)
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
StringName type = p_type?p_type:get_type_name();
|
StringName type = p_type?p_type:get_type_name();
|
||||||
|
|||||||
@@ -649,6 +649,7 @@ void TextEdit::_notification(int p_what) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (completion_active) {
|
if (completion_active) {
|
||||||
// code completion box
|
// code completion box
|
||||||
Ref<StyleBox> csb = get_stylebox("completion");
|
Ref<StyleBox> csb = get_stylebox("completion");
|
||||||
@@ -682,6 +683,7 @@ void TextEdit::_notification(int p_what) {
|
|||||||
completion_rect.pos.y=cursor_pos.y-th;
|
completion_rect.pos.y=cursor_pos.y-th;
|
||||||
} else {
|
} else {
|
||||||
completion_rect.pos.y=cursor_pos.y+get_row_height()+csb->get_offset().y;
|
completion_rect.pos.y=cursor_pos.y+get_row_height()+csb->get_offset().y;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cursor_pos.x-nofs+w+scrollw > get_size().width) {
|
if (cursor_pos.x-nofs+w+scrollw > get_size().width) {
|
||||||
@@ -721,6 +723,64 @@ void TextEdit::_notification(int p_what) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (completion_hint!="") {
|
||||||
|
|
||||||
|
Ref<StyleBox> sb = get_stylebox("panel","TooltipPanel");
|
||||||
|
Ref<Font> font = cache.font;
|
||||||
|
Color font_color = get_color("font_color","TooltipLabel");
|
||||||
|
|
||||||
|
|
||||||
|
int max_w=0;
|
||||||
|
int sc = completion_hint.get_slice_count("\n");
|
||||||
|
int offset=0;
|
||||||
|
int spacing=0;
|
||||||
|
for(int i=0;i<sc;i++) {
|
||||||
|
|
||||||
|
String l = completion_hint.get_slice("\n",i);
|
||||||
|
int len = font->get_string_size(l).x;
|
||||||
|
max_w = MAX(len,max_w);
|
||||||
|
if (i==0) {
|
||||||
|
offset = font->get_string_size(l.substr(0,l.find(String::chr(0xFFFF)))).x;
|
||||||
|
} else {
|
||||||
|
spacing+=cache.line_spacing;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Size2 size = Size2(max_w,sc*font->get_height()+spacing);
|
||||||
|
Size2 minsize = size+sb->get_minimum_size();
|
||||||
|
|
||||||
|
|
||||||
|
if (completion_hint_offset==-0xFFFF) {
|
||||||
|
completion_hint_offset=cursor_pos.x-offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Point2 hint_ofs = Vector2(completion_hint_offset,cursor_pos.y-minsize.y);
|
||||||
|
draw_style_box(sb,Rect2(hint_ofs,minsize));
|
||||||
|
|
||||||
|
spacing=0;
|
||||||
|
for(int i=0;i<sc;i++) {
|
||||||
|
int begin=0;
|
||||||
|
int end=0;
|
||||||
|
String l = completion_hint.get_slice("\n",i);
|
||||||
|
|
||||||
|
if (l.find(String::chr(0xFFFF))!=-1) {
|
||||||
|
begin = font->get_string_size(l.substr(0,l.find(String::chr(0xFFFF)))).x;
|
||||||
|
end = font->get_string_size(l.substr(0,l.rfind(String::chr(0xFFFF)))).x;
|
||||||
|
}
|
||||||
|
|
||||||
|
draw_string(font,hint_ofs+sb->get_offset()+Vector2(0,font->get_ascent()+font->get_height()*i+spacing),l.replace(String::chr(0xFFFF),""),font_color);
|
||||||
|
if (end>0) {
|
||||||
|
Vector2 b = hint_ofs+sb->get_offset()+Vector2(begin,font->get_height()+font->get_height()*i+spacing-1);
|
||||||
|
draw_line(b,b+Vector2(end-begin,0),font_color);
|
||||||
|
}
|
||||||
|
spacing+=cache.line_spacing;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
} break;
|
} break;
|
||||||
@@ -918,6 +978,7 @@ void TextEdit::_input_event(const InputEvent& p_input_event) {
|
|||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
_cancel_completion();
|
_cancel_completion();
|
||||||
|
_cancel_code_hint();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mb.pressed) {
|
if (mb.pressed) {
|
||||||
@@ -1172,6 +1233,7 @@ void TextEdit::_input_event(const InputEvent& p_input_event) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_cancel_completion();
|
_cancel_completion();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TEST CONTROL FIRST!! */
|
/* TEST CONTROL FIRST!! */
|
||||||
@@ -1268,6 +1330,7 @@ void TextEdit::_input_event(const InputEvent& p_input_event) {
|
|||||||
break;
|
break;
|
||||||
unselect=true;
|
unselect=true;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
if (k.unicode>=32 && !k.mod.command && !k.mod.alt && !k.mod.meta)
|
if (k.unicode>=32 && !k.mod.command && !k.mod.alt && !k.mod.meta)
|
||||||
clear=true;
|
clear=true;
|
||||||
@@ -1317,6 +1380,13 @@ void TextEdit::_input_event(const InputEvent& p_input_event) {
|
|||||||
_insert_text_at_cursor(ins);
|
_insert_text_at_cursor(ins);
|
||||||
_push_current_op();
|
_push_current_op();
|
||||||
|
|
||||||
|
} break;
|
||||||
|
case KEY_ESCAPE: {
|
||||||
|
if (completion_hint!="") {
|
||||||
|
completion_hint="";
|
||||||
|
update();
|
||||||
|
|
||||||
|
}
|
||||||
} break;
|
} break;
|
||||||
case KEY_TAB: {
|
case KEY_TAB: {
|
||||||
|
|
||||||
@@ -1454,6 +1524,7 @@ void TextEdit::_input_event(const InputEvent& p_input_event) {
|
|||||||
|
|
||||||
if (k.mod.shift)
|
if (k.mod.shift)
|
||||||
_post_shift_selection();
|
_post_shift_selection();
|
||||||
|
_cancel_code_hint();
|
||||||
|
|
||||||
} break;
|
} break;
|
||||||
case KEY_DOWN: {
|
case KEY_DOWN: {
|
||||||
@@ -1473,6 +1544,7 @@ void TextEdit::_input_event(const InputEvent& p_input_event) {
|
|||||||
|
|
||||||
if (k.mod.shift)
|
if (k.mod.shift)
|
||||||
_post_shift_selection();
|
_post_shift_selection();
|
||||||
|
_cancel_code_hint();
|
||||||
|
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
@@ -2333,6 +2405,30 @@ String TextEdit::get_text() {
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
String TextEdit::get_text_for_completion() {
|
||||||
|
|
||||||
|
String longthing;
|
||||||
|
int len = text.size();
|
||||||
|
for (int i=0;i<len;i++) {
|
||||||
|
|
||||||
|
if (i==cursor.line) {
|
||||||
|
longthing+=text[i].substr(0,cursor.column);
|
||||||
|
longthing+=String::chr(0xFFFF); //not unicode, represents the cursor
|
||||||
|
longthing+=text[i].substr(cursor.column,text[i].size());
|
||||||
|
} else {
|
||||||
|
|
||||||
|
longthing+=text[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (i!=len-1)
|
||||||
|
longthing+="\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
return longthing;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
String TextEdit::get_line(int line) const {
|
String TextEdit::get_line(int line) const {
|
||||||
|
|
||||||
@@ -2966,12 +3062,23 @@ void TextEdit::_confirm_completion() {
|
|||||||
|
|
||||||
if (same)
|
if (same)
|
||||||
cursor_set_column(cursor.column+remaining.length());
|
cursor_set_column(cursor.column+remaining.length());
|
||||||
else
|
else {
|
||||||
insert_text_at_cursor(remaining);
|
insert_text_at_cursor(remaining);
|
||||||
|
if (remaining.ends_with("(") && auto_brace_completion_enabled) {
|
||||||
|
insert_text_at_cursor(")");
|
||||||
|
cursor.column--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
_cancel_completion();
|
_cancel_completion();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void TextEdit::_cancel_code_hint() {
|
||||||
|
completion_hint="";
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
|
||||||
void TextEdit::_cancel_completion() {
|
void TextEdit::_cancel_completion() {
|
||||||
|
|
||||||
if (!completion_active)
|
if (!completion_active)
|
||||||
@@ -2982,17 +3089,29 @@ void TextEdit::_cancel_completion() {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool _is_completable(CharType c) {
|
||||||
|
|
||||||
|
return !_is_symbol(c) || c=='"' || c=='\'';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void TextEdit::_update_completion_candidates() {
|
void TextEdit::_update_completion_candidates() {
|
||||||
|
|
||||||
String l = text[cursor.line];
|
String l = text[cursor.line];
|
||||||
int cofs = CLAMP(cursor.column,0,l.length());
|
int cofs = CLAMP(cursor.column,0,l.length());
|
||||||
|
|
||||||
|
|
||||||
String s;
|
String s;
|
||||||
while(cofs>0 && l[cofs-1]>32 && !_is_symbol(l[cofs-1])) {
|
|
||||||
|
while(cofs>0 && l[cofs-1]>32 && _is_completable(l[cofs-1])) {
|
||||||
s=String::chr(l[cofs-1])+s;
|
s=String::chr(l[cofs-1])+s;
|
||||||
|
if (l[cofs-1]=='\'' || l[cofs-1]=='"')
|
||||||
|
break;
|
||||||
|
|
||||||
cofs--;
|
cofs--;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
update();
|
update();
|
||||||
|
|
||||||
if (s=="" && (cofs==0 || !completion_prefixes.has(String::chr(l[cofs-1])))) {
|
if (s=="" && (cofs==0 || !completion_prefixes.has(String::chr(l[cofs-1])))) {
|
||||||
@@ -3055,36 +3174,24 @@ void TextEdit::_update_completion_candidates() {
|
|||||||
completion_enabled=true;
|
completion_enabled=true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void TextEdit::query_code_comple() {
|
void TextEdit::query_code_comple() {
|
||||||
|
|
||||||
String l = text[cursor.line];
|
String l = text[cursor.line];
|
||||||
int ofs = CLAMP(cursor.column,0,l.length());
|
int ofs = CLAMP(cursor.column,0,l.length());
|
||||||
String cs;
|
|
||||||
while(ofs>0 && l[ofs-1]>32) {
|
|
||||||
|
|
||||||
if (_is_symbol(l[ofs-1])) {
|
if (ofs>0 && (_is_completable(l[ofs-1]) || completion_prefixes.has(String::chr(l[ofs-1]))))
|
||||||
String s;
|
emit_signal("request_completion");
|
||||||
while(ofs>0 && l[ofs-1]>32 && _is_symbol(l[ofs-1])) {
|
|
||||||
s=String::chr(l[ofs-1])+s;
|
|
||||||
ofs--;
|
|
||||||
}
|
|
||||||
if (completion_prefixes.has(s))
|
|
||||||
cs=s+cs;
|
|
||||||
else
|
|
||||||
break;
|
|
||||||
} else {
|
|
||||||
|
|
||||||
cs=String::chr(l[ofs-1])+cs;
|
|
||||||
ofs--;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cs!="") {
|
|
||||||
emit_signal("request_completion",cs,cursor.line);
|
|
||||||
|
|
||||||
}
|
void TextEdit::set_code_hint(const String& p_hint) {
|
||||||
|
|
||||||
|
completion_hint=p_hint;
|
||||||
|
completion_hint_offset=-0xFFFF;
|
||||||
|
update();
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextEdit::code_complete(const Vector<String> &p_strings) {
|
void TextEdit::code_complete(const Vector<String> &p_strings) {
|
||||||
@@ -3236,7 +3343,7 @@ void TextEdit::_bind_methods() {
|
|||||||
|
|
||||||
ADD_SIGNAL(MethodInfo("cursor_changed"));
|
ADD_SIGNAL(MethodInfo("cursor_changed"));
|
||||||
ADD_SIGNAL(MethodInfo("text_changed"));
|
ADD_SIGNAL(MethodInfo("text_changed"));
|
||||||
ADD_SIGNAL(MethodInfo("request_completion",PropertyInfo(Variant::STRING,"keyword"),PropertyInfo(Variant::INT,"line")));
|
ADD_SIGNAL(MethodInfo("request_completion"));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -185,6 +185,8 @@ class TextEdit : public Control {
|
|||||||
int completion_index;
|
int completion_index;
|
||||||
Rect2i completion_rect;
|
Rect2i completion_rect;
|
||||||
int completion_line_ofs;
|
int completion_line_ofs;
|
||||||
|
String completion_hint;
|
||||||
|
int completion_hint_offset;
|
||||||
|
|
||||||
bool setting_text;
|
bool setting_text;
|
||||||
|
|
||||||
@@ -261,6 +263,7 @@ class TextEdit : public Control {
|
|||||||
|
|
||||||
void _clear();
|
void _clear();
|
||||||
void _cancel_completion();
|
void _cancel_completion();
|
||||||
|
void _cancel_code_hint();
|
||||||
void _confirm_completion();
|
void _confirm_completion();
|
||||||
void _update_completion_candidates();
|
void _update_completion_candidates();
|
||||||
|
|
||||||
@@ -378,8 +381,11 @@ public:
|
|||||||
|
|
||||||
void set_completion(bool p_enabled,const Vector<String>& p_prefixes);
|
void set_completion(bool p_enabled,const Vector<String>& p_prefixes);
|
||||||
void code_complete(const Vector<String> &p_strings);
|
void code_complete(const Vector<String> &p_strings);
|
||||||
|
void set_code_hint(const String& p_hint);
|
||||||
void query_code_comple();
|
void query_code_comple();
|
||||||
|
|
||||||
|
String get_text_for_completion();
|
||||||
|
|
||||||
TextEdit();
|
TextEdit();
|
||||||
~TextEdit();
|
~TextEdit();
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1731,6 +1731,26 @@ NodePath Node::get_import_path() const {
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static void _add_nodes_to_options(const Node *p_base,const Node *p_node,List<String>*r_options) {
|
||||||
|
|
||||||
|
if (p_node!=p_base && !p_node->get_owner())
|
||||||
|
return;
|
||||||
|
String n = p_base->get_path_to(p_node);
|
||||||
|
r_options->push_back("\""+n+"\"");
|
||||||
|
for(int i=0;i<p_node->get_child_count();i++) {
|
||||||
|
_add_nodes_to_options(p_base,p_node->get_child(i),r_options);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Node::get_argument_options(const StringName& p_function,int p_idx,List<String>*r_options) const {
|
||||||
|
|
||||||
|
String pf=p_function;
|
||||||
|
if ((pf=="has_node" || pf=="get_node") && p_idx==0) {
|
||||||
|
|
||||||
|
_add_nodes_to_options(this,this,r_options);
|
||||||
|
}
|
||||||
|
Object::get_argument_options(p_function,p_idx,r_options);
|
||||||
|
}
|
||||||
|
|
||||||
void Node::_bind_methods() {
|
void Node::_bind_methods() {
|
||||||
|
|
||||||
|
|||||||
@@ -284,6 +284,7 @@ public:
|
|||||||
NodePath get_import_path() const;
|
NodePath get_import_path() const;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
void get_argument_options(const StringName& p_function,int p_idx,List<String>*r_options) const;
|
||||||
|
|
||||||
_FORCE_INLINE_ Viewport *get_viewport() const { return data.viewport; }
|
_FORCE_INLINE_ Viewport *get_viewport() const { return data.viewport; }
|
||||||
|
|
||||||
|
|||||||
@@ -458,6 +458,8 @@ FixedMaterial::~FixedMaterial() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool ShaderMaterial::_set(const StringName& p_name, const Variant& p_value) {
|
bool ShaderMaterial::_set(const StringName& p_name, const Variant& p_value) {
|
||||||
|
|
||||||
if (p_name==SceneStringNames::get_singleton()->shader_shader) {
|
if (p_name==SceneStringNames::get_singleton()->shader_shader) {
|
||||||
@@ -558,7 +560,21 @@ void ShaderMaterial::_bind_methods() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void ShaderMaterial::get_argument_options(const StringName& p_function,int p_idx,List<String>*r_options) const {
|
||||||
|
|
||||||
|
String f = p_function.operator String();
|
||||||
|
if ((f=="get_shader_param" || f=="set_shader_param") && p_idx==0) {
|
||||||
|
|
||||||
|
if (shader.is_valid()) {
|
||||||
|
List<PropertyInfo> pl;
|
||||||
|
shader->get_param_list(&pl);
|
||||||
|
for (List<PropertyInfo>::Element *E=pl.front();E;E=E->next()) {
|
||||||
|
r_options->push_back(E->get().name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Material::get_argument_options(p_function,p_idx,r_options);
|
||||||
|
}
|
||||||
|
|
||||||
ShaderMaterial::ShaderMaterial() :Material(VisualServer::get_singleton()->material_create()){
|
ShaderMaterial::ShaderMaterial() :Material(VisualServer::get_singleton()->material_create()){
|
||||||
|
|
||||||
|
|||||||
@@ -243,6 +243,7 @@ public:
|
|||||||
void set_shader_param(const StringName& p_param,const Variant& p_value);
|
void set_shader_param(const StringName& p_param,const Variant& p_value);
|
||||||
Variant get_shader_param(const StringName& p_param) const;
|
Variant get_shader_param(const StringName& p_param) const;
|
||||||
|
|
||||||
|
void get_argument_options(const StringName& p_function,int p_idx,List<String>*r_options) const;
|
||||||
|
|
||||||
ShaderMaterial();
|
ShaderMaterial();
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -487,6 +487,7 @@ FindReplaceDialog::FindReplaceDialog() {
|
|||||||
|
|
||||||
vb->add_child(error_label);
|
vb->add_child(error_label);
|
||||||
|
|
||||||
|
|
||||||
set_hide_on_ok(false);
|
set_hide_on_ok(false);
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -507,15 +508,19 @@ void CodeTextEditor::_text_changed() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void CodeTextEditor::_code_complete_timer_timeout() {
|
void CodeTextEditor::_code_complete_timer_timeout() {
|
||||||
|
if (!is_visible())
|
||||||
|
return;
|
||||||
if (enable_complete_timer)
|
if (enable_complete_timer)
|
||||||
text_editor->query_code_comple();
|
text_editor->query_code_comple();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CodeTextEditor::_complete_request(const String& p_request, int p_line) {
|
void CodeTextEditor::_complete_request() {
|
||||||
|
|
||||||
List<String> entries;
|
List<String> entries;
|
||||||
_code_complete_script(text_editor->get_text(),p_request,p_line,&entries);
|
_code_complete_script(text_editor->get_text_for_completion(),&entries);
|
||||||
// print_line("COMPLETE: "+p_request);
|
// print_line("COMPLETE: "+p_request);
|
||||||
|
if (entries.size()==0)
|
||||||
|
return;
|
||||||
Vector<String> strs;
|
Vector<String> strs;
|
||||||
strs.resize(entries.size());
|
strs.resize(entries.size());
|
||||||
int i=0;
|
int i=0;
|
||||||
@@ -555,7 +560,7 @@ void CodeTextEditor::_on_settings_change() {
|
|||||||
|
|
||||||
// AUTO BRACE COMPLETION
|
// AUTO BRACE COMPLETION
|
||||||
text_editor->set_auto_brace_completion(
|
text_editor->set_auto_brace_completion(
|
||||||
EDITOR_DEF("text_editor/auto_brace_complete", false)
|
EDITOR_DEF("text_editor/auto_brace_complete", true)
|
||||||
);
|
);
|
||||||
|
|
||||||
code_complete_timer->set_wait_time(
|
code_complete_timer->set_wait_time(
|
||||||
@@ -632,6 +637,8 @@ CodeTextEditor::CodeTextEditor() {
|
|||||||
text_editor->connect("request_completion", this,"_complete_request");
|
text_editor->connect("request_completion", this,"_complete_request");
|
||||||
Vector<String> cs;
|
Vector<String> cs;
|
||||||
cs.push_back(".");
|
cs.push_back(".");
|
||||||
|
cs.push_back(",");
|
||||||
|
cs.push_back("(");
|
||||||
text_editor->set_completion(true,cs);
|
text_editor->set_completion(true,cs);
|
||||||
idle->connect("timeout", this,"_text_changed_idle_timeout");
|
idle->connect("timeout", this,"_text_changed_idle_timeout");
|
||||||
|
|
||||||
|
|||||||
@@ -135,7 +135,7 @@ class CodeTextEditor : public Control {
|
|||||||
|
|
||||||
void _on_settings_change();
|
void _on_settings_change();
|
||||||
|
|
||||||
void _complete_request(const String& p_request,int p_line);
|
void _complete_request();
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
void set_error(const String& p_error);
|
void set_error(const String& p_error);
|
||||||
@@ -143,7 +143,7 @@ protected:
|
|||||||
|
|
||||||
virtual void _load_theme_settings() {}
|
virtual void _load_theme_settings() {}
|
||||||
virtual void _validate_script()=0;
|
virtual void _validate_script()=0;
|
||||||
virtual void _code_complete_script(const String& p_code, const String& p_keyword,int p_line, List<String>* r_options) {};
|
virtual void _code_complete_script(const String& p_code, List<String>* r_options) {};
|
||||||
|
|
||||||
|
|
||||||
void _text_changed_idle_timeout();
|
void _text_changed_idle_timeout();
|
||||||
|
|||||||
@@ -120,6 +120,8 @@ void CollisionPolygonEditor::_wip_close() {
|
|||||||
|
|
||||||
bool CollisionPolygonEditor::forward_spatial_input_event(Camera* p_camera,const InputEvent& p_event) {
|
bool CollisionPolygonEditor::forward_spatial_input_event(Camera* p_camera,const InputEvent& p_event) {
|
||||||
|
|
||||||
|
if (!node)
|
||||||
|
return false;
|
||||||
|
|
||||||
Transform gt = node->get_global_transform();
|
Transform gt = node->get_global_transform();
|
||||||
float depth = node->get_depth()*0.5;
|
float depth = node->get_depth()*0.5;
|
||||||
|
|||||||
@@ -384,9 +384,35 @@ void ScriptTextEditor::_validate_script() {
|
|||||||
_update_name();
|
_update_name();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScriptTextEditor::_code_complete_script(const String& p_code, const String& p_keyword,int p_line, List<String>* r_options) {
|
|
||||||
|
|
||||||
Error err = script->get_language()->complete_keyword(p_code,p_line,script->get_path().get_base_dir(),p_keyword,r_options);
|
static Node* _find_node_for_script(Node* p_base, Node*p_current, const Ref<Script>& p_script) {
|
||||||
|
|
||||||
|
if (p_current->get_owner()!=p_base && p_base!=p_current)
|
||||||
|
return NULL;
|
||||||
|
Ref<Script> c = p_current->get_script();
|
||||||
|
if (c==p_script)
|
||||||
|
return p_current;
|
||||||
|
for(int i=0;i<p_current->get_child_count();i++) {
|
||||||
|
Node *found = _find_node_for_script(p_base,p_current->get_child(i),p_script);
|
||||||
|
if (found)
|
||||||
|
return found;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScriptTextEditor::_code_complete_script(const String& p_code, List<String>* r_options) {
|
||||||
|
|
||||||
|
Node *base = get_tree()->get_edited_scene_root();
|
||||||
|
if (base) {
|
||||||
|
base = _find_node_for_script(base,base,script);
|
||||||
|
}
|
||||||
|
String hint;
|
||||||
|
Error err = script->get_language()->complete_code(p_code,script->get_path().get_base_dir(),base,r_options,hint);
|
||||||
|
if (hint!="") {
|
||||||
|
get_text_edit()->set_code_hint(hint);
|
||||||
|
print_line("hint: "+hint.replace(String::chr(0xFFFF),"|"));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -85,7 +85,7 @@ protected:
|
|||||||
|
|
||||||
|
|
||||||
virtual void _validate_script();
|
virtual void _validate_script();
|
||||||
virtual void _code_complete_script(const String& p_code,const String& p_keyword, int p_line, List<String>* r_options);
|
virtual void _code_complete_script(const String& p_code, List<String>* r_options);
|
||||||
virtual void _load_theme_settings();
|
virtual void _load_theme_settings();
|
||||||
void _notification(int p_what);
|
void _notification(int p_what);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user