godot/modules/visual_script/visual_script_nodes.cpp
Juan Linietsky 9865650b43 Added a simpler way to do sub-functions in both visual and gdscript with the subcall node.
With this, visual script is almost done (missing registering custom nodes from addon).
All this is probably pretty broken, too and needs a lot of testing.
2016-08-08 01:21:22 -03:00

2477 lines
63 KiB
C++

#include "visual_script_nodes.h"
#include "global_constants.h"
#include "globals.h"
#include "scene/main/scene_main_loop.h"
#include "os/os.h"
#include "scene/main/node.h"
//////////////////////////////////////////
////////////////FUNCTION//////////////////
//////////////////////////////////////////
bool VisualScriptFunction::_set(const StringName& p_name, const Variant& p_value) {
if (p_name=="argument_count") {
int new_argc=p_value;
int argc = arguments.size();
if (argc==new_argc)
return true;
arguments.resize(new_argc);
for(int i=argc;i<new_argc;i++) {
arguments[i].name="arg"+itos(i+1);
arguments[i].type=Variant::NIL;
}
ports_changed_notify();
_change_notify();
return true;
}
if (String(p_name).begins_with("argument/")) {
int idx = String(p_name).get_slice("/",1).to_int()-1;
ERR_FAIL_INDEX_V(idx,arguments.size(),false);
String what = String(p_name).get_slice("/",2);
if (what=="type") {
Variant::Type new_type = Variant::Type(int(p_value));
arguments[idx].type=new_type;
ports_changed_notify();
return true;
}
if (what=="name") {
arguments[idx].name=p_value;
ports_changed_notify();
return true;
}
}
if (p_name=="stack/stackless") {
set_stack_less(p_value);
return true;
}
if (p_name=="stack/size") {
stack_size=p_value;
return true;
}
return false;
}
bool VisualScriptFunction::_get(const StringName& p_name,Variant &r_ret) const {
if (p_name=="argument_count") {
r_ret = arguments.size();
return true;
}
if (String(p_name).begins_with("argument/")) {
int idx = String(p_name).get_slice("/",1).to_int()-1;
ERR_FAIL_INDEX_V(idx,arguments.size(),false);
String what = String(p_name).get_slice("/",2);
if (what=="type") {
r_ret = arguments[idx].type;
return true;
}
if (what=="name") {
r_ret = arguments[idx].name;
return true;
}
}
if (p_name=="stack/stackless") {
r_ret=stack_less;
return true;
}
if (p_name=="stack/size") {
r_ret=stack_size;
return true;
}
return false;
}
void VisualScriptFunction::_get_property_list( List<PropertyInfo> *p_list) const {
p_list->push_back(PropertyInfo(Variant::INT,"argument_count",PROPERTY_HINT_RANGE,"0,256"));
String argt="Variant";
for(int i=1;i<Variant::VARIANT_MAX;i++) {
argt+=","+Variant::get_type_name(Variant::Type(i));
}
for(int i=0;i<arguments.size();i++) {
p_list->push_back(PropertyInfo(Variant::INT,"argument/"+itos(i+1)+"/type",PROPERTY_HINT_ENUM,argt));
p_list->push_back(PropertyInfo(Variant::STRING,"argument/"+itos(i+1)+"/name"));
}
if (!stack_less) {
p_list->push_back(PropertyInfo(Variant::INT,"stack/size",PROPERTY_HINT_RANGE,"1,100000"));
}
p_list->push_back(PropertyInfo(Variant::BOOL,"stack/stackless"));
}
int VisualScriptFunction::get_output_sequence_port_count() const {
return 1;
}
bool VisualScriptFunction::has_input_sequence_port() const{
return false;
}
int VisualScriptFunction::get_input_value_port_count() const{
return 0;
}
int VisualScriptFunction::get_output_value_port_count() const{
return arguments.size();
}
String VisualScriptFunction::get_output_sequence_port_text(int p_port) const {
return String();
}
PropertyInfo VisualScriptFunction::get_input_value_port_info(int p_idx) const{
ERR_FAIL_V(PropertyInfo());
return PropertyInfo();
}
PropertyInfo VisualScriptFunction::get_output_value_port_info(int p_idx) const{
ERR_FAIL_INDEX_V(p_idx,arguments.size(),PropertyInfo());
PropertyInfo out;
out.type=arguments[p_idx].type;
out.name=arguments[p_idx].name;
return out;
}
String VisualScriptFunction::get_caption() const {
return "Function";
}
String VisualScriptFunction::get_text() const {
return get_name(); //use name as function name I guess
}
void VisualScriptFunction::add_argument(Variant::Type p_type,const String& p_name,int p_index){
Argument arg;
arg.name=p_name;
arg.type=p_type;
if (p_index>=0)
arguments.insert(p_index,arg);
else
arguments.push_back(arg);
ports_changed_notify();
}
void VisualScriptFunction::set_argument_type(int p_argidx,Variant::Type p_type){
ERR_FAIL_INDEX(p_argidx,arguments.size());
arguments[p_argidx].type=p_type;
ports_changed_notify();
}
Variant::Type VisualScriptFunction::get_argument_type(int p_argidx) const {
ERR_FAIL_INDEX_V(p_argidx,arguments.size(),Variant::NIL);
return arguments[p_argidx].type;
}
void VisualScriptFunction::set_argument_name(int p_argidx,const String& p_name) {
ERR_FAIL_INDEX(p_argidx,arguments.size());
arguments[p_argidx].name=p_name;
ports_changed_notify();
}
String VisualScriptFunction::get_argument_name(int p_argidx) const {
ERR_FAIL_INDEX_V(p_argidx,arguments.size(),String());
return arguments[p_argidx].name;
}
void VisualScriptFunction::remove_argument(int p_argidx) {
ERR_FAIL_INDEX(p_argidx,arguments.size());
arguments.remove(p_argidx);
ports_changed_notify();
}
int VisualScriptFunction::get_argument_count() const {
return arguments.size();
}
class VisualScriptNodeInstanceFunction : public VisualScriptNodeInstance {
public:
VisualScriptFunction *node;
VisualScriptInstance *instance;
//virtual int get_working_memory_size() const { return 0; }
//virtual bool is_output_port_unsequenced(int p_idx) const { return false; }
//virtual bool get_output_port_unsequenced(int p_idx,Variant* r_value,Variant* p_working_mem,String &r_error) const { return true; }
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) {
int ac = node->get_argument_count();
for(int i=0;i<ac;i++) {
#ifdef DEBUG_ENABLED
Variant::Type expected = node->get_argument_type(i);
if (expected!=Variant::NIL) {
if (!Variant::can_convert_strict(p_inputs[i]->get_type(),expected)) {
r_error.error=Variant::CallError::CALL_ERROR_INVALID_ARGUMENT;
r_error.expected=expected;
r_error.argument=i;
return 0;
}
}
#endif
*p_outputs[i]=*p_inputs[i];
}
return 0;
}
};
VisualScriptNodeInstance* VisualScriptFunction::instance(VisualScriptInstance* p_instance) {
VisualScriptNodeInstanceFunction * instance = memnew(VisualScriptNodeInstanceFunction );
instance->node=this;
instance->instance=p_instance;
return instance;
}
VisualScriptFunction::VisualScriptFunction() {
stack_size=256;
stack_less=false;
}
void VisualScriptFunction::set_stack_less(bool p_enable) {
stack_less=p_enable;
_change_notify();
}
bool VisualScriptFunction::is_stack_less() const {
return stack_less;
}
void VisualScriptFunction::set_stack_size(int p_size) {
ERR_FAIL_COND(p_size <1 || p_size>100000);
stack_size=p_size;
}
int VisualScriptFunction::get_stack_size() const {
return stack_size;
}
//////////////////////////////////////////
////////////////OPERATOR//////////////////
//////////////////////////////////////////
int VisualScriptOperator::get_output_sequence_port_count() const {
return 1;
}
bool VisualScriptOperator::has_input_sequence_port() const{
return true;
}
int VisualScriptOperator::get_input_value_port_count() const{
return (op==Variant::OP_BIT_NEGATE || op==Variant::OP_NOT || op==Variant::OP_NEGATE) ? 1 : 2;
}
int VisualScriptOperator::get_output_value_port_count() const{
return 1;
}
String VisualScriptOperator::get_output_sequence_port_text(int p_port) const {
return String();
}
PropertyInfo VisualScriptOperator::get_input_value_port_info(int p_idx) const{
static const Variant::Type port_types[Variant::OP_MAX][2]={
{Variant::NIL,Variant::NIL}, //OP_EQUAL,
{Variant::NIL,Variant::NIL}, //OP_NOT_EQUAL,
{Variant::NIL,Variant::NIL}, //OP_LESS,
{Variant::NIL,Variant::NIL}, //OP_LESS_EQUAL,
{Variant::NIL,Variant::NIL}, //OP_GREATER,
{Variant::NIL,Variant::NIL}, //OP_GREATER_EQUAL,
//mathematic
{Variant::NIL,Variant::NIL}, //OP_ADD,
{Variant::NIL,Variant::NIL}, //OP_SUBSTRACT,
{Variant::NIL,Variant::NIL}, //OP_MULTIPLY,
{Variant::NIL,Variant::NIL}, //OP_DIVIDE,
{Variant::NIL,Variant::NIL}, //OP_NEGATE,
{Variant::INT,Variant::INT}, //OP_MODULE,
{Variant::STRING,Variant::STRING}, //OP_STRING_CONCAT,
//bitwise
{Variant::INT,Variant::INT}, //OP_SHIFT_LEFT,
{Variant::INT,Variant::INT}, //OP_SHIFT_RIGHT,
{Variant::INT,Variant::INT}, //OP_BIT_AND,
{Variant::INT,Variant::INT}, //OP_BIT_OR,
{Variant::INT,Variant::INT}, //OP_BIT_XOR,
{Variant::INT,Variant::INT}, //OP_BIT_NEGATE,
//logic
{Variant::BOOL,Variant::BOOL}, //OP_AND,
{Variant::BOOL,Variant::BOOL}, //OP_OR,
{Variant::BOOL,Variant::BOOL}, //OP_XOR,
{Variant::BOOL,Variant::BOOL}, //OP_NOT,
//containment
{Variant::NIL,Variant::NIL} //OP_IN,
};
ERR_FAIL_INDEX_V(p_idx,Variant::OP_MAX,PropertyInfo());
PropertyInfo pinfo;
pinfo.name=p_idx==0?"A":"B";
pinfo.type=port_types[op][p_idx];
return pinfo;
}
PropertyInfo VisualScriptOperator::get_output_value_port_info(int p_idx) const{
static const Variant::Type port_types[Variant::OP_MAX]={
//comparation
Variant::BOOL, //OP_EQUAL,
Variant::BOOL, //OP_NOT_EQUAL,
Variant::BOOL, //OP_LESS,
Variant::BOOL, //OP_LESS_EQUAL,
Variant::BOOL, //OP_GREATER,
Variant::BOOL, //OP_GREATER_EQUAL,
//mathematic
Variant::NIL, //OP_ADD,
Variant::NIL, //OP_SUBSTRACT,
Variant::NIL, //OP_MULTIPLY,
Variant::NIL, //OP_DIVIDE,
Variant::NIL, //OP_NEGATE,
Variant::INT, //OP_MODULE,
Variant::STRING, //OP_STRING_CONCAT,
//bitwise
Variant::INT, //OP_SHIFT_LEFT,
Variant::INT, //OP_SHIFT_RIGHT,
Variant::INT, //OP_BIT_AND,
Variant::INT, //OP_BIT_OR,
Variant::INT, //OP_BIT_XOR,
Variant::INT, //OP_BIT_NEGATE,
//logic
Variant::BOOL, //OP_AND,
Variant::BOOL, //OP_OR,
Variant::BOOL, //OP_XOR,
Variant::BOOL, //OP_NOT,
//containment
Variant::BOOL //OP_IN,
};
PropertyInfo pinfo;
pinfo.name="";
pinfo.type=port_types[op];
return pinfo;
}
static const char* op_names[]={
//comparation
"Equal", //OP_EQUAL,
"NotEqual", //OP_NOT_EQUAL,
"Less", //OP_LESS,
"LessEqual", //OP_LESS_EQUAL,
"Greater", //OP_GREATER,
"GreaterEq", //OP_GREATER_EQUAL,
//mathematic
"Add", //OP_ADD,
"Subtract", //OP_SUBSTRACT,
"Multiply", //OP_MULTIPLY,
"Divide", //OP_DIVIDE,
"Negate", //OP_NEGATE,
"Remainder", //OP_MODULE,
"Concat", //OP_STRING_CONCAT,
//bitwise
"ShiftLeft", //OP_SHIFT_LEFT,
"ShiftRight", //OP_SHIFT_RIGHT,
"BitAnd", //OP_BIT_AND,
"BitOr", //OP_BIT_OR,
"BitXor", //OP_BIT_XOR,
"BitNeg", //OP_BIT_NEGATE,
//logic
"And", //OP_AND,
"Or", //OP_OR,
"Xor", //OP_XOR,
"Not", //OP_NOT,
//containment
"In", //OP_IN,
};
String VisualScriptOperator::get_caption() const {
return op_names[op];
}
String VisualScriptOperator::get_text() const {
static const wchar_t* op_names[]={
//comparation
L"A = B", //OP_EQUAL,
L"A \u2260 B", //OP_NOT_EQUAL,
L"A < B", //OP_LESS,
L"A \u2264 B", //OP_LESS_EQUAL,
L"A > B", //OP_GREATER,
L"A \u2265 B", //OP_GREATER_EQUAL,
//mathematic
L"A + B", //OP_ADD,
L"A - B", //OP_SUBSTRACT,
L"A x B", //OP_MULTIPLY,
L"A \u00F7 B", //OP_DIVIDE,
L"\u00AC A", //OP_NEGATE,
L"A mod B", //OP_MODULE,
L"A .. B", //OP_STRING_CONCAT,
//bitwise
L"A << B", //OP_SHIFT_LEFT,
L"A >> B", //OP_SHIFT_RIGHT,
L"A & B", //OP_BIT_AND,
L"A | B", //OP_BIT_OR,
L"A ^ B", //OP_BIT_XOR,
L"~A", //OP_BIT_NEGATE,
//logic
L"A and B", //OP_AND,
L"A or B", //OP_OR,
L"A xor B", //OP_XOR,
L"not A", //OP_NOT,
};
return op_names[op];
}
void VisualScriptOperator::set_operator(Variant::Operator p_op) {
if (op==p_op)
return;
op=p_op;
ports_changed_notify();
}
Variant::Operator VisualScriptOperator::get_operator() const{
return op;
}
void VisualScriptOperator::_bind_methods() {
ObjectTypeDB::bind_method(_MD("set_operator","op"),&VisualScriptOperator::set_operator);
ObjectTypeDB::bind_method(_MD("get_operator"),&VisualScriptOperator::get_operator);
String types;
for(int i=0;i<Variant::OP_MAX;i++) {
if (i>0)
types+=",";
types+=op_names[i];
}
ADD_PROPERTY(PropertyInfo(Variant::INT,"operator_value/type",PROPERTY_HINT_ENUM,types),_SCS("set_operator"),_SCS("get_operator"));
}
class VisualScriptNodeInstanceOperator : public VisualScriptNodeInstance {
public:
bool unary;
Variant::Operator op;
//virtual int get_working_memory_size() const { return 0; }
//virtual bool is_output_port_unsequenced(int p_idx) const { return false; }
//virtual bool get_output_port_unsequenced(int p_idx,Variant* r_value,Variant* p_working_mem,String &r_error) const { return true; }
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) {
bool valid;
if (unary) {
Variant::evaluate(op,*p_inputs[0],Variant(),*p_outputs[0],valid);
} else {
Variant::evaluate(op,*p_inputs[0],*p_inputs[1],*p_outputs[0],valid);
}
if (!valid) {
r_error.error=Variant::CallError::CALL_ERROR_INVALID_METHOD;
if (p_outputs[0]->get_type()==Variant::STRING) {
r_error_str=*p_outputs[0];
} else {
if (unary)
r_error_str=String(op_names[op])+RTR(": Invalid argument of type: ")+Variant::get_type_name(p_inputs[0]->get_type());
else
r_error_str=String(op_names[op])+RTR(": Invalid arguments: ")+"A: "+Variant::get_type_name(p_inputs[0]->get_type())+" B: "+Variant::get_type_name(p_inputs[1]->get_type());
}
}
return 0;
}
};
VisualScriptNodeInstance* VisualScriptOperator::instance(VisualScriptInstance* p_instance) {
VisualScriptNodeInstanceOperator * instance = memnew(VisualScriptNodeInstanceOperator );
instance->unary=get_input_value_port_count()==1;
instance->op=op;
return instance;
}
VisualScriptOperator::VisualScriptOperator() {
op=Variant::OP_ADD;
}
template<Variant::Operator OP>
static Ref<VisualScriptNode> create_op_node(const String& p_name) {
Ref<VisualScriptOperator> node;
node.instance();
node->set_operator(OP);
return node;
}
//////////////////////////////////////////
////////////////VARIABLE GET//////////////////
//////////////////////////////////////////
int VisualScriptVariableGet::get_output_sequence_port_count() const {
return 0;
}
bool VisualScriptVariableGet::has_input_sequence_port() const{
return false;
}
int VisualScriptVariableGet::get_input_value_port_count() const{
return 0;
}
int VisualScriptVariableGet::get_output_value_port_count() const{
return 1;
}
String VisualScriptVariableGet::get_output_sequence_port_text(int p_port) const {
return String();
}
PropertyInfo VisualScriptVariableGet::get_input_value_port_info(int p_idx) const{
return PropertyInfo();
}
PropertyInfo VisualScriptVariableGet::get_output_value_port_info(int p_idx) const{
PropertyInfo pinfo;
pinfo.name="value";
if (get_visual_script().is_valid() && get_visual_script()->has_variable(variable)) {
PropertyInfo vinfo = get_visual_script()->get_variable_info(variable);
pinfo.type=vinfo.type;
pinfo.hint=vinfo.hint;
pinfo.hint_string=vinfo.hint_string;
}
return pinfo;
}
String VisualScriptVariableGet::get_caption() const {
return "Variable";
}
String VisualScriptVariableGet::get_text() const {
return variable;
}
void VisualScriptVariableGet::set_variable(StringName p_variable) {
if (variable==p_variable)
return;
variable=p_variable;
ports_changed_notify();
}
StringName VisualScriptVariableGet::get_variable() const{
return variable;
}
void VisualScriptVariableGet::_validate_property(PropertyInfo& property) const {
if (property.name=="variable/name" && get_visual_script().is_valid()) {
Ref<VisualScript> vs = get_visual_script();
List<StringName> vars;
vs->get_variable_list(&vars);
String vhint;
for (List<StringName>::Element *E=vars.front();E;E=E->next()) {
if (vhint!=String())
vhint+=",";
vhint+=E->get().operator String();
}
property.hint=PROPERTY_HINT_ENUM;
property.hint_string=vhint;
}
}
void VisualScriptVariableGet::_bind_methods() {
ObjectTypeDB::bind_method(_MD("set_variable","name"),&VisualScriptVariableGet::set_variable);
ObjectTypeDB::bind_method(_MD("get_variable"),&VisualScriptVariableGet::get_variable);
ADD_PROPERTY(PropertyInfo(Variant::STRING,"variable/name"),_SCS("set_variable"),_SCS("get_variable"));
}
class VisualScriptNodeInstanceVariableGet : public VisualScriptNodeInstance {
public:
VisualScriptVariableGet *node;
VisualScriptInstance *instance;
StringName variable;
//virtual int get_working_memory_size() const { return 0; }
virtual bool is_output_port_unsequenced(int p_idx) const { return true; }
virtual bool get_output_port_unsequenced(int p_idx,Variant* r_value,Variant* p_working_mem,String &r_error) const {
if (instance->get_variable(variable,r_value)==false) {
r_error=RTR("VariableGet not found in script: ")+"'"+String(variable)+"'";
return false;
} else {
return true;
}
}
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) {
return 0;
}
};
VisualScriptNodeInstance* VisualScriptVariableGet::instance(VisualScriptInstance* p_instance) {
VisualScriptNodeInstanceVariableGet * instance = memnew(VisualScriptNodeInstanceVariableGet );
instance->node=this;
instance->instance=p_instance;
instance->variable=variable;
return instance;
}
VisualScriptVariableGet::VisualScriptVariableGet() {
}
//////////////////////////////////////////
////////////////VARIABLE GET//////////////////
//////////////////////////////////////////
int VisualScriptVariableSet::get_output_sequence_port_count() const {
return 1;
}
bool VisualScriptVariableSet::has_input_sequence_port() const{
return true;
}
int VisualScriptVariableSet::get_input_value_port_count() const{
return 1;
}
int VisualScriptVariableSet::get_output_value_port_count() const{
return 0;
}
String VisualScriptVariableSet::get_output_sequence_port_text(int p_port) const {
return String();
}
PropertyInfo VisualScriptVariableSet::get_input_value_port_info(int p_idx) const{
PropertyInfo pinfo;
pinfo.name="set";
if (get_visual_script().is_valid() && get_visual_script()->has_variable(variable)) {
PropertyInfo vinfo = get_visual_script()->get_variable_info(variable);
pinfo.type=vinfo.type;
pinfo.hint=vinfo.hint;
pinfo.hint_string=vinfo.hint_string;
}
return pinfo;
}
PropertyInfo VisualScriptVariableSet::get_output_value_port_info(int p_idx) const{
return PropertyInfo();
}
String VisualScriptVariableSet::get_caption() const {
return "VariableSet";
}
String VisualScriptVariableSet::get_text() const {
return variable;
}
void VisualScriptVariableSet::set_variable(StringName p_variable) {
if (variable==p_variable)
return;
variable=p_variable;
ports_changed_notify();
}
StringName VisualScriptVariableSet::get_variable() const{
return variable;
}
void VisualScriptVariableSet::_validate_property(PropertyInfo& property) const {
if (property.name=="variable/name" && get_visual_script().is_valid()) {
Ref<VisualScript> vs = get_visual_script();
List<StringName> vars;
vs->get_variable_list(&vars);
String vhint;
for (List<StringName>::Element *E=vars.front();E;E=E->next()) {
if (vhint!=String())
vhint+=",";
vhint+=E->get().operator String();
}
property.hint=PROPERTY_HINT_ENUM;
property.hint_string=vhint;
}
}
void VisualScriptVariableSet::_bind_methods() {
ObjectTypeDB::bind_method(_MD("set_variable","name"),&VisualScriptVariableSet::set_variable);
ObjectTypeDB::bind_method(_MD("get_variable"),&VisualScriptVariableSet::get_variable);
ADD_PROPERTY(PropertyInfo(Variant::STRING,"variable/name"),_SCS("set_variable"),_SCS("get_variable"));
}
class VisualScriptNodeInstanceVariableSet : public VisualScriptNodeInstance {
public:
VisualScriptVariableSet *node;
VisualScriptInstance *instance;
StringName variable;
//virtual int get_working_memory_size() const { return 0; }
virtual bool is_output_port_unsequenced(int p_idx) const { return false; }
virtual bool get_output_port_unsequenced(int p_idx,Variant* r_value,Variant* p_working_mem,String &r_error) const { return false; }
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 (instance->set_variable(variable,*p_inputs[0])==false) {
r_error.error=Variant::CallError::CALL_ERROR_INVALID_METHOD ;
r_error_str=RTR("VariableSet not found in script: ")+"'"+String(variable)+"'";
}
return 0;
}
};
VisualScriptNodeInstance* VisualScriptVariableSet::instance(VisualScriptInstance* p_instance) {
VisualScriptNodeInstanceVariableSet * instance = memnew(VisualScriptNodeInstanceVariableSet );
instance->node=this;
instance->instance=p_instance;
instance->variable=variable;
return instance;
}
VisualScriptVariableSet::VisualScriptVariableSet() {
}
//////////////////////////////////////////
////////////////CONSTANT//////////////////
//////////////////////////////////////////
int VisualScriptConstant::get_output_sequence_port_count() const {
return 0;
}
bool VisualScriptConstant::has_input_sequence_port() const{
return false;
}
int VisualScriptConstant::get_input_value_port_count() const{
return 0;
}
int VisualScriptConstant::get_output_value_port_count() const{
return 1;
}
String VisualScriptConstant::get_output_sequence_port_text(int p_port) const {
return String();
}
PropertyInfo VisualScriptConstant::get_input_value_port_info(int p_idx) const{
return PropertyInfo();
}
PropertyInfo VisualScriptConstant::get_output_value_port_info(int p_idx) const{
PropertyInfo pinfo;
pinfo.name="get";
pinfo.type=type;
return pinfo;
}
String VisualScriptConstant::get_caption() const {
return "Constant";
}
String VisualScriptConstant::get_text() const {
return String(value);
}
void VisualScriptConstant::set_constant_type(Variant::Type p_type) {
if (type==p_type)
return;
type=p_type;
ports_changed_notify();
Variant::CallError ce;
value=Variant::construct(type,NULL,0,ce);
_change_notify();
}
Variant::Type VisualScriptConstant::get_constant_type() const{
return type;
}
void VisualScriptConstant::set_constant_value(Variant p_value){
if (value==p_value)
return;
value=p_value;
ports_changed_notify();
}
Variant VisualScriptConstant::get_constant_value() const{
return value;
}
void VisualScriptConstant::_validate_property(PropertyInfo& property) const {
if (property.name=="constant/value") {
property.type=type;
if (type==Variant::NIL)
property.usage=0; //do not save if nil
}
}
void VisualScriptConstant::_bind_methods() {
ObjectTypeDB::bind_method(_MD("set_constant_type","type"),&VisualScriptConstant::set_constant_type);
ObjectTypeDB::bind_method(_MD("get_constant_type"),&VisualScriptConstant::get_constant_type);
ObjectTypeDB::bind_method(_MD("set_constant_value","value"),&VisualScriptConstant::set_constant_value);
ObjectTypeDB::bind_method(_MD("get_constant_value"),&VisualScriptConstant::get_constant_value);
String argt="Null";
for(int i=1;i<Variant::VARIANT_MAX;i++) {
argt+=","+Variant::get_type_name(Variant::Type(i));
}
ADD_PROPERTY(PropertyInfo(Variant::INT,"constant/type",PROPERTY_HINT_ENUM,argt),_SCS("set_constant_type"),_SCS("get_constant_type"));
ADD_PROPERTY(PropertyInfo(Variant::NIL,"constant/value"),_SCS("set_constant_value"),_SCS("get_constant_value"));
}
class VisualScriptNodeInstanceConstant : public VisualScriptNodeInstance {
public:
Variant constant;
//virtual int get_working_memory_size() const { return 0; }
virtual bool is_output_port_unsequenced(int p_idx) const { return true; }
virtual bool get_output_port_unsequenced(int p_idx,Variant* r_value,Variant* p_working_mem,String &r_error) const {
*r_value=constant;
return true;
}
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) {
return 0;
}
};
VisualScriptNodeInstance* VisualScriptConstant::instance(VisualScriptInstance* p_instance) {
VisualScriptNodeInstanceConstant * instance = memnew(VisualScriptNodeInstanceConstant );
instance->constant=value;
return instance;
}
VisualScriptConstant::VisualScriptConstant() {
type=Variant::NIL;
}
//////////////////////////////////////////
////////////////INDEX////////////////////
//////////////////////////////////////////
int VisualScriptIndexGet::get_output_sequence_port_count() const {
return 1;
}
bool VisualScriptIndexGet::has_input_sequence_port() const{
return true;
}
int VisualScriptIndexGet::get_input_value_port_count() const{
return 2;
}
int VisualScriptIndexGet::get_output_value_port_count() const{
return 1;
}
String VisualScriptIndexGet::get_output_sequence_port_text(int p_port) const {
return String();
}
PropertyInfo VisualScriptIndexGet::get_input_value_port_info(int p_idx) const{
if (p_idx==0) {
return PropertyInfo(Variant::NIL,"base");
} else {
return PropertyInfo(Variant::NIL,"index");
}
}
PropertyInfo VisualScriptIndexGet::get_output_value_port_info(int p_idx) const{
return PropertyInfo();
}
String VisualScriptIndexGet::get_caption() const {
return "IndexGet";
}
String VisualScriptIndexGet::get_text() const {
return String("get");
}
class VisualScriptNodeInstanceIndexGet : public VisualScriptNodeInstance {
public:
//virtual int get_working_memory_size() const { return 0; }
//virtual bool is_output_port_unsequenced(int p_idx) const { return true; }
//virtual bool get_output_port_unsequenced(int p_idx,Variant* r_value,Variant* p_working_mem,String &r_error) const { return false; }
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) {
bool valid;
*p_outputs[0] = p_inputs[0]->get(*p_inputs[1],&valid);
if (!valid) {
r_error.error=Variant::CallError::CALL_ERROR_INVALID_METHOD;
r_error_str="Invalid get: "+p_inputs[0]->get_construct_string();
}
return 0;
}
};
VisualScriptNodeInstance* VisualScriptIndexGet::instance(VisualScriptInstance* p_instance) {
VisualScriptNodeInstanceIndexGet * instance = memnew(VisualScriptNodeInstanceIndexGet );
return instance;
}
VisualScriptIndexGet::VisualScriptIndexGet() {
}
//////////////////////////////////////////
////////////////INDEXSET//////////////////
//////////////////////////////////////////
int VisualScriptIndexSet::get_output_sequence_port_count() const {
return 1;
}
bool VisualScriptIndexSet::has_input_sequence_port() const{
return true;
}
int VisualScriptIndexSet::get_input_value_port_count() const{
return 3;
}
int VisualScriptIndexSet::get_output_value_port_count() const{
return 0;
}
String VisualScriptIndexSet::get_output_sequence_port_text(int p_port) const {
return String();
}
PropertyInfo VisualScriptIndexSet::get_input_value_port_info(int p_idx) const{
if (p_idx==0) {
return PropertyInfo(Variant::NIL,"base");
} else if (p_idx==1){
return PropertyInfo(Variant::NIL,"index");
} else {
return PropertyInfo(Variant::NIL,"value");
}
}
PropertyInfo VisualScriptIndexSet::get_output_value_port_info(int p_idx) const{
return PropertyInfo();
}
String VisualScriptIndexSet::get_caption() const {
return "IndexSet";
}
String VisualScriptIndexSet::get_text() const {
return String("set");
}
class VisualScriptNodeInstanceIndexSet : public VisualScriptNodeInstance {
public:
//virtual int get_working_memory_size() const { return 0; }
//virtual bool is_output_port_unsequenced(int p_idx) const { return true; }
//virtual bool get_output_port_unsequenced(int p_idx,Variant* r_value,Variant* p_working_mem,String &r_error) const { return false; }
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) {
bool valid;
*p_outputs[0]=*p_inputs[0];
p_outputs[0]->set(*p_inputs[1],*p_inputs[2],&valid);
if (!valid) {
r_error.error=Variant::CallError::CALL_ERROR_INVALID_METHOD;
r_error_str="Invalid set: "+p_inputs[1]->get_construct_string();
}
return 0;
}
};
VisualScriptNodeInstance* VisualScriptIndexSet::instance(VisualScriptInstance* p_instance) {
VisualScriptNodeInstanceIndexSet * instance = memnew(VisualScriptNodeInstanceIndexSet );
return instance;
}
VisualScriptIndexSet::VisualScriptIndexSet() {
}
//////////////////////////////////////////
////////////////GLOBALCONSTANT///////////
//////////////////////////////////////////
int VisualScriptGlobalConstant::get_output_sequence_port_count() const {
return 0;
}
bool VisualScriptGlobalConstant::has_input_sequence_port() const{
return false;
}
int VisualScriptGlobalConstant::get_input_value_port_count() const{
return 0;
}
int VisualScriptGlobalConstant::get_output_value_port_count() const{
return 1;
}
String VisualScriptGlobalConstant::get_output_sequence_port_text(int p_port) const {
return String();
}
PropertyInfo VisualScriptGlobalConstant::get_input_value_port_info(int p_idx) const{
return PropertyInfo();
}
PropertyInfo VisualScriptGlobalConstant::get_output_value_port_info(int p_idx) const{
return PropertyInfo(Variant::REAL,"value");
}
String VisualScriptGlobalConstant::get_caption() const {
return "GlobalConst";
}
String VisualScriptGlobalConstant::get_text() const {
return GlobalConstants::get_global_constant_name(index);
}
void VisualScriptGlobalConstant::set_global_constant(int p_which) {
index=p_which;
_change_notify();
ports_changed_notify();
}
int VisualScriptGlobalConstant::get_global_constant() {
return index;
}
class VisualScriptNodeInstanceGlobalConstant : public VisualScriptNodeInstance {
public:
int index;
//virtual int get_working_memory_size() const { return 0; }
virtual bool is_output_port_unsequenced(int p_idx) const { return true; }
virtual bool get_output_port_unsequenced(int p_idx,Variant* r_value,Variant* p_working_mem,String &r_error) const {
*r_value = GlobalConstants::get_global_constant_value(index);
return true;
}
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) {
return 0;
}
};
VisualScriptNodeInstance* VisualScriptGlobalConstant::instance(VisualScriptInstance* p_instance) {
VisualScriptNodeInstanceGlobalConstant * instance = memnew(VisualScriptNodeInstanceGlobalConstant );
instance->index=index;
return instance;
}
void VisualScriptGlobalConstant::_bind_methods() {
ObjectTypeDB::bind_method(_MD("set_global_constant","index"),&VisualScriptGlobalConstant::set_global_constant);
ObjectTypeDB::bind_method(_MD("get_global_constant"),&VisualScriptGlobalConstant::get_global_constant);
String cc;
for(int i=0;i<GlobalConstants::get_global_constant_count();i++) {
if (i>0)
cc+=",";
cc+=GlobalConstants::get_global_constant_name(i);
}
ADD_PROPERTY(PropertyInfo(Variant::INT,"constant",PROPERTY_HINT_ENUM,cc),_SCS("set_global_constant"),_SCS("get_global_constant"));
}
VisualScriptGlobalConstant::VisualScriptGlobalConstant() {
index=0;
}
//////////////////////////////////////////
////////////////MATHCONSTANT///////////
//////////////////////////////////////////
const char* VisualScriptMathConstant::const_name[MATH_CONSTANT_MAX]={
"One",
"PI",
"PIx2",
"PI/2",
"E",
"Sqrt2",
};
double VisualScriptMathConstant::const_value[MATH_CONSTANT_MAX]={
1.0,
Math_PI,
Math_PI*2,
Math_PI*0.5,
2.71828182845904523536,
Math::sqrt(2.0)
};
int VisualScriptMathConstant::get_output_sequence_port_count() const {
return 0;
}
bool VisualScriptMathConstant::has_input_sequence_port() const{
return false;
}
int VisualScriptMathConstant::get_input_value_port_count() const{
return 0;
}
int VisualScriptMathConstant::get_output_value_port_count() const{
return 1;
}
String VisualScriptMathConstant::get_output_sequence_port_text(int p_port) const {
return String();
}
PropertyInfo VisualScriptMathConstant::get_input_value_port_info(int p_idx) const{
return PropertyInfo();
}
PropertyInfo VisualScriptMathConstant::get_output_value_port_info(int p_idx) const{
return PropertyInfo(Variant::REAL,"value");
}
String VisualScriptMathConstant::get_caption() const {
return "MathConst";
}
String VisualScriptMathConstant::get_text() const {
return const_name[constant];
}
void VisualScriptMathConstant::set_math_constant(MathConstant p_which) {
constant=p_which;
_change_notify();
ports_changed_notify();
}
VisualScriptMathConstant::MathConstant VisualScriptMathConstant::get_math_constant() {
return constant;
}
class VisualScriptNodeInstanceMathConstant : public VisualScriptNodeInstance {
public:
float value;
//virtual int get_working_memory_size() const { return 0; }
virtual bool is_output_port_unsequenced(int p_idx) const { return true; }
virtual bool get_output_port_unsequenced(int p_idx,Variant* r_value,Variant* p_working_mem,String &r_error) const {
*r_value = value;
return true;
}
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) {
return 0;
}
};
VisualScriptNodeInstance* VisualScriptMathConstant::instance(VisualScriptInstance* p_instance) {
VisualScriptNodeInstanceMathConstant * instance = memnew(VisualScriptNodeInstanceMathConstant );
instance->value=const_value[constant];
return instance;
}
void VisualScriptMathConstant::_bind_methods() {
ObjectTypeDB::bind_method(_MD("set_math_constant","which"),&VisualScriptMathConstant::set_math_constant);
ObjectTypeDB::bind_method(_MD("get_math_constant"),&VisualScriptMathConstant::get_math_constant);
String cc;
for(int i=0;i<MATH_CONSTANT_MAX;i++) {
if (i>0)
cc+=",";
cc+=const_name[i];
}
ADD_PROPERTY(PropertyInfo(Variant::INT,"constant",PROPERTY_HINT_ENUM,cc),_SCS("set_math_constant"),_SCS("get_math_constant"));
}
VisualScriptMathConstant::VisualScriptMathConstant() {
constant=MATH_CONSTANT_ONE;
}
//////////////////////////////////////////
////////////////GLOBALSINGLETON///////////
//////////////////////////////////////////
int VisualScriptEngineSingleton::get_output_sequence_port_count() const {
return 0;
}
bool VisualScriptEngineSingleton::has_input_sequence_port() const{
return false;
}
int VisualScriptEngineSingleton::get_input_value_port_count() const{
return 0;
}
int VisualScriptEngineSingleton::get_output_value_port_count() const{
return 1;
}
String VisualScriptEngineSingleton::get_output_sequence_port_text(int p_port) const {
return String();
}
PropertyInfo VisualScriptEngineSingleton::get_input_value_port_info(int p_idx) const{
return PropertyInfo();
}
PropertyInfo VisualScriptEngineSingleton::get_output_value_port_info(int p_idx) const{
return PropertyInfo(Variant::OBJECT,"instance");
}
String VisualScriptEngineSingleton::get_caption() const {
return "EngineSingleton";
}
String VisualScriptEngineSingleton::get_text() const {
return singleton;
}
void VisualScriptEngineSingleton::set_singleton(const String& p_string) {
singleton=p_string;
_change_notify();
ports_changed_notify();
}
String VisualScriptEngineSingleton::get_singleton() {
return singleton;
}
class VisualScriptNodeInstanceEngineSingleton : public VisualScriptNodeInstance {
public:
Object* singleton;
//virtual int get_working_memory_size() const { return 0; }
virtual bool is_output_port_unsequenced(int p_idx) const { return true; }
virtual bool get_output_port_unsequenced(int p_idx,Variant* r_value,Variant* p_working_mem,String &r_error) const {
*r_value=singleton;
return true;
}
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) {
return 0;
}
};
VisualScriptNodeInstance* VisualScriptEngineSingleton::instance(VisualScriptInstance* p_instance) {
VisualScriptNodeInstanceEngineSingleton * instance = memnew(VisualScriptNodeInstanceEngineSingleton );
instance->singleton=Globals::get_singleton()->get_singleton_object(singleton);
return instance;
}
void VisualScriptEngineSingleton::_bind_methods() {
ObjectTypeDB::bind_method(_MD("set_singleton","name"),&VisualScriptEngineSingleton::set_singleton);
ObjectTypeDB::bind_method(_MD("get_singleton"),&VisualScriptEngineSingleton::get_singleton);
String cc;
List<Globals::Singleton> singletons;
Globals::get_singleton()->get_singletons(&singletons);
for (List<Globals::Singleton>::Element *E=singletons.front();E;E=E->next()) {
if (E->get().name=="VS" || E->get().name=="PS" || E->get().name=="PS2D" || E->get().name=="AS" || E->get().name=="TS" || E->get().name=="SS" || E->get().name=="SS2D")
continue; //skip these, too simple named
if (cc!=String())
cc+=",";
cc+=E->get().name;
}
ADD_PROPERTY(PropertyInfo(Variant::STRING,"constant",PROPERTY_HINT_ENUM,cc),_SCS("set_singleton"),_SCS("get_singleton"));
}
VisualScriptEngineSingleton::VisualScriptEngineSingleton() {
singleton=String();
}
//////////////////////////////////////////
////////////////GETNODE///////////
//////////////////////////////////////////
int VisualScriptSceneNode::get_output_sequence_port_count() const {
return 0;
}
bool VisualScriptSceneNode::has_input_sequence_port() const{
return false;
}
int VisualScriptSceneNode::get_input_value_port_count() const{
return 0;
}
int VisualScriptSceneNode::get_output_value_port_count() const{
return 1;
}
String VisualScriptSceneNode::get_output_sequence_port_text(int p_port) const {
return String();
}
PropertyInfo VisualScriptSceneNode::get_input_value_port_info(int p_idx) const{
return PropertyInfo();
}
PropertyInfo VisualScriptSceneNode::get_output_value_port_info(int p_idx) const{
return PropertyInfo(Variant::OBJECT,"node");
}
String VisualScriptSceneNode::get_caption() const {
return "SceneNode";
}
String VisualScriptSceneNode::get_text() const {
return path.simplified();
}
void VisualScriptSceneNode::set_node_path(const NodePath& p_path) {
path=p_path;
_change_notify();
ports_changed_notify();
}
NodePath VisualScriptSceneNode::get_node_path() {
return path;
}
class VisualScriptNodeInstanceSceneNode : public VisualScriptNodeInstance {
public:
VisualScriptSceneNode *node;
VisualScriptInstance *instance;
NodePath path;
//virtual int get_working_memory_size() const { return 0; }
virtual bool is_output_port_unsequenced(int p_idx) const { return true; }
virtual bool get_output_port_unsequenced(int p_idx,Variant* r_value,Variant* p_working_mem,String &r_error) const {
Node* node = instance->get_owner_ptr()->cast_to<Node>();
if (!node) {
r_error="Base object is not a Node!";
return false;
}
Node* another = node->get_node(path);
if (!node) {
r_error="Path does not lead Node!";
return false;
}
*r_value=another;
return true;
}
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) {
return 0;
}
};
VisualScriptNodeInstance* VisualScriptSceneNode::instance(VisualScriptInstance* p_instance) {
VisualScriptNodeInstanceSceneNode * instance = memnew(VisualScriptNodeInstanceSceneNode );
instance->node=this;
instance->instance=p_instance;
instance->path=path;
return instance;
}
#ifdef TOOLS_ENABLED
static Node* _find_script_node(Node* p_edited_scene,Node* p_current_node,const Ref<Script> &script) {
if (p_edited_scene!=p_current_node && p_current_node->get_owner()!=p_edited_scene)
return NULL;
Ref<Script> scr = p_current_node->get_script();
if (scr.is_valid() && scr==script)
return p_current_node;
for(int i=0;i<p_current_node->get_child_count();i++) {
Node *n = _find_script_node(p_edited_scene,p_current_node->get_child(i),script);
if (n)
return n;
}
return NULL;
}
#endif
void VisualScriptSceneNode::_validate_property(PropertyInfo& property) const {
#ifdef TOOLS_ENABLED
if (property.name=="node_path") {
Ref<Script> script = get_visual_script();
if (!script.is_valid())
return;
MainLoop * main_loop = OS::get_singleton()->get_main_loop();
if (!main_loop)
return;
SceneTree *scene_tree = main_loop->cast_to<SceneTree>();
if (!scene_tree)
return;
Node *edited_scene = scene_tree->get_edited_scene_root();
if (!edited_scene)
return;
Node* script_node = _find_script_node(edited_scene,edited_scene,script);
if (!script_node)
return;
property.hint_string=script_node->get_path();
}
#endif
}
void VisualScriptSceneNode::_bind_methods() {
ObjectTypeDB::bind_method(_MD("set_node_path","path"),&VisualScriptSceneNode::set_node_path);
ObjectTypeDB::bind_method(_MD("get_node_path"),&VisualScriptSceneNode::get_node_path);
ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH,"node_path",PROPERTY_HINT_NODE_PATH_TO_EDITED_NODE),_SCS("set_node_path"),_SCS("get_node_path"));
}
VisualScriptSceneNode::VisualScriptSceneNode() {
path=String(".");
}
//////////////////////////////////////////
////////////////SceneTree///////////
//////////////////////////////////////////
int VisualScriptSceneTree::get_output_sequence_port_count() const {
return 0;
}
bool VisualScriptSceneTree::has_input_sequence_port() const{
return false;
}
int VisualScriptSceneTree::get_input_value_port_count() const{
return 0;
}
int VisualScriptSceneTree::get_output_value_port_count() const{
return 1;
}
String VisualScriptSceneTree::get_output_sequence_port_text(int p_port) const {
return String();
}
PropertyInfo VisualScriptSceneTree::get_input_value_port_info(int p_idx) const{
return PropertyInfo();
}
PropertyInfo VisualScriptSceneTree::get_output_value_port_info(int p_idx) const{
return PropertyInfo(Variant::OBJECT,"instance");
}
String VisualScriptSceneTree::get_caption() const {
return "SceneTree";
}
String VisualScriptSceneTree::get_text() const {
return "";
}
class VisualScriptNodeInstanceSceneTree : public VisualScriptNodeInstance {
public:
VisualScriptSceneTree *node;
VisualScriptInstance *instance;
//virtual int get_working_memory_size() const { return 0; }
virtual bool is_output_port_unsequenced(int p_idx) const { return true; }
virtual bool get_output_port_unsequenced(int p_idx,Variant* r_value,Variant* p_working_mem,String &r_error) const {
Node* node = instance->get_owner_ptr()->cast_to<Node>();
if (!node) {
r_error="Base object is not a Node!";
return false;
}
SceneTree* tree = node->get_tree();
if (!tree) {
r_error="Attempt to get SceneTree while node is not in the active tree.";
return false;
}
*r_value=tree;
return true;
}
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) {
return 0;
}
};
VisualScriptNodeInstance* VisualScriptSceneTree::instance(VisualScriptInstance* p_instance) {
VisualScriptNodeInstanceSceneTree * instance = memnew(VisualScriptNodeInstanceSceneTree );
instance->node=this;
instance->instance=p_instance;
return instance;
}
void VisualScriptSceneTree::_validate_property(PropertyInfo& property) const {
}
void VisualScriptSceneTree::_bind_methods() {
}
VisualScriptSceneTree::VisualScriptSceneTree() {
}
//////////////////////////////////////////
////////////////RESPATH///////////
//////////////////////////////////////////
int VisualScriptResourcePath::get_output_sequence_port_count() const {
return 0;
}
bool VisualScriptResourcePath::has_input_sequence_port() const{
return false;
}
int VisualScriptResourcePath::get_input_value_port_count() const{
return 0;
}
int VisualScriptResourcePath::get_output_value_port_count() const{
return 1;
}
String VisualScriptResourcePath::get_output_sequence_port_text(int p_port) const {
return String();
}
PropertyInfo VisualScriptResourcePath::get_input_value_port_info(int p_idx) const{
return PropertyInfo();
}
PropertyInfo VisualScriptResourcePath::get_output_value_port_info(int p_idx) const{
return PropertyInfo(Variant::STRING,"path");
}
String VisualScriptResourcePath::get_caption() const {
return "ResourcePath";
}
String VisualScriptResourcePath::get_text() const {
return path;
}
void VisualScriptResourcePath::set_resource_path(const String& p_path) {
path=p_path;
_change_notify();
ports_changed_notify();
}
String VisualScriptResourcePath::get_resource_path() {
return path;
}
class VisualScriptNodeInstanceResourcePath : public VisualScriptNodeInstance {
public:
String path;
//virtual int get_working_memory_size() const { return 0; }
virtual bool is_output_port_unsequenced(int p_idx) const { return true; }
virtual bool get_output_port_unsequenced(int p_idx,Variant* r_value,Variant* p_working_mem,String &r_error) const {
*r_value = path;
return true;
}
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) {
return 0;
}
};
VisualScriptNodeInstance* VisualScriptResourcePath::instance(VisualScriptInstance* p_instance) {
VisualScriptNodeInstanceResourcePath * instance = memnew(VisualScriptNodeInstanceResourcePath );
instance->path=path;
return instance;
}
void VisualScriptResourcePath::_bind_methods() {
ObjectTypeDB::bind_method(_MD("set_resource_path","path"),&VisualScriptResourcePath::set_resource_path);
ObjectTypeDB::bind_method(_MD("get_resource_path"),&VisualScriptResourcePath::get_resource_path);
ADD_PROPERTY(PropertyInfo(Variant::STRING,"path",PROPERTY_HINT_FILE),_SCS("set_resource_path"),_SCS("get_resource_path"));
}
VisualScriptResourcePath::VisualScriptResourcePath() {
path="";
}
//////////////////////////////////////////
////////////////SELF///////////
//////////////////////////////////////////
int VisualScriptSelf::get_output_sequence_port_count() const {
return 0;
}
bool VisualScriptSelf::has_input_sequence_port() const{
return false;
}
int VisualScriptSelf::get_input_value_port_count() const{
return 0;
}
int VisualScriptSelf::get_output_value_port_count() const{
return 1;
}
String VisualScriptSelf::get_output_sequence_port_text(int p_port) const {
return String();
}
PropertyInfo VisualScriptSelf::get_input_value_port_info(int p_idx) const{
return PropertyInfo();
}
PropertyInfo VisualScriptSelf::get_output_value_port_info(int p_idx) const{
return PropertyInfo(Variant::OBJECT,"instance");
}
String VisualScriptSelf::get_caption() const {
return "Self";
}
String VisualScriptSelf::get_text() const {
if (get_visual_script().is_valid())
return get_visual_script()->get_instance_base_type();
else
return "";
}
class VisualScriptNodeInstanceSelf : public VisualScriptNodeInstance {
public:
VisualScriptInstance* instance;
//virtual int get_working_memory_size() const { return 0; }
virtual bool is_output_port_unsequenced(int p_idx) const { return true; }
virtual bool get_output_port_unsequenced(int p_idx,Variant* r_value,Variant* p_working_mem,String &r_error) const {
*r_value = instance->get_owner_ptr();
return true;
}
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) {
return 0;
}
};
VisualScriptNodeInstance* VisualScriptSelf::instance(VisualScriptInstance* p_instance) {
VisualScriptNodeInstanceSelf * instance = memnew(VisualScriptNodeInstanceSelf );
instance->instance=p_instance;
return instance;
}
void VisualScriptSelf::_bind_methods() {
}
VisualScriptSelf::VisualScriptSelf() {
}
//////////////////////////////////////////
////////////////CUSTOM (SCRIPTED)///////////
//////////////////////////////////////////
int VisualScriptCustomNode::get_output_sequence_port_count() const {
if (get_script_instance() && get_script_instance()->has_method("_get_output_sequence_port_count")) {
return get_script_instance()->call("_get_output_sequence_port_count");
}
return 0;
}
bool VisualScriptCustomNode::has_input_sequence_port() const{
if (get_script_instance() && get_script_instance()->has_method("_has_input_sequence_port")) {
return get_script_instance()->call("_has_input_sequence_port");
}
return false;
}
int VisualScriptCustomNode::get_input_value_port_count() const{
if (get_script_instance() && get_script_instance()->has_method("_get_input_value_port_count")) {
return get_script_instance()->call("_get_input_value_port_count");
}
return 0;
}
int VisualScriptCustomNode::get_output_value_port_count() const{
if (get_script_instance() && get_script_instance()->has_method("_get_output_value_port_count")) {
return get_script_instance()->call("_get_output_value_port_count");
}
return 0;
}
String VisualScriptCustomNode::get_output_sequence_port_text(int p_port) const {
if (get_script_instance() && get_script_instance()->has_method("_get_output_sequence_port_text")) {
return get_script_instance()->call("_get_output_sequence_port_text",p_port);
}
return String();
}
PropertyInfo VisualScriptCustomNode::get_input_value_port_info(int p_idx) const{
PropertyInfo info;
if (get_script_instance() && get_script_instance()->has_method("_get_input_value_port_type")) {
info.type=Variant::Type(int(get_script_instance()->call("_get_input_value_port_type",p_idx)));
}
if (get_script_instance() && get_script_instance()->has_method("_get_input_value_port_name")) {
info.name=get_script_instance()->call("_get_input_value_port_name",p_idx);
}
return info;
}
PropertyInfo VisualScriptCustomNode::get_output_value_port_info(int p_idx) const{
PropertyInfo info;
if (get_script_instance() && get_script_instance()->has_method("_get_output_value_port_type")) {
info.type=Variant::Type(int(get_script_instance()->call("_get_output_value_port_type",p_idx)));
}
if (get_script_instance() && get_script_instance()->has_method("_get_output_value_port_name")) {
info.name=get_script_instance()->call("_get_output_value_port_name",p_idx);
}
return info;
}
String VisualScriptCustomNode::get_caption() const {
if (get_script_instance() && get_script_instance()->has_method("_get_caption")) {
return get_script_instance()->call("_get_caption");
}
return "CustomNode";
}
String VisualScriptCustomNode::get_text() const {
if (get_script_instance() && get_script_instance()->has_method("_get_text")) {
return get_script_instance()->call("_get_text");
}
return "";
}
String VisualScriptCustomNode::get_category() const {
if (get_script_instance() && get_script_instance()->has_method("_get_category")) {
return get_script_instance()->call("_get_category");
}
return "custom";
}
class VisualScriptNodeInstanceCustomNode : public VisualScriptNodeInstance {
public:
VisualScriptInstance* instance;
VisualScriptCustomNode *node;
int in_count;
int out_count;
int work_mem_size;
Vector<bool> out_unsequenced;
virtual int get_working_memory_size() const { return work_mem_size; }
virtual bool is_output_port_unsequenced(int p_idx) const { return out_unsequenced[p_idx]; }
virtual bool get_output_port_unsequenced(int p_idx,Variant* r_value,Variant* p_working_mem,String &r_error) const {
if (!node->get_script_instance() || !node->get_script_instance()->has_method(VisualScriptLanguage::singleton->_get_output_port_unsequenced)) {
#ifdef DEBUG_ENABLED
r_error=RTR("Custom node has no _get_output_port_unsequenced(idx,wmem), but unsequenced ports were specified.");
return false;
}
#endif
Array work_mem(true);
work_mem.resize(work_mem_size);
*r_value = node->get_script_instance()->call(VisualScriptLanguage::singleton->_get_output_port_unsequenced,p_idx,work_mem);
for(int i=0;i<work_mem_size;i++) {
if (i<work_mem.size()) {
p_working_mem[i]=work_mem[i];
}
}
return true;
}
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 (node->get_script_instance()) {
#ifdef DEBUG_ENABLED
if (!node->get_script_instance()->has_method(VisualScriptLanguage::singleton->_step)) {
r_error_str=RTR("Custom node has no _step() method, can't process graph.");
r_error.error=Variant::CallError::CALL_ERROR_INVALID_METHOD;
return 0;
}
#endif
Array in_values(true);
Array out_values(true);
Array work_mem(true);
in_values.resize(in_count);
for(int i=0;i<in_count;i++) {
in_values[i]=p_inputs[i];
}
out_values.resize(in_count);
work_mem.resize(work_mem_size);
for(int i=0;i<work_mem_size;i++) {
work_mem[i]=p_working_mem[i];
}
int ret_out;
Variant ret = node->get_script_instance()->call(VisualScriptLanguage::singleton->_step,in_values,out_values,p_start_mode,work_mem);
if (ret.get_type()==Variant::STRING) {
r_error_str=ret;
r_error.error=Variant::CallError::CALL_ERROR_INVALID_METHOD;
return 0;
} else if (ret.is_num()) {
ret_out=ret;
} else {
r_error_str=RTR("Invalid return value from _step(), must be integer (seq out), or string (error).");
r_error.error=Variant::CallError::CALL_ERROR_INVALID_METHOD;
return 0;
}
for(int i=0;i<out_count;i++) {
if (i<out_values.size()) {
*p_outputs[i]=out_values[i];
}
}
for(int i=0;i<work_mem_size;i++) {
if (i<work_mem.size()) {
p_working_mem[i]=work_mem[i];
}
}
return ret_out;
}
return 0;
}
};
VisualScriptNodeInstance* VisualScriptCustomNode::instance(VisualScriptInstance* p_instance) {
VisualScriptNodeInstanceCustomNode * instance = memnew(VisualScriptNodeInstanceCustomNode );
instance->instance=p_instance;
instance->in_count=get_input_value_port_count();
instance->out_count=get_output_value_port_count();
for(int i=0;i<instance->out_count;i++) {
bool unseq = get_script_instance() && get_script_instance()->has_method("_is_output_port_unsequenced") && bool(get_script_instance()->call("_is_output_port_unsequenced",i));
instance->out_unsequenced.push_back(unseq);
}
if (get_script_instance() && get_script_instance()->has_method("_get_working_memory_size")) {
instance->work_mem_size = get_script_instance()->call("_get_working_memory_size");
} else {
instance->work_mem_size=0;
}
return instance;
}
void VisualScriptCustomNode::_bind_methods() {
BIND_VMETHOD( MethodInfo(Variant::INT,"_get_output_sequence_port_count") );
BIND_VMETHOD( MethodInfo(Variant::BOOL,"_has_input_sequence_port") );
BIND_VMETHOD( MethodInfo(Variant::STRING,"_get_output_sequence_port_text",PropertyInfo(Variant::INT,"idx")) );
BIND_VMETHOD( MethodInfo(Variant::INT,"_get_input_value_port_count") );
BIND_VMETHOD( MethodInfo(Variant::INT,"_get_output_value_port_count") );
BIND_VMETHOD( MethodInfo(Variant::INT,"_get_input_value_port_type",PropertyInfo(Variant::INT,"idx")) );
BIND_VMETHOD( MethodInfo(Variant::STRING,"_get_input_value_port_name",PropertyInfo(Variant::INT,"idx")) );
BIND_VMETHOD( MethodInfo(Variant::INT,"_get_output_value_port_type",PropertyInfo(Variant::INT,"idx")) );
BIND_VMETHOD( MethodInfo(Variant::STRING,"_get_output_value_port_name",PropertyInfo(Variant::INT,"idx")) );
BIND_VMETHOD( MethodInfo(Variant::STRING,"_get_caption") );
BIND_VMETHOD( MethodInfo(Variant::STRING,"_get_text") );
BIND_VMETHOD( MethodInfo(Variant::STRING,"_get_category") );
BIND_VMETHOD( MethodInfo(Variant::INT,"_get_working_memory_size") );
BIND_VMETHOD( MethodInfo(Variant::INT,"_is_output_port_unsequenced",PropertyInfo(Variant::INT,"idx")) );
BIND_VMETHOD( MethodInfo(Variant::INT,"_get_output_port_unsequenced",PropertyInfo(Variant::INT,"idx"),PropertyInfo(Variant::ARRAY,"work_mem")) );
BIND_VMETHOD( MethodInfo(Variant::NIL,"_step:Variant",PropertyInfo(Variant::ARRAY,"inputs"),PropertyInfo(Variant::ARRAY,"outputs"),PropertyInfo(Variant::INT,"start_mode"),PropertyInfo(Variant::ARRAY,"working_mem")) );
BIND_CONSTANT( START_MODE_BEGIN_SEQUENCE );
BIND_CONSTANT( START_MODE_CONTINUE_SEQUENCE );
BIND_CONSTANT( START_MODE_RESUME_YIELD );
BIND_CONSTANT( STEP_PUSH_STACK_BIT );
BIND_CONSTANT( STEP_GO_BACK_BIT );
BIND_CONSTANT( STEP_NO_ADVANCE_BIT );
BIND_CONSTANT( STEP_EXIT_FUNCTION_BIT );
BIND_CONSTANT( STEP_YIELD_BIT );
}
VisualScriptCustomNode::VisualScriptCustomNode() {
}
//////////////////////////////////////////
////////////////SUBCALL///////////
//////////////////////////////////////////
int VisualScriptSubCall::get_output_sequence_port_count() const {
return 1;
}
bool VisualScriptSubCall::has_input_sequence_port() const{
return true;
}
int VisualScriptSubCall::get_input_value_port_count() const{
Ref<Script> script = get_script();
if (script.is_valid() && script->has_method(VisualScriptLanguage::singleton->_subcall)) {
MethodInfo mi = script->get_method_info(VisualScriptLanguage::singleton->_subcall);
return mi.arguments.size();
}
return 0;
}
int VisualScriptSubCall::get_output_value_port_count() const{
return 1;
}
String VisualScriptSubCall::get_output_sequence_port_text(int p_port) const {
return String();
}
PropertyInfo VisualScriptSubCall::get_input_value_port_info(int p_idx) const{
Ref<Script> script = get_script();
if (script.is_valid() && script->has_method(VisualScriptLanguage::singleton->_subcall)) {
MethodInfo mi = script->get_method_info(VisualScriptLanguage::singleton->_subcall);
return mi.arguments[p_idx];
}
return PropertyInfo();
}
PropertyInfo VisualScriptSubCall::get_output_value_port_info(int p_idx) const{
Ref<Script> script = get_script();
if (script.is_valid() && script->has_method(VisualScriptLanguage::singleton->_subcall)) {
MethodInfo mi = script->get_method_info(VisualScriptLanguage::singleton->_subcall);
return mi.return_val;
}
return PropertyInfo();
}
String VisualScriptSubCall::get_caption() const {
return "SubCall";
}
String VisualScriptSubCall::get_text() const {
return "";
}
String VisualScriptSubCall::get_category() const {
return "custom";
}
class VisualScriptNodeInstanceSubCall : public VisualScriptNodeInstance {
public:
VisualScriptInstance* instance;
VisualScriptSubCall *subcall;
int input_args;
bool valid;
//virtual int get_working_memory_size() const { return 0; }
//virtual bool is_output_port_unsequenced(int p_idx) const { return false; }
//virtual bool get_output_port_unsequenced(int p_idx,Variant* r_value,Variant* p_working_mem,String &r_error) const { return false; };
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 (!valid) {
r_error_str="Node requires a script with a _subcall(<args>) method to work.";
r_error.error=Variant::CallError::CALL_ERROR_INVALID_METHOD;
return 0;
}
*p_outputs[0]=subcall->call(VisualScriptLanguage::singleton->_subcall,p_inputs,input_args,r_error_str);
return 0;
}
};
VisualScriptNodeInstance* VisualScriptSubCall::instance(VisualScriptInstance* p_instance) {
VisualScriptNodeInstanceSubCall * instance = memnew(VisualScriptNodeInstanceSubCall );
instance->instance=p_instance;
Ref<Script> script = get_script();
if (script.is_valid() && script->has_method(VisualScriptLanguage::singleton->_subcall)) {
instance->valid=true;
instance->input_args=get_input_value_port_count();
} else {
instance->valid=false;
}
return instance;
}
void VisualScriptSubCall::_bind_methods() {
BIND_VMETHOD( MethodInfo(Variant::NIL,"_subcall",PropertyInfo(Variant::NIL,"arguments:Variant")) );
}
VisualScriptSubCall::VisualScriptSubCall() {
}
void register_visual_script_nodes() {
VisualScriptLanguage::singleton->add_register_func("data/set_variable",create_node_generic<VisualScriptVariableGet>);
VisualScriptLanguage::singleton->add_register_func("data/get_variable",create_node_generic<VisualScriptVariableSet>);
VisualScriptLanguage::singleton->add_register_func("data/constant",create_node_generic<VisualScriptConstant>);
VisualScriptLanguage::singleton->add_register_func("data/global_constant",create_node_generic<VisualScriptGlobalConstant>);
VisualScriptLanguage::singleton->add_register_func("data/math_constant",create_node_generic<VisualScriptMathConstant>);
VisualScriptLanguage::singleton->add_register_func("data/engine_singleton",create_node_generic<VisualScriptEngineSingleton>);
VisualScriptLanguage::singleton->add_register_func("data/scene_node",create_node_generic<VisualScriptSceneNode>);
VisualScriptLanguage::singleton->add_register_func("data/scene_tree",create_node_generic<VisualScriptSceneTree>);
VisualScriptLanguage::singleton->add_register_func("data/resource_path",create_node_generic<VisualScriptResourcePath>);
VisualScriptLanguage::singleton->add_register_func("data/self",create_node_generic<VisualScriptSelf>);
VisualScriptLanguage::singleton->add_register_func("custom/custom_node",create_node_generic<VisualScriptCustomNode>);
VisualScriptLanguage::singleton->add_register_func("custom/sub_call",create_node_generic<VisualScriptSubCall>);
VisualScriptLanguage::singleton->add_register_func("index/get_index",create_node_generic<VisualScriptIndexGet>);
VisualScriptLanguage::singleton->add_register_func("index/set_index",create_node_generic<VisualScriptIndexSet>);
VisualScriptLanguage::singleton->add_register_func("operators/compare/equal",create_op_node<Variant::OP_EQUAL>);
VisualScriptLanguage::singleton->add_register_func("operators/compare/not_equal",create_op_node<Variant::OP_NOT_EQUAL>);
VisualScriptLanguage::singleton->add_register_func("operators/compare/less",create_op_node<Variant::OP_LESS>);
VisualScriptLanguage::singleton->add_register_func("operators/compare/less_equal",create_op_node<Variant::OP_LESS_EQUAL>);
VisualScriptLanguage::singleton->add_register_func("operators/compare/greater",create_op_node<Variant::OP_GREATER>);
VisualScriptLanguage::singleton->add_register_func("operators/compare/greater_equal",create_op_node<Variant::OP_GREATER_EQUAL>);
//mathematic
VisualScriptLanguage::singleton->add_register_func("operators/math/add",create_op_node<Variant::OP_ADD>);
VisualScriptLanguage::singleton->add_register_func("operators/math/subtract",create_op_node<Variant::OP_SUBSTRACT>);
VisualScriptLanguage::singleton->add_register_func("operators/math/multiply",create_op_node<Variant::OP_MULTIPLY>);
VisualScriptLanguage::singleton->add_register_func("operators/math/divide",create_op_node<Variant::OP_DIVIDE>);
VisualScriptLanguage::singleton->add_register_func("operators/math/negate",create_op_node<Variant::OP_NEGATE>);
VisualScriptLanguage::singleton->add_register_func("operators/math/remainder",create_op_node<Variant::OP_MODULE>);
VisualScriptLanguage::singleton->add_register_func("operators/math/string_concat",create_op_node<Variant::OP_STRING_CONCAT>);
//bitwise
VisualScriptLanguage::singleton->add_register_func("operators/bitwise/shift_left",create_op_node<Variant::OP_SHIFT_LEFT>);
VisualScriptLanguage::singleton->add_register_func("operators/bitwise/shift_right",create_op_node<Variant::OP_SHIFT_RIGHT>);
VisualScriptLanguage::singleton->add_register_func("operators/bitwise/bit_and",create_op_node<Variant::OP_BIT_AND>);
VisualScriptLanguage::singleton->add_register_func("operators/bitwise/bit_or",create_op_node<Variant::OP_BIT_OR>);
VisualScriptLanguage::singleton->add_register_func("operators/bitwise/bit_xor",create_op_node<Variant::OP_BIT_XOR>);
VisualScriptLanguage::singleton->add_register_func("operators/bitwise/bit_negate",create_op_node<Variant::OP_BIT_NEGATE>);
//logic
VisualScriptLanguage::singleton->add_register_func("operators/logic/and",create_op_node<Variant::OP_AND>);
VisualScriptLanguage::singleton->add_register_func("operators/logic/or",create_op_node<Variant::OP_OR>);
VisualScriptLanguage::singleton->add_register_func("operators/logic/xor",create_op_node<Variant::OP_XOR>);
VisualScriptLanguage::singleton->add_register_func("operators/logic/not",create_op_node<Variant::OP_NOT>);
VisualScriptLanguage::singleton->add_register_func("operators/logic/in",create_op_node<Variant::OP_IN>);
}