1
0
mirror of https://github.com/godotengine/godot.git synced 2025-11-08 12:40:44 +00:00

Plugin support for visual shaders

This commit is contained in:
Yuri Roubinski
2019-08-09 22:51:48 +03:00
parent 1dae4c9e7f
commit 33e9fce1bb
8 changed files with 452 additions and 32 deletions

View File

@@ -117,6 +117,12 @@ void VisualShaderNode::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::INT, "output_port_for_preview"), "set_output_port_for_preview", "get_output_port_for_preview");
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "default_input_values", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "_set_default_input_values", "_get_default_input_values");
ADD_SIGNAL(MethodInfo("editor_refresh_request"));
BIND_ENUM_CONSTANT(PORT_TYPE_SCALAR);
BIND_ENUM_CONSTANT(PORT_TYPE_VECTOR);
BIND_ENUM_CONSTANT(PORT_TYPE_BOOLEAN);
BIND_ENUM_CONSTANT(PORT_TYPE_TRANSFORM);
BIND_ENUM_CONSTANT(PORT_TYPE_ICON_COLOR);
}
VisualShaderNode::VisualShaderNode() {
@@ -125,6 +131,147 @@ VisualShaderNode::VisualShaderNode() {
/////////////////////////////////////////////////////////
void VisualShaderNodeCustom::update_ports() {
ERR_FAIL_COND(!get_script_instance());
input_ports.clear();
if (get_script_instance()->has_method("_get_input_port_count")) {
int input_port_count = (int)get_script_instance()->call("_get_input_port_count");
bool has_name = get_script_instance()->has_method("_get_input_port_name");
bool has_type = get_script_instance()->has_method("_get_input_port_type");
for (int i = 0; i < input_port_count; i++) {
Port port;
if (has_name) {
port.name = (String)get_script_instance()->call("_get_input_port_name", i);
} else {
port.name = "in" + itos(i);
}
if (has_type) {
port.type = (int)get_script_instance()->call("_get_input_port_type", i);
} else {
port.type = (int)PortType::PORT_TYPE_SCALAR;
}
input_ports.push_back(port);
}
}
output_ports.clear();
if (get_script_instance()->has_method("_get_output_port_count")) {
int output_port_count = (int)get_script_instance()->call("_get_output_port_count");
bool has_name = get_script_instance()->has_method("_get_output_port_name");
bool has_type = get_script_instance()->has_method("_get_output_port_type");
for (int i = 0; i < output_port_count; i++) {
Port port;
if (has_name) {
port.name = (String)get_script_instance()->call("_get_output_port_name", i);
} else {
port.name = "out" + itos(i);
}
if (has_type) {
port.type = (int)get_script_instance()->call("_get_output_port_type", i);
} else {
port.type = (int)PortType::PORT_TYPE_SCALAR;
}
output_ports.push_back(port);
}
}
}
String VisualShaderNodeCustom::get_caption() const {
ERR_FAIL_COND_V(!get_script_instance(), "");
if (get_script_instance()->has_method("_get_name")) {
return (String)get_script_instance()->call("_get_name");
}
return "Unnamed";
}
int VisualShaderNodeCustom::get_input_port_count() const {
return input_ports.size();
}
VisualShaderNodeCustom::PortType VisualShaderNodeCustom::get_input_port_type(int p_port) const {
ERR_FAIL_INDEX_V(p_port, input_ports.size(), PORT_TYPE_SCALAR);
return (PortType)input_ports[p_port].type;
}
String VisualShaderNodeCustom::get_input_port_name(int p_port) const {
ERR_FAIL_INDEX_V(p_port, input_ports.size(), "");
return input_ports[p_port].name;
}
int VisualShaderNodeCustom::get_output_port_count() const {
return output_ports.size();
}
VisualShaderNodeCustom::PortType VisualShaderNodeCustom::get_output_port_type(int p_port) const {
ERR_FAIL_INDEX_V(p_port, output_ports.size(), PORT_TYPE_SCALAR);
return (PortType)output_ports[p_port].type;
}
String VisualShaderNodeCustom::get_output_port_name(int p_port) const {
ERR_FAIL_INDEX_V(p_port, output_ports.size(), "");
return output_ports[p_port].name;
}
String VisualShaderNodeCustom::generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview) const {
ERR_FAIL_COND_V(!get_script_instance(), "");
ERR_FAIL_COND_V(!get_script_instance()->has_method("_get_code"), "");
Array input_vars;
for (int i = 0; i < get_input_port_count(); i++) {
input_vars.push_back(p_input_vars[i]);
}
Array output_vars;
for (int i = 0; i < get_output_port_count(); i++) {
output_vars.push_back(p_output_vars[i]);
}
String code = "\t{\n";
String _code = (String)get_script_instance()->call("_get_code", input_vars, output_vars, (int)p_mode, (int)p_type);
bool nend = _code.ends_with("\n");
_code = _code.insert(0, "\t\t");
_code = _code.replace("\n", "\n\t\t");
code += _code;
if (!nend) {
code += "\n\t}";
} else {
code.remove(code.size() - 1);
code += "}";
}
return code;
}
String VisualShaderNodeCustom::generate_global_per_node(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const {
ERR_FAIL_COND_V(!get_script_instance(), "");
if (get_script_instance()->has_method("_get_global_code")) {
String code = "// " + get_caption() + "\n";
code += (String)get_script_instance()->call("_get_global_code", (int)p_mode);
code += "\n";
return code;
}
return "";
}
void VisualShaderNodeCustom::_bind_methods() {
BIND_VMETHOD(MethodInfo(Variant::STRING, "_get_name"));
BIND_VMETHOD(MethodInfo(Variant::STRING, "_get_description"));
BIND_VMETHOD(MethodInfo(Variant::STRING, "_get_category"));
BIND_VMETHOD(MethodInfo(Variant::STRING, "_get_subcategory"));
BIND_VMETHOD(MethodInfo(Variant::INT, "_get_return_icon_type"));
BIND_VMETHOD(MethodInfo(Variant::INT, "_get_input_port_count"));
BIND_VMETHOD(MethodInfo(Variant::INT, "_get_input_port_type", PropertyInfo(Variant::INT, "port")));
BIND_VMETHOD(MethodInfo(Variant::STRING, "_get_input_port_name", PropertyInfo(Variant::INT, "port")));
BIND_VMETHOD(MethodInfo(Variant::INT, "_get_output_port_count"));
BIND_VMETHOD(MethodInfo(Variant::INT, "_get_output_port_type", PropertyInfo(Variant::INT, "port")));
BIND_VMETHOD(MethodInfo(Variant::STRING, "_get_output_port_name", PropertyInfo(Variant::INT, "port")));
BIND_VMETHOD(MethodInfo(Variant::STRING, "_get_code", PropertyInfo(Variant::ARRAY, "input_vars"), PropertyInfo(Variant::ARRAY, "output_vars"), PropertyInfo(Variant::INT, "mode"), PropertyInfo(Variant::INT, "type")));
BIND_VMETHOD(MethodInfo(Variant::STRING, "_get_global_code", PropertyInfo(Variant::INT, "mode")));
}
VisualShaderNodeCustom::VisualShaderNodeCustom() {
}
/////////////////////////////////////////////////////////
void VisualShader::add_node(Type p_type, const Ref<VisualShaderNode> &p_node, const Vector2 &p_position, int p_id) {
ERR_FAIL_COND(p_node.is_null());
ERR_FAIL_COND(p_id < 2);
@@ -150,6 +297,11 @@ void VisualShader::add_node(Type p_type, const Ref<VisualShaderNode> &p_node, co
n.node->connect("changed", this, "_queue_update");
Ref<VisualShaderNodeCustom> custom = n.node;
if (custom.is_valid()) {
custom->update_ports();
}
g->nodes[p_id] = n;
_queue_update();
@@ -965,6 +1117,7 @@ Error VisualShader::_write_node(Type type, StringBuilder &global_code, StringBui
bool skip_global = input.is_valid() && for_preview;
if (!skip_global) {
global_code += vsnode->generate_global(get_mode(), type, node);
if (!r_classes.has(vsnode->get_class_name())) {
@@ -976,7 +1129,6 @@ Error VisualShader::_write_node(Type type, StringBuilder &global_code, StringBui
}
}
//handle normally
code += vsnode->generate_code(get_mode(), type, node, inputs, outputs, for_preview);
code += "\n"; //