예제 #1
0
	virtual int step(const Variant **p_inputs, Variant **p_outputs, StartMode p_start_mode, Variant *p_working_mem, Variant::CallError &r_error, String &r_error_str) {

		if (p_start_mode == START_MODE_RESUME_YIELD) {
			return 0; //resuming yield
		} else {
			//yield

			Object *object = NULL;

			switch (call_mode) {

				case VisualScriptYieldSignal::CALL_MODE_SELF: {

					object = instance->get_owner_ptr();

				} break;
				case VisualScriptYieldSignal::CALL_MODE_NODE_PATH: {

					Node *node = Object::cast_to<Node>(instance->get_owner_ptr());
					if (!node) {
						r_error.error = Variant::CallError::CALL_ERROR_INVALID_METHOD;
						r_error_str = "Base object is not a Node!";
						return 0;
					}

					Node *another = node->get_node(node_path);
					if (!another) {
						r_error.error = Variant::CallError::CALL_ERROR_INVALID_METHOD;
						r_error_str = "Path does not lead Node!";
						return 0;
					}

					object = another;

				} break;
				case VisualScriptYieldSignal::CALL_MODE_INSTANCE: {

					object = *p_inputs[0];
					if (!object) {
						r_error.error = Variant::CallError::CALL_ERROR_INVALID_METHOD;
						r_error_str = "Supplied instance input is null.";
						return 0;
					}

				} break;
			}

			Ref<VisualScriptFunctionState> state;
			state.instance();

			state->connect_to_signal(object, signal, Array());

			*p_working_mem = state;

			return STEP_YIELD_BIT;
		}
	}
예제 #2
0
	//virtual int get_working_memory_size() const { return 0; }
	//execute by parsing the tree directly
	virtual bool _execute(const Variant **p_inputs, VisualScriptExpression::ENode *p_node, Variant &r_ret, String &r_error_str, Variant::CallError &ce) {

		switch (p_node->type) {
			case VisualScriptExpression::ENode::TYPE_INPUT: {

				const VisualScriptExpression::InputNode *in = static_cast<const VisualScriptExpression::InputNode *>(p_node);
				r_ret = *p_inputs[in->index];
			} break;
			case VisualScriptExpression::ENode::TYPE_CONSTANT: {

				const VisualScriptExpression::ConstantNode *c = static_cast<const VisualScriptExpression::ConstantNode *>(p_node);
				r_ret = c->value;

			} break;
			case VisualScriptExpression::ENode::TYPE_SELF: {

				r_ret = instance->get_owner_ptr();
			} break;
			case VisualScriptExpression::ENode::TYPE_OPERATOR: {

				const VisualScriptExpression::OperatorNode *op = static_cast<const VisualScriptExpression::OperatorNode *>(p_node);

				Variant a;
				bool ret = _execute(p_inputs, op->nodes[0], a, r_error_str, ce);
				if (ret)
					return true;

				Variant b;

				if (op->nodes[1]) {
					ret = _execute(p_inputs, op->nodes[1], b, r_error_str, ce);
					if (ret)
						return true;
				}

				bool valid = true;
				Variant::evaluate(op->op, a, b, r_ret, valid);
				if (!valid) {
					r_error_str = "Invalid operands to operator " + Variant::get_operator_name(op->op) + ": " + Variant::get_type_name(a.get_type()) + " and " + Variant::get_type_name(b.get_type()) + ".";
					return true;
				}

			} break;
			case VisualScriptExpression::ENode::TYPE_INDEX: {

				const VisualScriptExpression::IndexNode *index = static_cast<const VisualScriptExpression::IndexNode *>(p_node);

				Variant base;
				bool ret = _execute(p_inputs, index->base, base, r_error_str, ce);
				if (ret)
					return true;

				Variant idx;

				ret = _execute(p_inputs, index->index, idx, r_error_str, ce);
				if (ret)
					return true;

				bool valid;
				r_ret = base.get(idx, &valid);
				if (!valid) {
					r_error_str = "Invalid index of type " + Variant::get_type_name(idx.get_type()) + " for base of type " + Variant::get_type_name(base.get_type()) + ".";
					return true;
				}

			} break;
			case VisualScriptExpression::ENode::TYPE_NAMED_INDEX: {

				const VisualScriptExpression::NamedIndexNode *index = static_cast<const VisualScriptExpression::NamedIndexNode *>(p_node);

				Variant base;
				bool ret = _execute(p_inputs, index->base, base, r_error_str, ce);
				if (ret)
					return true;

				bool valid;
				r_ret = base.get_named(index->name, &valid);
				if (!valid) {
					r_error_str = "Invalid index '" + String(index->name) + "' for base of type " + Variant::get_type_name(base.get_type()) + ".";
					return true;
				}

			} break;
			case VisualScriptExpression::ENode::TYPE_ARRAY: {
				const VisualScriptExpression::ArrayNode *array = static_cast<const VisualScriptExpression::ArrayNode *>(p_node);

				Array arr;
				arr.resize(array->array.size());
				for (int i = 0; i < array->array.size(); i++) {

					Variant value;
					bool ret = _execute(p_inputs, array->array[i], value, r_error_str, ce);
					if (ret)
						return true;
					arr[i] = value;
				}

				r_ret = arr;

			} break;
			case VisualScriptExpression::ENode::TYPE_DICTIONARY: {
				const VisualScriptExpression::DictionaryNode *dictionary = static_cast<const VisualScriptExpression::DictionaryNode *>(p_node);

				Dictionary d;
				for (int i = 0; i < dictionary->dict.size(); i += 2) {

					Variant key;
					bool ret = _execute(p_inputs, dictionary->dict[i + 0], key, r_error_str, ce);
					if (ret)
						return true;

					Variant value;
					ret = _execute(p_inputs, dictionary->dict[i + 1], value, r_error_str, ce);
					if (ret)
						return true;

					d[key] = value;
				}

				r_ret = d;
			} break;
			case VisualScriptExpression::ENode::TYPE_CONSTRUCTOR: {

				const VisualScriptExpression::ConstructorNode *constructor = static_cast<const VisualScriptExpression::ConstructorNode *>(p_node);

				Vector<Variant> arr;
				Vector<const Variant *> argp;
				arr.resize(constructor->arguments.size());
				argp.resize(constructor->arguments.size());

				for (int i = 0; i < constructor->arguments.size(); i++) {

					Variant value;
					bool ret = _execute(p_inputs, constructor->arguments[i], value, r_error_str, ce);
					if (ret)
						return true;
					arr[i] = value;
					argp[i] = &arr[i];
				}

				r_ret = Variant::construct(constructor->data_type, argp.ptr(), argp.size(), ce);

				if (ce.error != Variant::CallError::CALL_OK) {
					r_error_str = "Invalid arguments to construct '" + Variant::get_type_name(constructor->data_type) + "'.";
					return true;
				}

			} break;
			case VisualScriptExpression::ENode::TYPE_BUILTIN_FUNC: {

				const VisualScriptExpression::BuiltinFuncNode *bifunc = static_cast<const VisualScriptExpression::BuiltinFuncNode *>(p_node);

				Vector<Variant> arr;
				Vector<const Variant *> argp;
				arr.resize(bifunc->arguments.size());
				argp.resize(bifunc->arguments.size());

				for (int i = 0; i < bifunc->arguments.size(); i++) {

					Variant value;
					bool ret = _execute(p_inputs, bifunc->arguments[i], value, r_error_str, ce);
					if (ret)
						return true;
					arr[i] = value;
					argp[i] = &arr[i];
				}

				VisualScriptBuiltinFunc::exec_func(bifunc->func, argp.ptr(), &r_ret, ce, r_error_str);

				if (ce.error != Variant::CallError::CALL_OK) {
					r_error_str = "Builtin Call Failed. " + r_error_str;
					return true;
				}

			} break;
			case VisualScriptExpression::ENode::TYPE_CALL: {

				const VisualScriptExpression::CallNode *call = static_cast<const VisualScriptExpression::CallNode *>(p_node);

				Variant base;
				bool ret = _execute(p_inputs, call->base, base, r_error_str, ce);
				if (ret)
					return true;

				Vector<Variant> arr;
				Vector<const Variant *> argp;
				arr.resize(call->arguments.size());
				argp.resize(call->arguments.size());

				for (int i = 0; i < call->arguments.size(); i++) {

					Variant value;
					bool ret = _execute(p_inputs, call->arguments[i], value, r_error_str, ce);
					if (ret)
						return true;
					arr[i] = value;
					argp[i] = &arr[i];
				}

				r_ret = base.call(call->method, argp.ptr(), argp.size(), ce);

				if (ce.error != Variant::CallError::CALL_OK) {
					r_error_str = "On call to '" + String(call->method) + "':";
					return true;
				}

			} break;
		}
		return false;
	}