summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/variant_op.cpp89
-rw-r--r--modules/gdscript/gd_parser.cpp58
2 files changed, 147 insertions, 0 deletions
diff --git a/core/variant_op.cpp b/core/variant_op.cpp
index 281d2e8192..3924d3af77 100644
--- a/core/variant_op.cpp
+++ b/core/variant_op.cpp
@@ -2934,6 +2934,38 @@ bool Variant::iter_init(Variant& r_iter,bool &valid) const {
valid=true;
switch(type) {
+ case INT: {
+ r_iter=0;
+ return _data._int>0;
+ } break;
+ case REAL: {
+ r_iter=0.0;
+ return _data._real>0.0;
+ } break;
+ case VECTOR2: {
+ real_t from = reinterpret_cast<const Vector2*>(_data._mem)->x;
+ real_t to = reinterpret_cast<const Vector2*>(_data._mem)->y;
+
+ r_iter=from;
+
+ return from < to;
+ } break;
+ case VECTOR3: {
+ real_t from = reinterpret_cast<const Vector3*>(_data._mem)->x;
+ real_t to = reinterpret_cast<const Vector3*>(_data._mem)->y;
+ real_t step = reinterpret_cast<const Vector3*>(_data._mem)->z;
+
+ r_iter=from;
+
+ if (from == to ) {
+ return false;
+ } else if (from < to) {
+ return step>0.0;
+ } else {
+ return step<0.0;
+ }
+ //return true;
+ } break;
case OBJECT: {
#ifdef DEBUG_ENABLED
@@ -3059,7 +3091,48 @@ bool Variant::iter_next(Variant& r_iter,bool &valid) const {
valid=true;
switch(type) {
+ case INT: {
+
+ int64_t idx = r_iter;
+ idx++;
+ if (idx >= _data._int)
+ return false;
+ r_iter = idx;
+ return true;
+ } break;
+ case REAL: {
+ double idx = r_iter;
+ idx+=1.0;
+ if (idx >= _data._real)
+ return false;
+ r_iter = idx;
+ return true;
+ } break;
+ case VECTOR2: {
+ real_t idx = r_iter;
+ idx+=1.0;
+ if (idx>=reinterpret_cast<const Vector2*>(_data._mem)->y)
+ return false;
+ r_iter=idx;
+ return true;
+ } break;
+ case VECTOR3: {
+ real_t to = reinterpret_cast<const Vector3*>(_data._mem)->y;
+ real_t step = reinterpret_cast<const Vector3*>(_data._mem)->z;
+
+ real_t idx = r_iter;
+ idx+=step;
+
+ if (step<0.0 && idx <= to)
+ return false;
+
+ if (step>0.0 && idx >= to)
+ return false;
+
+ r_iter=idx;
+ return true;
+ } break;
case OBJECT: {
#ifdef DEBUG_ENABLED
@@ -3204,6 +3277,22 @@ Variant Variant::iter_get(const Variant& r_iter,bool &r_valid) const {
r_valid=true;
switch(type) {
+ case INT: {
+
+ return r_iter;
+ } break;
+ case REAL: {
+
+ return r_iter;
+ } break;
+ case VECTOR2: {
+
+ return r_iter;
+ } break;
+ case VECTOR3: {
+
+ return r_iter;
+ } break;
case OBJECT: {
#ifdef DEBUG_ENABLED
diff --git a/modules/gdscript/gd_parser.cpp b/modules/gdscript/gd_parser.cpp
index aab6946364..6aed7c9491 100644
--- a/modules/gdscript/gd_parser.cpp
+++ b/modules/gdscript/gd_parser.cpp
@@ -2004,6 +2004,64 @@ void GDParser::_parse_block(BlockNode *p_block,bool p_static) {
return;
}
+ if (container->type==Node::TYPE_OPERATOR) {
+
+ OperatorNode* op = static_cast<OperatorNode*>(container);
+ if (op->op==OperatorNode::OP_CALL && op->arguments[0]->type==Node::TYPE_BUILT_IN_FUNCTION && static_cast<BuiltInFunctionNode*>(op->arguments[0])->function==GDFunctions::GEN_RANGE) {
+ //iterating a range, so see if range() can be optimized without allocating memory, by replacing it by vectors (which can work as iterable too!)
+
+ Vector<Node*> args;
+ Vector<double> constants;
+
+ bool constant=true;
+
+ for(int i=1;i<op->arguments.size();i++) {
+ args.push_back(op->arguments[i]);
+ if (constant && op->arguments[i]->type==Node::TYPE_CONSTANT) {
+ ConstantNode *c = static_cast<ConstantNode*>(op->arguments[i]);
+ if (c->value.get_type()==Variant::REAL || c->value.get_type()==Variant::INT) {
+ constants.push_back(c->value);
+ } else {
+ constant=false;
+ }
+ }
+ }
+
+ if (args.size()>0 || args.size()<4) {
+
+ if (constant) {
+
+ ConstantNode *cn = alloc_node<ConstantNode>();
+ switch(args.size()) {
+ case 1: cn->value=constants[0]; break;
+ case 2: cn->value=Vector2(constants[0],constants[1]); break;
+ case 3: cn->value=Vector3(constants[0],constants[1],constants[2]); break;
+ }
+ container=cn;
+ } else {
+ OperatorNode *on = alloc_node<OperatorNode>();
+ on->op=OperatorNode::OP_CALL;
+
+ TypeNode *tn = alloc_node<TypeNode>();
+ on->arguments.push_back(tn);
+
+ switch(args.size()) {
+ case 1: tn->vtype=Variant::REAL; break;
+ case 2: tn->vtype=Variant::VECTOR2; break;
+ case 3: tn->vtype=Variant::VECTOR3; break;
+ }
+
+ for(int i=0;i<args.size();i++) {
+ on->arguments.push_back(args[i]);
+ }
+
+ container=on;
+ }
+ }
+ }
+
+ }
+
ControlFlowNode *cf_for = alloc_node<ControlFlowNode>();
cf_for->cf_type=ControlFlowNode::CF_FOR;