summaryrefslogtreecommitdiff
path: root/scene/resources/visual_shader.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'scene/resources/visual_shader.cpp')
-rw-r--r--scene/resources/visual_shader.cpp549
1 files changed, 476 insertions, 73 deletions
diff --git a/scene/resources/visual_shader.cpp b/scene/resources/visual_shader.cpp
index 77d4dee21e..b8d2003e68 100644
--- a/scene/resources/visual_shader.cpp
+++ b/scene/resources/visual_shader.cpp
@@ -63,6 +63,52 @@ bool VisualShaderNode::is_port_separator(int p_index) const {
return false;
}
+bool VisualShaderNode::is_output_port_connected(int p_port) const {
+ if (connected_output_ports.has(p_port)) {
+ return connected_output_ports[p_port];
+ }
+ return false;
+}
+
+void VisualShaderNode::set_output_port_connected(int p_port, bool p_connected) {
+ if (p_connected) {
+ connected_output_ports[p_port] = true;
+ ++connected_output_count;
+ } else {
+ --connected_output_count;
+ if (connected_output_count == 0) {
+ connected_output_ports[p_port] = false;
+ }
+ }
+}
+
+bool VisualShaderNode::is_input_port_connected(int p_port) const {
+ if (connected_input_ports.has(p_port)) {
+ return connected_input_ports[p_port];
+ }
+ return false;
+}
+
+void VisualShaderNode::set_input_port_connected(int p_port, bool p_connected) {
+ connected_input_ports[p_port] = p_connected;
+}
+
+bool VisualShaderNode::is_generate_input_var(int p_port) const {
+ return true;
+}
+
+bool VisualShaderNode::is_code_generated() const {
+ return true;
+}
+
+bool VisualShaderNode::is_show_prop_names() const {
+ return false;
+}
+
+bool VisualShaderNode::is_use_prop_slots() const {
+ return false;
+}
+
Vector<VisualShader::DefaultTextureParam> VisualShaderNode::get_default_texture_parameters(VisualShader::Type p_type, int p_id) const {
return Vector<VisualShader::DefaultTextureParam>();
}
@@ -134,8 +180,6 @@ void VisualShaderNode::_bind_methods() {
}
VisualShaderNode::VisualShaderNode() {
- port_preview = -1;
- simple_decl = true;
}
/////////////////////////////////////////////////////////
@@ -281,6 +325,14 @@ VisualShaderNodeCustom::VisualShaderNodeCustom() {
/////////////////////////////////////////////////////////
+void VisualShader::set_shader_type(Type p_type) {
+ current_type = p_type;
+}
+
+VisualShader::Type VisualShader::get_shader_type() const {
+ return current_type;
+}
+
void VisualShader::set_version(const String &p_version) {
version = p_version;
}
@@ -429,6 +481,7 @@ void VisualShader::remove_node(Type p_type, int p_id) {
g->connections.erase(E);
if (E->get().from_node == p_id) {
g->nodes[E->get().to_node].prev_connected_nodes.erase(p_id);
+ g->nodes[E->get().to_node].node->set_input_port_connected(E->get().to_port, false);
}
}
E = N;
@@ -526,6 +579,8 @@ void VisualShader::connect_nodes_forced(Type p_type, int p_from_node, int p_from
c.to_port = p_to_port;
g->connections.push_back(c);
g->nodes[p_to_node].prev_connected_nodes.push_back(p_from_node);
+ g->nodes[p_from_node].node->set_output_port_connected(p_from_port, true);
+ g->nodes[p_to_node].node->set_input_port_connected(p_to_port, true);
_queue_update();
}
@@ -557,6 +612,8 @@ Error VisualShader::connect_nodes(Type p_type, int p_from_node, int p_from_port,
c.to_port = p_to_port;
g->connections.push_back(c);
g->nodes[p_to_node].prev_connected_nodes.push_back(p_from_node);
+ g->nodes[p_from_node].node->set_output_port_connected(p_from_port, true);
+ g->nodes[p_to_node].node->set_input_port_connected(p_to_port, true);
_queue_update();
return OK;
@@ -570,6 +627,8 @@ void VisualShader::disconnect_nodes(Type p_type, int p_from_node, int p_from_por
if (E->get().from_node == p_from_node && E->get().from_port == p_from_port && E->get().to_node == p_to_node && E->get().to_port == p_to_port) {
g->connections.erase(E);
g->nodes[p_to_node].prev_connected_nodes.erase(p_from_node);
+ g->nodes[p_from_node].node->set_output_port_connected(p_from_port, false);
+ g->nodes[p_to_node].node->set_input_port_connected(p_to_port, false);
_queue_update();
return;
}
@@ -875,8 +934,12 @@ VisualShader::RenderModeEnums VisualShader::render_mode_enums[] = {
static const char *type_string[VisualShader::TYPE_MAX] = {
"vertex",
"fragment",
- "light"
+ "light",
+ "emit",
+ "process",
+ "end"
};
+
bool VisualShader::_set(const StringName &p_name, const Variant &p_value) {
String name = p_name;
if (name == "mode") {
@@ -1105,6 +1168,38 @@ Error VisualShader::_write_node(Type type, StringBuilder &global_code, StringBui
// then this node
+ Vector<VisualShader::DefaultTextureParam> params = vsnode->get_default_texture_parameters(type, node);
+ for (int i = 0; i < params.size(); i++) {
+ def_tex_params.push_back(params[i]);
+ }
+
+ Ref<VisualShaderNodeInput> input = vsnode;
+ bool skip_global = input.is_valid() && for_preview;
+
+ if (!skip_global) {
+ Ref<VisualShaderNodeUniform> uniform = vsnode;
+ if (!uniform.is_valid() || !uniform->is_global_code_generated()) {
+ global_code += vsnode->generate_global(get_mode(), type, node);
+ }
+
+ String class_name = vsnode->get_class_name();
+ if (class_name == "VisualShaderNodeCustom") {
+ class_name = vsnode->get_script_instance()->get_script()->get_path();
+ }
+ if (!r_classes.has(class_name)) {
+ global_code_per_node += vsnode->generate_global_per_node(get_mode(), type, node);
+ for (int i = 0; i < TYPE_MAX; i++) {
+ global_code_per_func[Type(i)] += vsnode->generate_global_per_func(get_mode(), Type(i), node);
+ }
+ r_classes.insert(class_name);
+ }
+ }
+
+ if (!vsnode->is_code_generated()) { // just generate globals and ignore locals
+ processed.insert(node);
+ return OK;
+ }
+
code += "// " + vsnode->get_caption() + ":" + itos(node) + "\n";
Vector<String> input_vars;
@@ -1163,6 +1258,10 @@ Error VisualShader::_write_node(Type type, StringBuilder &global_code, StringBui
inputs[i] = "int(" + src_var + ")";
}
} else {
+ if (!vsnode->is_generate_input_var(i)) {
+ continue;
+ }
+
Variant defval = vsnode->get_input_port_default_value(i);
if (defval.get_type() == Variant::FLOAT) {
float val = defval;
@@ -1255,36 +1354,25 @@ Error VisualShader::_write_node(Type type, StringBuilder &global_code, StringBui
}
}
- Vector<VisualShader::DefaultTextureParam> params = vsnode->get_default_texture_parameters(type, node);
- for (int i = 0; i < params.size(); i++) {
- def_tex_params.push_back(params[i]);
- }
+ code += vsnode->generate_code(get_mode(), type, node, inputs, outputs, for_preview);
- Ref<VisualShaderNodeInput> input = vsnode;
- bool skip_global = input.is_valid() && for_preview;
+ code += "\n"; //
+ processed.insert(node);
- if (!skip_global) {
- global_code += vsnode->generate_global(get_mode(), type, node);
+ return OK;
+}
- String class_name = vsnode->get_class_name();
- if (class_name == "VisualShaderNodeCustom") {
- class_name = vsnode->get_script_instance()->get_script()->get_language()->get_global_class_name(vsnode->get_script_instance()->get_script()->get_path());
- }
- if (!r_classes.has(class_name)) {
- global_code_per_node += vsnode->generate_global_per_node(get_mode(), type, node);
- for (int i = 0; i < TYPE_MAX; i++) {
- global_code_per_func[Type(i)] += vsnode->generate_global_per_func(get_mode(), Type(i), node);
+bool VisualShader::has_func_name(RenderingServer::ShaderMode p_mode, const String &p_func_name) const {
+ if (!ShaderTypes::get_singleton()->get_functions(p_mode).has(p_func_name)) {
+ if (p_mode == RenderingServer::ShaderMode::SHADER_PARTICLES) {
+ if (p_func_name == "emit" || p_func_name == "process" || p_func_name == "end") {
+ return true;
}
- r_classes.insert(class_name);
}
+ return false;
}
- code += vsnode->generate_code(get_mode(), type, node, inputs, outputs, for_preview);
-
- code += "\n"; //
- processed.insert(node);
-
- return OK;
+ return true;
}
void VisualShader::_update_shader() const {
@@ -1310,10 +1398,19 @@ void VisualShader::_update_shader() const {
{
//fill render mode enums
int idx = 0;
+ bool specular = false;
while (render_mode_enums[idx].string) {
if (shader_mode == render_mode_enums[idx].mode) {
- if (modes.has(render_mode_enums[idx].string)) {
- int which = modes[render_mode_enums[idx].string];
+ if (shader_mode == Shader::MODE_SPATIAL) {
+ if (String(render_mode_enums[idx].string) == "specular") {
+ specular = true;
+ }
+ }
+ if (modes.has(render_mode_enums[idx].string) || specular) {
+ int which = 0;
+ if (modes.has(render_mode_enums[idx].string)) {
+ which = modes[render_mode_enums[idx].string];
+ }
int count = 0;
for (int i = 0; i < ShaderTypes::get_singleton()->get_modes(RenderingServer::ShaderMode(shader_mode)).size(); i++) {
String mode = ShaderTypes::get_singleton()->get_modes(RenderingServer::ShaderMode(shader_mode))[i];
@@ -1349,11 +1446,14 @@ void VisualShader::_update_shader() const {
global_code += "render_mode " + render_mode + ";\n\n";
}
- static const char *func_name[TYPE_MAX] = { "vertex", "fragment", "light" };
+ static const char *func_name[TYPE_MAX] = { "vertex", "fragment", "light", "emit", "process", "end" };
String global_expressions;
+ Set<String> used_uniform_names;
+ List<VisualShaderNodeUniform *> uniforms;
+
for (int i = 0, index = 0; i < TYPE_MAX; i++) {
- if (!ShaderTypes::get_singleton()->get_functions(RenderingServer::ShaderMode(shader_mode)).has(func_name[i])) {
+ if (!has_func_name(RenderingServer::ShaderMode(shader_mode), func_name[i])) {
continue;
}
@@ -1367,11 +1467,31 @@ void VisualShader::_update_shader() const {
expr += "\n";
global_expressions += expr;
}
+ Ref<VisualShaderNodeUniformRef> uniform_ref = Object::cast_to<VisualShaderNodeUniformRef>(E->get().node.ptr());
+ if (uniform_ref.is_valid()) {
+ used_uniform_names.insert(uniform_ref->get_uniform_name());
+ }
+ Ref<VisualShaderNodeUniform> uniform = Object::cast_to<VisualShaderNodeUniform>(E->get().node.ptr());
+ if (uniform.is_valid()) {
+ uniforms.push_back(uniform.ptr());
+ }
}
}
+ for (int i = 0; i < uniforms.size(); i++) {
+ VisualShaderNodeUniform *uniform = uniforms[i];
+ if (used_uniform_names.has(uniform->get_uniform_name())) {
+ global_code += uniform->generate_global(get_mode(), Type(i), -1);
+ const_cast<VisualShaderNodeUniform *>(uniform)->set_global_code_generated(true);
+ } else {
+ const_cast<VisualShaderNodeUniform *>(uniform)->set_global_code_generated(false);
+ }
+ }
+
+ Map<int, String> code_map;
+
for (int i = 0; i < TYPE_MAX; i++) {
- if (!ShaderTypes::get_singleton()->get_functions(RenderingServer::ShaderMode(shader_mode)).has(func_name[i])) {
+ if (!has_func_name(RenderingServer::ShaderMode(shader_mode), func_name[i])) {
continue;
}
@@ -1379,6 +1499,8 @@ void VisualShader::_update_shader() const {
VMap<ConnectionKey, const List<Connection>::Element *> input_connections;
VMap<ConnectionKey, const List<Connection>::Element *> output_connections;
+ StringBuilder func_code;
+
for (const List<Connection>::Element *E = graph[i].connections.front(); E; E = E->next()) {
ConnectionKey from_key;
from_key.node = E->get().from_node;
@@ -1392,14 +1514,30 @@ void VisualShader::_update_shader() const {
input_connections.insert(to_key, E);
}
-
- code += "\nvoid " + String(func_name[i]) + "() {\n";
+ if (shader_mode != Shader::MODE_PARTICLES) {
+ func_code += "\nvoid " + String(func_name[i]) + "() {\n";
+ }
+ insertion_pos.insert(i, code.get_string_length() + func_code.get_string_length());
Set<int> processed;
- Error err = _write_node(Type(i), global_code, global_code_per_node, global_code_per_func, code, default_tex_params, input_connections, output_connections, NODE_ID_OUTPUT, processed, false, classes);
+ Error err = _write_node(Type(i), global_code, global_code_per_node, global_code_per_func, func_code, default_tex_params, input_connections, output_connections, NODE_ID_OUTPUT, processed, false, classes);
ERR_FAIL_COND(err != OK);
- insertion_pos.insert(i, code.get_string_length());
+ if (shader_mode == Shader::MODE_PARTICLES) {
+ code_map.insert(i, func_code);
+ } else {
+ func_code += "}\n";
+ code += func_code;
+ }
+ }
+
+ if (shader_mode == Shader::MODE_PARTICLES) {
+ code += "\nvoid compute() {\n";
+ code += "\tif (RESTART) {\n";
+ code += code_map[TYPE_EMIT];
+ code += "\t} else {\n";
+ code += code_map[TYPE_PROCESS];
+ code += "\t}\n";
code += "}\n";
}
@@ -1410,7 +1548,7 @@ void VisualShader::_update_shader() const {
final_code += global_expressions;
String tcode = code;
for (int i = 0; i < TYPE_MAX; i++) {
- if (!ShaderTypes::get_singleton()->get_functions(RenderingServer::ShaderMode(shader_mode)).has(func_name[i])) {
+ if (!has_func_name(RenderingServer::ShaderMode(shader_mode), func_name[i])) {
continue;
}
tcode = tcode.insert(insertion_pos[i], global_code_per_func[Type(i)]);
@@ -1489,9 +1627,14 @@ void VisualShader::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "graph_offset", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_graph_offset", "get_graph_offset");
ADD_PROPERTY(PropertyInfo(Variant::STRING, "version", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_version", "get_version");
+ ADD_PROPERTY_DEFAULT("code", ""); // Inherited from Shader, prevents showing default code as override in docs.
+
BIND_ENUM_CONSTANT(TYPE_VERTEX);
BIND_ENUM_CONSTANT(TYPE_FRAGMENT);
BIND_ENUM_CONSTANT(TYPE_LIGHT);
+ BIND_ENUM_CONSTANT(TYPE_EMIT);
+ BIND_ENUM_CONSTANT(TYPE_PROCESS);
+ BIND_ENUM_CONSTANT(TYPE_END);
BIND_ENUM_CONSTANT(TYPE_MAX);
BIND_CONSTANT(NODE_ID_INVALID);
@@ -1499,8 +1642,6 @@ void VisualShader::_bind_methods() {
}
VisualShader::VisualShader() {
- shader_mode = Shader::MODE_SPATIAL;
-
for (int i = 0; i < TYPE_MAX; i++) {
Ref<VisualShaderNodeOutput> output;
output.instance();
@@ -1509,8 +1650,6 @@ VisualShader::VisualShader() {
graph[i].nodes[NODE_ID_OUTPUT].node = output;
graph[i].nodes[NODE_ID_OUTPUT].position = Vector2(400, 150);
}
-
- dirty = true;
}
///////////////////////////////////////////////////////////
@@ -1633,22 +1772,50 @@ const VisualShaderNodeInput::Port VisualShaderNodeInput::ports[] = {
{ Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_SCALAR, "time", "TIME" },
{ Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_SAMPLER, "texture", "TEXTURE" },
- // Particles, Vertex
- { Shader::MODE_PARTICLES, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR, "color", "COLOR.rgb" },
- { Shader::MODE_PARTICLES, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR, "alpha", "COLOR.a" },
- { Shader::MODE_PARTICLES, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR, "velocity", "VELOCITY" },
- { Shader::MODE_PARTICLES, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR, "restart", "float(RESTART ? 1.0 : 0.0)" },
- { Shader::MODE_PARTICLES, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR, "active", "float(ACTIVE ? 1.0 : 0.0)" },
- { Shader::MODE_PARTICLES, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR, "custom", "CUSTOM.rgb" },
- { Shader::MODE_PARTICLES, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR, "custom_alpha", "CUSTOM.a" },
- { Shader::MODE_PARTICLES, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_TRANSFORM, "transform", "TRANSFORM" },
-
- { Shader::MODE_PARTICLES, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR, "delta", "DELTA" },
- { Shader::MODE_PARTICLES, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR, "lifetime", "LIFETIME" },
- { Shader::MODE_PARTICLES, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR_INT, "index", "INDEX" },
-
- { Shader::MODE_PARTICLES, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_TRANSFORM, "emission_transform", "EMISSION_TRANSFORM" },
- { Shader::MODE_PARTICLES, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR, "time", "TIME" },
+ // Particles, Emit
+ { Shader::MODE_PARTICLES, VisualShader::TYPE_EMIT, VisualShaderNode::PORT_TYPE_VECTOR, "color", "COLOR.rgb" },
+ { Shader::MODE_PARTICLES, VisualShader::TYPE_EMIT, VisualShaderNode::PORT_TYPE_SCALAR, "alpha", "COLOR.a" },
+ { Shader::MODE_PARTICLES, VisualShader::TYPE_EMIT, VisualShaderNode::PORT_TYPE_VECTOR, "velocity", "VELOCITY" },
+ { Shader::MODE_PARTICLES, VisualShader::TYPE_EMIT, VisualShaderNode::PORT_TYPE_SCALAR, "restart", "float(RESTART ? 1.0 : 0.0)" },
+ { Shader::MODE_PARTICLES, VisualShader::TYPE_EMIT, VisualShaderNode::PORT_TYPE_SCALAR, "active", "float(ACTIVE ? 1.0 : 0.0)" },
+ { Shader::MODE_PARTICLES, VisualShader::TYPE_EMIT, VisualShaderNode::PORT_TYPE_VECTOR, "custom", "CUSTOM.rgb" },
+ { Shader::MODE_PARTICLES, VisualShader::TYPE_EMIT, VisualShaderNode::PORT_TYPE_SCALAR, "custom_alpha", "CUSTOM.a" },
+ { Shader::MODE_PARTICLES, VisualShader::TYPE_EMIT, VisualShaderNode::PORT_TYPE_TRANSFORM, "transform", "TRANSFORM" },
+ { Shader::MODE_PARTICLES, VisualShader::TYPE_EMIT, VisualShaderNode::PORT_TYPE_SCALAR, "delta", "DELTA" },
+ { Shader::MODE_PARTICLES, VisualShader::TYPE_EMIT, VisualShaderNode::PORT_TYPE_SCALAR, "lifetime", "LIFETIME" },
+ { Shader::MODE_PARTICLES, VisualShader::TYPE_EMIT, VisualShaderNode::PORT_TYPE_SCALAR_INT, "index", "INDEX" },
+ { Shader::MODE_PARTICLES, VisualShader::TYPE_EMIT, VisualShaderNode::PORT_TYPE_TRANSFORM, "emission_transform", "EMISSION_TRANSFORM" },
+ { Shader::MODE_PARTICLES, VisualShader::TYPE_EMIT, VisualShaderNode::PORT_TYPE_SCALAR, "time", "TIME" },
+
+ // Particles, Process
+ { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS, VisualShaderNode::PORT_TYPE_VECTOR, "color", "COLOR.rgb" },
+ { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS, VisualShaderNode::PORT_TYPE_SCALAR, "alpha", "COLOR.a" },
+ { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS, VisualShaderNode::PORT_TYPE_VECTOR, "velocity", "VELOCITY" },
+ { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS, VisualShaderNode::PORT_TYPE_SCALAR, "restart", "float(RESTART ? 1.0 : 0.0)" },
+ { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS, VisualShaderNode::PORT_TYPE_SCALAR, "active", "float(ACTIVE ? 1.0 : 0.0)" },
+ { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS, VisualShaderNode::PORT_TYPE_VECTOR, "custom", "CUSTOM.rgb" },
+ { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS, VisualShaderNode::PORT_TYPE_SCALAR, "custom_alpha", "CUSTOM.a" },
+ { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS, VisualShaderNode::PORT_TYPE_TRANSFORM, "transform", "TRANSFORM" },
+ { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS, VisualShaderNode::PORT_TYPE_SCALAR, "delta", "DELTA" },
+ { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS, VisualShaderNode::PORT_TYPE_SCALAR, "lifetime", "LIFETIME" },
+ { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS, VisualShaderNode::PORT_TYPE_SCALAR_INT, "index", "INDEX" },
+ { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS, VisualShaderNode::PORT_TYPE_TRANSFORM, "emission_transform", "EMISSION_TRANSFORM" },
+ { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS, VisualShaderNode::PORT_TYPE_SCALAR, "time", "TIME" },
+
+ // Particles, End
+ { Shader::MODE_PARTICLES, VisualShader::TYPE_END, VisualShaderNode::PORT_TYPE_VECTOR, "color", "COLOR.rgb" },
+ { Shader::MODE_PARTICLES, VisualShader::TYPE_END, VisualShaderNode::PORT_TYPE_SCALAR, "alpha", "COLOR.a" },
+ { Shader::MODE_PARTICLES, VisualShader::TYPE_END, VisualShaderNode::PORT_TYPE_VECTOR, "velocity", "VELOCITY" },
+ { Shader::MODE_PARTICLES, VisualShader::TYPE_END, VisualShaderNode::PORT_TYPE_SCALAR, "restart", "float(RESTART ? 1.0 : 0.0)" },
+ { Shader::MODE_PARTICLES, VisualShader::TYPE_END, VisualShaderNode::PORT_TYPE_SCALAR, "active", "float(ACTIVE ? 1.0 : 0.0)" },
+ { Shader::MODE_PARTICLES, VisualShader::TYPE_END, VisualShaderNode::PORT_TYPE_VECTOR, "custom", "CUSTOM.rgb" },
+ { Shader::MODE_PARTICLES, VisualShader::TYPE_END, VisualShaderNode::PORT_TYPE_SCALAR, "custom_alpha", "CUSTOM.a" },
+ { Shader::MODE_PARTICLES, VisualShader::TYPE_END, VisualShaderNode::PORT_TYPE_TRANSFORM, "transform", "TRANSFORM" },
+ { Shader::MODE_PARTICLES, VisualShader::TYPE_END, VisualShaderNode::PORT_TYPE_SCALAR, "delta", "DELTA" },
+ { Shader::MODE_PARTICLES, VisualShader::TYPE_END, VisualShaderNode::PORT_TYPE_SCALAR, "lifetime", "LIFETIME" },
+ { Shader::MODE_PARTICLES, VisualShader::TYPE_END, VisualShaderNode::PORT_TYPE_SCALAR_INT, "index", "INDEX" },
+ { Shader::MODE_PARTICLES, VisualShader::TYPE_END, VisualShaderNode::PORT_TYPE_TRANSFORM, "emission_transform", "EMISSION_TRANSFORM" },
+ { Shader::MODE_PARTICLES, VisualShader::TYPE_END, VisualShaderNode::PORT_TYPE_SCALAR, "time", "TIME" },
// Sky, Fragment
{ Shader::MODE_SKY, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_BOOLEAN, "at_cubemap_pass", "AT_CUBEMAP_PASS" },
@@ -1950,10 +2117,218 @@ void VisualShaderNodeInput::_bind_methods() {
}
VisualShaderNodeInput::VisualShaderNodeInput() {
- input_name = "[None]";
- // changed when set
- shader_type = VisualShader::TYPE_MAX;
- shader_mode = Shader::MODE_MAX;
+}
+
+////////////// UniformRef
+
+List<VisualShaderNodeUniformRef::Uniform> uniforms;
+
+void VisualShaderNodeUniformRef::add_uniform(const String &p_name, UniformType p_type) {
+ uniforms.push_back({ p_name, p_type });
+}
+
+void VisualShaderNodeUniformRef::clear_uniforms() {
+ uniforms.clear();
+}
+
+bool VisualShaderNodeUniformRef::has_uniform(const String &p_name) {
+ for (List<VisualShaderNodeUniformRef::Uniform>::Element *E = uniforms.front(); E; E = E->next()) {
+ if (E->get().name == p_name) {
+ return true;
+ }
+ }
+ return false;
+}
+
+String VisualShaderNodeUniformRef::get_caption() const {
+ return "UniformRef";
+}
+
+int VisualShaderNodeUniformRef::get_input_port_count() const {
+ return 0;
+}
+
+VisualShaderNodeUniformRef::PortType VisualShaderNodeUniformRef::get_input_port_type(int p_port) const {
+ return PortType::PORT_TYPE_SCALAR;
+}
+
+String VisualShaderNodeUniformRef::get_input_port_name(int p_port) const {
+ return "";
+}
+
+int VisualShaderNodeUniformRef::get_output_port_count() const {
+ switch (uniform_type) {
+ case UniformType::UNIFORM_TYPE_FLOAT:
+ return 1;
+ case UniformType::UNIFORM_TYPE_INT:
+ return 1;
+ case UniformType::UNIFORM_TYPE_BOOLEAN:
+ return 1;
+ case UniformType::UNIFORM_TYPE_VECTOR:
+ return 1;
+ case UniformType::UNIFORM_TYPE_TRANSFORM:
+ return 1;
+ case UniformType::UNIFORM_TYPE_COLOR:
+ return 2;
+ case UniformType::UNIFORM_TYPE_SAMPLER:
+ return 1;
+ default:
+ break;
+ }
+ return 1;
+}
+
+VisualShaderNodeUniformRef::PortType VisualShaderNodeUniformRef::get_output_port_type(int p_port) const {
+ switch (uniform_type) {
+ case UniformType::UNIFORM_TYPE_FLOAT:
+ return PortType::PORT_TYPE_SCALAR;
+ case UniformType::UNIFORM_TYPE_INT:
+ return PortType::PORT_TYPE_SCALAR_INT;
+ case UniformType::UNIFORM_TYPE_BOOLEAN:
+ return PortType::PORT_TYPE_BOOLEAN;
+ case UniformType::UNIFORM_TYPE_VECTOR:
+ return PortType::PORT_TYPE_VECTOR;
+ case UniformType::UNIFORM_TYPE_TRANSFORM:
+ return PortType::PORT_TYPE_TRANSFORM;
+ case UniformType::UNIFORM_TYPE_COLOR:
+ if (p_port == 0) {
+ return PortType::PORT_TYPE_VECTOR;
+ } else if (p_port == 1) {
+ return PORT_TYPE_SCALAR;
+ }
+ break;
+ case UniformType::UNIFORM_TYPE_SAMPLER:
+ return PortType::PORT_TYPE_SAMPLER;
+ default:
+ break;
+ }
+ return PORT_TYPE_SCALAR;
+}
+
+String VisualShaderNodeUniformRef::get_output_port_name(int p_port) const {
+ switch (uniform_type) {
+ case UniformType::UNIFORM_TYPE_FLOAT:
+ return "";
+ case UniformType::UNIFORM_TYPE_INT:
+ return "";
+ case UniformType::UNIFORM_TYPE_BOOLEAN:
+ return "";
+ case UniformType::UNIFORM_TYPE_VECTOR:
+ return "";
+ case UniformType::UNIFORM_TYPE_TRANSFORM:
+ return "";
+ case UniformType::UNIFORM_TYPE_COLOR:
+ if (p_port == 0) {
+ return "rgb";
+ } else if (p_port == 1) {
+ return "alpha";
+ }
+ break;
+ case UniformType::UNIFORM_TYPE_SAMPLER:
+ return "";
+ break;
+ default:
+ break;
+ }
+ return "";
+}
+
+void VisualShaderNodeUniformRef::set_uniform_name(const String &p_name) {
+ uniform_name = p_name;
+ if (uniform_name != "[None]") {
+ uniform_type = get_uniform_type_by_name(uniform_name);
+ } else {
+ uniform_type = UniformType::UNIFORM_TYPE_FLOAT;
+ }
+ emit_changed();
+}
+
+String VisualShaderNodeUniformRef::get_uniform_name() const {
+ return uniform_name;
+}
+
+int VisualShaderNodeUniformRef::get_uniforms_count() const {
+ return uniforms.size();
+}
+
+String VisualShaderNodeUniformRef::get_uniform_name_by_index(int p_idx) const {
+ if (p_idx >= 0 && p_idx < uniforms.size()) {
+ return uniforms[p_idx].name;
+ }
+ return "";
+}
+
+VisualShaderNodeUniformRef::UniformType VisualShaderNodeUniformRef::get_uniform_type_by_name(const String &p_name) const {
+ for (int i = 0; i < uniforms.size(); i++) {
+ if (uniforms[i].name == p_name) {
+ return uniforms[i].type;
+ }
+ }
+ return UniformType::UNIFORM_TYPE_FLOAT;
+}
+
+VisualShaderNodeUniformRef::UniformType VisualShaderNodeUniformRef::get_uniform_type_by_index(int p_idx) const {
+ if (p_idx >= 0 && p_idx < uniforms.size()) {
+ return uniforms[p_idx].type;
+ }
+ return UniformType::UNIFORM_TYPE_FLOAT;
+}
+
+String VisualShaderNodeUniformRef::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 {
+ switch (uniform_type) {
+ case UniformType::UNIFORM_TYPE_FLOAT:
+ if (uniform_name == "[None]") {
+ return "\t" + p_output_vars[0] + " = 0.0;\n";
+ }
+ return "\t" + p_output_vars[0] + " = " + get_uniform_name() + ";\n";
+ case UniformType::UNIFORM_TYPE_INT:
+ return "\t" + p_output_vars[0] + " = " + get_uniform_name() + ";\n";
+ case UniformType::UNIFORM_TYPE_BOOLEAN:
+ return "\t" + p_output_vars[0] + " = " + get_uniform_name() + ";\n";
+ case UniformType::UNIFORM_TYPE_VECTOR:
+ return "\t" + p_output_vars[0] + " = " + get_uniform_name() + ";\n";
+ case UniformType::UNIFORM_TYPE_TRANSFORM:
+ return "\t" + p_output_vars[0] + " = " + get_uniform_name() + ";\n";
+ case UniformType::UNIFORM_TYPE_COLOR: {
+ String code = "\t" + p_output_vars[0] + " = " + get_uniform_name() + ".rgb;\n";
+ code += "\t" + p_output_vars[1] + " = " + get_uniform_name() + ".a;\n";
+ return code;
+ } break;
+ case UniformType::UNIFORM_TYPE_SAMPLER:
+ break;
+ default:
+ break;
+ }
+ return "";
+}
+
+void VisualShaderNodeUniformRef::_set_uniform_type(int p_uniform_type) {
+ uniform_type = (UniformType)p_uniform_type;
+}
+
+int VisualShaderNodeUniformRef::_get_uniform_type() const {
+ return (int)uniform_type;
+}
+
+void VisualShaderNodeUniformRef::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("set_uniform_name", "name"), &VisualShaderNodeUniformRef::set_uniform_name);
+ ClassDB::bind_method(D_METHOD("get_uniform_name"), &VisualShaderNodeUniformRef::get_uniform_name);
+
+ ClassDB::bind_method(D_METHOD("_set_uniform_type", "type"), &VisualShaderNodeUniformRef::_set_uniform_type);
+ ClassDB::bind_method(D_METHOD("_get_uniform_type"), &VisualShaderNodeUniformRef::_get_uniform_type);
+
+ ADD_PROPERTY(PropertyInfo(Variant::STRING_NAME, "uniform_name", PROPERTY_HINT_ENUM, ""), "set_uniform_name", "get_uniform_name");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "uniform_type", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "_set_uniform_type", "_get_uniform_type");
+}
+
+Vector<StringName> VisualShaderNodeUniformRef::get_editable_properties() const {
+ Vector<StringName> props;
+ props.push_back("uniform_name");
+ props.push_back("uniform_type");
+ return props;
+}
+
+VisualShaderNodeUniformRef::VisualShaderNodeUniformRef() {
}
////////////////////////////////////////////
@@ -2012,13 +2387,30 @@ const VisualShaderNodeOutput::Port VisualShaderNodeOutput::ports[] = {
// Canvas Item, Light
{ Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR, "light", "LIGHT.rgb" },
{ Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_SCALAR, "light_alpha", "LIGHT.a" },
- // Particles, Vertex
- { Shader::MODE_PARTICLES, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR, "color", "COLOR.rgb" },
- { Shader::MODE_PARTICLES, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR, "alpha", "COLOR.a" },
- { Shader::MODE_PARTICLES, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR, "velocity", "VELOCITY" },
- { Shader::MODE_PARTICLES, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR, "custom", "CUSTOM.rgb" },
- { Shader::MODE_PARTICLES, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR, "custom_alpha", "CUSTOM.a" },
- { Shader::MODE_PARTICLES, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_TRANSFORM, "transform", "TRANSFORM" },
+ // Particles, Emit
+ { Shader::MODE_PARTICLES, VisualShader::TYPE_EMIT, VisualShaderNode::PORT_TYPE_VECTOR, "color", "COLOR.rgb" },
+ { Shader::MODE_PARTICLES, VisualShader::TYPE_EMIT, VisualShaderNode::PORT_TYPE_SCALAR, "alpha", "COLOR.a" },
+ { Shader::MODE_PARTICLES, VisualShader::TYPE_EMIT, VisualShaderNode::PORT_TYPE_VECTOR, "velocity", "VELOCITY" },
+ { Shader::MODE_PARTICLES, VisualShader::TYPE_EMIT, VisualShaderNode::PORT_TYPE_VECTOR, "custom", "CUSTOM.rgb" },
+ { Shader::MODE_PARTICLES, VisualShader::TYPE_EMIT, VisualShaderNode::PORT_TYPE_SCALAR, "custom_alpha", "CUSTOM.a" },
+ { Shader::MODE_PARTICLES, VisualShader::TYPE_EMIT, VisualShaderNode::PORT_TYPE_TRANSFORM, "transform", "TRANSFORM" },
+ { Shader::MODE_PARTICLES, VisualShader::TYPE_EMIT, VisualShaderNode::PORT_TYPE_BOOLEAN, "active", "ACTIVE" },
+ // Particles, Process
+ { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS, VisualShaderNode::PORT_TYPE_VECTOR, "color", "COLOR.rgb" },
+ { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS, VisualShaderNode::PORT_TYPE_SCALAR, "alpha", "COLOR.a" },
+ { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS, VisualShaderNode::PORT_TYPE_VECTOR, "velocity", "VELOCITY" },
+ { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS, VisualShaderNode::PORT_TYPE_VECTOR, "custom", "CUSTOM.rgb" },
+ { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS, VisualShaderNode::PORT_TYPE_SCALAR, "custom_alpha", "CUSTOM.a" },
+ { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS, VisualShaderNode::PORT_TYPE_TRANSFORM, "transform", "TRANSFORM" },
+ { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS, VisualShaderNode::PORT_TYPE_BOOLEAN, "active", "ACTIVE" },
+ // Particles, End
+ { Shader::MODE_PARTICLES, VisualShader::TYPE_END, VisualShaderNode::PORT_TYPE_VECTOR, "color", "COLOR.rgb" },
+ { Shader::MODE_PARTICLES, VisualShader::TYPE_END, VisualShaderNode::PORT_TYPE_SCALAR, "alpha", "COLOR.a" },
+ { Shader::MODE_PARTICLES, VisualShader::TYPE_END, VisualShaderNode::PORT_TYPE_VECTOR, "velocity", "VELOCITY" },
+ { Shader::MODE_PARTICLES, VisualShader::TYPE_END, VisualShaderNode::PORT_TYPE_VECTOR, "custom", "CUSTOM.rgb" },
+ { Shader::MODE_PARTICLES, VisualShader::TYPE_END, VisualShaderNode::PORT_TYPE_SCALAR, "custom_alpha", "CUSTOM.a" },
+ { Shader::MODE_PARTICLES, VisualShader::TYPE_END, VisualShaderNode::PORT_TYPE_TRANSFORM, "transform", "TRANSFORM" },
+ { Shader::MODE_PARTICLES, VisualShader::TYPE_END, VisualShaderNode::PORT_TYPE_BOOLEAN, "active", "ACTIVE" },
// Sky, Fragment
{ Shader::MODE_SKY, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR, "color", "COLOR" },
{ Shader::MODE_SKY, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR, "alpha", "ALPHA" },
@@ -2149,6 +2541,14 @@ VisualShaderNodeUniform::Qualifier VisualShaderNodeUniform::get_qualifier() cons
return qualifier;
}
+void VisualShaderNodeUniform::set_global_code_generated(bool p_enabled) {
+ global_code_generated = p_enabled;
+}
+
+bool VisualShaderNodeUniform::is_global_code_generated() const {
+ return global_code_generated;
+}
+
void VisualShaderNodeUniform::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_uniform_name", "name"), &VisualShaderNodeUniform::set_uniform_name);
ClassDB::bind_method(D_METHOD("get_uniform_name"), &VisualShaderNodeUniform::get_uniform_name);
@@ -2198,7 +2598,6 @@ Vector<StringName> VisualShaderNodeUniform::get_editable_properties() const {
}
VisualShaderNodeUniform::VisualShaderNodeUniform() {
- qualifier = QUAL_NONE;
}
////////////// GroupBase
@@ -2330,6 +2729,7 @@ void VisualShaderNodeGroupBase::add_input_port(int p_id, int p_type, const Strin
}
_apply_port_changes();
+ emit_changed();
}
void VisualShaderNodeGroupBase::remove_input_port(int p_id) {
@@ -2354,6 +2754,7 @@ void VisualShaderNodeGroupBase::remove_input_port(int p_id) {
}
_apply_port_changes();
+ emit_changed();
}
int VisualShaderNodeGroupBase::get_input_port_count() const {
@@ -2398,6 +2799,7 @@ void VisualShaderNodeGroupBase::add_output_port(int p_id, int p_type, const Stri
}
_apply_port_changes();
+ emit_changed();
}
void VisualShaderNodeGroupBase::remove_output_port(int p_id) {
@@ -2422,6 +2824,7 @@ void VisualShaderNodeGroupBase::remove_output_port(int p_id) {
}
_apply_port_changes();
+ emit_changed();
}
int VisualShaderNodeGroupBase::get_output_port_count() const {
@@ -2468,6 +2871,7 @@ void VisualShaderNodeGroupBase::set_input_port_type(int p_id, int p_type) {
inputs = inputs.insert(index, itos(p_type));
_apply_port_changes();
+ emit_changed();
}
VisualShaderNodeGroupBase::PortType VisualShaderNodeGroupBase::get_input_port_type(int p_id) const {
@@ -2503,6 +2907,7 @@ void VisualShaderNodeGroupBase::set_input_port_name(int p_id, const String &p_na
inputs = inputs.insert(index, p_name);
_apply_port_changes();
+ emit_changed();
}
String VisualShaderNodeGroupBase::get_input_port_name(int p_id) const {
@@ -2538,6 +2943,7 @@ void VisualShaderNodeGroupBase::set_output_port_type(int p_id, int p_type) {
outputs = outputs.insert(index, itos(p_type));
_apply_port_changes();
+ emit_changed();
}
VisualShaderNodeGroupBase::PortType VisualShaderNodeGroupBase::get_output_port_type(int p_id) const {
@@ -2573,6 +2979,7 @@ void VisualShaderNodeGroupBase::set_output_port_name(int p_id, const String &p_n
outputs = outputs.insert(index, p_name);
_apply_port_changes();
+ emit_changed();
}
String VisualShaderNodeGroupBase::get_output_port_name(int p_id) const {
@@ -2672,10 +3079,6 @@ String VisualShaderNodeGroupBase::generate_code(Shader::Mode p_mode, VisualShade
}
VisualShaderNodeGroupBase::VisualShaderNodeGroupBase() {
- size = Size2(0, 0);
- inputs = "";
- outputs = "";
- editable = false;
simple_decl = false;
}
@@ -2687,6 +3090,7 @@ String VisualShaderNodeExpression::get_caption() const {
void VisualShaderNodeExpression::set_expression(const String &p_expression) {
expression = p_expression;
+ emit_changed();
}
String VisualShaderNodeExpression::get_expression() const {
@@ -2800,7 +3204,6 @@ void VisualShaderNodeExpression::_bind_methods() {
}
VisualShaderNodeExpression::VisualShaderNodeExpression() {
- expression = "";
set_editable(true);
}