Merge pull request #31449 from Chaosus/vs_global_expression

Added global expressions to visual shaders
This commit is contained in:
Rémi Verschelde 2019-08-18 17:31:39 +02:00 committed by GitHub
commit 9cd58b6916
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 75 additions and 13 deletions

View File

@ -524,21 +524,23 @@ void VisualShaderEditor::_update_graph() {
offset->set_custom_minimum_size(Size2(0, 6 * EDSCALE));
node->add_child(offset);
HBoxContainer *hb2 = memnew(HBoxContainer);
if (group_node->is_editable()) {
HBoxContainer *hb2 = memnew(HBoxContainer);
Button *add_input_btn = memnew(Button);
add_input_btn->set_text(TTR("Add input +"));
add_input_btn->connect("pressed", this, "_add_input_port", varray(nodes[n_i], group_node->get_free_input_port_id(), VisualShaderNode::PORT_TYPE_VECTOR, "input" + itos(group_node->get_free_input_port_id())), CONNECT_DEFERRED);
hb2->add_child(add_input_btn);
Button *add_input_btn = memnew(Button);
add_input_btn->set_text(TTR("Add input +"));
add_input_btn->connect("pressed", this, "_add_input_port", varray(nodes[n_i], group_node->get_free_input_port_id(), VisualShaderNode::PORT_TYPE_VECTOR, "input" + itos(group_node->get_free_input_port_id())), CONNECT_DEFERRED);
hb2->add_child(add_input_btn);
hb2->add_spacer();
hb2->add_spacer();
Button *add_output_btn = memnew(Button);
add_output_btn->set_text(TTR("Add output +"));
add_output_btn->connect("pressed", this, "_add_output_port", varray(nodes[n_i], group_node->get_free_output_port_id(), VisualShaderNode::PORT_TYPE_VECTOR, "output" + itos(group_node->get_free_output_port_id())), CONNECT_DEFERRED);
hb2->add_child(add_output_btn);
Button *add_output_btn = memnew(Button);
add_output_btn->set_text(TTR("Add output +"));
add_output_btn->connect("pressed", this, "_add_output_port", varray(nodes[n_i], group_node->get_free_output_port_id(), VisualShaderNode::PORT_TYPE_VECTOR, "output" + itos(group_node->get_free_output_port_id())), CONNECT_DEFERRED);
hb2->add_child(add_output_btn);
node->add_child(hb2);
node->add_child(hb2);
}
}
for (int i = 0; i < MAX(vsnode->get_input_port_count(), vsnode->get_output_port_count()); i++) {
@ -2528,6 +2530,7 @@ VisualShaderEditor::VisualShaderEditor() {
add_options.push_back(AddOption("Expression", "Special", "", "VisualShaderNodeExpression", TTR("Custom Godot Shader Language expression, with custom amount of input and output ports. This is a direct injection of code into the vertex/fragment/light function, do not use it to write the function declarations inside.")));
add_options.push_back(AddOption("Fresnel", "Special", "", "VisualShaderNodeFresnel", TTR("Returns falloff based on the dot product of surface normal and view direction of camera (pass associated inputs to it)."), -1, VisualShaderNode::PORT_TYPE_SCALAR));
add_options.push_back(AddOption("GlobalExpression", "Special", "", "VisualShaderNodeGlobalExpression", TTR("Custom Godot Shader Language expression, which placed on top of the resulted shader. You can place various function definitions inside and call it later in the Expressions. You can also declare varyings, uniforms and constants.")));
add_options.push_back(AddOption("ScalarDerivativeFunc", "Special", "Common", "VisualShaderNodeScalarDerivativeFunc", TTR("(Fragment/Light mode only) Scalar derivative function."), -1, VisualShaderNode::PORT_TYPE_SCALAR, VisualShader::TYPE_FRAGMENT | VisualShader::TYPE_LIGHT, -1, -1, true));
add_options.push_back(AddOption("VectorDerivativeFunc", "Special", "Common", "VisualShaderNodeVectorDerivativeFunc", TTR("(Fragment/Light mode only) Vector derivative function."), -1, VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_FRAGMENT | VisualShader::TYPE_LIGHT, -1, -1, true));

View File

@ -530,6 +530,7 @@ void register_scene_types() {
ClassDB::register_class<VisualShaderNodeSwitch>();
ClassDB::register_class<VisualShaderNodeFresnel>();
ClassDB::register_class<VisualShaderNodeExpression>();
ClassDB::register_class<VisualShaderNodeGlobalExpression>();
ClassDB::register_class<VisualShaderNodeIs>();
ClassDB::register_class<VisualShaderNodeCompare>();

View File

@ -1205,6 +1205,22 @@ void VisualShader::_update_shader() const {
static const char *func_name[TYPE_MAX] = { "vertex", "fragment", "light" };
String global_expressions;
for (int i = 0, index = 0; i < TYPE_MAX; i++) {
for (Map<int, Node>::Element *E = graph[i].nodes.front(); E; E = E->next()) {
Ref<VisualShaderNodeGlobalExpression> global_expression = Object::cast_to<VisualShaderNodeGlobalExpression>(E->get().node.ptr());
if (global_expression.is_valid()) {
String expr = "";
expr += "// " + global_expression->get_caption() + ":" + itos(index++) + "\n";
expr += global_expression->generate_global(get_mode(), Type(i), -1);
expr = expr.replace("\n", "\n\t");
expr += "\n";
global_expressions += expr;
}
}
}
for (int i = 0; i < TYPE_MAX; i++) {
//make it faster to go around through shader
@ -1239,6 +1255,7 @@ void VisualShader::_update_shader() const {
global_code += "\n\n";
String final_code = global_code;
final_code += global_code_per_node;
final_code += global_expressions;
String tcode = code;
for (int i = 0; i < TYPE_MAX; i++) {
tcode = tcode.insert(insertion_pos[i], global_code_per_func[Type(i)]);
@ -2333,6 +2350,14 @@ void VisualShaderNodeGroupBase::_apply_port_changes() {
}
}
void VisualShaderNodeGroupBase::set_editable(bool p_enabled) {
editable = p_enabled;
}
bool VisualShaderNodeGroupBase::is_editable() const {
return editable;
}
void VisualShaderNodeGroupBase::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_size", "size"), &VisualShaderNodeGroupBase::set_size);
@ -2368,6 +2393,9 @@ void VisualShaderNodeGroupBase::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_control", "control", "index"), &VisualShaderNodeGroupBase::set_control);
ClassDB::bind_method(D_METHOD("get_control", "index"), &VisualShaderNodeGroupBase::get_control);
ClassDB::bind_method(D_METHOD("set_editable", "enabled"), &VisualShaderNodeGroupBase::set_editable);
ClassDB::bind_method(D_METHOD("is_editable"), &VisualShaderNodeGroupBase::is_editable);
}
String VisualShaderNodeGroupBase::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 {
@ -2378,6 +2406,7 @@ VisualShaderNodeGroupBase::VisualShaderNodeGroupBase() {
size = Size2(0, 0);
inputs = "";
outputs = "";
editable = false;
}
////////////// Expression
@ -2504,4 +2533,19 @@ void VisualShaderNodeExpression::_bind_methods() {
VisualShaderNodeExpression::VisualShaderNodeExpression() {
expression = "";
set_editable(true);
}
////////////// Global Expression
String VisualShaderNodeGlobalExpression::get_caption() const {
return "GlobalExpression";
}
String VisualShaderNodeGlobalExpression::generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const {
return expression;
}
VisualShaderNodeGlobalExpression::VisualShaderNodeGlobalExpression() {
set_editable(false);
}

View File

@ -371,6 +371,7 @@ protected:
Vector2 size;
String inputs;
String outputs;
bool editable;
struct Port {
PortType type;
@ -426,6 +427,9 @@ public:
void set_control(Control *p_control, int p_index);
Control *get_control(int p_index);
void set_editable(bool p_enabled);
bool is_editable() const;
virtual String 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 = false) const;
VisualShaderNodeGroupBase();
@ -434,10 +438,9 @@ public:
class VisualShaderNodeExpression : public VisualShaderNodeGroupBase {
GDCLASS(VisualShaderNodeExpression, VisualShaderNodeGroupBase);
private:
protected:
String expression;
protected:
static void _bind_methods();
public:
@ -453,4 +456,15 @@ public:
VisualShaderNodeExpression();
};
class VisualShaderNodeGlobalExpression : public VisualShaderNodeExpression {
GDCLASS(VisualShaderNodeGlobalExpression, VisualShaderNodeExpression);
public:
virtual String get_caption() const;
virtual String generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const;
VisualShaderNodeGlobalExpression();
};
#endif // VISUAL_SHADER_H