summaryrefslogtreecommitdiff
path: root/modules
diff options
context:
space:
mode:
Diffstat (limited to 'modules')
-rw-r--r--modules/SCsub2
-rw-r--r--modules/gdscript/SCsub2
-rw-r--r--modules/gdscript/gd_editor.cpp63
-rw-r--r--modules/gdscript/gd_functions.cpp9
-rw-r--r--modules/gdscript/gd_parser.cpp138
-rw-r--r--modules/gdscript/gd_parser.h3
-rw-r--r--modules/gdscript/gd_script.cpp41
-rw-r--r--modules/gdscript/gd_script.h19
-rw-r--r--modules/gdscript/gd_tokenizer.cpp12
-rw-r--r--modules/gridmap/SCsub3
-rw-r--r--modules/gridmap/grid_map.cpp71
-rw-r--r--modules/gridmap/grid_map.h2
-rw-r--r--modules/gridmap/grid_map_editor_plugin.cpp24
-rw-r--r--modules/gridmap/grid_map_editor_plugin.h7
14 files changed, 348 insertions, 48 deletions
diff --git a/modules/SCsub b/modules/SCsub
index d215f72c08..9215bfd48f 100644
--- a/modules/SCsub
+++ b/modules/SCsub
@@ -19,5 +19,3 @@ for x in env.module_list:
lib = env_modules.Library("modules",env.modules_sources)
env.Prepend(LIBS=[lib])
-
-
diff --git a/modules/gdscript/SCsub b/modules/gdscript/SCsub
index d20da72b72..403fe68f66 100644
--- a/modules/gdscript/SCsub
+++ b/modules/gdscript/SCsub
@@ -3,5 +3,3 @@ Import('env')
env.add_source_files(env.modules_sources,"*.cpp")
Export('env')
-
-
diff --git a/modules/gdscript/gd_editor.cpp b/modules/gdscript/gd_editor.cpp
index 7cb9882f3a..381edcba50 100644
--- a/modules/gdscript/gd_editor.cpp
+++ b/modules/gdscript/gd_editor.cpp
@@ -998,6 +998,44 @@ static bool _guess_identifier_type_in_block(GDCompletionContext& context,int p_l
return false;
}
+
+static bool _guess_identifier_from_assignment_in_function(GDCompletionContext& context,const StringName& p_identifier, const StringName& p_function,GDCompletionIdentifier &r_type) {
+
+ const GDParser::FunctionNode* func=NULL;
+ for(int i=0;i<context._class->functions.size();i++) {
+ if (context._class->functions[i]->name==p_function) {
+ func=context._class->functions[i];
+ break;
+ }
+ }
+
+ if (!func)
+ return false;
+
+ for(int i=0;i<func->body->statements.size();i++) {
+
+
+
+ if (func->body->statements[i]->type==GDParser::BlockNode::TYPE_OPERATOR) {
+ const GDParser::OperatorNode *op = static_cast<const GDParser::OperatorNode *>(func->body->statements[i]);
+ if (op->op==GDParser::OperatorNode::OP_ASSIGN) {
+
+ if (op->arguments.size() && op->arguments[0]->type==GDParser::Node::TYPE_IDENTIFIER) {
+
+ const GDParser::IdentifierNode *id = static_cast<const GDParser::IdentifierNode *>(op->arguments[0]);
+
+ if (id->name==p_identifier) {
+
+ return _guess_expression_type(context,op->arguments[1],func->body->statements[i]->line,r_type);
+ }
+ }
+ }
+ }
+ }
+
+ return false;
+}
+
static bool _guess_identifier_type(GDCompletionContext& context,int p_line,const StringName& p_identifier,GDCompletionIdentifier &r_type) {
//go to block first
@@ -1089,8 +1127,22 @@ static bool _guess_identifier_type(GDCompletionContext& context,int p_line,const
r_type=_get_type_from_pinfo(context._class->variables[i]._export);
return true;
} else if (context._class->variables[i].expression) {
- return _guess_expression_type(context,context._class->variables[i].expression,context._class->variables[i].line,r_type);
+
+ bool rtype = _guess_expression_type(context,context._class->variables[i].expression,context._class->variables[i].line,r_type);
+ if (rtype && r_type.type!=Variant::NIL)
+ return true;
+ //return _guess_expression_type(context,context._class->variables[i].expression,context._class->variables[i].line,r_type);
}
+
+ //try to guess from assignment in construtor or _ready
+ if (_guess_identifier_from_assignment_in_function(context,p_identifier,"_ready",r_type))
+ return true;
+ if (_guess_identifier_from_assignment_in_function(context,p_identifier,"_enter_tree",r_type))
+ return true;
+ if (_guess_identifier_from_assignment_in_function(context,p_identifier,"_init",r_type))
+ return true;
+
+ return false;
}
}
}
@@ -1239,6 +1291,15 @@ static void _find_identifiers(GDCompletionContext& context,int p_line,bool p_onl
const GDParser::BlockNode *block=context.block;
+ if (context.function) {
+
+ const GDParser::FunctionNode* f = context.function;
+
+ for (int i=0;i<f->arguments.size();i++) {
+ result.insert(f->arguments[i].operator String());
+ }
+ }
+
while(block) {
GDCompletionContext c = context;
diff --git a/modules/gdscript/gd_functions.cpp b/modules/gdscript/gd_functions.cpp
index 37ddb2bc41..6f51ac5312 100644
--- a/modules/gdscript/gd_functions.cpp
+++ b/modules/gdscript/gd_functions.cpp
@@ -904,6 +904,15 @@ void GDFunctions::call(Function p_func,const Variant **p_args,int p_arg_count,Va
r_ret = gdscr->_new(NULL,0,r_error);
+ GDInstance *ins = static_cast<GDInstance*>(static_cast<Object*>(r_ret)->get_script_instance());
+ Ref<GDScript> gd_ref = ins->get_script();
+
+ for(Map<StringName,GDScript::MemberInfo>::Element *E = gd_ref->member_indices.front(); E; E = E->next()) {
+ if(d.has(E->key())) {
+ ins->members[E->get().index] = d[E->key()];
+ }
+ }
+
} break;
case HASH: {
diff --git a/modules/gdscript/gd_parser.cpp b/modules/gdscript/gd_parser.cpp
index afe8c9aa71..c55bfee591 100644
--- a/modules/gdscript/gd_parser.cpp
+++ b/modules/gdscript/gd_parser.cpp
@@ -65,8 +65,10 @@ bool GDParser::_enter_indent_block(BlockNode* p_block) {
if (tokenizer->get_token()!=GDTokenizer::TK_COLON) {
-
- _set_error("':' expected at end of line.");
+ // report location at the previous token (on the previous line)
+ int error_line = tokenizer->get_token_line(-1);
+ int error_column = tokenizer->get_token_column(-1);
+ _set_error("':' expected at end of line.",error_line,error_column);
return false;
}
tokenizer->advance();
@@ -170,6 +172,7 @@ void GDParser::_make_completable_call(int p_arg) {
completion_line=tokenizer->get_token_line();
completion_argument=p_arg;
completion_block=current_block;
+ completion_found=true;
tokenizer->advance();
}
@@ -190,6 +193,7 @@ bool GDParser::_get_completable_identifier(CompletionType p_type,StringName& ide
completion_function=current_function;
completion_line=tokenizer->get_token_line();
completion_block=current_block;
+ completion_found=true;
tokenizer->advance();
if (tokenizer->get_token()==GDTokenizer::TK_IDENTIFIER) {
@@ -1414,6 +1418,24 @@ GDParser::Node* GDParser::_parse_and_reduce_expression(Node *p_parent,bool p_sta
return expr;
}
+bool GDParser::_recover_from_completion() {
+
+ if (!completion_found) {
+ return false; //can't recover if no completion
+ }
+ //skip stuff until newline
+ while(tokenizer->get_token()!=GDTokenizer::TK_NEWLINE && tokenizer->get_token()!=GDTokenizer::TK_EOF && tokenizer->get_token()!=GDTokenizer::TK_ERROR) {
+ tokenizer->advance();
+ }
+ completion_found=false;
+ error_set=false;
+ if(tokenizer->get_token() == GDTokenizer::TK_ERROR){
+ error_set = true;
+ }
+
+ return true;
+}
+
void GDParser::_parse_block(BlockNode *p_block,bool p_static) {
int indent_level = tab_level.back()->get();
@@ -1511,8 +1533,14 @@ void GDParser::_parse_block(BlockNode *p_block,bool p_static) {
Node *subexpr=NULL;
subexpr = _parse_and_reduce_expression(p_block,p_static);
- if (!subexpr)
+ if (!subexpr) {
+ if (_recover_from_completion()) {
+ break;
+ }
return;
+ }
+
+
lv->assign=subexpr;
assigned=subexpr;
@@ -1543,8 +1571,12 @@ void GDParser::_parse_block(BlockNode *p_block,bool p_static) {
tokenizer->advance();
Node *condition = _parse_and_reduce_expression(p_block,p_static);
- if (!condition)
+ if (!condition) {
+ if (_recover_from_completion()) {
+ break;
+ }
return;
+ }
ControlFlowNode *cf_if = alloc_node<ControlFlowNode>();
@@ -1598,8 +1630,12 @@ void GDParser::_parse_block(BlockNode *p_block,bool p_static) {
//condition
Node *condition = _parse_and_reduce_expression(p_block,p_static);
- if (!condition)
+ if (!condition) {
+ if (_recover_from_completion()) {
+ break;
+ }
return;
+ }
cf_else->arguments.push_back(condition);
cf_else->cf_type=ControlFlowNode::CF_IF;
@@ -1660,8 +1696,12 @@ void GDParser::_parse_block(BlockNode *p_block,bool p_static) {
tokenizer->advance();
Node *condition = _parse_and_reduce_expression(p_block,p_static);
- if (!condition)
+ if (!condition) {
+ if (_recover_from_completion()) {
+ break;
+ }
return;
+ }
ControlFlowNode *cf_while = alloc_node<ControlFlowNode>();
@@ -1706,8 +1746,12 @@ void GDParser::_parse_block(BlockNode *p_block,bool p_static) {
tokenizer->advance();
Node *container = _parse_and_reduce_expression(p_block,p_static);
- if (!container)
+ if (!container) {
+ if (_recover_from_completion()) {
+ break;
+ }
return;
+ }
ControlFlowNode *cf_for = alloc_node<ControlFlowNode>();
@@ -1771,8 +1815,12 @@ void GDParser::_parse_block(BlockNode *p_block,bool p_static) {
} else {
//expect expression
Node *retexpr = _parse_and_reduce_expression(p_block,p_static);
- if (!retexpr)
+ if (!retexpr) {
+ if (_recover_from_completion()) {
+ break;
+ }
return;
+ }
cf_return->arguments.push_back(retexpr);
p_block->statements.push_back(cf_return);
if (!_end_statement()) {
@@ -1787,8 +1835,12 @@ void GDParser::_parse_block(BlockNode *p_block,bool p_static) {
tokenizer->advance();
Node *condition = _parse_and_reduce_expression(p_block,p_static);
- if (!condition)
+ if (!condition) {
+ if (_recover_from_completion()) {
+ break;
+ }
return;
+ }
AssertNode *an = alloc_node<AssertNode>();
an->condition=condition;
p_block->statements.push_back(an);
@@ -1801,8 +1853,12 @@ void GDParser::_parse_block(BlockNode *p_block,bool p_static) {
default: {
Node *expression = _parse_and_reduce_expression(p_block,p_static,false,true);
- if (!expression)
+ if (!expression) {
+ if (_recover_from_completion()) {
+ break;
+ }
return;
+ }
p_block->statements.push_back(expression);
if (!_end_statement()) {
_set_error("Expected end of statement after expression.");
@@ -1886,9 +1942,15 @@ void GDParser::_parse_extends(ClassNode *p_class) {
p_class->extends_used=true;
- //see if inheritance happens from a file
tokenizer->advance();
+ if (tokenizer->get_token()==GDTokenizer::TK_BUILT_IN_TYPE && tokenizer->get_token_type()==Variant::OBJECT) {
+ p_class->extends_class.push_back(Variant::get_type_name(Variant::OBJECT));
+ tokenizer->advance();
+ return;
+ }
+
+ // see if inheritance happens from a file
if (tokenizer->get_token()==GDTokenizer::TK_CONSTANT) {
Variant constant = tokenizer->get_token_constant();
@@ -2315,6 +2377,17 @@ void GDParser::_parse_class(ClassNode *p_class) {
case Variant::INT: {
+ if (tokenizer->get_token()==GDTokenizer::TK_IDENTIFIER && tokenizer->get_token_identifier()=="FLAGS") {
+
+ current_export.hint=PROPERTY_HINT_ALL_FLAGS;
+ tokenizer->advance();
+ if (tokenizer->get_token()!=GDTokenizer::TK_PARENTHESIS_CLOSE) {
+ _set_error("Expected ')' in hint.");
+ return;
+ }
+ break;
+ }
+
if (tokenizer->get_token()==GDTokenizer::TK_CONSTANT && tokenizer->get_token_constant().get_type()==Variant::STRING) {
//enumeration
current_export.hint=PROPERTY_HINT_ENUM;
@@ -2356,6 +2429,16 @@ void GDParser::_parse_class(ClassNode *p_class) {
}; //fallthrough to use the same
case Variant::REAL: {
+ if (tokenizer->get_token()==GDTokenizer::TK_IDENTIFIER && tokenizer->get_token_identifier()=="EASE") {
+ current_export.hint=PROPERTY_HINT_EXP_EASING;
+ tokenizer->advance();
+ if (tokenizer->get_token()!=GDTokenizer::TK_PARENTHESIS_CLOSE) {
+ _set_error("Expected ')' in hint.");
+ return;
+ }
+ break;
+ }
+
float sign=1.0;
if (tokenizer->get_token()==GDTokenizer::TK_OP_SUB) {
@@ -2506,6 +2589,17 @@ void GDParser::_parse_class(ClassNode *p_class) {
}
break;
}
+
+ if (tokenizer->get_token()==GDTokenizer::TK_IDENTIFIER && tokenizer->get_token_identifier()=="MULTILINE") {
+
+ current_export.hint=PROPERTY_HINT_MULTILINE_TEXT;
+ tokenizer->advance();
+ if (tokenizer->get_token()!=GDTokenizer::TK_PARENTHESIS_CLOSE) {
+ _set_error("Expected ')' in hint.");
+ return;
+ }
+ break;
+ }
} break;
case Variant::COLOR: {
@@ -2607,14 +2701,18 @@ void GDParser::_parse_class(ClassNode *p_class) {
Node *subexpr=NULL;
- subexpr = _parse_and_reduce_expression(p_class,false);
- if (!subexpr)
+ subexpr = _parse_and_reduce_expression(p_class,false,autoexport);
+ if (!subexpr) {
+ if (_recover_from_completion()) {
+ break;
+ }
return;
+ }
member.expression=subexpr;
if (autoexport) {
- if (subexpr->type==Node::TYPE_ARRAY) {
+ if (1)/*(subexpr->type==Node::TYPE_ARRAY) {
member._export.type=Variant::ARRAY;
@@ -2622,7 +2720,7 @@ void GDParser::_parse_class(ClassNode *p_class) {
member._export.type=Variant::DICTIONARY;
- } else {
+ } else*/ {
if (subexpr->type!=Node::TYPE_CONSTANT) {
@@ -2738,8 +2836,12 @@ void GDParser::_parse_class(ClassNode *p_class) {
Node *subexpr=NULL;
subexpr = _parse_and_reduce_expression(p_class,true,true);
- if (!subexpr)
+ if (!subexpr) {
+ if (_recover_from_completion()) {
+ break;
+ }
return;
+ }
if (subexpr->type!=Node::TYPE_CONSTANT) {
_set_error("Expected constant expression");
@@ -2834,6 +2936,7 @@ Error GDParser::parse_bytecode(const Vector<uint8_t> &p_bytecode,const String& p
completion_class=NULL;
completion_function=NULL;
completion_block=NULL;
+ completion_found=false;
current_block=NULL;
current_class=NULL;
current_function=NULL;
@@ -2856,6 +2959,7 @@ Error GDParser::parse(const String& p_code, const String& p_base_path, bool p_ju
completion_class=NULL;
completion_function=NULL;
completion_block=NULL;
+ completion_found=false;
current_block=NULL;
current_class=NULL;
@@ -2899,6 +3003,8 @@ void GDParser::clear() {
current_block=NULL;
current_class=NULL;
+ completion_found=false;
+
current_function=NULL;
validating=false;
diff --git a/modules/gdscript/gd_parser.h b/modules/gdscript/gd_parser.h
index fd8a2576fa..04f3dff3de 100644
--- a/modules/gdscript/gd_parser.h
+++ b/modules/gdscript/gd_parser.h
@@ -276,7 +276,6 @@ public:
};
struct NewLineNode : public Node {
- int line;
NewLineNode() { type=TYPE_NEWLINE; }
};
@@ -419,10 +418,12 @@ private:
BlockNode *completion_block;
int completion_line;
int completion_argument;
+ bool completion_found;
PropertyInfo current_export;
void _set_error(const String& p_error, int p_line=-1, int p_column=-1);
+ bool _recover_from_completion();
bool _parse_arguments(Node* p_parent, Vector<Node*>& p_args, bool p_static, bool p_can_codecomplete=false);
diff --git a/modules/gdscript/gd_script.cpp b/modules/gdscript/gd_script.cpp
index 53ae0c8702..c3cc779bce 100644
--- a/modules/gdscript/gd_script.cpp
+++ b/modules/gdscript/gd_script.cpp
@@ -1449,7 +1449,7 @@ Object *GDNativeClass::instance() {
-GDInstance* GDScript::_create_instance(const Variant** p_args,int p_argcount,Object *p_owner,bool p_isref) {
+GDInstance* GDScript::_create_instance(const Variant** p_args,int p_argcount,Object *p_owner,bool p_isref,Variant::CallError& r_error) {
/* STEP 1, CREATE */
@@ -1465,14 +1465,13 @@ GDInstance* GDScript::_create_instance(const Variant** p_args,int p_argcount,Obj
instances.insert(instance->owner);
- Variant::CallError err;
- initializer->call(instance,p_args,p_argcount,err);
+ initializer->call(instance,p_args,p_argcount,r_error);
- if (err.error!=Variant::CallError::CALL_OK) {
+ if (r_error.error!=Variant::CallError::CALL_OK) {
instance->script=Ref<GDScript>();
instance->owner->set_script_instance(NULL);
instances.erase(p_owner);
- ERR_FAIL_COND_V(err.error!=Variant::CallError::CALL_OK, NULL); //error consrtucting
+ ERR_FAIL_COND_V(r_error.error!=Variant::CallError::CALL_OK, NULL); //error constructing
}
//@TODO make thread safe
@@ -1505,7 +1504,7 @@ Variant GDScript::_new(const Variant** p_args,int p_argcount,Variant::CallError&
}
- GDInstance* instance = _create_instance(p_args,p_argcount,owner,r!=NULL);
+ GDInstance* instance = _create_instance(p_args,p_argcount,owner,r!=NULL,r_error);
if (!instance) {
if (ref.is_null()) {
memdelete(owner); //no owner, sorry
@@ -1637,7 +1636,8 @@ ScriptInstance* GDScript::instance_create(Object *p_this) {
}
}
- return _create_instance(NULL,0,p_this,p_this->cast_to<Reference>());
+ Variant::CallError unchecked_error;
+ return _create_instance(NULL,0,p_this,p_this->cast_to<Reference>(),unchecked_error);
}
bool GDScript::instance_has(const Object *p_this) const {
@@ -2274,6 +2274,26 @@ bool GDInstance::get(const StringName& p_name, Variant &r_ret) const {
return false;
}
+
+Variant::Type GDInstance::get_property_type(const StringName& p_name,bool *r_is_valid) const {
+
+
+ const GDScript *sptr=script.ptr();
+ while(sptr) {
+
+ if (sptr->member_info.has(p_name)) {
+ if (r_is_valid)
+ *r_is_valid=true;
+ return sptr->member_info[p_name].type;
+ }
+ sptr = sptr->_base;
+ }
+
+ if (r_is_valid)
+ *r_is_valid=false;
+ return Variant::NIL;
+}
+
void GDInstance::get_property_list(List<PropertyInfo> *p_properties) const {
// exported members, not doen yet!
@@ -2710,7 +2730,10 @@ GDScriptLanguage::~GDScriptLanguage() {
/*************** RESOURCE ***************/
-RES ResourceFormatLoaderGDScript::load(const String &p_path,const String& p_original_path) {
+RES ResourceFormatLoaderGDScript::load(const String &p_path, const String& p_original_path, Error *r_error) {
+
+ if (r_error)
+ *r_error=ERR_FILE_CANT_OPEN;
GDScript *script = memnew( GDScript );
@@ -2742,6 +2765,8 @@ RES ResourceFormatLoaderGDScript::load(const String &p_path,const String& p_orig
script->reload();
}
+ if (r_error)
+ *r_error=OK;
return scriptres;
}
diff --git a/modules/gdscript/gd_script.h b/modules/gdscript/gd_script.h
index 1e1279d5f5..3d16b59065 100644
--- a/modules/gdscript/gd_script.h
+++ b/modules/gdscript/gd_script.h
@@ -286,7 +286,7 @@ friend class GDScriptLanguage;
String name;
- GDInstance* _create_instance(const Variant** p_args,int p_argcount,Object *p_owner,bool p_isref);
+ GDInstance* _create_instance(const Variant** p_args,int p_argcount,Object *p_owner,bool p_isref,Variant::CallError &r_error);
void _set_subclass_path(Ref<GDScript>& p_sc,const String& p_path);
@@ -373,6 +373,8 @@ public:
virtual bool set(const StringName& p_name, const Variant& p_value);
virtual bool get(const StringName& p_name, Variant &r_ret) const;
virtual void get_property_list(List<PropertyInfo> *p_properties) const;
+ virtual Variant::Type get_property_type(const StringName& p_name,bool *r_is_valid=NULL) const;
+
virtual void get_method_list(List<MethodInfo> *p_list) const;
virtual bool has_method(const StringName& p_method) const;
@@ -475,6 +477,19 @@ public:
}
+ virtual Vector<StackInfo> debug_get_current_stack_info() {
+ if (Thread::get_main_ID()!=Thread::get_caller_ID())
+ return Vector<StackInfo>();
+
+ Vector<StackInfo> csi;
+ csi.resize(_debug_call_stack_pos);
+ for(int i=0;i<_debug_call_stack_pos;i++) {
+ csi[_debug_call_stack_pos-i-1].line=_call_stack[i].line?*_call_stack[i].line:0;
+ csi[_debug_call_stack_pos-i-1].script=Ref<GDScript>(_call_stack[i].function->get_script());
+ }
+ return csi;
+ }
+
struct {
StringName _init;
@@ -544,7 +559,7 @@ public:
class ResourceFormatLoaderGDScript : public ResourceFormatLoader {
public:
- virtual RES load(const String &p_path,const String& p_original_path="");
+ virtual RES load(const String &p_path,const String& p_original_path="",Error *r_error=NULL);
virtual void get_recognized_extensions(List<String> *p_extensions) const;
virtual bool handles_type(const String& p_type) const;
virtual String get_resource_type(const String &p_path) const;
diff --git a/modules/gdscript/gd_tokenizer.cpp b/modules/gdscript/gd_tokenizer.cpp
index 8b25b38bd3..e445701669 100644
--- a/modules/gdscript/gd_tokenizer.cpp
+++ b/modules/gdscript/gd_tokenizer.cpp
@@ -97,6 +97,7 @@ const char* GDTokenizer::token_names[TK_MAX]={
"preload",
"assert",
"yield",
+"signal",
"'['",
"']'",
"'{'",
@@ -642,6 +643,11 @@ void GDTokenizerText::_advance() {
str+=res;
} else {
+ if (CharType(GETCHAR(i))=='\n') {
+ line++;
+ column=0;
+ }
+
str+=CharType(GETCHAR(i));
}
i++;
@@ -768,20 +774,15 @@ void GDTokenizerText::_advance() {
{Variant::INT,"int"},
{Variant::REAL,"float"},
{Variant::STRING,"String"},
- {Variant::VECTOR2,"vec2"},
{Variant::VECTOR2,"Vector2"},
{Variant::RECT2,"Rect2"},
{Variant::MATRIX32,"Matrix32"},
- {Variant::MATRIX32,"mat32"},
- {Variant::VECTOR3,"vec3"},
{Variant::VECTOR3,"Vector3"},
{Variant::_AABB,"AABB"},
{Variant::_AABB,"Rect3"},
{Variant::PLANE,"Plane"},
{Variant::QUAT,"Quat"},
- {Variant::MATRIX3,"mat3"},
{Variant::MATRIX3,"Matrix3"},
- {Variant::TRANSFORM,"trn"},
{Variant::TRANSFORM,"Transform"},
{Variant::COLOR,"Color"},
{Variant::IMAGE,"Image"},
@@ -789,7 +790,6 @@ void GDTokenizerText::_advance() {
{Variant::OBJECT,"Object"},
{Variant::INPUT_EVENT,"InputEvent"},
{Variant::NODE_PATH,"NodePath"},
- {Variant::DICTIONARY,"dict"},
{Variant::DICTIONARY,"Dictionary"},
{Variant::ARRAY,"Array"},
{Variant::RAW_ARRAY,"RawArray"},
diff --git a/modules/gridmap/SCsub b/modules/gridmap/SCsub
index 4cb47e7e67..211a043468 100644
--- a/modules/gridmap/SCsub
+++ b/modules/gridmap/SCsub
@@ -1,6 +1,3 @@
Import('env')
env.add_source_files(env.modules_sources,"*.cpp")
-
-
-
diff --git a/modules/gridmap/grid_map.cpp b/modules/gridmap/grid_map.cpp
index 4f0daf329f..ad7c392cd0 100644
--- a/modules/gridmap/grid_map.cpp
+++ b/modules/gridmap/grid_map.cpp
@@ -34,7 +34,7 @@
#include "scene/3d/baked_light_instance.h"
#include "io/marshalls.h"
#include "scene/scene_string_names.h"
-
+#include "os/os.h"
bool GridMap::_set(const StringName& p_name, const Variant& p_value) {
@@ -393,8 +393,12 @@ void GridMap::set_cell_item(int p_x,int p_y,int p_z, int p_item,int p_rot){
if (g.items.empty()) {
PhysicsServer::get_singleton()->free(g.static_body);
+ if (g.collision_debug.is_valid()) {
+ PhysicsServer::get_singleton()->free(g.collision_debug);
+ PhysicsServer::get_singleton()->free(g.collision_debug_instance);
+ }
- memdelete(&g);
+ memdelete(&g);
octant_map.erase(octantkey);
} else {
@@ -422,6 +426,20 @@ void GridMap::set_cell_item(int p_x,int p_y,int p_z, int p_item,int p_rot){
if (is_inside_world())
PhysicsServer::get_singleton()->body_set_space(g->static_body,get_world()->get_space());
+ SceneTree *st=SceneTree::get_singleton();
+
+ if (st && st->is_debugging_collisions_hint()) {
+
+ g->collision_debug=VisualServer::get_singleton()->mesh_create();
+ g->collision_debug_instance=VisualServer::get_singleton()->instance_create();
+ VisualServer::get_singleton()->instance_set_base(g->collision_debug_instance,g->collision_debug);
+ if (is_inside_world()) {
+ VisualServer::get_singleton()->instance_set_scenario(g->collision_debug_instance,get_world()->get_scenario());
+ VisualServer::get_singleton()->instance_set_transform(g->collision_debug_instance,get_global_transform());
+ }
+
+ }
+
octant_map[octantkey]=g;
}
@@ -512,6 +530,13 @@ void GridMap::_octant_enter_world(const OctantKey &p_key) {
//print_line("BODYPOS: "+get_global_transform());
+ if (g.collision_debug_instance.is_valid()) {
+ VS::get_singleton()->instance_set_scenario(g.collision_debug_instance,get_world()->get_scenario());
+ VS::get_singleton()->instance_set_transform(g.collision_debug_instance,get_global_transform());
+ if (area_map.has(p_key.area)) {
+ VS::get_singleton()->instance_set_room(g.collision_debug_instance,area_map[p_key.area]->instance);
+ }
+ }
if (g.baked.is_valid()) {
Transform xf = get_global_transform();
@@ -545,6 +570,10 @@ void GridMap::_octant_transform(const OctantKey &p_key) {
Octant&g = *octant_map[p_key];
PhysicsServer::get_singleton()->body_set_state(g.static_body,PhysicsServer::BODY_STATE_TRANSFORM,get_global_transform());
+ if (g.collision_debug_instance.is_valid()) {
+ VS::get_singleton()->instance_set_transform(g.collision_debug_instance,get_global_transform());
+ }
+
if (g.baked.is_valid()) {
Transform xf = get_global_transform();
@@ -572,6 +601,13 @@ void GridMap::_octant_update(const OctantKey &p_key) {
PhysicsServer::get_singleton()->body_clear_shapes(g.static_body);
+ if (g.collision_debug.is_valid()) {
+
+ VS::get_singleton()->mesh_clear(g.collision_debug);
+ }
+
+ DVector<Vector3> col_debug;
+
for(Map<int,Octant::ItemInstances>::Element *E=g.items.front();E;E=E->next()) {
Octant::ItemInstances &ii=E->get();
@@ -609,6 +645,7 @@ void GridMap::_octant_update(const OctantKey &p_key) {
xform.basis.scale(Vector3(cell_scale,cell_scale,cell_scale));
ii.multimesh->set_instance_transform(idx,xform);
+ //ii.multimesh->set_instance_transform(idx,Transform() );
ii.multimesh->set_instance_color(idx,Color(1,1,1,1));
//print_line("MMINST: "+xform);
@@ -624,8 +661,11 @@ void GridMap::_octant_update(const OctantKey &p_key) {
if (ii.shape.is_valid()) {
PhysicsServer::get_singleton()->body_add_shape(g.static_body,ii.shape->get_rid(),xform);
- // print_line("PHIS x: "+xform);
+ if (g.collision_debug.is_valid()) {
+ ii.shape->add_vertices_to_array(col_debug,xform);
+ }
+ // print_line("PHIS x: "+xform);
}
idx++;
@@ -636,6 +676,20 @@ void GridMap::_octant_update(const OctantKey &p_key) {
}
+ if (col_debug.size()) {
+
+
+ Array arr;
+ arr.resize(VS::ARRAY_MAX);
+ arr[VS::ARRAY_VERTEX]=col_debug;
+
+ VS::get_singleton()->mesh_add_surface(g.collision_debug,VS::PRIMITIVE_LINES,arr);
+ SceneTree *st=SceneTree::get_singleton();
+ if (st) {
+ VS::get_singleton()->mesh_surface_set_material( g.collision_debug, 0,st->get_debug_collision_material()->get_rid() );
+ }
+ }
+
g.dirty=false;
}
@@ -656,6 +710,12 @@ void GridMap::_octant_exit_world(const OctantKey &p_key) {
}
+ if (g.collision_debug_instance.is_valid()) {
+
+ VS::get_singleton()->instance_set_room(g.collision_debug_instance,RID());
+ VS::get_singleton()->instance_set_scenario(g.collision_debug_instance,RID());
+ }
+
for(Map<int,Octant::ItemInstances>::Element *E=g.items.front();E;E=E->next()) {
VS::get_singleton()->instance_set_scenario(E->get().multimesh_instance,RID());
@@ -959,6 +1019,11 @@ void GridMap::_clear_internal(bool p_keep_areas) {
if (E->get()->bake_instance.is_valid())
VS::get_singleton()->free(E->get()->bake_instance);
+ if (E->get()->collision_debug.is_valid())
+ VS::get_singleton()->free(E->get()->collision_debug);
+ if (E->get()->collision_debug_instance.is_valid())
+ VS::get_singleton()->free(E->get()->collision_debug_instance);
+
PhysicsServer::get_singleton()->free(E->get()->static_body);
memdelete(E->get());
diff --git a/modules/gridmap/grid_map.h b/modules/gridmap/grid_map.h
index dff9fe3d68..9d3b1dcf95 100644
--- a/modules/gridmap/grid_map.h
+++ b/modules/gridmap/grid_map.h
@@ -93,6 +93,8 @@ class GridMap : public Spatial {
Ref<Mesh> baked;
RID bake_instance;
+ RID collision_debug;
+ RID collision_debug_instance;
bool dirty;
RID static_body;
diff --git a/modules/gridmap/grid_map_editor_plugin.cpp b/modules/gridmap/grid_map_editor_plugin.cpp
index 3d56b04cac..e4559ca100 100644
--- a/modules/gridmap/grid_map_editor_plugin.cpp
+++ b/modules/gridmap/grid_map_editor_plugin.cpp
@@ -220,7 +220,9 @@ void GridMapEditor::_menu_option(int p_option) {
} break;
-
+ case MENU_OPTION_GRIDMAP_SETTINGS: {
+ settings_dialog->popup_centered(settings_vbc->get_combined_minimum_size() + Size2(50, 50));
+ } break;
}
}
@@ -304,7 +306,7 @@ bool GridMapEditor::do_input_action(Camera* p_camera,const Point2& p_point,bool
p.d=edit_floor[edit_axis]*node->get_cell_size();
Vector3 inters;
- if (!p.intersects_segment(from,from+normal*500,&inters))
+ if (!p.intersects_segment(from, from + normal * settings_pick_distance->get_val(), &inters))
return false;
@@ -1249,6 +1251,24 @@ GridMapEditor::GridMapEditor(EditorNode *p_editor) {
//options->get_popup()->add_separator();
//options->get_popup()->add_item("Configure",MENU_OPTION_CONFIGURE);
+ options->get_popup()->add_separator();
+ options->get_popup()->add_item("Settings", MENU_OPTION_GRIDMAP_SETTINGS);
+
+ settings_dialog = memnew(ConfirmationDialog);
+ settings_dialog->set_title("GridMap Settings");
+ add_child(settings_dialog);
+ settings_vbc = memnew(VBoxContainer);
+ settings_vbc->set_custom_minimum_size(Size2(200, 0));
+ settings_dialog->add_child(settings_vbc);
+ settings_dialog->set_child_rect(settings_vbc);
+
+ settings_pick_distance = memnew(SpinBox);
+ settings_pick_distance->set_max(10000.0f);
+ settings_pick_distance->set_min(500.0f);
+ settings_pick_distance->set_step(1.0f);
+ settings_pick_distance->set_val(EDITOR_DEF("gridmap_editor/pick_distance", 5000.0));
+ settings_vbc->add_margin_child("Pick Distance:", settings_pick_distance);
+
clip_mode=CLIP_DISABLED;
options->get_popup()->connect("item_pressed", this,"_menu_option");
diff --git a/modules/gridmap/grid_map_editor_plugin.h b/modules/gridmap/grid_map_editor_plugin.h
index 26fe8f20dc..03b2d4226e 100644
--- a/modules/gridmap/grid_map_editor_plugin.h
+++ b/modules/gridmap/grid_map_editor_plugin.h
@@ -78,6 +78,9 @@ class GridMapEditor : public VBoxContainer {
ToolButton *mode_thumbnail;
ToolButton *mode_list;
HBoxContainer *spatial_editor_hb;
+ ConfirmationDialog *settings_dialog;
+ VBoxContainer *settings_vbc;
+ SpinBox *settings_pick_distance;
struct SetItem {
@@ -165,8 +168,8 @@ class GridMapEditor : public VBoxContainer {
MENU_OPTION_SELECTION_MAKE_AREA,
MENU_OPTION_SELECTION_MAKE_EXTERIOR_CONNECTOR,
MENU_OPTION_SELECTION_CLEAR,
- MENU_OPTION_REMOVE_AREA
-
+ MENU_OPTION_REMOVE_AREA,
+ MENU_OPTION_GRIDMAP_SETTINGS
};