Bläddra i källkod

-Fix bugs related to PoolVector crashes
-Added ability to request nodes using $Name in GDScript :)

Juan Linietsky 8 år sedan
förälder
incheckning
8b912d1115

+ 33 - 5
core/dvector.h

@@ -127,15 +127,30 @@ class PoolVector {
 
 		MemoryPool::alloc_mutex->unlock();
 
+
 		if (MemoryPool::memory_pool) {
 
 
 		} else {
 			alloc->mem = memalloc( alloc->size );
-			copymem( alloc->mem, old_alloc->mem, alloc->size );
 		}
 
-		if (old_alloc->refcount.unref()) {
+		{
+			Write w;
+			w._ref(alloc);
+			Read r;
+			r._ref(old_alloc);
+
+			int cur_elements = alloc->size/sizeof(T);
+			T*dst = (T*)w.ptr();
+			const T*src = (const T*)r.ptr();
+			for(int i=0;i<cur_elements;i++) {
+				memnew_placement(&dst[i],T(src[i]));
+			}
+		}
+
+
+		if (old_alloc->refcount.unref()==true) {
 			//this should never happen but..
 
 #ifdef DEBUG_ENABLED
@@ -144,6 +159,17 @@ class PoolVector {
 			MemoryPool::alloc_mutex->unlock();
 #endif
 
+			{
+				Write w;
+				w._ref(old_alloc);
+
+				int cur_elements = old_alloc->size/sizeof(T);
+				T*elems = (T*)w.ptr();
+				for(int i=0;i<cur_elements;i++) {
+					elems[i].~T();
+				}
+
+			}
 
 			if (MemoryPool::memory_pool) {
 				//resize memory pool
@@ -151,6 +177,7 @@ class PoolVector {
 				//if some resize
 			} else {
 
+
 				memfree( old_alloc->mem );
 				old_alloc->mem=NULL;
 				old_alloc->size=0;
@@ -190,7 +217,7 @@ class PoolVector {
 		if (!alloc)
 			return;
 
-		if (!alloc->refcount.unref()) {
+		if (alloc->refcount.unref()==false) {
 			alloc=NULL;
 			return;
 		}
@@ -199,7 +226,8 @@ class PoolVector {
 
 		{
 			int cur_elements = alloc->size/sizeof(T);
-			Write w;
+			Write w = write();
+
 			for (int i=0;i<cur_elements;i++) {
 
 				w[i].~T();
@@ -585,7 +613,7 @@ Error PoolVector<T>::resize(int p_size) {
 	} else {
 
 		{
-			Write w;
+			Write w = write();
 			for (int i=p_size;i<cur_elements;i++) {
 
 				w[i].~T();

+ 86 - 0
modules/gdscript/gd_parser.cpp

@@ -265,6 +265,92 @@ GDParser::Node* GDParser::_parse_expression(Node *p_parent,bool p_static,bool p_
 
 			tokenizer->advance();
 			expr=subexpr;
+		} else if (tokenizer->get_token()==GDTokenizer::TK_DOLLAR) {
+			tokenizer->advance();
+
+			String path;
+
+			bool need_identifier=true;
+			bool done=false;
+
+			while(!done) {
+
+				switch(tokenizer->get_token()) {
+					case GDTokenizer::TK_CURSOR: {
+						completion_cursor=StringName();
+						completion_type=COMPLETION_GET_NODE;
+						completion_class=current_class;
+						completion_function=current_function;
+						completion_line=tokenizer->get_token_line();
+						completion_cursor=path;
+						completion_argument=0;
+						completion_block=current_block;
+						completion_found=true;
+						tokenizer->advance();
+					} break;
+					case GDTokenizer::TK_CONSTANT: {
+
+						if (!need_identifier)
+							break;
+
+						if (tokenizer->get_token_constant().get_type()!=Variant::STRING) {
+							_set_error("Expected string constant or identifier after '$' or '/'.");
+							return NULL;
+						}
+
+						path+=String(tokenizer->get_token_constant());
+						tokenizer->advance();
+
+					} break;
+					case GDTokenizer::TK_IDENTIFIER: {
+
+						if (!need_identifier)
+							break;
+
+						path+=String(tokenizer->get_token_identifier());
+						tokenizer->advance();
+						need_identifier=false;
+
+					} break;
+					case GDTokenizer::TK_OP_DIV: {
+
+						if (need_identifier)
+							break;
+
+						path+="/";
+						tokenizer->advance();
+						need_identifier=true;
+
+					} break;
+					default: {
+						done=true;
+						break;
+					}
+				}
+			}
+
+			if (path=="") {
+				_set_error("Path expected after $.");
+				return NULL;
+
+			}
+
+			OperatorNode *op = alloc_node<OperatorNode>();
+			op->op=OperatorNode::OP_CALL;
+
+			op->arguments.push_back(alloc_node<SelfNode>());
+
+			IdentifierNode *funcname = alloc_node<IdentifierNode>();
+			funcname->name="get_node";
+
+			op->arguments.push_back(funcname);
+
+			ConstantNode *nodepath = alloc_node<ConstantNode>();
+			nodepath->value = NodePath(StringName(path));
+			op->arguments.push_back(nodepath);
+
+			expr=op;
+
 		} else if (tokenizer->get_token()==GDTokenizer::TK_CURSOR) {
 			tokenizer->advance();
 			continue; //no point in cursor in the middle of expression

+ 1 - 0
modules/gdscript/gd_parser.h

@@ -376,6 +376,7 @@ public:
 	enum CompletionType {
 		COMPLETION_NONE,
 		COMPLETION_BUILT_IN_TYPE_CONSTANT,
+		COMPLETION_GET_NODE,
 		COMPLETION_FUNCTION,
 		COMPLETION_IDENTIFIER,
 		COMPLETION_PARENT_FUNCTION,

+ 3 - 0
modules/gdscript/gd_tokenizer.cpp

@@ -460,6 +460,9 @@ void GDTokenizerText::_advance() {
 			case ':':
 				_make_token(TK_COLON); //for methods maybe but now useless.
 				break;
+			case '$':
+				_make_token(TK_DOLLAR); //for the get_node() shortener
+				break;
 			case '^': {
 				if (GETCHAR(1)=='=') {
 					_make_token(TK_OP_ASSIGN_BIT_XOR);

+ 1 - 0
modules/gdscript/gd_tokenizer.h

@@ -123,6 +123,7 @@ public:
 		TK_PERIOD,
 		TK_QUESTION_MARK,
 		TK_COLON,
+		TK_DOLLAR,
 		TK_NEWLINE,
 		TK_CONST_PI,
 		TK_ERROR,