godot/modules/visual_script/visual_script_nodes.cpp
reduz 455c06ecd4 Implement Vector4, Vector4i, Projection
Implement built-in classes Vector4, Vector4i and Projection.

* Two versions of Vector4 (float and integer).
* A Projection class, which is a 4x4 matrix specialized in projection types.

These types have been requested for a long time, but given they were very corner case they were not added before.
Because in Godot 4, reimplementing parts of the rendering engine is now possible, access to these types (heavily used by the rendering code) becomes a necessity.

**Q**: Why Projection and not Matrix4?
**A**: Godot does not use Matrix2, Matrix3, Matrix4x3, etc. naming convention because, within the engine, these types always have a *purpose*. As such, Godot names them: Transform2D, Transform3D or Basis. In this case, this 4x4 matrix is _always_ used as a _Projection_, hence the naming.
2022-07-23 14:00:01 +02:00

4073 lines
118 KiB
C++

/*************************************************************************/
/* visual_script_nodes.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "visual_script_nodes.h"
#include "core/config/engine.h"
#include "core/config/project_settings.h"
#include "core/core_constants.h"
#include "core/input/input.h"
#include "core/os/os.h"
#include "scene/main/node.h"
#include "scene/main/scene_tree.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.write[i].name = "arg" + itos(i + 1);
arguments.write[i].type = Variant::NIL;
}
ports_changed_notify();
notify_property_list_changed();
return true;
}
if (String(p_name).begins_with("argument_")) {
int idx = String(p_name).get_slicec('_', 1).get_slicec('/', 0).to_int() - 1;
ERR_FAIL_INDEX_V(idx, arguments.size(), false);
String what = String(p_name).get_slice("/", 1);
if (what == "type") {
Variant::Type new_type = Variant::Type(int(p_value));
arguments.write[idx].type = new_type;
ports_changed_notify();
return true;
}
if (what == "name") {
arguments.write[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;
}
if (p_name == "rpc/mode") {
rpc_mode = Multiplayer::RPCMode(int(p_value));
return true;
}
if (p_name == "sequenced/sequenced") {
sequenced = p_value;
ports_changed_notify();
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_slicec('_', 1).get_slicec('/', 0).to_int() - 1;
ERR_FAIL_INDEX_V(idx, arguments.size(), false);
String what = String(p_name).get_slice("/", 1);
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;
}
if (p_name == "rpc/mode") {
r_ret = rpc_mode;
return true;
}
if (p_name == "sequenced/sequenced") {
r_ret = sequenced;
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 = "Any";
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"));
}
p_list->push_back(PropertyInfo(Variant::BOOL, "sequenced/sequenced"));
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"));
p_list->push_back(PropertyInfo(Variant::INT, "rpc/mode", PROPERTY_HINT_ENUM, "Disabled,Any,Authority"));
}
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());
}
PropertyInfo VisualScriptFunction::get_output_value_port_info(int p_idx) const {
// Need to check it without ERR_FAIL_COND, to prevent warnings from appearing on node creation via dragging.
if (p_idx < 0 || p_idx >= arguments.size()) {
return PropertyInfo();
}
PropertyInfo out;
out.type = arguments[p_idx].type;
out.name = arguments[p_idx].name;
out.hint = arguments[p_idx].hint;
out.hint_string = arguments[p_idx].hint_string;
return out;
}
String VisualScriptFunction::get_caption() const {
return RTR("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, const PropertyHint p_hint, const String &p_hint_string) {
Argument arg;
arg.name = p_name;
arg.type = p_type;
arg.hint = p_hint;
arg.hint_string = p_hint_string;
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.write[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.write[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_at(p_argidx);
ports_changed_notify();
}
int VisualScriptFunction::get_argument_count() const {
return arguments.size();
}
void VisualScriptFunction::set_rpc_mode(Multiplayer::RPCMode p_mode) {
rpc_mode = p_mode;
}
Multiplayer::RPCMode VisualScriptFunction::get_rpc_mode() const {
return rpc_mode;
}
class VisualScriptNodeInstanceFunction : public VisualScriptNodeInstance {
public:
VisualScriptFunction *node = nullptr;
VisualScriptInstance *instance = nullptr;
//virtual int get_working_memory_size() const override { return 0; }
virtual int step(const Variant **p_inputs, Variant **p_outputs, StartMode p_start_mode, Variant *p_working_mem, Callable::CallError &r_error, String &r_error_str) override {
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 = Callable::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::instantiate(VisualScriptInstance *p_instance) {
VisualScriptNodeInstanceFunction *instance = memnew(VisualScriptNodeInstanceFunction);
instance->node = this;
instance->instance = p_instance;
return instance;
}
void VisualScriptFunction::reset_state() {
arguments.clear();
stack_size = 256;
stack_less = false;
sequenced = true;
rpc_mode = Multiplayer::RPC_MODE_DISABLED;
}
VisualScriptFunction::VisualScriptFunction() {
stack_size = 256;
stack_less = false;
sequenced = true;
rpc_mode = Multiplayer::RPC_MODE_DISABLED;
}
void VisualScriptFunction::set_stack_less(bool p_enable) {
stack_less = p_enable;
notify_property_list_changed();
}
bool VisualScriptFunction::is_stack_less() const {
return stack_less;
}
void VisualScriptFunction::set_sequenced(bool p_enable) {
sequenced = p_enable;
}
bool VisualScriptFunction::is_sequenced() const {
return sequenced;
}
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;
}
//////////////////////////////////////////
/////////////////LISTS////////////////////
//////////////////////////////////////////
int VisualScriptLists::get_output_sequence_port_count() const {
if (sequenced) {
return 1;
}
return 0;
}
bool VisualScriptLists::has_input_sequence_port() const {
return sequenced;
}
String VisualScriptLists::get_output_sequence_port_text(int p_port) const {
return "";
}
int VisualScriptLists::get_input_value_port_count() const {
return inputports.size();
}
int VisualScriptLists::get_output_value_port_count() const {
return outputports.size();
}
PropertyInfo VisualScriptLists::get_input_value_port_info(int p_idx) const {
ERR_FAIL_INDEX_V(p_idx, inputports.size(), PropertyInfo());
PropertyInfo pi;
pi.name = inputports[p_idx].name;
pi.type = inputports[p_idx].type;
return pi;
}
PropertyInfo VisualScriptLists::get_output_value_port_info(int p_idx) const {
ERR_FAIL_INDEX_V(p_idx, outputports.size(), PropertyInfo());
PropertyInfo pi;
pi.name = outputports[p_idx].name;
pi.type = outputports[p_idx].type;
return pi;
}
bool VisualScriptLists::is_input_port_editable() const {
return ((flags & INPUT_EDITABLE) == INPUT_EDITABLE);
}
bool VisualScriptLists::is_input_port_name_editable() const {
return ((flags & INPUT_NAME_EDITABLE) == INPUT_NAME_EDITABLE);
}
bool VisualScriptLists::is_input_port_type_editable() const {
return ((flags & INPUT_TYPE_EDITABLE) == INPUT_TYPE_EDITABLE);
}
bool VisualScriptLists::is_output_port_editable() const {
return ((flags & OUTPUT_EDITABLE) == OUTPUT_EDITABLE);
}
bool VisualScriptLists::is_output_port_name_editable() const {
return ((flags & INPUT_NAME_EDITABLE) == INPUT_NAME_EDITABLE);
}
bool VisualScriptLists::is_output_port_type_editable() const {
return ((flags & INPUT_TYPE_EDITABLE) == INPUT_TYPE_EDITABLE);
}
// for the inspector
bool VisualScriptLists::_set(const StringName &p_name, const Variant &p_value) {
if (p_name == "input_count" && is_input_port_editable()) {
int new_argc = p_value;
int argc = inputports.size();
if (argc == new_argc) {
return true;
}
inputports.resize(new_argc);
for (int i = argc; i < new_argc; i++) {
inputports.write[i].name = "arg" + itos(i + 1);
inputports.write[i].type = Variant::NIL;
}
ports_changed_notify();
notify_property_list_changed();
return true;
}
if (String(p_name).begins_with("input_") && is_input_port_editable()) {
int idx = String(p_name).get_slicec('_', 1).get_slicec('/', 0).to_int() - 1;
ERR_FAIL_INDEX_V(idx, inputports.size(), false);
String what = String(p_name).get_slice("/", 1);
if (what == "type") {
Variant::Type new_type = Variant::Type(int(p_value));
inputports.write[idx].type = new_type;
ports_changed_notify();
return true;
}
if (what == "name") {
inputports.write[idx].name = p_value;
ports_changed_notify();
return true;
}
}
if (p_name == "output_count" && is_output_port_editable()) {
int new_argc = p_value;
int argc = outputports.size();
if (argc == new_argc) {
return true;
}
outputports.resize(new_argc);
for (int i = argc; i < new_argc; i++) {
outputports.write[i].name = "arg" + itos(i + 1);
outputports.write[i].type = Variant::NIL;
}
ports_changed_notify();
notify_property_list_changed();
return true;
}
if (String(p_name).begins_with("output_") && is_output_port_editable()) {
int idx = String(p_name).get_slicec('_', 1).get_slicec('/', 0).to_int() - 1;
ERR_FAIL_INDEX_V(idx, outputports.size(), false);
String what = String(p_name).get_slice("/", 1);
if (what == "type") {
Variant::Type new_type = Variant::Type(int(p_value));
outputports.write[idx].type = new_type;
ports_changed_notify();
return true;
}
if (what == "name") {
outputports.write[idx].name = p_value;
ports_changed_notify();
return true;
}
}
if (p_name == "sequenced/sequenced") {
sequenced = p_value;
ports_changed_notify();
return true;
}
return false;
}
bool VisualScriptLists::_get(const StringName &p_name, Variant &r_ret) const {
if (p_name == "input_count" && is_input_port_editable()) {
r_ret = inputports.size();
return true;
}
if (String(p_name).begins_with("input_") && is_input_port_editable()) {
int idx = String(p_name).get_slicec('_', 1).get_slicec('/', 0).to_int() - 1;
ERR_FAIL_INDEX_V(idx, inputports.size(), false);
String what = String(p_name).get_slice("/", 1);
if (what == "type") {
r_ret = inputports[idx].type;
return true;
}
if (what == "name") {
r_ret = inputports[idx].name;
return true;
}
}
if (p_name == "output_count" && is_output_port_editable()) {
r_ret = outputports.size();
return true;
}
if (String(p_name).begins_with("output_") && is_output_port_editable()) {
int idx = String(p_name).get_slicec('_', 1).get_slicec('/', 0).to_int() - 1;
ERR_FAIL_INDEX_V(idx, outputports.size(), false);
String what = String(p_name).get_slice("/", 1);
if (what == "type") {
r_ret = outputports[idx].type;
return true;
}
if (what == "name") {
r_ret = outputports[idx].name;
return true;
}
}
if (p_name == "sequenced/sequenced") {
r_ret = sequenced;
return true;
}
return false;
}
void VisualScriptLists::_get_property_list(List<PropertyInfo> *p_list) const {
if (is_input_port_editable()) {
p_list->push_back(PropertyInfo(Variant::INT, "input_count", PROPERTY_HINT_RANGE, "0,256"));
String argt = "Any";
for (int i = 1; i < Variant::VARIANT_MAX; i++) {
argt += "," + Variant::get_type_name(Variant::Type(i));
}
for (int i = 0; i < inputports.size(); i++) {
p_list->push_back(PropertyInfo(Variant::INT, "input_" + itos(i + 1) + "/type", PROPERTY_HINT_ENUM, argt));
p_list->push_back(PropertyInfo(Variant::STRING, "input_" + itos(i + 1) + "/name"));
}
}
if (is_output_port_editable()) {
p_list->push_back(PropertyInfo(Variant::INT, "output_count", PROPERTY_HINT_RANGE, "0,256"));
String argt = "Any";
for (int i = 1; i < Variant::VARIANT_MAX; i++) {
argt += "," + Variant::get_type_name(Variant::Type(i));
}
for (int i = 0; i < outputports.size(); i++) {
p_list->push_back(PropertyInfo(Variant::INT, "output_" + itos(i + 1) + "/type", PROPERTY_HINT_ENUM, argt));
p_list->push_back(PropertyInfo(Variant::STRING, "output_" + itos(i + 1) + "/name"));
}
}
p_list->push_back(PropertyInfo(Variant::BOOL, "sequenced/sequenced"));
}
// input data port interaction
void VisualScriptLists::add_input_data_port(Variant::Type p_type, const String &p_name, int p_index) {
if (!is_input_port_editable()) {
return;
}
Port inp;
inp.name = p_name;
inp.type = p_type;
if (p_index >= 0) {
inputports.insert(p_index, inp);
} else {
inputports.push_back(inp);
}
ports_changed_notify();
notify_property_list_changed();
}
void VisualScriptLists::set_input_data_port_type(int p_idx, Variant::Type p_type) {
if (!is_input_port_type_editable()) {
return;
}
ERR_FAIL_INDEX(p_idx, inputports.size());
inputports.write[p_idx].type = p_type;
ports_changed_notify();
notify_property_list_changed();
}
void VisualScriptLists::set_input_data_port_name(int p_idx, const String &p_name) {
if (!is_input_port_name_editable()) {
return;
}
ERR_FAIL_INDEX(p_idx, inputports.size());
inputports.write[p_idx].name = p_name;
ports_changed_notify();
notify_property_list_changed();
}
void VisualScriptLists::remove_input_data_port(int p_argidx) {
if (!is_input_port_editable()) {
return;
}
ERR_FAIL_INDEX(p_argidx, inputports.size());
inputports.remove_at(p_argidx);
ports_changed_notify();
notify_property_list_changed();
}
// output data port interaction
void VisualScriptLists::add_output_data_port(Variant::Type p_type, const String &p_name, int p_index) {
if (!is_output_port_editable()) {
return;
}
Port out;
out.name = p_name;
out.type = p_type;
if (p_index >= 0) {
outputports.insert(p_index, out);
} else {
outputports.push_back(out);
}
ports_changed_notify();
notify_property_list_changed();
}
void VisualScriptLists::set_output_data_port_type(int p_idx, Variant::Type p_type) {
if (!is_output_port_type_editable()) {
return;
}
ERR_FAIL_INDEX(p_idx, outputports.size());
outputports.write[p_idx].type = p_type;
ports_changed_notify();
notify_property_list_changed();
}
void VisualScriptLists::set_output_data_port_name(int p_idx, const String &p_name) {
if (!is_output_port_name_editable()) {
return;
}
ERR_FAIL_INDEX(p_idx, outputports.size());
outputports.write[p_idx].name = p_name;
ports_changed_notify();
notify_property_list_changed();
}
void VisualScriptLists::remove_output_data_port(int p_argidx) {
if (!is_output_port_editable()) {
return;
}
ERR_FAIL_INDEX(p_argidx, outputports.size());
outputports.remove_at(p_argidx);
ports_changed_notify();
notify_property_list_changed();
}
// sequences
void VisualScriptLists::set_sequenced(bool p_enable) {
if (sequenced == p_enable) {
return;
}
sequenced = p_enable;
ports_changed_notify();
}
bool VisualScriptLists::is_sequenced() const {
return sequenced;
}
void VisualScriptLists::reset_state() {
inputports.clear();
outputports.clear();
sequenced = false;
flags = 0;
}
VisualScriptLists::VisualScriptLists() {
// initialize
sequenced = false;
flags = 0;
}
void VisualScriptLists::_bind_methods() {
ClassDB::bind_method(D_METHOD("add_input_data_port", "type", "name", "index"), &VisualScriptLists::add_input_data_port);
ClassDB::bind_method(D_METHOD("set_input_data_port_name", "index", "name"), &VisualScriptLists::set_input_data_port_name);
ClassDB::bind_method(D_METHOD("set_input_data_port_type", "index", "type"), &VisualScriptLists::set_input_data_port_type);
ClassDB::bind_method(D_METHOD("remove_input_data_port", "index"), &VisualScriptLists::remove_input_data_port);
ClassDB::bind_method(D_METHOD("add_output_data_port", "type", "name", "index"), &VisualScriptLists::add_output_data_port);
ClassDB::bind_method(D_METHOD("set_output_data_port_name", "index", "name"), &VisualScriptLists::set_output_data_port_name);
ClassDB::bind_method(D_METHOD("set_output_data_port_type", "index", "type"), &VisualScriptLists::set_output_data_port_type);
ClassDB::bind_method(D_METHOD("remove_output_data_port", "index"), &VisualScriptLists::remove_output_data_port);
}
//////////////////////////////////////////
//////////////COMPOSEARRAY////////////////
//////////////////////////////////////////
int VisualScriptComposeArray::get_output_sequence_port_count() const {
if (sequenced) {
return 1;
}
return 0;
}
bool VisualScriptComposeArray::has_input_sequence_port() const {
return sequenced;
}
String VisualScriptComposeArray::get_output_sequence_port_text(int p_port) const {
return "";
}
int VisualScriptComposeArray::get_input_value_port_count() const {
return inputports.size();
}
int VisualScriptComposeArray::get_output_value_port_count() const {
return 1;
}
PropertyInfo VisualScriptComposeArray::get_input_value_port_info(int p_idx) const {
ERR_FAIL_INDEX_V(p_idx, inputports.size(), PropertyInfo());
PropertyInfo pi;
pi.name = inputports[p_idx].name;
pi.type = inputports[p_idx].type;
return pi;
}
PropertyInfo VisualScriptComposeArray::get_output_value_port_info(int p_idx) const {
PropertyInfo pi;
pi.name = "out";
pi.type = Variant::ARRAY;
return pi;
}
String VisualScriptComposeArray::get_caption() const {
return RTR("Compose Array");
}
String VisualScriptComposeArray::get_text() const {
return "";
}
class VisualScriptComposeArrayNode : public VisualScriptNodeInstance {
public:
int input_count = 0;
virtual int get_working_memory_size() const override { return 0; }
virtual int step(const Variant **p_inputs, Variant **p_outputs, StartMode p_start_mode, Variant *p_working_mem, Callable::CallError &r_error, String &r_error_str) override {
if (input_count > 0) {
Array arr;
for (int i = 0; i < input_count; i++) {
arr.push_back((*p_inputs[i]));
}
Variant va = Variant(arr);
*p_outputs[0] = va;
}
return 0;
}
};
VisualScriptNodeInstance *VisualScriptComposeArray::instantiate(VisualScriptInstance *p_instance) {
VisualScriptComposeArrayNode *instance = memnew(VisualScriptComposeArrayNode);
instance->input_count = inputports.size();
return instance;
}
VisualScriptComposeArray::VisualScriptComposeArray() {
// initialize stuff here
sequenced = false;
flags = INPUT_EDITABLE;
}
//////////////////////////////////////////
////////////////OPERATOR//////////////////
//////////////////////////////////////////
int VisualScriptOperator::get_output_sequence_port_count() const {
return 0;
}
bool VisualScriptOperator::has_input_sequence_port() const {
return false;
}
int VisualScriptOperator::get_input_value_port_count() const {
return (op == Variant::OP_BIT_NEGATE || op == Variant::OP_NOT || op == Variant::OP_NEGATE || op == Variant::OP_POSITIVE) ? 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_SUBTRACT,
{ Variant::NIL, Variant::NIL }, //OP_MULTIPLY,
{ Variant::NIL, Variant::NIL }, //OP_DIVIDE,
{ Variant::NIL, Variant::NIL }, //OP_NEGATE,
{ Variant::NIL, Variant::NIL }, //OP_POSITIVE,
{ Variant::INT, Variant::INT }, //OP_MODULE,
//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, 2, PropertyInfo());
PropertyInfo pinfo;
pinfo.name = p_idx == 0 ? "A" : "B";
pinfo.type = port_types[op][p_idx];
if (pinfo.type == Variant::NIL) {
pinfo.type = typed;
}
return pinfo;
}
PropertyInfo VisualScriptOperator::get_output_value_port_info(int p_idx) const {
static const Variant::Type port_types[Variant::OP_MAX] = {
//comparison
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_SUBTRACT,
Variant::NIL, //OP_MULTIPLY,
Variant::NIL, //OP_DIVIDE,
Variant::NIL, //OP_NEGATE,
Variant::NIL, //OP_POSITIVE,
Variant::INT, //OP_MODULE,
//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];
if (pinfo.type == Variant::NIL) {
pinfo.type = typed;
}
return pinfo;
}
String VisualScriptOperator::get_caption() const {
switch (op) {
// comparison
case Variant::OP_EQUAL:
return U"A = B";
case Variant::OP_NOT_EQUAL:
return U"A \u2260 B";
case Variant::OP_LESS:
return U"A < B";
case Variant::OP_LESS_EQUAL:
return U"A \u2264 B";
case Variant::OP_GREATER:
return U"A > B";
case Variant::OP_GREATER_EQUAL:
return U"A \u2265 B";
// mathematic
case Variant::OP_ADD:
return U"A + B";
case Variant::OP_SUBTRACT:
return U"A - B";
case Variant::OP_MULTIPLY:
return U"A \u00D7 B";
case Variant::OP_DIVIDE:
return U"A \u00F7 B";
case Variant::OP_NEGATE:
return U"\u00AC A";
case Variant::OP_POSITIVE:
return U"+ A";
case Variant::OP_MODULE:
return U"A mod B";
// bitwise
case Variant::OP_SHIFT_LEFT:
return U"A << B";
case Variant::OP_SHIFT_RIGHT:
return U"A >> B";
case Variant::OP_BIT_AND:
return U"A & B";
case Variant::OP_BIT_OR:
return U"A | B";
case Variant::OP_BIT_XOR:
return U"A ^ B";
case Variant::OP_BIT_NEGATE:
return U"~A";
// logic
case Variant::OP_AND:
return U"A and B";
case Variant::OP_OR:
return U"A or B";
case Variant::OP_XOR:
return U"A xor B";
case Variant::OP_NOT:
return U"not A";
case Variant::OP_IN:
return U"A in B";
default: {
ERR_FAIL_V_MSG(
U"Unknown node",
U"Unknown node type encountered, caption not available.");
}
}
}
String VisualScriptOperator::get_operator_name(Variant::Operator p_op) {
switch (p_op) {
// comparison
case Variant::OP_EQUAL:
return "Are Equal";
case Variant::OP_NOT_EQUAL:
return "Are Not Equal";
case Variant::OP_LESS:
return "Less Than";
case Variant::OP_LESS_EQUAL:
return "Less Than or Equal";
case Variant::OP_GREATER:
return "Greater Than";
case Variant::OP_GREATER_EQUAL:
return "Greater Than or Equal";
// mathematic
case Variant::OP_ADD:
return "Add";
case Variant::OP_SUBTRACT:
return "Subtract";
case Variant::OP_MULTIPLY:
return "Multiply";
case Variant::OP_DIVIDE:
return "Divide";
case Variant::OP_NEGATE:
return "Negate";
case Variant::OP_POSITIVE:
return "Positive";
case Variant::OP_MODULE:
return "Remainder";
// bitwise
case Variant::OP_SHIFT_LEFT:
return "Bit Shift Left";
case Variant::OP_SHIFT_RIGHT:
return "Bit Shift Right";
case Variant::OP_BIT_AND:
return "Bit And";
case Variant::OP_BIT_OR:
return "Bit Or";
case Variant::OP_BIT_XOR:
return "Bit Xor";
case Variant::OP_BIT_NEGATE:
return "Bit Negate";
// logic
case Variant::OP_AND:
return "And";
case Variant::OP_OR:
return "Or";
case Variant::OP_XOR:
return "Xor";
case Variant::OP_NOT:
return "Not";
case Variant::OP_IN:
return "In";
default: {
ERR_FAIL_INDEX_V(p_op, Variant::OP_MAX, "");
return "Unknown Operator";
}
}
}
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::set_typed(Variant::Type p_op) {
if (typed == p_op) {
return;
}
typed = p_op;
ports_changed_notify();
}
Variant::Type VisualScriptOperator::get_typed() const {
return typed;
}
void VisualScriptOperator::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_operator", "op"), &VisualScriptOperator::set_operator);
ClassDB::bind_method(D_METHOD("get_operator"), &VisualScriptOperator::get_operator);
ClassDB::bind_method(D_METHOD("set_typed", "type"), &VisualScriptOperator::set_typed);
ClassDB::bind_method(D_METHOD("get_typed"), &VisualScriptOperator::get_typed);
String types;
for (int i = 0; i < Variant::OP_MAX; i++) {
if (i > 0) {
types += ",";
}
types += get_operator_name(static_cast<Variant::Operator>(i));
}
String argt = "Any";
for (int i = 1; i < Variant::VARIANT_MAX; i++) {
argt += "," + Variant::get_type_name(Variant::Type(i));
}
ADD_PROPERTY(PropertyInfo(Variant::INT, "operator", PROPERTY_HINT_ENUM, types), "set_operator", "get_operator");
ADD_PROPERTY(PropertyInfo(Variant::INT, "type", PROPERTY_HINT_ENUM, argt), "set_typed", "get_typed");
}
class VisualScriptNodeInstanceOperator : public VisualScriptNodeInstance {
public:
bool unary = false;
Variant::Operator op;
//virtual int get_working_memory_size() const override { return 0; }
virtual int step(const Variant **p_inputs, Variant **p_outputs, StartMode p_start_mode, Variant *p_working_mem, Callable::CallError &r_error, String &r_error_str) override {
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 = Callable::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(Variant::get_operator_name(op)) + ": " + RTR("Invalid argument of type:") + " " + Variant::get_type_name(p_inputs[0]->get_type());
} else {
r_error_str = String(Variant::get_operator_name(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::instantiate(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;
typed = Variant::NIL;
}
template <Variant::Operator OP>
static Ref<VisualScriptNode> create_op_node(const String &p_name) {
Ref<VisualScriptOperator> node;
node.instantiate();
node->set_operator(OP);
return node;
}
//////////////////////////////////////////
////////////////OPERATOR//////////////////
//////////////////////////////////////////
int VisualScriptSelect::get_output_sequence_port_count() const {
return 0;
}
bool VisualScriptSelect::has_input_sequence_port() const {
return false;
}
int VisualScriptSelect::get_input_value_port_count() const {
return 3;
}
int VisualScriptSelect::get_output_value_port_count() const {
return 1;
}
String VisualScriptSelect::get_output_sequence_port_text(int p_port) const {
return String();
}
PropertyInfo VisualScriptSelect::get_input_value_port_info(int p_idx) const {
if (p_idx == 0) {
return PropertyInfo(Variant::BOOL, "cond");
} else if (p_idx == 1) {
return PropertyInfo(typed, "a");
} else {
return PropertyInfo(typed, "b");
}
}
PropertyInfo VisualScriptSelect::get_output_value_port_info(int p_idx) const {
return PropertyInfo(typed, "out");
}
String VisualScriptSelect::get_caption() const {
return RTR("Select");
}
String VisualScriptSelect::get_text() const {
return RTR("a if cond, else b");
}
void VisualScriptSelect::set_typed(Variant::Type p_op) {
if (typed == p_op) {
return;
}
typed = p_op;
ports_changed_notify();
}
Variant::Type VisualScriptSelect::get_typed() const {
return typed;
}
void VisualScriptSelect::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_typed", "type"), &VisualScriptSelect::set_typed);
ClassDB::bind_method(D_METHOD("get_typed"), &VisualScriptSelect::get_typed);
String argt = "Any";
for (int i = 1; i < Variant::VARIANT_MAX; i++) {
argt += "," + Variant::get_type_name(Variant::Type(i));
}
ADD_PROPERTY(PropertyInfo(Variant::INT, "type", PROPERTY_HINT_ENUM, argt), "set_typed", "get_typed");
}
class VisualScriptNodeInstanceSelect : public VisualScriptNodeInstance {
public:
//virtual int get_working_memory_size() const override { return 0; }
virtual int step(const Variant **p_inputs, Variant **p_outputs, StartMode p_start_mode, Variant *p_working_mem, Callable::CallError &r_error, String &r_error_str) override {
bool cond = *p_inputs[0];
if (cond) {
*p_outputs[0] = *p_inputs[1];
} else {
*p_outputs[0] = *p_inputs[2];
}
return 0;
}
};
VisualScriptNodeInstance *VisualScriptSelect::instantiate(VisualScriptInstance *p_instance) {
VisualScriptNodeInstanceSelect *instance = memnew(VisualScriptNodeInstanceSelect);
return instance;
}
VisualScriptSelect::VisualScriptSelect() {
typed = Variant::NIL;
}
//////////////////////////////////////////
////////////////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 vformat(RTR("Get %s"), 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 == "var_name" && get_visual_script().is_valid()) {
Ref<VisualScript> vs = get_visual_script();
List<StringName> vars;
vs->get_variable_list(&vars);
String vhint;
for (const StringName &E : vars) {
if (!vhint.is_empty()) {
vhint += ",";
}
vhint += E.operator String();
}
property.hint = PROPERTY_HINT_ENUM;
property.hint_string = vhint;
}
}
void VisualScriptVariableGet::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_variable", "name"), &VisualScriptVariableGet::set_variable);
ClassDB::bind_method(D_METHOD("get_variable"), &VisualScriptVariableGet::get_variable);
ADD_PROPERTY(PropertyInfo(Variant::STRING, "var_name"), "set_variable", "get_variable");
}
class VisualScriptNodeInstanceVariableGet : public VisualScriptNodeInstance {
public:
VisualScriptVariableGet *node = nullptr;
VisualScriptInstance *instance = nullptr;
StringName variable;
virtual int step(const Variant **p_inputs, Variant **p_outputs, StartMode p_start_mode, Variant *p_working_mem, Callable::CallError &r_error, String &r_error_str) override {
if (!instance->get_variable(variable, p_outputs[0])) {
r_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD;
r_error_str = RTR("VariableGet not found in script:") + " '" + String(variable) + "'";
return 0;
}
return 0;
}
};
VisualScriptNodeInstance *VisualScriptVariableGet::instantiate(VisualScriptInstance *p_instance) {
VisualScriptNodeInstanceVariableGet *instance = memnew(VisualScriptNodeInstanceVariableGet);
instance->node = this;
instance->instance = p_instance;
instance->variable = variable;
return instance;
}
VisualScriptVariableGet::VisualScriptVariableGet() {
}
//////////////////////////////////////////
////////////////VARIABLE SET//////////////////
//////////////////////////////////////////
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 vformat(RTR("Set %s"), 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 == "var_name" && get_visual_script().is_valid()) {
Ref<VisualScript> vs = get_visual_script();
List<StringName> vars;
vs->get_variable_list(&vars);
String vhint;
for (const StringName &E : vars) {
if (!vhint.is_empty()) {
vhint += ",";
}
vhint += E.operator String();
}
property.hint = PROPERTY_HINT_ENUM;
property.hint_string = vhint;
}
}
void VisualScriptVariableSet::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_variable", "name"), &VisualScriptVariableSet::set_variable);
ClassDB::bind_method(D_METHOD("get_variable"), &VisualScriptVariableSet::get_variable);
ADD_PROPERTY(PropertyInfo(Variant::STRING, "var_name"), "set_variable", "get_variable");
}
class VisualScriptNodeInstanceVariableSet : public VisualScriptNodeInstance {
public:
VisualScriptVariableSet *node = nullptr;
VisualScriptInstance *instance = nullptr;
StringName variable;
//virtual int get_working_memory_size() const override { return 0; }
virtual int step(const Variant **p_inputs, Variant **p_outputs, StartMode p_start_mode, Variant *p_working_mem, Callable::CallError &r_error, String &r_error_str) override {
if (!instance->set_variable(variable, *p_inputs[0])) {
r_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD;
r_error_str = RTR("VariableSet not found in script:") + " '" + String(variable) + "'";
}
return 0;
}
};
VisualScriptNodeInstance *VisualScriptVariableSet::instantiate(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 = String(value);
pinfo.type = type;
return pinfo;
}
String VisualScriptConstant::get_caption() const {
return RTR("Constant");
}
void VisualScriptConstant::set_constant_type(Variant::Type p_type) {
if (type == p_type) {
return;
}
type = p_type;
Callable::CallError ce;
Variant::construct(type, value, nullptr, 0, ce);
ports_changed_notify();
notify_property_list_changed();
}
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 == "value") {
property.type = type;
if (type == Variant::NIL) {
property.usage = PROPERTY_USAGE_NONE; //do not save if nil
}
}
}
void VisualScriptConstant::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_constant_type", "type"), &VisualScriptConstant::set_constant_type);
ClassDB::bind_method(D_METHOD("get_constant_type"), &VisualScriptConstant::get_constant_type);
ClassDB::bind_method(D_METHOD("set_constant_value", "value"), &VisualScriptConstant::set_constant_value);
ClassDB::bind_method(D_METHOD("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, "type", PROPERTY_HINT_ENUM, argt), "set_constant_type", "get_constant_type");
ADD_PROPERTY(PropertyInfo(Variant::NIL, "value", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NIL_IS_VARIANT | PROPERTY_USAGE_DEFAULT), "set_constant_value", "get_constant_value");
}
class VisualScriptNodeInstanceConstant : public VisualScriptNodeInstance {
public:
Variant constant;
//virtual int get_working_memory_size() const override { return 0; }
virtual int step(const Variant **p_inputs, Variant **p_outputs, StartMode p_start_mode, Variant *p_working_mem, Callable::CallError &r_error, String &r_error_str) override {
*p_outputs[0] = constant;
return 0;
}
};
VisualScriptNodeInstance *VisualScriptConstant::instantiate(VisualScriptInstance *p_instance) {
VisualScriptNodeInstanceConstant *instance = memnew(VisualScriptNodeInstanceConstant);
instance->constant = value;
return instance;
}
VisualScriptConstant::VisualScriptConstant() {
type = Variant::NIL;
}
//////////////////////////////////////////
////////////////PRELOAD//////////////////
//////////////////////////////////////////
int VisualScriptPreload::get_output_sequence_port_count() const {
return 0;
}
bool VisualScriptPreload::has_input_sequence_port() const {
return false;
}
int VisualScriptPreload::get_input_value_port_count() const {
return 0;
}
int VisualScriptPreload::get_output_value_port_count() const {
return 1;
}
String VisualScriptPreload::get_output_sequence_port_text(int p_port) const {
return String();
}
PropertyInfo VisualScriptPreload::get_input_value_port_info(int p_idx) const {
return PropertyInfo();
}
PropertyInfo VisualScriptPreload::get_output_value_port_info(int p_idx) const {
PropertyInfo pinfo;
pinfo.type = Variant::OBJECT;
if (preload.is_valid()) {
pinfo.hint = PROPERTY_HINT_RESOURCE_TYPE;
pinfo.hint_string = preload->get_class();
if (preload->get_path().is_resource_file()) {
pinfo.name = preload->get_path();
} else if (!preload->get_name().is_empty()) {
pinfo.name = preload->get_name();
} else {
pinfo.name = preload->get_class();
}
} else {
pinfo.name = "<empty>";
}
return pinfo;
}
String VisualScriptPreload::get_caption() const {
return RTR("Preload");
}
void VisualScriptPreload::set_preload(const Ref<Resource> &p_preload) {
if (preload == p_preload) {
return;
}
preload = p_preload;
ports_changed_notify();
}
Ref<Resource> VisualScriptPreload::get_preload() const {
return preload;
}
void VisualScriptPreload::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_preload", "resource"), &VisualScriptPreload::set_preload);
ClassDB::bind_method(D_METHOD("get_preload"), &VisualScriptPreload::get_preload);
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "resource", PROPERTY_HINT_RESOURCE_TYPE, "Resource"), "set_preload", "get_preload");
}
class VisualScriptNodeInstancePreload : public VisualScriptNodeInstance {
public:
Ref<Resource> preload;
//virtual int get_working_memory_size() const override { return 0; }
virtual int step(const Variant **p_inputs, Variant **p_outputs, StartMode p_start_mode, Variant *p_working_mem, Callable::CallError &r_error, String &r_error_str) override {
*p_outputs[0] = preload;
return 0;
}
};
VisualScriptNodeInstance *VisualScriptPreload::instantiate(VisualScriptInstance *p_instance) {
VisualScriptNodeInstancePreload *instance = memnew(VisualScriptNodeInstancePreload);
instance->preload = preload;
return instance;
}
VisualScriptPreload::VisualScriptPreload() {
}
//////////////////////////////////////////
////////////////INDEX////////////////////
//////////////////////////////////////////
int VisualScriptIndexGet::get_output_sequence_port_count() const {
return 0;
}
bool VisualScriptIndexGet::has_input_sequence_port() const {
return false;
}
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 RTR("Get Index");
}
class VisualScriptNodeInstanceIndexGet : public VisualScriptNodeInstance {
public:
//virtual int get_working_memory_size() const override { return 0; }
virtual int step(const Variant **p_inputs, Variant **p_outputs, StartMode p_start_mode, Variant *p_working_mem, Callable::CallError &r_error, String &r_error_str) override {
bool valid;
*p_outputs[0] = p_inputs[0]->get(*p_inputs[1], &valid);
if (!valid) {
r_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD;
r_error_str = "Invalid get: " + p_inputs[0]->get_construct_string();
}
return 0;
}
};
VisualScriptNodeInstance *VisualScriptIndexGet::instantiate(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 RTR("Set Index");
}
class VisualScriptNodeInstanceIndexSet : public VisualScriptNodeInstance {
public:
//virtual int get_working_memory_size() const override { return 0; }
virtual int step(const Variant **p_inputs, Variant **p_outputs, StartMode p_start_mode, Variant *p_working_mem, Callable::CallError &r_error, String &r_error_str) override {
bool valid;
((Variant *)p_inputs[0])->set(*p_inputs[1], *p_inputs[2], &valid);
if (!valid) {
r_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD;
r_error_str = "Invalid set: " + p_inputs[1]->get_construct_string();
}
return 0;
}
};
VisualScriptNodeInstance *VisualScriptIndexSet::instantiate(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 {
String name = CoreConstants::get_global_constant_name(index);
return PropertyInfo(Variant::INT, name);
}
String VisualScriptGlobalConstant::get_caption() const {
return RTR("Global Constant");
}
void VisualScriptGlobalConstant::set_global_constant(int p_which) {
index = p_which;
notify_property_list_changed();
ports_changed_notify();
}
int VisualScriptGlobalConstant::get_global_constant() {
return index;
}
class VisualScriptNodeInstanceGlobalConstant : public VisualScriptNodeInstance {
public:
int index = 0;
virtual int step(const Variant **p_inputs, Variant **p_outputs, StartMode p_start_mode, Variant *p_working_mem, Callable::CallError &r_error, String &r_error_str) override {
*p_outputs[0] = CoreConstants::get_global_constant_value(index);
return 0;
}
};
VisualScriptNodeInstance *VisualScriptGlobalConstant::instantiate(VisualScriptInstance *p_instance) {
VisualScriptNodeInstanceGlobalConstant *instance = memnew(VisualScriptNodeInstanceGlobalConstant);
instance->index = index;
return instance;
}
void VisualScriptGlobalConstant::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_global_constant", "index"), &VisualScriptGlobalConstant::set_global_constant);
ClassDB::bind_method(D_METHOD("get_global_constant"), &VisualScriptGlobalConstant::get_global_constant);
String cc;
for (int i = 0; i < CoreConstants::get_global_constant_count(); i++) {
if (i > 0) {
cc += ",";
}
cc += CoreConstants::get_global_constant_name(i);
}
ADD_PROPERTY(PropertyInfo(Variant::INT, "constant", PROPERTY_HINT_ENUM, cc), "set_global_constant", "get_global_constant");
}
VisualScriptGlobalConstant::VisualScriptGlobalConstant() {
index = 0;
}
//////////////////////////////////////////
////////////////CLASSCONSTANT///////////
//////////////////////////////////////////
int VisualScriptClassConstant::get_output_sequence_port_count() const {
return 0;
}
bool VisualScriptClassConstant::has_input_sequence_port() const {
return false;
}
int VisualScriptClassConstant::get_input_value_port_count() const {
return 0;
}
int VisualScriptClassConstant::get_output_value_port_count() const {
return 1;
}
String VisualScriptClassConstant::get_output_sequence_port_text(int p_port) const {
return String();
}
PropertyInfo VisualScriptClassConstant::get_input_value_port_info(int p_idx) const {
return PropertyInfo();
}
PropertyInfo VisualScriptClassConstant::get_output_value_port_info(int p_idx) const {
if (name == "") {
return PropertyInfo(Variant::INT, String(base_type));
} else {
return PropertyInfo(Variant::INT, String(base_type) + "." + String(name));
}
}
String VisualScriptClassConstant::get_caption() const {
return RTR("Class Constant");
}
void VisualScriptClassConstant::set_class_constant(const StringName &p_which) {
name = p_which;
notify_property_list_changed();
ports_changed_notify();
}
StringName VisualScriptClassConstant::get_class_constant() {
return name;
}
void VisualScriptClassConstant::set_base_type(const StringName &p_which) {
base_type = p_which;
List<String> constants;
ClassDB::get_integer_constant_list(base_type, &constants, true);
if (constants.size() > 0) {
bool found_name = false;
for (const String &E : constants) {
if (E == name) {
found_name = true;
break;
}
}
if (!found_name) {
name = constants[0];
}
} else {
name = "";
}
notify_property_list_changed();
ports_changed_notify();
}
StringName VisualScriptClassConstant::get_base_type() {
return base_type;
}
class VisualScriptNodeInstanceClassConstant : public VisualScriptNodeInstance {
public:
int value = 0;
bool valid = false;
virtual int step(const Variant **p_inputs, Variant **p_outputs, StartMode p_start_mode, Variant *p_working_mem, Callable::CallError &r_error, String &r_error_str) override {
if (!valid) {
r_error_str = "Invalid constant name, pick a valid class constant.";
r_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD;
}
*p_outputs[0] = value;
return 0;
}
};
VisualScriptNodeInstance *VisualScriptClassConstant::instantiate(VisualScriptInstance *p_instance) {
VisualScriptNodeInstanceClassConstant *instance = memnew(VisualScriptNodeInstanceClassConstant);
instance->value = ClassDB::get_integer_constant(base_type, name, &instance->valid);
return instance;
}
void VisualScriptClassConstant::_validate_property(PropertyInfo &property) const {
if (property.name == "constant") {
List<String> constants;
ClassDB::get_integer_constant_list(base_type, &constants, true);
property.hint_string = "";
for (const String &E : constants) {
if (!property.hint_string.is_empty()) {
property.hint_string += ",";
}
property.hint_string += E;
}
}
}
void VisualScriptClassConstant::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_class_constant", "name"), &VisualScriptClassConstant::set_class_constant);
ClassDB::bind_method(D_METHOD("get_class_constant"), &VisualScriptClassConstant::get_class_constant);
ClassDB::bind_method(D_METHOD("set_base_type", "name"), &VisualScriptClassConstant::set_base_type);
ClassDB::bind_method(D_METHOD("get_base_type"), &VisualScriptClassConstant::get_base_type);
ADD_PROPERTY(PropertyInfo(Variant::STRING, "base_type", PROPERTY_HINT_TYPE_STRING, "Object"), "set_base_type", "get_base_type");
ADD_PROPERTY(PropertyInfo(Variant::STRING, "constant", PROPERTY_HINT_ENUM, ""), "set_class_constant", "get_class_constant");
}
VisualScriptClassConstant::VisualScriptClassConstant() {
base_type = "Object";
}
//////////////////////////////////////////
////////////////BASICTYPECONSTANT///////////
//////////////////////////////////////////
int VisualScriptBasicTypeConstant::get_output_sequence_port_count() const {
return 0;
}
bool VisualScriptBasicTypeConstant::has_input_sequence_port() const {
return false;
}
int VisualScriptBasicTypeConstant::get_input_value_port_count() const {
return 0;
}
int VisualScriptBasicTypeConstant::get_output_value_port_count() const {
return 1;
}
String VisualScriptBasicTypeConstant::get_output_sequence_port_text(int p_port) const {
return String();
}
PropertyInfo VisualScriptBasicTypeConstant::get_input_value_port_info(int p_idx) const {
return PropertyInfo();
}
PropertyInfo VisualScriptBasicTypeConstant::get_output_value_port_info(int p_idx) const {
return PropertyInfo(type, "value");
}
String VisualScriptBasicTypeConstant::get_caption() const {
return RTR("Basic Constant");
}
String VisualScriptBasicTypeConstant::get_text() const {
if (name == "") {
return Variant::get_type_name(type);
} else {
return Variant::get_type_name(type) + "." + String(name);
}
}
void VisualScriptBasicTypeConstant::set_basic_type_constant(const StringName &p_which) {
name = p_which;
notify_property_list_changed();
ports_changed_notify();
}
StringName VisualScriptBasicTypeConstant::get_basic_type_constant() const {
return name;
}
void VisualScriptBasicTypeConstant::set_basic_type(Variant::Type p_which) {
type = p_which;
List<StringName> constants;
Variant::get_constants_for_type(type, &constants);
if (constants.size() > 0) {
bool found_name = false;
for (const StringName &E : constants) {
if (E == name) {
found_name = true;
break;
}
}
if (!found_name) {
name = constants[0];
}
} else {
name = "";
}
notify_property_list_changed();
ports_changed_notify();
}
Variant::Type VisualScriptBasicTypeConstant::get_basic_type() const {
return type;
}
class VisualScriptNodeInstanceBasicTypeConstant : public VisualScriptNodeInstance {
public:
Variant value;
bool valid = false;
virtual int step(const Variant **p_inputs, Variant **p_outputs, StartMode p_start_mode, Variant *p_working_mem, Callable::CallError &r_error, String &r_error_str) override {
if (!valid) {
r_error_str = "Invalid constant name, pick a valid basic type constant.";
r_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD;
}
*p_outputs[0] = value;
return 0;
}
};
VisualScriptNodeInstance *VisualScriptBasicTypeConstant::instantiate(VisualScriptInstance *p_instance) {
VisualScriptNodeInstanceBasicTypeConstant *instance = memnew(VisualScriptNodeInstanceBasicTypeConstant);
instance->value = Variant::get_constant_value(type, name, &instance->valid);
return instance;
}
void VisualScriptBasicTypeConstant::_validate_property(PropertyInfo &property) const {
if (property.name == "constant") {
List<StringName> constants;
Variant::get_constants_for_type(type, &constants);
if (constants.size() == 0) {
property.usage = PROPERTY_USAGE_NONE;
return;
}
property.hint_string = "";
for (const StringName &E : constants) {
if (!property.hint_string.is_empty()) {
property.hint_string += ",";
}
property.hint_string += String(E);
}
}
}
void VisualScriptBasicTypeConstant::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_basic_type", "name"), &VisualScriptBasicTypeConstant::set_basic_type);
ClassDB::bind_method(D_METHOD("get_basic_type"), &VisualScriptBasicTypeConstant::get_basic_type);
ClassDB::bind_method(D_METHOD("set_basic_type_constant", "name"), &VisualScriptBasicTypeConstant::set_basic_type_constant);
ClassDB::bind_method(D_METHOD("get_basic_type_constant"), &VisualScriptBasicTypeConstant::get_basic_type_constant);
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, "basic_type", PROPERTY_HINT_ENUM, argt), "set_basic_type", "get_basic_type");
ADD_PROPERTY(PropertyInfo(Variant::STRING, "constant", PROPERTY_HINT_ENUM, ""), "set_basic_type_constant", "get_basic_type_constant");
}
VisualScriptBasicTypeConstant::VisualScriptBasicTypeConstant() {
type = Variant::NIL;
}
//////////////////////////////////////////
////////////////MATHCONSTANT///////////
//////////////////////////////////////////
const char *VisualScriptMathConstant::const_name[MATH_CONSTANT_MAX] = {
"One",
"PI",
"PI/2",
"TAU",
"E",
"Sqrt2",
"INF",
"NAN"
};
double VisualScriptMathConstant::const_value[MATH_CONSTANT_MAX] = {
1.0,
Math_PI,
Math_PI * 0.5,
Math_TAU,
2.71828182845904523536,
Math::sqrt(2.0),
INFINITY,
NAN
};
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::FLOAT, const_name[constant]);
}
String VisualScriptMathConstant::get_caption() const {
return RTR("Math Constant");
}
void VisualScriptMathConstant::set_math_constant(MathConstant p_which) {
constant = p_which;
notify_property_list_changed();
ports_changed_notify();
}
VisualScriptMathConstant::MathConstant VisualScriptMathConstant::get_math_constant() {
return constant;
}
class VisualScriptNodeInstanceMathConstant : public VisualScriptNodeInstance {
public:
float value = 0.0f;
virtual int step(const Variant **p_inputs, Variant **p_outputs, StartMode p_start_mode, Variant *p_working_mem, Callable::CallError &r_error, String &r_error_str) override {
*p_outputs[0] = value;
return 0;
}
};
VisualScriptNodeInstance *VisualScriptMathConstant::instantiate(VisualScriptInstance *p_instance) {
VisualScriptNodeInstanceMathConstant *instance = memnew(VisualScriptNodeInstanceMathConstant);
instance->value = const_value[constant];
return instance;
}
void VisualScriptMathConstant::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_math_constant", "which"), &VisualScriptMathConstant::set_math_constant);
ClassDB::bind_method(D_METHOD("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), "set_math_constant", "get_math_constant");
BIND_ENUM_CONSTANT(MATH_CONSTANT_ONE);
BIND_ENUM_CONSTANT(MATH_CONSTANT_PI);
BIND_ENUM_CONSTANT(MATH_CONSTANT_HALF_PI);
BIND_ENUM_CONSTANT(MATH_CONSTANT_TAU);
BIND_ENUM_CONSTANT(MATH_CONSTANT_E);
BIND_ENUM_CONSTANT(MATH_CONSTANT_SQRT2);
BIND_ENUM_CONSTANT(MATH_CONSTANT_INF);
BIND_ENUM_CONSTANT(MATH_CONSTANT_NAN);
BIND_ENUM_CONSTANT(MATH_CONSTANT_MAX);
}
VisualScriptMathConstant::VisualScriptMathConstant() {
constant = MATH_CONSTANT_ONE;
}
//////////////////////////////////////////
////////////////ENGINESINGLETON///////////
//////////////////////////////////////////
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, singleton);
}
String VisualScriptEngineSingleton::get_caption() const {
return RTR("Get Engine Singleton");
}
void VisualScriptEngineSingleton::set_singleton(const String &p_string) {
singleton = p_string;
notify_property_list_changed();
ports_changed_notify();
}
String VisualScriptEngineSingleton::get_singleton() {
return singleton;
}
class VisualScriptNodeInstanceEngineSingleton : public VisualScriptNodeInstance {
public:
Object *singleton = nullptr;
//virtual int get_working_memory_size() const override { return 0; }
virtual int step(const Variant **p_inputs, Variant **p_outputs, StartMode p_start_mode, Variant *p_working_mem, Callable::CallError &r_error, String &r_error_str) override {
*p_outputs[0] = singleton;
return 0;
}
};
VisualScriptNodeInstance *VisualScriptEngineSingleton::instantiate(VisualScriptInstance *p_instance) {
VisualScriptNodeInstanceEngineSingleton *instance = memnew(VisualScriptNodeInstanceEngineSingleton);
instance->singleton = Engine::get_singleton()->get_singleton_object(singleton);
return instance;
}
VisualScriptEngineSingleton::TypeGuess VisualScriptEngineSingleton::guess_output_type(TypeGuess *p_inputs, int p_output) const {
Object *obj = Engine::get_singleton()->get_singleton_object(singleton);
TypeGuess tg;
tg.type = Variant::OBJECT;
if (obj) {
tg.gdclass = obj->get_class();
tg.script = obj->get_script();
}
return tg;
}
void VisualScriptEngineSingleton::_validate_property(PropertyInfo &property) const {
String cc;
List<Engine::Singleton> singletons;
Engine::get_singleton()->get_singletons(&singletons);
for (const Engine::Singleton &E : singletons) {
if (E.name == "VS" || E.name == "PS" || E.name == "PS2D" || E.name == "AS" || E.name == "TS" || E.name == "SS" || E.name == "SS2D") {
continue; //skip these, too simple named
}
if (!cc.is_empty()) {
cc += ",";
}
cc += E.name;
}
property.hint = PROPERTY_HINT_ENUM;
property.hint_string = cc;
}
void VisualScriptEngineSingleton::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_singleton", "name"), &VisualScriptEngineSingleton::set_singleton);
ClassDB::bind_method(D_METHOD("get_singleton"), &VisualScriptEngineSingleton::get_singleton);
ADD_PROPERTY(PropertyInfo(Variant::STRING, "constant"), "set_singleton", "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, path.simplified());
}
String VisualScriptSceneNode::get_caption() const {
return RTR("Get Scene Node");
}
void VisualScriptSceneNode::set_node_path(const NodePath &p_path) {
path = p_path;
notify_property_list_changed();
ports_changed_notify();
}
NodePath VisualScriptSceneNode::get_node_path() {
return path;
}
class VisualScriptNodeInstanceSceneNode : public VisualScriptNodeInstance {
public:
VisualScriptSceneNode *node = nullptr;
VisualScriptInstance *instance = nullptr;
NodePath path;
//virtual int get_working_memory_size() const override { return 0; }
virtual int step(const Variant **p_inputs, Variant **p_outputs, StartMode p_start_mode, Variant *p_working_mem, Callable::CallError &r_error, String &r_error_str) override {
Node *node = Object::cast_to<Node>(instance->get_owner_ptr());
if (!node) {
r_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD;
r_error_str = "Base object is not a Node!";
return 0;
}
Node *another = node->get_node(path);
if (!another) {
r_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD;
r_error_str = "Path does not lead Node!";
return 0;
}
*p_outputs[0] = another;
return 0;
}
};
VisualScriptNodeInstance *VisualScriptSceneNode::instantiate(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 nullptr;
}
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 nullptr;
}
#endif
VisualScriptSceneNode::TypeGuess VisualScriptSceneNode::guess_output_type(TypeGuess *p_inputs, int p_output) const {
VisualScriptSceneNode::TypeGuess tg;
tg.type = Variant::OBJECT;
tg.gdclass = SNAME("Node");
#ifdef TOOLS_ENABLED
Ref<Script> script = get_visual_script();
if (!script.is_valid()) {
return tg;
}
MainLoop *main_loop = OS::get_singleton()->get_main_loop();
SceneTree *scene_tree = Object::cast_to<SceneTree>(main_loop);
if (!scene_tree) {
return tg;
}
Node *edited_scene = scene_tree->get_edited_scene_root();
if (!edited_scene) {
return tg;
}
Node *script_node = _find_script_node(edited_scene, edited_scene, script);
if (!script_node) {
return tg;
}
Node *another = script_node->get_node(path);
if (another) {
tg.gdclass = another->get_class();
tg.script = another->get_script();
}
#endif
return tg;
}
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();
SceneTree *scene_tree = Object::cast_to<SceneTree>(main_loop);
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() {
ClassDB::bind_method(D_METHOD("set_node_path", "path"), &VisualScriptSceneNode::set_node_path);
ClassDB::bind_method(D_METHOD("get_node_path"), &VisualScriptSceneNode::get_node_path);
ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "node_path", PROPERTY_HINT_NODE_PATH_TO_EDITED_NODE), "set_node_path", "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, "Scene Tree", PROPERTY_HINT_TYPE_STRING, "SceneTree");
}
String VisualScriptSceneTree::get_caption() const {
return RTR("Get Scene Tree");
}
class VisualScriptNodeInstanceSceneTree : public VisualScriptNodeInstance {
public:
VisualScriptSceneTree *node = nullptr;
VisualScriptInstance *instance = nullptr;
//virtual int get_working_memory_size() const override { return 0; }
virtual int step(const Variant **p_inputs, Variant **p_outputs, StartMode p_start_mode, Variant *p_working_mem, Callable::CallError &r_error, String &r_error_str) override {
Node *node = Object::cast_to<Node>(instance->get_owner_ptr());
if (!node) {
r_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD;
r_error_str = "Base object is not a Node!";
return 0;
}
SceneTree *tree = node->get_tree();
if (!tree) {
r_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD;
r_error_str = "Attempt to get SceneTree while node is not in the active tree.";
return 0;
}
*p_outputs[0] = tree;
return 0;
}
};
VisualScriptNodeInstance *VisualScriptSceneTree::instantiate(VisualScriptInstance *p_instance) {
VisualScriptNodeInstanceSceneTree *instance = memnew(VisualScriptNodeInstanceSceneTree);
instance->node = this;
instance->instance = p_instance;
return instance;
}
VisualScriptSceneTree::TypeGuess VisualScriptSceneTree::guess_output_type(TypeGuess *p_inputs, int p_output) const {
TypeGuess tg;
tg.type = Variant::OBJECT;
tg.gdclass = SNAME("SceneTree");
return tg;
}
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 RTR("Resource Path");
}
void VisualScriptResourcePath::set_resource_path(const String &p_path) {
path = p_path;
notify_property_list_changed();
ports_changed_notify();
}
String VisualScriptResourcePath::get_resource_path() {
return path;
}
class VisualScriptNodeInstanceResourcePath : public VisualScriptNodeInstance {
public:
String path;
//virtual int get_working_memory_size() const override { return 0; }
virtual int step(const Variant **p_inputs, Variant **p_outputs, StartMode p_start_mode, Variant *p_working_mem, Callable::CallError &r_error, String &r_error_str) override {
*p_outputs[0] = path;
return 0;
}
};
VisualScriptNodeInstance *VisualScriptResourcePath::instantiate(VisualScriptInstance *p_instance) {
VisualScriptNodeInstanceResourcePath *instance = memnew(VisualScriptNodeInstanceResourcePath);
instance->path = path;
return instance;
}
void VisualScriptResourcePath::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_resource_path", "path"), &VisualScriptResourcePath::set_resource_path);
ClassDB::bind_method(D_METHOD("get_resource_path"), &VisualScriptResourcePath::get_resource_path);
ADD_PROPERTY(PropertyInfo(Variant::STRING, "path", PROPERTY_HINT_FILE), "set_resource_path", "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 {
StringName type_name;
if (get_visual_script().is_valid()) {
type_name = get_visual_script()->get_instance_base_type();
} else {
type_name = SNAME("instance");
}
return PropertyInfo(Variant::OBJECT, type_name);
}
String VisualScriptSelf::get_caption() const {
return RTR("Get Self");
}
class VisualScriptNodeInstanceSelf : public VisualScriptNodeInstance {
public:
VisualScriptInstance *instance = nullptr;
//virtual int get_working_memory_size() const override { return 0; }
virtual int step(const Variant **p_inputs, Variant **p_outputs, StartMode p_start_mode, Variant *p_working_mem, Callable::CallError &r_error, String &r_error_str) override {
*p_outputs[0] = instance->get_owner_ptr();
return 0;
}
};
VisualScriptNodeInstance *VisualScriptSelf::instantiate(VisualScriptInstance *p_instance) {
VisualScriptNodeInstanceSelf *instance = memnew(VisualScriptNodeInstanceSelf);
instance->instance = p_instance;
return instance;
}
VisualScriptSelf::TypeGuess VisualScriptSelf::guess_output_type(TypeGuess *p_inputs, int p_output) const {
VisualScriptSceneNode::TypeGuess tg;
tg.type = Variant::OBJECT;
tg.gdclass = SNAME("Object");
Ref<Script> script = get_visual_script();
if (!script.is_valid()) {
return tg;
}
tg.gdclass = script->get_instance_base_type();
tg.script = script;
return tg;
}
void VisualScriptSelf::_bind_methods() {
}
VisualScriptSelf::VisualScriptSelf() {
}
//////////////////////////////////////////
////////////////CUSTOM (SCRIPTED)///////////
//////////////////////////////////////////
int VisualScriptCustomNode::get_output_sequence_port_count() const {
int ret;
if (GDVIRTUAL_CALL(_get_output_sequence_port_count, ret)) {
return ret;
}
return 0;
}
bool VisualScriptCustomNode::has_input_sequence_port() const {
bool ret;
if (GDVIRTUAL_CALL(_has_input_sequence_port, ret)) {
return ret;
}
return false;
}
int VisualScriptCustomNode::get_input_value_port_count() const {
int ret;
if (GDVIRTUAL_CALL(_get_input_value_port_count, ret)) {
return ret;
}
return 0;
}
int VisualScriptCustomNode::get_output_value_port_count() const {
int ret;
if (GDVIRTUAL_CALL(_get_output_value_port_count, ret)) {
return ret;
}
return 0;
}
String VisualScriptCustomNode::get_output_sequence_port_text(int p_port) const {
String ret;
if (GDVIRTUAL_CALL(_get_output_sequence_port_text, p_port, ret)) {
return ret;
}
return String();
}
PropertyInfo VisualScriptCustomNode::get_input_value_port_info(int p_idx) const {
PropertyInfo info;
{
int type;
if (GDVIRTUAL_CALL(_get_input_value_port_type, p_idx, type)) {
info.type = Variant::Type(type);
}
}
{
String name;
if (GDVIRTUAL_CALL(_get_input_value_port_name, p_idx, name)) {
info.name = name;
}
}
{
int hint;
if (GDVIRTUAL_CALL(_get_input_value_port_hint, p_idx, hint)) {
info.hint = PropertyHint(hint);
}
}
{
String hint_string;
if (GDVIRTUAL_CALL(_get_input_value_port_hint_string, p_idx, hint_string)) {
info.hint_string = hint_string;
}
}
return info;
}
PropertyInfo VisualScriptCustomNode::get_output_value_port_info(int p_idx) const {
PropertyInfo info;
{
int type;
if (GDVIRTUAL_CALL(_get_output_value_port_type, p_idx, type)) {
info.type = Variant::Type(type);
}
}
{
String name;
if (GDVIRTUAL_CALL(_get_output_value_port_name, p_idx, name)) {
info.name = name;
}
}
{
int hint;
if (GDVIRTUAL_CALL(_get_output_value_port_hint, p_idx, hint)) {
info.hint = PropertyHint(hint);
}
}
{
String hint_string;
if (GDVIRTUAL_CALL(_get_output_value_port_hint_string, p_idx, hint_string)) {
info.hint_string = hint_string;
}
}
return info;
}
VisualScriptCustomNode::TypeGuess VisualScriptCustomNode::guess_output_type(TypeGuess *p_inputs, int p_output) const {
TypeGuess tg;
PropertyInfo pi = VisualScriptCustomNode::get_output_value_port_info(p_output);
tg.type = pi.type;
if (pi.type == Variant::OBJECT) {
if (pi.hint == PROPERTY_HINT_RESOURCE_TYPE) {
if (pi.hint_string.is_resource_file()) {
tg.script = ResourceLoader::load(pi.hint_string);
} else if (ClassDB::class_exists(pi.hint_string)) {
tg.gdclass = pi.hint_string;
}
}
}
return tg;
}
String VisualScriptCustomNode::get_caption() const {
String ret;
if (GDVIRTUAL_CALL(_get_caption, ret)) {
return ret;
}
return RTR("CustomNode");
}
String VisualScriptCustomNode::get_text() const {
String ret;
if (GDVIRTUAL_CALL(_get_text, ret)) {
return ret;
}
return "";
}
String VisualScriptCustomNode::get_category() const {
String ret;
if (GDVIRTUAL_CALL(_get_category, ret)) {
return ret;
}
return "Custom";
}
class VisualScriptNodeInstanceCustomNode : public VisualScriptNodeInstance {
public:
VisualScriptInstance *instance = nullptr;
VisualScriptCustomNode *node = nullptr;
int in_count = 0;
int out_count = 0;
int work_mem_size = 0;
virtual int get_working_memory_size() const override { return work_mem_size; }
virtual int step(const Variant **p_inputs, Variant **p_outputs, StartMode p_start_mode, Variant *p_working_mem, Callable::CallError &r_error, String &r_error_str) override {
if (GDVIRTUAL_IS_OVERRIDDEN_PTR(node, _step)) {
Array in_values;
Array out_values;
Array work_mem;
in_values.resize(in_count);
for (int i = 0; i < in_count; i++) {
in_values[i] = *p_inputs[i];
}
out_values.resize(out_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;
GDVIRTUAL_CALL_PTR(node, _step, in_values, out_values, p_start_mode, work_mem, ret);
if (ret.get_type() == Variant::STRING) {
r_error_str = ret;
r_error.error = Callable::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 = Callable::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;
} else {
r_error_str = RTR("Custom node has no _step() method, can't process graph.");
r_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD;
}
return 0;
}
};
VisualScriptNodeInstance *VisualScriptCustomNode::instantiate(VisualScriptInstance *p_instance) {
VisualScriptNodeInstanceCustomNode *instance = memnew(VisualScriptNodeInstanceCustomNode);
instance->instance = p_instance;
instance->node = this;
instance->in_count = get_input_value_port_count();
instance->out_count = get_output_value_port_count();
instance->work_mem_size = 0;
GDVIRTUAL_CALL(_get_working_memory_size, instance->work_mem_size);
return instance;
}
void VisualScriptCustomNode::_script_changed() {
call_deferred(SNAME("ports_changed_notify"));
}
void VisualScriptCustomNode::_bind_methods() {
GDVIRTUAL_BIND(_get_output_sequence_port_count);
GDVIRTUAL_BIND(_has_input_sequence_port);
GDVIRTUAL_BIND(_get_output_sequence_port_text, "seq_idx");
GDVIRTUAL_BIND(_get_input_value_port_count);
GDVIRTUAL_BIND(_get_input_value_port_type, "input_idx");
GDVIRTUAL_BIND(_get_input_value_port_name, "input_idx");
GDVIRTUAL_BIND(_get_input_value_port_hint, "input_idx");
GDVIRTUAL_BIND(_get_input_value_port_hint_string, "input_idx");
GDVIRTUAL_BIND(_get_output_value_port_count);
GDVIRTUAL_BIND(_get_output_value_port_type, "output_idx");
GDVIRTUAL_BIND(_get_output_value_port_name, "output_idx");
GDVIRTUAL_BIND(_get_output_value_port_hint, "output_idx");
GDVIRTUAL_BIND(_get_output_value_port_hint_string, "output_idx");
GDVIRTUAL_BIND(_get_caption);
GDVIRTUAL_BIND(_get_text);
GDVIRTUAL_BIND(_get_category);
GDVIRTUAL_BIND(_get_working_memory_size);
GDVIRTUAL_BIND(_step, "inputs", "outputs", "start_mode", "working_mem");
BIND_ENUM_CONSTANT(START_MODE_BEGIN_SEQUENCE);
BIND_ENUM_CONSTANT(START_MODE_CONTINUE_SEQUENCE);
BIND_ENUM_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() {
connect("script_changed", callable_mp(this, &VisualScriptCustomNode::_script_changed));
}
//////////////////////////////////////////
////////////////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 RTR("SubCall");
}
String VisualScriptSubCall::get_text() const {
Ref<Script> script = get_script();
if (script.is_valid()) {
if (!script->get_name().is_empty()) {
return script->get_name();
}
if (script->get_path().is_resource_file()) {
return script->get_path().get_file();
}
return script->get_class();
}
return "";
}
String VisualScriptSubCall::get_category() const {
return "custom";
}
class VisualScriptNodeInstanceSubCall : public VisualScriptNodeInstance {
public:
VisualScriptInstance *instance = nullptr;
VisualScriptSubCall *subcall = nullptr;
int input_args = 0;
bool valid = false;
//virtual int get_working_memory_size() const override { return 0; }
virtual int step(const Variant **p_inputs, Variant **p_outputs, StartMode p_start_mode, Variant *p_working_mem, Callable::CallError &r_error, String &r_error_str) override {
if (!valid) {
r_error_str = "Node requires a script with a _subcall(<args>) method to work.";
r_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD;
return 0;
}
*p_outputs[0] = subcall->callp(VisualScriptLanguage::singleton->_subcall, p_inputs, input_args, r_error);
return 0;
}
};
VisualScriptNodeInstance *VisualScriptSubCall::instantiate(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() {
// Since this is script only, registering virtual function is no longer valid. Will have to go in docs.
}
VisualScriptSubCall::VisualScriptSubCall() {
}
//////////////////////////////////////////
////////////////Comment///////////
//////////////////////////////////////////
int VisualScriptComment::get_output_sequence_port_count() const {
return 0;
}
bool VisualScriptComment::has_input_sequence_port() const {
return false;
}
int VisualScriptComment::get_input_value_port_count() const {
return 0;
}
int VisualScriptComment::get_output_value_port_count() const {
return 0;
}
String VisualScriptComment::get_output_sequence_port_text(int p_port) const {
return String();
}
PropertyInfo VisualScriptComment::get_input_value_port_info(int p_idx) const {
return PropertyInfo();
}
PropertyInfo VisualScriptComment::get_output_value_port_info(int p_idx) const {
return PropertyInfo();
}
String VisualScriptComment::get_caption() const {
return title;
}
String VisualScriptComment::get_text() const {
return description;
}
void VisualScriptComment::set_title(const String &p_title) {
if (title == p_title) {
return;
}
title = p_title;
ports_changed_notify();
}
String VisualScriptComment::get_title() const {
return title;
}
void VisualScriptComment::set_description(const String &p_description) {
if (description == p_description) {
return;
}
description = p_description;
ports_changed_notify();
}
String VisualScriptComment::get_description() const {
return description;
}
void VisualScriptComment::set_size(const Size2 &p_size) {
if (size == p_size) {
return;
}
size = p_size;
ports_changed_notify();
}
Size2 VisualScriptComment::get_size() const {
return size;
}
String VisualScriptComment::get_category() const {
return "data";
}
class VisualScriptNodeInstanceComment : public VisualScriptNodeInstance {
public:
VisualScriptInstance *instance = nullptr;
//virtual int get_working_memory_size() const override { return 0; }
virtual int step(const Variant **p_inputs, Variant **p_outputs, StartMode p_start_mode, Variant *p_working_mem, Callable::CallError &r_error, String &r_error_str) override {
return 0;
}
};
VisualScriptNodeInstance *VisualScriptComment::instantiate(VisualScriptInstance *p_instance) {
VisualScriptNodeInstanceComment *instance = memnew(VisualScriptNodeInstanceComment);
instance->instance = p_instance;
return instance;
}
void VisualScriptComment::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_title", "title"), &VisualScriptComment::set_title);
ClassDB::bind_method(D_METHOD("get_title"), &VisualScriptComment::get_title);
ClassDB::bind_method(D_METHOD("set_description", "description"), &VisualScriptComment::set_description);
ClassDB::bind_method(D_METHOD("get_description"), &VisualScriptComment::get_description);
ClassDB::bind_method(D_METHOD("set_size", "size"), &VisualScriptComment::set_size);
ClassDB::bind_method(D_METHOD("get_size"), &VisualScriptComment::get_size);
ADD_PROPERTY(PropertyInfo(Variant::STRING, "title"), "set_title", "get_title");
ADD_PROPERTY(PropertyInfo(Variant::STRING, "description", PROPERTY_HINT_MULTILINE_TEXT), "set_description", "get_description");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "size"), "set_size", "get_size");
}
VisualScriptComment::VisualScriptComment() {
title = "Comment";
size = Size2(150, 150);
}
//////////////////////////////////////////
////////////////Constructor///////////
//////////////////////////////////////////
int VisualScriptConstructor::get_output_sequence_port_count() const {
return 0;
}
bool VisualScriptConstructor::has_input_sequence_port() const {
return false;
}
int VisualScriptConstructor::get_input_value_port_count() const {
return constructor.arguments.size();
}
int VisualScriptConstructor::get_output_value_port_count() const {
return 1;
}
String VisualScriptConstructor::get_output_sequence_port_text(int p_port) const {
return "";
}
PropertyInfo VisualScriptConstructor::get_input_value_port_info(int p_idx) const {
return constructor.arguments[p_idx];
}
PropertyInfo VisualScriptConstructor::get_output_value_port_info(int p_idx) const {
return PropertyInfo(type, "value");
}
String VisualScriptConstructor::get_caption() const {
return vformat(RTR("Construct %s"), Variant::get_type_name(type));
}
String VisualScriptConstructor::get_category() const {
return "functions";
}
void VisualScriptConstructor::set_constructor_type(Variant::Type p_type) {
if (type == p_type) {
return;
}
type = p_type;
ports_changed_notify();
}
Variant::Type VisualScriptConstructor::get_constructor_type() const {
return type;
}
void VisualScriptConstructor::set_constructor(const Dictionary &p_info) {
constructor = MethodInfo::from_dict(p_info);
ports_changed_notify();
}
Dictionary VisualScriptConstructor::get_constructor() const {
return constructor;
}
class VisualScriptNodeInstanceConstructor : public VisualScriptNodeInstance {
public:
VisualScriptInstance *instance = nullptr;
Variant::Type type;
int argcount = 0;
//virtual int get_working_memory_size() const override { return 0; }
virtual int step(const Variant **p_inputs, Variant **p_outputs, StartMode p_start_mode, Variant *p_working_mem, Callable::CallError &r_error, String &r_error_str) override {
Callable::CallError ce;
Variant::construct(type, *p_outputs[0], p_inputs, argcount, ce);
if (ce.error != Callable::CallError::CALL_OK) {
r_error_str = "Invalid arguments for constructor";
}
return 0;
}
};
VisualScriptNodeInstance *VisualScriptConstructor::instantiate(VisualScriptInstance *p_instance) {
VisualScriptNodeInstanceConstructor *instance = memnew(VisualScriptNodeInstanceConstructor);
instance->instance = p_instance;
instance->type = type;
instance->argcount = constructor.arguments.size();
return instance;
}
void VisualScriptConstructor::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_constructor_type", "type"), &VisualScriptConstructor::set_constructor_type);
ClassDB::bind_method(D_METHOD("get_constructor_type"), &VisualScriptConstructor::get_constructor_type);
ClassDB::bind_method(D_METHOD("set_constructor", "constructor"), &VisualScriptConstructor::set_constructor);
ClassDB::bind_method(D_METHOD("get_constructor"), &VisualScriptConstructor::get_constructor);
ADD_PROPERTY(PropertyInfo(Variant::INT, "type", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), "set_constructor_type", "get_constructor_type");
ADD_PROPERTY(PropertyInfo(Variant::DICTIONARY, "constructor", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), "set_constructor", "get_constructor");
}
VisualScriptConstructor::VisualScriptConstructor() {
type = Variant::NIL;
}
static HashMap<String, Pair<Variant::Type, MethodInfo>> constructor_map;
static Ref<VisualScriptNode> create_constructor_node(const String &p_name) {
ERR_FAIL_COND_V(!constructor_map.has(p_name), Ref<VisualScriptNode>());
Ref<VisualScriptConstructor> vsc;
vsc.instantiate();
vsc->set_constructor_type(constructor_map[p_name].first);
vsc->set_constructor(constructor_map[p_name].second);
return vsc;
}
//////////////////////////////////////////
////////////////LocalVar///////////
//////////////////////////////////////////
int VisualScriptLocalVar::get_output_sequence_port_count() const {
return 0;
}
bool VisualScriptLocalVar::has_input_sequence_port() const {
return false;
}
int VisualScriptLocalVar::get_input_value_port_count() const {
return 0;
}
int VisualScriptLocalVar::get_output_value_port_count() const {
return 1;
}
String VisualScriptLocalVar::get_output_sequence_port_text(int p_port) const {
return "";
}
PropertyInfo VisualScriptLocalVar::get_input_value_port_info(int p_idx) const {
return PropertyInfo();
}
PropertyInfo VisualScriptLocalVar::get_output_value_port_info(int p_idx) const {
return PropertyInfo(type, name);
}
String VisualScriptLocalVar::get_caption() const {
return RTR("Get Local Var");
}
String VisualScriptLocalVar::get_category() const {
return "data";
}
void VisualScriptLocalVar::set_var_name(const StringName &p_name) {
if (name == p_name) {
return;
}
name = p_name;
ports_changed_notify();
}
StringName VisualScriptLocalVar::get_var_name() const {
return name;
}
void VisualScriptLocalVar::set_var_type(Variant::Type p_type) {
type = p_type;
ports_changed_notify();
}
Variant::Type VisualScriptLocalVar::get_var_type() const {
return type;
}
class VisualScriptNodeInstanceLocalVar : public VisualScriptNodeInstance {
public:
VisualScriptInstance *instance = nullptr;
StringName name;
virtual int get_working_memory_size() const override { return 1; }
virtual int step(const Variant **p_inputs, Variant **p_outputs, StartMode p_start_mode, Variant *p_working_mem, Callable::CallError &r_error, String &r_error_str) override {
*p_outputs[0] = *p_working_mem;
return 0;
}
};
VisualScriptNodeInstance *VisualScriptLocalVar::instantiate(VisualScriptInstance *p_instance) {
VisualScriptNodeInstanceLocalVar *instance = memnew(VisualScriptNodeInstanceLocalVar);
instance->instance = p_instance;
instance->name = name;
return instance;
}
void VisualScriptLocalVar::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_var_name", "name"), &VisualScriptLocalVar::set_var_name);
ClassDB::bind_method(D_METHOD("get_var_name"), &VisualScriptLocalVar::get_var_name);
ClassDB::bind_method(D_METHOD("set_var_type", "type"), &VisualScriptLocalVar::set_var_type);
ClassDB::bind_method(D_METHOD("get_var_type"), &VisualScriptLocalVar::get_var_type);
String argt = "Any";
for (int i = 1; i < Variant::VARIANT_MAX; i++) {
argt += "," + Variant::get_type_name(Variant::Type(i));
}
ADD_PROPERTY(PropertyInfo(Variant::STRING, "var_name"), "set_var_name", "get_var_name");
ADD_PROPERTY(PropertyInfo(Variant::INT, "type", PROPERTY_HINT_ENUM, argt), "set_var_type", "get_var_type");
}
VisualScriptLocalVar::VisualScriptLocalVar() {
name = "new_local";
type = Variant::NIL;
}
//////////////////////////////////////////
////////////////LocalVar///////////
//////////////////////////////////////////
int VisualScriptLocalVarSet::get_output_sequence_port_count() const {
return 1;
}
bool VisualScriptLocalVarSet::has_input_sequence_port() const {
return true;
}
int VisualScriptLocalVarSet::get_input_value_port_count() const {
return 1;
}
int VisualScriptLocalVarSet::get_output_value_port_count() const {
return 1;
}
String VisualScriptLocalVarSet::get_output_sequence_port_text(int p_port) const {
return "";
}
PropertyInfo VisualScriptLocalVarSet::get_input_value_port_info(int p_idx) const {
return PropertyInfo(type, "set");
}
PropertyInfo VisualScriptLocalVarSet::get_output_value_port_info(int p_idx) const {
return PropertyInfo(type, "get");
}
String VisualScriptLocalVarSet::get_caption() const {
return RTR("Set Local Var");
}
String VisualScriptLocalVarSet::get_text() const {
return name;
}
String VisualScriptLocalVarSet::get_category() const {
return "data";
}
void VisualScriptLocalVarSet::set_var_name(const StringName &p_name) {
if (name == p_name) {
return;
}
name = p_name;
ports_changed_notify();
}
StringName VisualScriptLocalVarSet::get_var_name() const {
return name;
}
void VisualScriptLocalVarSet::set_var_type(Variant::Type p_type) {
type = p_type;
ports_changed_notify();
}
Variant::Type VisualScriptLocalVarSet::get_var_type() const {
return type;
}
class VisualScriptNodeInstanceLocalVarSet : public VisualScriptNodeInstance {
public:
VisualScriptInstance *instance = nullptr;
StringName name;
virtual int get_working_memory_size() const override { return 1; }
virtual int step(const Variant **p_inputs, Variant **p_outputs, StartMode p_start_mode, Variant *p_working_mem, Callable::CallError &r_error, String &r_error_str) override {
*p_working_mem = *p_inputs[0];
*p_outputs[0] = *p_working_mem;
return 0;
}
};
VisualScriptNodeInstance *VisualScriptLocalVarSet::instantiate(VisualScriptInstance *p_instance) {
VisualScriptNodeInstanceLocalVarSet *instance = memnew(VisualScriptNodeInstanceLocalVarSet);
instance->instance = p_instance;
instance->name = name;
return instance;
}
void VisualScriptLocalVarSet::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_var_name", "name"), &VisualScriptLocalVarSet::set_var_name);
ClassDB::bind_method(D_METHOD("get_var_name"), &VisualScriptLocalVarSet::get_var_name);
ClassDB::bind_method(D_METHOD("set_var_type", "type"), &VisualScriptLocalVarSet::set_var_type);
ClassDB::bind_method(D_METHOD("get_var_type"), &VisualScriptLocalVarSet::get_var_type);
String argt = "Any";
for (int i = 1; i < Variant::VARIANT_MAX; i++) {
argt += "," + Variant::get_type_name(Variant::Type(i));
}
ADD_PROPERTY(PropertyInfo(Variant::STRING, "var_name"), "set_var_name", "get_var_name");
ADD_PROPERTY(PropertyInfo(Variant::INT, "type", PROPERTY_HINT_ENUM, argt), "set_var_type", "get_var_type");
}
VisualScriptLocalVarSet::VisualScriptLocalVarSet() {
name = "new_local";
type = Variant::NIL;
}
//////////////////////////////////////////
////////////////LocalVar///////////
//////////////////////////////////////////
int VisualScriptInputAction::get_output_sequence_port_count() const {
return 0;
}
bool VisualScriptInputAction::has_input_sequence_port() const {
return false;
}
int VisualScriptInputAction::get_input_value_port_count() const {
return 0;
}
int VisualScriptInputAction::get_output_value_port_count() const {
return 1;
}
String VisualScriptInputAction::get_output_sequence_port_text(int p_port) const {
return "";
}
PropertyInfo VisualScriptInputAction::get_input_value_port_info(int p_idx) const {
return PropertyInfo();
}
PropertyInfo VisualScriptInputAction::get_output_value_port_info(int p_idx) const {
String mstr;
switch (mode) {
case MODE_PRESSED: {
mstr = "pressed";
} break;
case MODE_RELEASED: {
mstr = "not pressed";
} break;
case MODE_JUST_PRESSED: {
mstr = "just pressed";
} break;
case MODE_JUST_RELEASED: {
mstr = "just released";
} break;
}
return PropertyInfo(Variant::BOOL, mstr);
}
String VisualScriptInputAction::get_caption() const {
return vformat(RTR("Action %s"), name);
}
String VisualScriptInputAction::get_category() const {
return "data";
}
void VisualScriptInputAction::set_action_name(const StringName &p_name) {
if (name == p_name) {
return;
}
name = p_name;
ports_changed_notify();
}
StringName VisualScriptInputAction::get_action_name() const {
return name;
}
void VisualScriptInputAction::set_action_mode(Mode p_mode) {
if (mode == p_mode) {
return;
}
mode = p_mode;
ports_changed_notify();
}
VisualScriptInputAction::Mode VisualScriptInputAction::get_action_mode() const {
return mode;
}
class VisualScriptNodeInstanceInputAction : public VisualScriptNodeInstance {
public:
VisualScriptInstance *instance = nullptr;
StringName action;
VisualScriptInputAction::Mode mode;
virtual int step(const Variant **p_inputs, Variant **p_outputs, StartMode p_start_mode, Variant *p_working_mem, Callable::CallError &r_error, String &r_error_str) override {
switch (mode) {
case VisualScriptInputAction::MODE_PRESSED: {
*p_outputs[0] = Input::get_singleton()->is_action_pressed(action);
} break;
case VisualScriptInputAction::MODE_RELEASED: {
*p_outputs[0] = !Input::get_singleton()->is_action_pressed(action);
} break;
case VisualScriptInputAction::MODE_JUST_PRESSED: {
*p_outputs[0] = Input::get_singleton()->is_action_just_pressed(action);
} break;
case VisualScriptInputAction::MODE_JUST_RELEASED: {
*p_outputs[0] = Input::get_singleton()->is_action_just_released(action);
} break;
}
return 0;
}
};
VisualScriptNodeInstance *VisualScriptInputAction::instantiate(VisualScriptInstance *p_instance) {
VisualScriptNodeInstanceInputAction *instance = memnew(VisualScriptNodeInstanceInputAction);
instance->instance = p_instance;
instance->action = name;
instance->mode = mode;
return instance;
}
void VisualScriptInputAction::_validate_property(PropertyInfo &property) const {
if (property.name == "action") {
property.hint = PROPERTY_HINT_ENUM;
String actions;
List<PropertyInfo> pinfo;
ProjectSettings::get_singleton()->get_property_list(&pinfo);
Vector<String> al;
for (const PropertyInfo &pi : pinfo) {
if (!pi.name.begins_with("input/")) {
continue;
}
String name = pi.name.substr(pi.name.find("/") + 1, pi.name.length());
al.push_back(name);
}
al.sort();
for (int i = 0; i < al.size(); i++) {
if (!actions.is_empty()) {
actions += ",";
}
actions += al[i];
}
property.hint_string = actions;
}
}
void VisualScriptInputAction::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_action_name", "name"), &VisualScriptInputAction::set_action_name);
ClassDB::bind_method(D_METHOD("get_action_name"), &VisualScriptInputAction::get_action_name);
ClassDB::bind_method(D_METHOD("set_action_mode", "mode"), &VisualScriptInputAction::set_action_mode);
ClassDB::bind_method(D_METHOD("get_action_mode"), &VisualScriptInputAction::get_action_mode);
ADD_PROPERTY(PropertyInfo(Variant::STRING, "action"), "set_action_name", "get_action_name");
ADD_PROPERTY(PropertyInfo(Variant::INT, "mode", PROPERTY_HINT_ENUM, "Pressed,Released,JustPressed,JustReleased"), "set_action_mode", "get_action_mode");
BIND_ENUM_CONSTANT(MODE_PRESSED);
BIND_ENUM_CONSTANT(MODE_RELEASED);
BIND_ENUM_CONSTANT(MODE_JUST_PRESSED);
BIND_ENUM_CONSTANT(MODE_JUST_RELEASED);
}
VisualScriptInputAction::VisualScriptInputAction() {
name = "";
mode = MODE_PRESSED;
}
//////////////////////////////////////////
////////////////Constructor///////////
//////////////////////////////////////////
int VisualScriptDeconstruct::get_output_sequence_port_count() const {
return 0;
}
bool VisualScriptDeconstruct::has_input_sequence_port() const {
return false;
}
int VisualScriptDeconstruct::get_input_value_port_count() const {
return 1;
}
int VisualScriptDeconstruct::get_output_value_port_count() const {
return elements.size();
}
String VisualScriptDeconstruct::get_output_sequence_port_text(int p_port) const {
return "";
}
PropertyInfo VisualScriptDeconstruct::get_input_value_port_info(int p_idx) const {
return PropertyInfo(type, "value");
}
PropertyInfo VisualScriptDeconstruct::get_output_value_port_info(int p_idx) const {
return PropertyInfo(elements[p_idx].type, elements[p_idx].name);
}
String VisualScriptDeconstruct::get_caption() const {
return vformat(RTR("Deconstruct %s"), Variant::get_type_name(type));
}
String VisualScriptDeconstruct::get_category() const {
return "functions";
}
void VisualScriptDeconstruct::_update_elements() {
elements.clear();
Variant v;
Callable::CallError ce;
Variant::construct(type, v, nullptr, 0, ce);
List<PropertyInfo> pinfo;
v.get_property_list(&pinfo);
for (const PropertyInfo &E : pinfo) {
Element e;
e.name = E.name;
e.type = E.type;
elements.push_back(e);
}
}
void VisualScriptDeconstruct::set_deconstruct_type(Variant::Type p_type) {
if (type == p_type) {
return;
}
type = p_type;
_update_elements();
ports_changed_notify();
notify_property_list_changed(); //to make input appear/disappear
}
Variant::Type VisualScriptDeconstruct::get_deconstruct_type() const {
return type;
}
void VisualScriptDeconstruct::_set_elem_cache(const Array &p_elements) {
ERR_FAIL_COND(p_elements.size() % 2 == 1);
elements.resize(p_elements.size() / 2);
for (int i = 0; i < elements.size(); i++) {
elements.write[i].name = p_elements[i * 2 + 0];
elements.write[i].type = Variant::Type(int(p_elements[i * 2 + 1]));
}
}
Array VisualScriptDeconstruct::_get_elem_cache() const {
Array ret;
for (int i = 0; i < elements.size(); i++) {
ret.push_back(elements[i].name);
ret.push_back(elements[i].type);
}
return ret;
}
class VisualScriptNodeInstanceDeconstruct : public VisualScriptNodeInstance {
public:
VisualScriptInstance *instance = nullptr;
Vector<StringName> outputs;
//virtual int get_working_memory_size() const override { return 0; }
virtual int step(const Variant **p_inputs, Variant **p_outputs, StartMode p_start_mode, Variant *p_working_mem, Callable::CallError &r_error, String &r_error_str) override {
Variant in = *p_inputs[0];
for (int i = 0; i < outputs.size(); i++) {
bool valid;
*p_outputs[i] = in.get(outputs[i], &valid);
if (!valid) {
r_error_str = "Can't obtain element '" + String(outputs[i]) + "' from " + Variant::get_type_name(in.get_type());
r_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD;
return 0;
}
}
return 0;
}
};
VisualScriptNodeInstance *VisualScriptDeconstruct::instantiate(VisualScriptInstance *p_instance) {
VisualScriptNodeInstanceDeconstruct *instance = memnew(VisualScriptNodeInstanceDeconstruct);
instance->instance = p_instance;
instance->outputs.resize(elements.size());
for (int i = 0; i < elements.size(); i++) {
instance->outputs.write[i] = elements[i].name;
}
return instance;
}
void VisualScriptDeconstruct::_validate_property(PropertyInfo &property) const {
}
void VisualScriptDeconstruct::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_deconstruct_type", "type"), &VisualScriptDeconstruct::set_deconstruct_type);
ClassDB::bind_method(D_METHOD("get_deconstruct_type"), &VisualScriptDeconstruct::get_deconstruct_type);
ClassDB::bind_method(D_METHOD("_set_elem_cache", "_cache"), &VisualScriptDeconstruct::_set_elem_cache);
ClassDB::bind_method(D_METHOD("_get_elem_cache"), &VisualScriptDeconstruct::_get_elem_cache);
String argt = "Any";
for (int i = 1; i < Variant::VARIANT_MAX; i++) {
argt += "," + Variant::get_type_name(Variant::Type(i));
}
ADD_PROPERTY(PropertyInfo(Variant::INT, "type", PROPERTY_HINT_ENUM, argt), "set_deconstruct_type", "get_deconstruct_type");
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "elem_cache", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), "_set_elem_cache", "_get_elem_cache");
}
VisualScriptDeconstruct::VisualScriptDeconstruct() {
type = Variant::NIL;
}
template <Variant::Type T>
static Ref<VisualScriptNode> create_node_deconst_typed(const String &p_name) {
Ref<VisualScriptDeconstruct> node;
node.instantiate();
node->set_deconstruct_type(T);
return node;
}
void register_visual_script_nodes() {
VisualScriptLanguage::singleton->add_register_func("data/set_variable", create_node_generic<VisualScriptVariableSet>);
VisualScriptLanguage::singleton->add_register_func("data/get_variable", create_node_generic<VisualScriptVariableGet>);
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("data/comment", create_node_generic<VisualScriptComment>);
VisualScriptLanguage::singleton->add_register_func("data/get_local_variable", create_node_generic<VisualScriptLocalVar>);
VisualScriptLanguage::singleton->add_register_func("data/set_local_variable", create_node_generic<VisualScriptLocalVarSet>);
VisualScriptLanguage::singleton->add_register_func("data/preload", create_node_generic<VisualScriptPreload>);
VisualScriptLanguage::singleton->add_register_func("data/action", create_node_generic<VisualScriptInputAction>);
VisualScriptLanguage::singleton->add_register_func("constants/constant", create_node_generic<VisualScriptConstant>);
VisualScriptLanguage::singleton->add_register_func("constants/math_constant", create_node_generic<VisualScriptMathConstant>);
VisualScriptLanguage::singleton->add_register_func("constants/class_constant", create_node_generic<VisualScriptClassConstant>);
VisualScriptLanguage::singleton->add_register_func("constants/global_constant", create_node_generic<VisualScriptGlobalConstant>);
VisualScriptLanguage::singleton->add_register_func("constants/basic_type_constant", create_node_generic<VisualScriptBasicTypeConstant>);
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_SUBTRACT>);
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/positive", create_op_node<Variant::OP_POSITIVE>);
VisualScriptLanguage::singleton->add_register_func("operators/math/remainder", create_op_node<Variant::OP_MODULE>);
//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>);
VisualScriptLanguage::singleton->add_register_func("operators/logic/select", create_node_generic<VisualScriptSelect>);
VisualScriptLanguage::singleton->add_register_func("functions/deconstruct/" + Variant::get_type_name(Variant::Type::VECTOR2), create_node_deconst_typed<Variant::Type::VECTOR2>);
VisualScriptLanguage::singleton->add_register_func("functions/deconstruct/" + Variant::get_type_name(Variant::Type::VECTOR2I), create_node_deconst_typed<Variant::Type::VECTOR2I>);
VisualScriptLanguage::singleton->add_register_func("functions/deconstruct/" + Variant::get_type_name(Variant::Type::VECTOR3), create_node_deconst_typed<Variant::Type::VECTOR3>);
VisualScriptLanguage::singleton->add_register_func("functions/deconstruct/" + Variant::get_type_name(Variant::Type::VECTOR3I), create_node_deconst_typed<Variant::Type::VECTOR3I>);
VisualScriptLanguage::singleton->add_register_func("functions/deconstruct/" + Variant::get_type_name(Variant::Type::VECTOR4), create_node_deconst_typed<Variant::Type::VECTOR4>);
VisualScriptLanguage::singleton->add_register_func("functions/deconstruct/" + Variant::get_type_name(Variant::Type::VECTOR4I), create_node_deconst_typed<Variant::Type::VECTOR4I>);
VisualScriptLanguage::singleton->add_register_func("functions/deconstruct/" + Variant::get_type_name(Variant::Type::COLOR), create_node_deconst_typed<Variant::Type::COLOR>);
VisualScriptLanguage::singleton->add_register_func("functions/deconstruct/" + Variant::get_type_name(Variant::Type::RECT2), create_node_deconst_typed<Variant::Type::RECT2>);
VisualScriptLanguage::singleton->add_register_func("functions/deconstruct/" + Variant::get_type_name(Variant::Type::RECT2I), create_node_deconst_typed<Variant::Type::RECT2I>);
VisualScriptLanguage::singleton->add_register_func("functions/deconstruct/" + Variant::get_type_name(Variant::Type::TRANSFORM2D), create_node_deconst_typed<Variant::Type::TRANSFORM2D>);
VisualScriptLanguage::singleton->add_register_func("functions/deconstruct/" + Variant::get_type_name(Variant::Type::PLANE), create_node_deconst_typed<Variant::Type::PLANE>);
VisualScriptLanguage::singleton->add_register_func("functions/deconstruct/" + Variant::get_type_name(Variant::Type::QUATERNION), create_node_deconst_typed<Variant::Type::QUATERNION>);
VisualScriptLanguage::singleton->add_register_func("functions/deconstruct/" + Variant::get_type_name(Variant::Type::AABB), create_node_deconst_typed<Variant::Type::AABB>);
VisualScriptLanguage::singleton->add_register_func("functions/deconstruct/" + Variant::get_type_name(Variant::Type::BASIS), create_node_deconst_typed<Variant::Type::BASIS>);
VisualScriptLanguage::singleton->add_register_func("functions/deconstruct/" + Variant::get_type_name(Variant::Type::TRANSFORM3D), create_node_deconst_typed<Variant::Type::TRANSFORM3D>);
VisualScriptLanguage::singleton->add_register_func("functions/deconstruct/" + Variant::get_type_name(Variant::Type::PROJECTION), create_node_deconst_typed<Variant::Type::PROJECTION>);
VisualScriptLanguage::singleton->add_register_func("functions/compose_array", create_node_generic<VisualScriptComposeArray>);
for (int i = 1; i < Variant::VARIANT_MAX; i++) {
List<MethodInfo> constructors;
Variant::get_constructor_list(Variant::Type(i), &constructors);
for (const MethodInfo &E : constructors) {
if (E.arguments.size() > 0) {
String name = "functions/constructors/" + Variant::get_type_name(Variant::Type(i)) + "(";
for (int j = 0; j < E.arguments.size(); j++) {
if (j > 0) {
name += ", ";
}
if (E.arguments.size() == 1) {
name += Variant::get_type_name(E.arguments[j].type);
} else {
name += E.arguments[j].name;
}
}
name += ")";
VisualScriptLanguage::singleton->add_register_func(name, create_constructor_node);
Pair<Variant::Type, MethodInfo> pair;
pair.first = Variant::Type(i);
pair.second = E;
constructor_map[name] = pair;
}
}
}
}
void unregister_visual_script_nodes() {
constructor_map.clear();
}