You've already forked godot
mirror of
https://github.com/godotengine/godot.git
synced 2025-11-14 13:41:12 +00:00
Expression node for visual shaders
This commit is contained in:
@@ -159,6 +159,7 @@ Vector2 VisualShader::get_node_position(Type p_type, int p_id) const {
|
||||
ERR_FAIL_COND_V(!g->nodes.has(p_id), Vector2());
|
||||
return g->nodes[p_id].position;
|
||||
}
|
||||
|
||||
Ref<VisualShaderNode> VisualShader::get_node(Type p_type, int p_id) const {
|
||||
ERR_FAIL_INDEX_V(p_type, TYPE_MAX, Ref<VisualShaderNode>());
|
||||
const Graph *g = &graph[p_type];
|
||||
@@ -269,6 +270,18 @@ bool VisualShader::can_connect_nodes(Type p_type, int p_from_node, int p_from_po
|
||||
return true;
|
||||
}
|
||||
|
||||
void VisualShader::connect_nodes_forced(Type p_type, int p_from_node, int p_from_port, int p_to_node, int p_to_port) {
|
||||
ERR_FAIL_INDEX(p_type, TYPE_MAX);
|
||||
Graph *g = &graph[p_type];
|
||||
Connection c;
|
||||
c.from_node = p_from_node;
|
||||
c.from_port = p_from_port;
|
||||
c.to_node = p_to_node;
|
||||
c.to_port = p_to_port;
|
||||
g->connections.push_back(c);
|
||||
_queue_update();
|
||||
}
|
||||
|
||||
Error VisualShader::connect_nodes(Type p_type, int p_from_node, int p_from_port, int p_to_node, int p_to_port) {
|
||||
ERR_FAIL_INDEX_V(p_type, TYPE_MAX, ERR_CANT_CONNECT);
|
||||
Graph *g = &graph[p_type];
|
||||
@@ -304,6 +317,7 @@ Error VisualShader::connect_nodes(Type p_type, int p_from_node, int p_from_port,
|
||||
_queue_update();
|
||||
return OK;
|
||||
}
|
||||
|
||||
void VisualShader::disconnect_nodes(Type p_type, int p_from_node, int p_from_port, int p_to_node, int p_to_port) {
|
||||
ERR_FAIL_INDEX(p_type, TYPE_MAX);
|
||||
Graph *g = &graph[p_type];
|
||||
@@ -334,6 +348,7 @@ Array VisualShader::_get_node_connections(Type p_type) const {
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void VisualShader::get_node_connections(Type p_type, List<Connection> *r_connections) const {
|
||||
ERR_FAIL_INDEX(p_type, TYPE_MAX);
|
||||
const Graph *g = &graph[p_type];
|
||||
@@ -477,6 +492,54 @@ String VisualShader::generate_preview_shader(Type p_type, int p_node, int p_port
|
||||
|
||||
#define IS_SYMBOL_CHAR(m_d) (((m_d) >= 'a' && (m_d) <= 'z') || ((m_d) >= 'A' && (m_d) <= 'Z') || ((m_d) >= '0' && (m_d) <= '9') || (m_d) == '_')
|
||||
|
||||
String VisualShader::validate_port_name(const String &p_name, const List<String> &p_input_ports, const List<String> &p_output_ports) const {
|
||||
String name = p_name;
|
||||
|
||||
while (name.length() && !IS_INITIAL_CHAR(name[0])) {
|
||||
name = name.substr(1, name.length() - 1);
|
||||
}
|
||||
|
||||
if (name != String()) {
|
||||
|
||||
String valid_name;
|
||||
|
||||
for (int i = 0; i < name.length(); i++) {
|
||||
if (IS_SYMBOL_CHAR(name[i])) {
|
||||
valid_name += String::chr(name[i]);
|
||||
} else if (name[i] == ' ') {
|
||||
valid_name += "_";
|
||||
}
|
||||
}
|
||||
|
||||
name = valid_name;
|
||||
}
|
||||
|
||||
String valid_name = name;
|
||||
bool is_equal = false;
|
||||
|
||||
for (int i = 0; i < p_input_ports.size(); i++) {
|
||||
if (name == p_input_ports[i]) {
|
||||
is_equal = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!is_equal) {
|
||||
for (int i = 0; i < p_output_ports.size(); i++) {
|
||||
if (name == p_output_ports[i]) {
|
||||
is_equal = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (is_equal) {
|
||||
name = "";
|
||||
}
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
String VisualShader::validate_uniform_name(const String &p_name, const Ref<VisualShaderNodeUniform> &p_uniform) const {
|
||||
|
||||
String name = p_name; //validate name first
|
||||
@@ -596,7 +659,7 @@ bool VisualShader::_set(const StringName &p_name, const Variant &p_value) {
|
||||
Vector<int> conns = p_value;
|
||||
if (conns.size() % 4 == 0) {
|
||||
for (int i = 0; i < conns.size(); i += 4) {
|
||||
connect_nodes(type, conns[i + 0], conns[i + 1], conns[i + 2], conns[i + 3]);
|
||||
connect_nodes_forced(type, conns[i + 0], conns[i + 1], conns[i + 2], conns[i + 3]);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
@@ -611,6 +674,18 @@ bool VisualShader::_set(const StringName &p_name, const Variant &p_value) {
|
||||
} else if (what == "position") {
|
||||
set_node_position(type, id, p_value);
|
||||
return true;
|
||||
} else if (what == "size") {
|
||||
((VisualShaderNodeGroupBase *)get_node(type, id).ptr())->set_size(p_value);
|
||||
return true;
|
||||
} else if (what == "input_ports") {
|
||||
((VisualShaderNodeGroupBase *)get_node(type, id).ptr())->set_inputs(p_value);
|
||||
return true;
|
||||
} else if (what == "output_ports") {
|
||||
((VisualShaderNodeGroupBase *)get_node(type, id).ptr())->set_outputs(p_value);
|
||||
return true;
|
||||
} else if (what == "expression") {
|
||||
((VisualShaderNodeExpression *)get_node(type, id).ptr())->set_expression(p_value);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
@@ -668,6 +743,18 @@ bool VisualShader::_get(const StringName &p_name, Variant &r_ret) const {
|
||||
} else if (what == "position") {
|
||||
r_ret = get_node_position(type, id);
|
||||
return true;
|
||||
} else if (what == "size") {
|
||||
r_ret = ((VisualShaderNodeGroupBase *)get_node(type, id).ptr())->get_size();
|
||||
return true;
|
||||
} else if (what == "input_ports") {
|
||||
r_ret = ((VisualShaderNodeGroupBase *)get_node(type, id).ptr())->get_inputs();
|
||||
return true;
|
||||
} else if (what == "output_ports") {
|
||||
r_ret = ((VisualShaderNodeGroupBase *)get_node(type, id).ptr())->get_outputs();
|
||||
return true;
|
||||
} else if (what == "expression") {
|
||||
r_ret = ((VisualShaderNodeExpression *)get_node(type, id).ptr())->get_expression();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
@@ -727,6 +814,15 @@ void VisualShader::_get_property_list(List<PropertyInfo> *p_list) const {
|
||||
p_list->push_back(PropertyInfo(Variant::OBJECT, prop_name + "/node", PROPERTY_HINT_RESOURCE_TYPE, "VisualShaderNode", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_DO_NOT_SHARE_ON_DUPLICATE));
|
||||
}
|
||||
p_list->push_back(PropertyInfo(Variant::VECTOR2, prop_name + "/position", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR));
|
||||
|
||||
if (Object::cast_to<VisualShaderNodeGroupBase>(E->get().node.ptr()) != NULL) {
|
||||
p_list->push_back(PropertyInfo(Variant::VECTOR2, prop_name + "/size", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR));
|
||||
p_list->push_back(PropertyInfo(Variant::STRING, prop_name + "/input_ports", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR));
|
||||
p_list->push_back(PropertyInfo(Variant::STRING, prop_name + "/output_ports", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR));
|
||||
}
|
||||
if (Object::cast_to<VisualShaderNodeExpression>(E->get().node.ptr()) != NULL) {
|
||||
p_list->push_back(PropertyInfo(Variant::STRING, prop_name + "/expression", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR));
|
||||
}
|
||||
}
|
||||
p_list->push_back(PropertyInfo(Variant::POOL_INT_ARRAY, "nodes/" + String(type_string[i]) + "/connections", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR));
|
||||
}
|
||||
@@ -993,26 +1089,33 @@ void VisualShader::_input_type_changed(Type p_type, int p_id) {
|
||||
}
|
||||
}
|
||||
|
||||
void VisualShader::rebuild() {
|
||||
dirty = true;
|
||||
_update_shader();
|
||||
}
|
||||
|
||||
void VisualShader::_bind_methods() {
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_mode", "mode"), &VisualShader::set_mode);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("add_node", "type", "node", "position", "id"), &VisualShader::add_node);
|
||||
ClassDB::bind_method(D_METHOD("set_node_position", "type", "id", "position"), &VisualShader::set_node_position);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("get_node", "type", "id"), &VisualShader::get_node);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_node_position", "type", "id", "position"), &VisualShader::set_node_position);
|
||||
ClassDB::bind_method(D_METHOD("get_node_position", "type", "id"), &VisualShader::get_node_position);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("get_node_list", "type"), &VisualShader::get_node_list);
|
||||
ClassDB::bind_method(D_METHOD("get_valid_node_id", "type"), &VisualShader::get_valid_node_id);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("remove_node", "type", "id"), &VisualShader::remove_node);
|
||||
ClassDB::bind_method(D_METHOD("rebuild"), &VisualShader::rebuild);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("is_node_connection", "type", "from_node", "from_port", "to_node", "to_port"), &VisualShader::is_node_connection);
|
||||
ClassDB::bind_method(D_METHOD("can_connect_nodes", "type", "from_node", "from_port", "to_node", "to_port"), &VisualShader::is_node_connection);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("connect_nodes", "type", "from_node", "from_port", "to_node", "to_port"), &VisualShader::connect_nodes);
|
||||
ClassDB::bind_method(D_METHOD("disconnect_nodes", "type", "from_node", "from_port", "to_node", "to_port"), &VisualShader::disconnect_nodes);
|
||||
ClassDB::bind_method(D_METHOD("connect_nodes_forced", "type", "from_node", "from_port", "to_node", "to_port"), &VisualShader::connect_nodes_forced);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("get_node_connections", "type"), &VisualShader::_get_node_connections);
|
||||
|
||||
@@ -1627,3 +1730,553 @@ void VisualShaderNodeUniform::_bind_methods() {
|
||||
|
||||
VisualShaderNodeUniform::VisualShaderNodeUniform() {
|
||||
}
|
||||
|
||||
////////////// GroupBase
|
||||
|
||||
String VisualShaderNodeGroupBase::get_caption() const {
|
||||
return "Group";
|
||||
}
|
||||
|
||||
void VisualShaderNodeGroupBase::set_size(const Vector2 &p_size) {
|
||||
size = p_size;
|
||||
}
|
||||
|
||||
Vector2 VisualShaderNodeGroupBase::get_size() const {
|
||||
return size;
|
||||
}
|
||||
|
||||
void VisualShaderNodeGroupBase::set_inputs(const String &p_inputs) {
|
||||
|
||||
if (inputs == p_inputs)
|
||||
return;
|
||||
|
||||
clear_input_ports();
|
||||
|
||||
inputs = p_inputs;
|
||||
|
||||
Vector<String> input_strings = inputs.split(";", false);
|
||||
|
||||
int input_port_count = input_strings.size();
|
||||
|
||||
for (int i = 0; i < input_port_count; i++) {
|
||||
|
||||
Vector<String> arr = input_strings[i].split(",");
|
||||
|
||||
int port_idx = arr[0].to_int();
|
||||
int port_type = arr[1].to_int();
|
||||
String port_name = arr[2];
|
||||
|
||||
Port port;
|
||||
port.type = (PortType)port_type;
|
||||
port.name = port_name;
|
||||
input_ports[port_idx] = port;
|
||||
}
|
||||
}
|
||||
|
||||
String VisualShaderNodeGroupBase::get_inputs() const {
|
||||
return inputs;
|
||||
}
|
||||
|
||||
void VisualShaderNodeGroupBase::set_outputs(const String &p_outputs) {
|
||||
|
||||
if (outputs == p_outputs)
|
||||
return;
|
||||
|
||||
clear_output_ports();
|
||||
|
||||
outputs = p_outputs;
|
||||
|
||||
Vector<String> output_strings = outputs.split(";", false);
|
||||
|
||||
int output_port_count = output_strings.size();
|
||||
|
||||
for (int i = 0; i < output_port_count; i++) {
|
||||
|
||||
Vector<String> arr = output_strings[i].split(",");
|
||||
|
||||
int port_idx = arr[0].to_int();
|
||||
int port_type = arr[1].to_int();
|
||||
String port_name = arr[2];
|
||||
|
||||
Port port;
|
||||
port.type = (PortType)port_type;
|
||||
port.name = port_name;
|
||||
output_ports[port_idx] = port;
|
||||
}
|
||||
}
|
||||
|
||||
String VisualShaderNodeGroupBase::get_outputs() const {
|
||||
return outputs;
|
||||
}
|
||||
|
||||
void VisualShaderNodeGroupBase::add_input_port(int p_id, int p_type, const String &p_name) {
|
||||
|
||||
String str = itos(p_id) + "," + itos(p_type) + "," + p_name + ";";
|
||||
Vector<String> inputs_strings = inputs.split(";", false);
|
||||
int index = 0;
|
||||
if (p_id < inputs_strings.size()) {
|
||||
for (int i = 0; i < inputs_strings.size(); i++) {
|
||||
if (i == p_id) {
|
||||
inputs = inputs.insert(index, str);
|
||||
break;
|
||||
}
|
||||
index += inputs_strings[i].size();
|
||||
}
|
||||
} else {
|
||||
inputs += str;
|
||||
}
|
||||
|
||||
inputs_strings = inputs.split(";", false);
|
||||
index = 0;
|
||||
|
||||
for (int i = 0; i < inputs_strings.size(); i++) {
|
||||
int count = 0;
|
||||
for (int j = 0; j < inputs_strings[i].size(); j++) {
|
||||
if (inputs_strings[i][j] == ',') {
|
||||
break;
|
||||
}
|
||||
count++;
|
||||
}
|
||||
|
||||
inputs.erase(index, count);
|
||||
inputs = inputs.insert(index, itos(i));
|
||||
index += inputs_strings[i].size();
|
||||
}
|
||||
|
||||
_apply_port_changes();
|
||||
}
|
||||
|
||||
void VisualShaderNodeGroupBase::remove_input_port(int p_id) {
|
||||
|
||||
Vector<String> inputs_strings = inputs.split(";", false);
|
||||
int count = 0;
|
||||
int index = 0;
|
||||
for (int i = 0; i < inputs_strings.size(); i++) {
|
||||
Vector<String> arr = inputs_strings[i].split(",");
|
||||
if (arr[0].to_int() == p_id) {
|
||||
count = inputs_strings[i].size();
|
||||
break;
|
||||
}
|
||||
index += inputs_strings[i].size();
|
||||
}
|
||||
inputs.erase(index, count);
|
||||
|
||||
inputs_strings = inputs.split(";", false);
|
||||
for (int i = p_id; i < inputs_strings.size(); i++) {
|
||||
inputs = inputs.replace_first(inputs_strings[i].split(",")[0], itos(i));
|
||||
}
|
||||
|
||||
_apply_port_changes();
|
||||
}
|
||||
|
||||
int VisualShaderNodeGroupBase::get_input_port_count() const {
|
||||
return input_ports.size();
|
||||
}
|
||||
|
||||
bool VisualShaderNodeGroupBase::has_input_port(int p_id) const {
|
||||
return input_ports.has(p_id);
|
||||
}
|
||||
|
||||
void VisualShaderNodeGroupBase::add_output_port(int p_id, int p_type, const String &p_name) {
|
||||
|
||||
String str = itos(p_id) + "," + itos(p_type) + "," + p_name + ";";
|
||||
Vector<String> outputs_strings = outputs.split(";", false);
|
||||
int index = 0;
|
||||
if (p_id < outputs_strings.size()) {
|
||||
for (int i = 0; i < outputs_strings.size(); i++) {
|
||||
if (i == p_id) {
|
||||
outputs = outputs.insert(index, str);
|
||||
break;
|
||||
}
|
||||
index += outputs_strings[i].size();
|
||||
}
|
||||
} else {
|
||||
outputs += str;
|
||||
}
|
||||
|
||||
outputs_strings = outputs.split(";", false);
|
||||
index = 0;
|
||||
|
||||
for (int i = 0; i < outputs_strings.size(); i++) {
|
||||
int count = 0;
|
||||
for (int j = 0; j < outputs_strings[i].size(); j++) {
|
||||
if (outputs_strings[i][j] == ',') {
|
||||
break;
|
||||
}
|
||||
count++;
|
||||
}
|
||||
|
||||
outputs.erase(index, count);
|
||||
outputs = outputs.insert(index, itos(i));
|
||||
index += outputs_strings[i].size();
|
||||
}
|
||||
|
||||
_apply_port_changes();
|
||||
}
|
||||
|
||||
void VisualShaderNodeGroupBase::remove_output_port(int p_id) {
|
||||
|
||||
Vector<String> outputs_strings = outputs.split(";", false);
|
||||
int count = 0;
|
||||
int index = 0;
|
||||
for (int i = 0; i < outputs_strings.size(); i++) {
|
||||
Vector<String> arr = outputs_strings[i].split(",");
|
||||
if (arr[0].to_int() == p_id) {
|
||||
count = outputs_strings[i].size();
|
||||
break;
|
||||
}
|
||||
index += outputs_strings[i].size();
|
||||
}
|
||||
outputs.erase(index, count);
|
||||
|
||||
outputs_strings = outputs.split(";", false);
|
||||
for (int i = p_id; i < outputs_strings.size(); i++) {
|
||||
outputs = outputs.replace_first(outputs_strings[i].split(",")[0], itos(i));
|
||||
}
|
||||
|
||||
_apply_port_changes();
|
||||
}
|
||||
|
||||
int VisualShaderNodeGroupBase::get_output_port_count() const {
|
||||
return output_ports.size();
|
||||
}
|
||||
|
||||
bool VisualShaderNodeGroupBase::has_output_port(int p_id) const {
|
||||
return output_ports.has(p_id);
|
||||
}
|
||||
|
||||
void VisualShaderNodeGroupBase::clear_input_ports() {
|
||||
input_ports.clear();
|
||||
}
|
||||
|
||||
void VisualShaderNodeGroupBase::clear_output_ports() {
|
||||
output_ports.clear();
|
||||
}
|
||||
|
||||
void VisualShaderNodeGroupBase::set_input_port_type(int p_id, int p_type) {
|
||||
|
||||
if (input_ports[p_id].type == p_type)
|
||||
return;
|
||||
|
||||
Vector<String> inputs_strings = inputs.split(";", false);
|
||||
int count = 0;
|
||||
int index = 0;
|
||||
for (int i = 0; i < inputs_strings.size(); i++) {
|
||||
Vector<String> arr = inputs_strings[i].split(",");
|
||||
if (arr[0].to_int() == p_id) {
|
||||
index += arr[0].size();
|
||||
count = arr[1].size() - 1;
|
||||
break;
|
||||
}
|
||||
index += inputs_strings[i].size();
|
||||
}
|
||||
|
||||
inputs.erase(index, count);
|
||||
|
||||
inputs = inputs.insert(index, itos(p_type));
|
||||
|
||||
_apply_port_changes();
|
||||
}
|
||||
|
||||
VisualShaderNodeGroupBase::PortType VisualShaderNodeGroupBase::get_input_port_type(int p_id) const {
|
||||
ERR_FAIL_COND_V(!input_ports.has(p_id), (PortType)0);
|
||||
return input_ports[p_id].type;
|
||||
}
|
||||
|
||||
void VisualShaderNodeGroupBase::set_input_port_name(int p_id, const String &p_name) {
|
||||
|
||||
if (input_ports[p_id].name == p_name)
|
||||
return;
|
||||
|
||||
Vector<String> inputs_strings = inputs.split(";", false);
|
||||
int count = 0;
|
||||
int index = 0;
|
||||
for (int i = 0; i < inputs_strings.size(); i++) {
|
||||
Vector<String> arr = inputs_strings[i].split(",");
|
||||
if (arr[0].to_int() == p_id) {
|
||||
index += arr[0].size() + arr[1].size();
|
||||
count = arr[2].size() - 1;
|
||||
break;
|
||||
}
|
||||
index += inputs_strings[i].size();
|
||||
}
|
||||
|
||||
inputs.erase(index, count);
|
||||
|
||||
inputs = inputs.insert(index, p_name);
|
||||
|
||||
_apply_port_changes();
|
||||
}
|
||||
|
||||
String VisualShaderNodeGroupBase::get_input_port_name(int p_id) const {
|
||||
ERR_FAIL_COND_V(!input_ports.has(p_id), "");
|
||||
return input_ports[p_id].name;
|
||||
}
|
||||
|
||||
void VisualShaderNodeGroupBase::set_output_port_type(int p_id, int p_type) {
|
||||
|
||||
if (output_ports[p_id].type == p_type)
|
||||
return;
|
||||
|
||||
Vector<String> output_strings = outputs.split(";", false);
|
||||
int count = 0;
|
||||
int index = 0;
|
||||
for (int i = 0; i < output_strings.size(); i++) {
|
||||
Vector<String> arr = output_strings[i].split(",");
|
||||
if (arr[0].to_int() == p_id) {
|
||||
index += arr[0].size();
|
||||
count = arr[1].size() - 1;
|
||||
break;
|
||||
}
|
||||
index += output_strings[i].size();
|
||||
}
|
||||
|
||||
outputs.erase(index, count);
|
||||
|
||||
outputs = outputs.insert(index, itos(p_type));
|
||||
|
||||
_apply_port_changes();
|
||||
}
|
||||
|
||||
VisualShaderNodeGroupBase::PortType VisualShaderNodeGroupBase::get_output_port_type(int p_id) const {
|
||||
ERR_FAIL_COND_V(!output_ports.has(p_id), (PortType)0);
|
||||
return output_ports[p_id].type;
|
||||
}
|
||||
|
||||
void VisualShaderNodeGroupBase::set_output_port_name(int p_id, const String &p_name) {
|
||||
if (output_ports[p_id].name == p_name)
|
||||
return;
|
||||
|
||||
Vector<String> output_strings = outputs.split(";", false);
|
||||
int count = 0;
|
||||
int index = 0;
|
||||
for (int i = 0; i < output_strings.size(); i++) {
|
||||
Vector<String> arr = output_strings[i].split(",");
|
||||
if (arr[0].to_int() == p_id) {
|
||||
index += arr[0].size() + arr[1].size();
|
||||
count = arr[2].size() - 1;
|
||||
break;
|
||||
}
|
||||
index += output_strings[i].size();
|
||||
}
|
||||
|
||||
outputs.erase(index, count);
|
||||
|
||||
outputs = outputs.insert(index, p_name);
|
||||
|
||||
_apply_port_changes();
|
||||
}
|
||||
|
||||
String VisualShaderNodeGroupBase::get_output_port_name(int p_id) const {
|
||||
ERR_FAIL_COND_V(!output_ports.has(p_id), "");
|
||||
return output_ports[p_id].name;
|
||||
}
|
||||
|
||||
int VisualShaderNodeGroupBase::get_free_input_port_id() const {
|
||||
return input_ports.size();
|
||||
}
|
||||
|
||||
int VisualShaderNodeGroupBase::get_free_output_port_id() const {
|
||||
return output_ports.size();
|
||||
}
|
||||
|
||||
void VisualShaderNodeGroupBase::set_control(Control *p_control, int p_index) {
|
||||
controls[p_index] = p_control;
|
||||
}
|
||||
|
||||
Control *VisualShaderNodeGroupBase::get_control(int p_index) {
|
||||
ERR_FAIL_COND_V(!controls.has(p_index), NULL);
|
||||
return controls[p_index];
|
||||
}
|
||||
|
||||
void VisualShaderNodeGroupBase::_apply_port_changes() {
|
||||
|
||||
Vector<String> inputs_strings = inputs.split(";", false);
|
||||
Vector<String> outputs_strings = outputs.split(";", false);
|
||||
|
||||
clear_input_ports();
|
||||
clear_output_ports();
|
||||
|
||||
for (int i = 0; i < inputs_strings.size(); i++) {
|
||||
Vector<String> arr = inputs_strings[i].split(",");
|
||||
Port port;
|
||||
port.type = (PortType)arr[1].to_int();
|
||||
port.name = arr[2];
|
||||
input_ports[i] = port;
|
||||
}
|
||||
for (int i = 0; i < outputs_strings.size(); i++) {
|
||||
Vector<String> arr = outputs_strings[i].split(",");
|
||||
Port port;
|
||||
port.type = (PortType)arr[1].to_int();
|
||||
port.name = arr[2];
|
||||
output_ports[i] = port;
|
||||
}
|
||||
}
|
||||
|
||||
void VisualShaderNodeGroupBase::_bind_methods() {
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_size", "size"), &VisualShaderNodeGroupBase::set_size);
|
||||
ClassDB::bind_method(D_METHOD("get_size"), &VisualShaderNodeGroupBase::get_size);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_inputs", "inputs"), &VisualShaderNodeGroupBase::set_inputs);
|
||||
ClassDB::bind_method(D_METHOD("get_inputs"), &VisualShaderNodeGroupBase::get_inputs);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_outputs", "outputs"), &VisualShaderNodeGroupBase::set_outputs);
|
||||
ClassDB::bind_method(D_METHOD("get_outputs"), &VisualShaderNodeGroupBase::get_outputs);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("add_input_port", "id", "type", "name"), &VisualShaderNodeGroupBase::add_input_port);
|
||||
ClassDB::bind_method(D_METHOD("remove_input_port", "id"), &VisualShaderNodeGroupBase::remove_input_port);
|
||||
ClassDB::bind_method(D_METHOD("get_input_port_count"), &VisualShaderNodeGroupBase::get_input_port_count);
|
||||
ClassDB::bind_method(D_METHOD("has_input_port", "id"), &VisualShaderNodeGroupBase::has_input_port);
|
||||
ClassDB::bind_method(D_METHOD("clear_input_ports"), &VisualShaderNodeGroupBase::clear_input_ports);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("add_output_port", "id", "type", "name"), &VisualShaderNodeGroupBase::add_output_port);
|
||||
ClassDB::bind_method(D_METHOD("remove_output_port", "id"), &VisualShaderNodeGroupBase::remove_output_port);
|
||||
ClassDB::bind_method(D_METHOD("get_output_port_count"), &VisualShaderNodeGroupBase::get_output_port_count);
|
||||
ClassDB::bind_method(D_METHOD("has_output_port", "id"), &VisualShaderNodeGroupBase::has_output_port);
|
||||
ClassDB::bind_method(D_METHOD("clear_output_ports"), &VisualShaderNodeGroupBase::clear_output_ports);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_input_port_name"), &VisualShaderNodeGroupBase::set_input_port_name);
|
||||
ClassDB::bind_method(D_METHOD("set_input_port_type"), &VisualShaderNodeGroupBase::set_input_port_type);
|
||||
ClassDB::bind_method(D_METHOD("set_output_port_name"), &VisualShaderNodeGroupBase::set_output_port_name);
|
||||
ClassDB::bind_method(D_METHOD("set_output_port_type"), &VisualShaderNodeGroupBase::set_output_port_type);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("get_free_input_port_id"), &VisualShaderNodeGroupBase::get_free_input_port_id);
|
||||
ClassDB::bind_method(D_METHOD("get_free_output_port_id"), &VisualShaderNodeGroupBase::get_free_output_port_id);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_control", "control", "index"), &VisualShaderNodeGroupBase::set_control);
|
||||
ClassDB::bind_method(D_METHOD("get_control", "index"), &VisualShaderNodeGroupBase::get_control);
|
||||
}
|
||||
|
||||
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 {
|
||||
return "";
|
||||
}
|
||||
|
||||
VisualShaderNodeGroupBase::VisualShaderNodeGroupBase() {
|
||||
size = Size2(0, 0);
|
||||
inputs = "";
|
||||
outputs = "";
|
||||
}
|
||||
|
||||
////////////// Expression
|
||||
|
||||
String VisualShaderNodeExpression::get_caption() const {
|
||||
return "Expression";
|
||||
}
|
||||
|
||||
void VisualShaderNodeExpression::set_expression(const String &p_expression) {
|
||||
expression = p_expression;
|
||||
}
|
||||
|
||||
void VisualShaderNodeExpression::build() {
|
||||
emit_changed();
|
||||
}
|
||||
|
||||
String VisualShaderNodeExpression::get_expression() const {
|
||||
return expression;
|
||||
}
|
||||
|
||||
String VisualShaderNodeExpression::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 {
|
||||
|
||||
String _expression = expression;
|
||||
|
||||
_expression = _expression.insert(0, "\n");
|
||||
_expression = _expression.replace("\n", "\n\t\t");
|
||||
|
||||
static Vector<String> pre_symbols;
|
||||
if (pre_symbols.empty()) {
|
||||
pre_symbols.push_back("\t");
|
||||
pre_symbols.push_back("{");
|
||||
pre_symbols.push_back("[");
|
||||
pre_symbols.push_back("(");
|
||||
pre_symbols.push_back(" ");
|
||||
pre_symbols.push_back("-");
|
||||
pre_symbols.push_back("*");
|
||||
pre_symbols.push_back("/");
|
||||
pre_symbols.push_back("+");
|
||||
pre_symbols.push_back("=");
|
||||
pre_symbols.push_back("&");
|
||||
pre_symbols.push_back("|");
|
||||
pre_symbols.push_back("!");
|
||||
}
|
||||
|
||||
static Vector<String> post_symbols;
|
||||
if (post_symbols.empty()) {
|
||||
post_symbols.push_back("\t");
|
||||
post_symbols.push_back("\n");
|
||||
post_symbols.push_back("}");
|
||||
post_symbols.push_back("]");
|
||||
post_symbols.push_back(")");
|
||||
post_symbols.push_back(" ");
|
||||
post_symbols.push_back(".");
|
||||
post_symbols.push_back("-");
|
||||
post_symbols.push_back("*");
|
||||
post_symbols.push_back("/");
|
||||
post_symbols.push_back("+");
|
||||
post_symbols.push_back("=");
|
||||
post_symbols.push_back("&");
|
||||
post_symbols.push_back("|");
|
||||
post_symbols.push_back("!");
|
||||
}
|
||||
|
||||
for (int i = 0; i < get_input_port_count(); i++) {
|
||||
for (int j = 0; j < pre_symbols.size(); j++) {
|
||||
for (int k = 0; k < post_symbols.size(); k++) {
|
||||
_expression = _expression.replace(pre_symbols[j] + get_input_port_name(i) + post_symbols[k], pre_symbols[j] + p_input_vars[i] + post_symbols[k]);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < get_output_port_count(); i++) {
|
||||
for (int j = 0; j < pre_symbols.size(); j++) {
|
||||
for (int k = 0; k < post_symbols.size(); k++) {
|
||||
_expression = _expression.replace(pre_symbols[j] + get_output_port_name(i) + post_symbols[k], pre_symbols[j] + p_output_vars[i] + post_symbols[k]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
String output_initializer;
|
||||
|
||||
for (int i = 0; i < get_output_port_count(); i++) {
|
||||
int port_type = get_output_port_type(i);
|
||||
String tk = "";
|
||||
switch (port_type) {
|
||||
case PORT_TYPE_SCALAR:
|
||||
tk = "0.0";
|
||||
break;
|
||||
case PORT_TYPE_VECTOR:
|
||||
tk = "vec3(0.0, 0.0, 0.0)";
|
||||
break;
|
||||
case PORT_TYPE_BOOLEAN:
|
||||
tk = "false";
|
||||
break;
|
||||
case PORT_TYPE_TRANSFORM:
|
||||
tk = "mat4(1.0)";
|
||||
break;
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
output_initializer += "\t" + p_output_vars[i] + "=" + tk + ";\n";
|
||||
}
|
||||
|
||||
String code;
|
||||
code += output_initializer;
|
||||
code += "\t{";
|
||||
code += _expression;
|
||||
code += "\n\t}";
|
||||
|
||||
return code;
|
||||
}
|
||||
|
||||
void VisualShaderNodeExpression::_bind_methods() {
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_expression", "expression"), &VisualShaderNodeExpression::set_expression);
|
||||
ClassDB::bind_method(D_METHOD("get_expression"), &VisualShaderNodeExpression::get_expression);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("build"), &VisualShaderNodeExpression::build);
|
||||
|
||||
ADD_PROPERTY(PropertyInfo(Variant::STRING, "expression"), "set_expression", "get_expression");
|
||||
}
|
||||
|
||||
VisualShaderNodeExpression::VisualShaderNodeExpression() {
|
||||
expression = "";
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user