Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/nodes/intern/node_socket.cc')
-rw-r--r--source/blender/nodes/intern/node_socket.cc556
1 files changed, 556 insertions, 0 deletions
diff --git a/source/blender/nodes/intern/node_socket.cc b/source/blender/nodes/intern/node_socket.cc
new file mode 100644
index 00000000000..b23511c3bdb
--- /dev/null
+++ b/source/blender/nodes/intern/node_socket.cc
@@ -0,0 +1,556 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2007 Blender Foundation.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup nodes
+ */
+
+#include <limits.h>
+
+#include "DNA_node_types.h"
+
+#include "BLI_listbase.h"
+#include "BLI_math.h"
+#include "BLI_string.h"
+#include "BLI_utildefines.h"
+
+#include "BKE_lib_id.h"
+#include "BKE_node.h"
+
+#include "RNA_access.h"
+#include "RNA_types.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "NOD_socket.h"
+
+struct bNodeSocket *node_add_socket_from_template(struct bNodeTree *ntree,
+ struct bNode *node,
+ struct bNodeSocketTemplate *stemp,
+ int in_out)
+{
+ bNodeSocket *sock = nodeAddStaticSocket(
+ ntree, node, in_out, stemp->type, stemp->subtype, stemp->identifier, stemp->name);
+
+ sock->flag |= stemp->flag;
+
+ /* initialize default_value */
+ switch (stemp->type) {
+ case SOCK_FLOAT: {
+ bNodeSocketValueFloat *dval = (bNodeSocketValueFloat *)sock->default_value;
+ dval->value = stemp->val1;
+ dval->min = stemp->min;
+ dval->max = stemp->max;
+ break;
+ }
+ case SOCK_INT: {
+ bNodeSocketValueInt *dval = (bNodeSocketValueInt *)sock->default_value;
+ dval->value = (int)stemp->val1;
+ dval->min = (int)stemp->min;
+ dval->max = (int)stemp->max;
+ break;
+ }
+ case SOCK_BOOLEAN: {
+ bNodeSocketValueBoolean *dval = (bNodeSocketValueBoolean *)sock->default_value;
+ dval->value = (int)stemp->val1;
+ break;
+ }
+ case SOCK_VECTOR: {
+ bNodeSocketValueVector *dval = (bNodeSocketValueVector *)sock->default_value;
+ dval->value[0] = stemp->val1;
+ dval->value[1] = stemp->val2;
+ dval->value[2] = stemp->val3;
+ dval->min = stemp->min;
+ dval->max = stemp->max;
+ break;
+ }
+ case SOCK_RGBA: {
+ bNodeSocketValueRGBA *dval = (bNodeSocketValueRGBA *)sock->default_value;
+ dval->value[0] = stemp->val1;
+ dval->value[1] = stemp->val2;
+ dval->value[2] = stemp->val3;
+ dval->value[3] = stemp->val4;
+ break;
+ }
+ }
+
+ return sock;
+}
+
+static bNodeSocket *verify_socket_template(
+ bNodeTree *ntree, bNode *node, int in_out, ListBase *socklist, bNodeSocketTemplate *stemp)
+{
+ bNodeSocket *sock;
+
+ for (sock = (bNodeSocket *)socklist->first; sock; sock = sock->next) {
+ if (STREQLEN(sock->name, stemp->name, NODE_MAXSTR)) {
+ break;
+ }
+ }
+ if (sock) {
+ if (sock->type != stemp->type) {
+ nodeModifySocketType(ntree, node, sock, stemp->type, stemp->subtype);
+ }
+ sock->flag |= stemp->flag;
+ }
+ else {
+ /* no socket for this template found, make a new one */
+ sock = node_add_socket_from_template(ntree, node, stemp, in_out);
+ }
+
+ /* remove the new socket from the node socket list first,
+ * will be added back after verification. */
+ BLI_remlink(socklist, sock);
+
+ return sock;
+}
+
+static void verify_socket_template_list(bNodeTree *ntree,
+ bNode *node,
+ int in_out,
+ ListBase *socklist,
+ bNodeSocketTemplate *stemp_first)
+{
+ bNodeSocket *sock, *nextsock;
+ bNodeSocketTemplate *stemp;
+
+ /* no inputs anymore? */
+ if (stemp_first == NULL) {
+ for (sock = (bNodeSocket *)socklist->first; sock; sock = nextsock) {
+ nextsock = sock->next;
+ nodeRemoveSocket(ntree, node, sock);
+ }
+ }
+ else {
+ /* step by step compare */
+ stemp = stemp_first;
+ while (stemp->type != -1) {
+ stemp->sock = verify_socket_template(ntree, node, in_out, socklist, stemp);
+ stemp++;
+ }
+ /* leftovers are removed */
+ for (sock = (bNodeSocket *)socklist->first; sock; sock = nextsock) {
+ nextsock = sock->next;
+ nodeRemoveSocket(ntree, node, sock);
+ }
+
+ /* and we put back the verified sockets */
+ stemp = stemp_first;
+ if (socklist->first) {
+ /* Some dynamic sockets left, store the list start
+ * so we can add static sockets in front of it. */
+ sock = (bNodeSocket *)socklist->first;
+ while (stemp->type != -1) {
+ /* Put static sockets in front of dynamic. */
+ BLI_insertlinkbefore(socklist, sock, stemp->sock);
+ stemp++;
+ }
+ }
+ else {
+ while (stemp->type != -1) {
+ BLI_addtail(socklist, stemp->sock);
+ stemp++;
+ }
+ }
+ }
+}
+
+void node_verify_socket_templates(bNodeTree *ntree, bNode *node)
+{
+ bNodeType *ntype = node->typeinfo;
+ /* Don't try to match socket lists when there are no templates.
+ * This prevents dynamically generated sockets to be removed, like for
+ * group, image or render layer nodes. We have an explicit check for the
+ * render layer node since it still has fixed sockets too.
+ */
+ if (ntype) {
+ if (ntype->inputs && ntype->inputs[0].type >= 0) {
+ verify_socket_template_list(ntree, node, SOCK_IN, &node->inputs, ntype->inputs);
+ }
+ if (ntype->outputs && ntype->outputs[0].type >= 0 && node->type != CMP_NODE_R_LAYERS) {
+ verify_socket_template_list(ntree, node, SOCK_OUT, &node->outputs, ntype->outputs);
+ }
+ }
+}
+
+void node_socket_init_default_value(bNodeSocket *sock)
+{
+ int type = sock->typeinfo->type;
+ int subtype = sock->typeinfo->subtype;
+
+ if (sock->default_value) {
+ return; /* already initialized */
+ }
+
+ switch (type) {
+ case SOCK_FLOAT: {
+ bNodeSocketValueFloat *dval = (bNodeSocketValueFloat *)MEM_callocN(
+ sizeof(bNodeSocketValueFloat), "node socket value float");
+ dval->subtype = subtype;
+ dval->value = 0.0f;
+ dval->min = -FLT_MAX;
+ dval->max = FLT_MAX;
+
+ sock->default_value = dval;
+ break;
+ }
+ case SOCK_INT: {
+ bNodeSocketValueInt *dval = (bNodeSocketValueInt *)MEM_callocN(sizeof(bNodeSocketValueInt),
+ "node socket value int");
+ dval->subtype = subtype;
+ dval->value = 0;
+ dval->min = INT_MIN;
+ dval->max = INT_MAX;
+
+ sock->default_value = dval;
+ break;
+ }
+ case SOCK_BOOLEAN: {
+ bNodeSocketValueBoolean *dval = (bNodeSocketValueBoolean *)MEM_callocN(
+ sizeof(bNodeSocketValueBoolean), "node socket value bool");
+ dval->value = false;
+
+ sock->default_value = dval;
+ break;
+ }
+ case SOCK_VECTOR: {
+ static float default_value[] = {0.0f, 0.0f, 0.0f};
+ bNodeSocketValueVector *dval = (bNodeSocketValueVector *)MEM_callocN(
+ sizeof(bNodeSocketValueVector), "node socket value vector");
+ dval->subtype = subtype;
+ copy_v3_v3(dval->value, default_value);
+ dval->min = -FLT_MAX;
+ dval->max = FLT_MAX;
+
+ sock->default_value = dval;
+ break;
+ }
+ case SOCK_RGBA: {
+ static float default_value[] = {0.0f, 0.0f, 0.0f, 1.0f};
+ bNodeSocketValueRGBA *dval = (bNodeSocketValueRGBA *)MEM_callocN(
+ sizeof(bNodeSocketValueRGBA), "node socket value color");
+ copy_v4_v4(dval->value, default_value);
+
+ sock->default_value = dval;
+ break;
+ }
+ case SOCK_STRING: {
+ bNodeSocketValueString *dval = (bNodeSocketValueString *)MEM_callocN(
+ sizeof(bNodeSocketValueString), "node socket value string");
+ dval->subtype = subtype;
+ dval->value[0] = '\0';
+
+ sock->default_value = dval;
+ break;
+ }
+ case SOCK_OBJECT: {
+ bNodeSocketValueObject *dval = (bNodeSocketValueObject *)MEM_callocN(
+ sizeof(bNodeSocketValueObject), "node socket value object");
+ dval->value = NULL;
+
+ sock->default_value = dval;
+ break;
+ }
+ case SOCK_IMAGE: {
+ bNodeSocketValueImage *dval = (bNodeSocketValueImage *)MEM_callocN(
+ sizeof(bNodeSocketValueImage), "node socket value image");
+ dval->value = NULL;
+
+ sock->default_value = dval;
+ break;
+ }
+ }
+}
+
+void node_socket_copy_default_value(bNodeSocket *to, const bNodeSocket *from)
+{
+ /* sanity check */
+ if (to->type != from->type) {
+ return;
+ }
+
+ /* make sure both exist */
+ if (!from->default_value) {
+ return;
+ }
+ node_socket_init_default_value(to);
+
+ /* use label instead of name if it has been set */
+ if (from->label[0] != '\0') {
+ BLI_strncpy(to->name, from->label, NODE_MAXSTR);
+ }
+
+ switch (from->typeinfo->type) {
+ case SOCK_FLOAT: {
+ bNodeSocketValueFloat *toval = (bNodeSocketValueFloat *)to->default_value;
+ bNodeSocketValueFloat *fromval = (bNodeSocketValueFloat *)from->default_value;
+ *toval = *fromval;
+ break;
+ }
+ case SOCK_INT: {
+ bNodeSocketValueInt *toval = (bNodeSocketValueInt *)to->default_value;
+ bNodeSocketValueInt *fromval = (bNodeSocketValueInt *)from->default_value;
+ *toval = *fromval;
+ break;
+ }
+ case SOCK_BOOLEAN: {
+ bNodeSocketValueBoolean *toval = (bNodeSocketValueBoolean *)to->default_value;
+ bNodeSocketValueBoolean *fromval = (bNodeSocketValueBoolean *)from->default_value;
+ *toval = *fromval;
+ break;
+ }
+ case SOCK_VECTOR: {
+ bNodeSocketValueVector *toval = (bNodeSocketValueVector *)to->default_value;
+ bNodeSocketValueVector *fromval = (bNodeSocketValueVector *)from->default_value;
+ *toval = *fromval;
+ break;
+ }
+ case SOCK_RGBA: {
+ bNodeSocketValueRGBA *toval = (bNodeSocketValueRGBA *)to->default_value;
+ bNodeSocketValueRGBA *fromval = (bNodeSocketValueRGBA *)from->default_value;
+ *toval = *fromval;
+ break;
+ }
+ case SOCK_STRING: {
+ bNodeSocketValueString *toval = (bNodeSocketValueString *)to->default_value;
+ bNodeSocketValueString *fromval = (bNodeSocketValueString *)from->default_value;
+ *toval = *fromval;
+ break;
+ }
+ case SOCK_OBJECT: {
+ bNodeSocketValueObject *toval = (bNodeSocketValueObject *)to->default_value;
+ bNodeSocketValueObject *fromval = (bNodeSocketValueObject *)from->default_value;
+ *toval = *fromval;
+ id_us_plus(&toval->value->id);
+ break;
+ }
+ case SOCK_IMAGE: {
+ bNodeSocketValueImage *toval = (bNodeSocketValueImage *)to->default_value;
+ bNodeSocketValueImage *fromval = (bNodeSocketValueImage *)from->default_value;
+ *toval = *fromval;
+ id_us_plus(&toval->value->id);
+ break;
+ }
+ }
+
+ to->flag |= (from->flag & SOCK_HIDE_VALUE);
+}
+
+static void standard_node_socket_interface_init_socket(bNodeTree *UNUSED(ntree),
+ bNodeSocket *stemp,
+ bNode *UNUSED(node),
+ bNodeSocket *sock,
+ const char *UNUSED(data_path))
+{
+ /* initialize the type value */
+ sock->type = sock->typeinfo->type;
+
+ /* XXX socket interface 'type' value is not used really,
+ * but has to match or the copy function will bail out
+ */
+ stemp->type = stemp->typeinfo->type;
+ /* copy default_value settings */
+ node_socket_copy_default_value(sock, stemp);
+}
+
+/* copies settings that are not changed for each socket instance */
+static void standard_node_socket_interface_verify_socket(bNodeTree *UNUSED(ntree),
+ bNodeSocket *stemp,
+ bNode *UNUSED(node),
+ bNodeSocket *sock,
+ const char *UNUSED(data_path))
+{
+ /* sanity check */
+ if (sock->type != stemp->typeinfo->type) {
+ return;
+ }
+
+ /* make sure both exist */
+ if (!stemp->default_value) {
+ return;
+ }
+ node_socket_init_default_value(sock);
+
+ switch (stemp->typeinfo->type) {
+ case SOCK_FLOAT: {
+ bNodeSocketValueFloat *toval = (bNodeSocketValueFloat *)sock->default_value;
+ bNodeSocketValueFloat *fromval = (bNodeSocketValueFloat *)stemp->default_value;
+ toval->min = fromval->min;
+ toval->max = fromval->max;
+ break;
+ }
+ case SOCK_INT: {
+ bNodeSocketValueInt *toval = (bNodeSocketValueInt *)sock->default_value;
+ bNodeSocketValueInt *fromval = (bNodeSocketValueInt *)stemp->default_value;
+ toval->min = fromval->min;
+ toval->max = fromval->max;
+ break;
+ }
+ case SOCK_VECTOR: {
+ bNodeSocketValueVector *toval = (bNodeSocketValueVector *)sock->default_value;
+ bNodeSocketValueVector *fromval = (bNodeSocketValueVector *)stemp->default_value;
+ toval->min = fromval->min;
+ toval->max = fromval->max;
+ break;
+ }
+ }
+}
+
+static void standard_node_socket_interface_from_socket(bNodeTree *UNUSED(ntree),
+ bNodeSocket *stemp,
+ bNode *UNUSED(node),
+ bNodeSocket *sock)
+{
+ /* initialize settings */
+ stemp->type = stemp->typeinfo->type;
+ node_socket_copy_default_value(stemp, sock);
+}
+
+extern "C" void ED_init_standard_node_socket_type(bNodeSocketType *);
+
+static bNodeSocketType *make_standard_socket_type(int type, int subtype)
+{
+ const char *socket_idname = nodeStaticSocketType(type, subtype);
+ const char *interface_idname = nodeStaticSocketInterfaceType(type, subtype);
+ bNodeSocketType *stype;
+ StructRNA *srna;
+
+ stype = (bNodeSocketType *)MEM_callocN(sizeof(bNodeSocketType), "node socket C type");
+ stype->free_self = (void (*)(bNodeSocketType * stype)) MEM_freeN;
+ BLI_strncpy(stype->idname, socket_idname, sizeof(stype->idname));
+
+ /* set the RNA type
+ * uses the exact same identifier as the socket type idname */
+ srna = stype->ext_socket.srna = RNA_struct_find(socket_idname);
+ BLI_assert(srna != NULL);
+ /* associate the RNA type with the socket type */
+ RNA_struct_blender_type_set(srna, stype);
+
+ /* set the interface RNA type */
+ srna = stype->ext_interface.srna = RNA_struct_find(interface_idname);
+ BLI_assert(srna != NULL);
+ /* associate the RNA type with the socket type */
+ RNA_struct_blender_type_set(srna, stype);
+
+ /* extra type info for standard socket types */
+ stype->type = type;
+ stype->subtype = subtype;
+
+ /* XXX bad-level call! needed for setting draw callbacks */
+ ED_init_standard_node_socket_type(stype);
+
+ stype->interface_init_socket = standard_node_socket_interface_init_socket;
+ stype->interface_from_socket = standard_node_socket_interface_from_socket;
+ stype->interface_verify_socket = standard_node_socket_interface_verify_socket;
+
+ stype->use_link_limits_of_type = true;
+ stype->input_link_limit = 1;
+ stype->output_link_limit = 0xFFF;
+
+ return stype;
+}
+
+extern "C" void ED_init_node_socket_type_virtual(bNodeSocketType *);
+
+static bNodeSocketType *make_socket_type_virtual(void)
+{
+ const char *socket_idname = "NodeSocketVirtual";
+ bNodeSocketType *stype;
+ StructRNA *srna;
+
+ stype = (bNodeSocketType *)MEM_callocN(sizeof(bNodeSocketType), "node socket C type");
+ stype->free_self = (void (*)(bNodeSocketType * stype)) MEM_freeN;
+ BLI_strncpy(stype->idname, socket_idname, sizeof(stype->idname));
+
+ /* set the RNA type
+ * uses the exact same identifier as the socket type idname */
+ srna = stype->ext_socket.srna = RNA_struct_find(socket_idname);
+ BLI_assert(srna != NULL);
+ /* associate the RNA type with the socket type */
+ RNA_struct_blender_type_set(srna, stype);
+
+ /* extra type info for standard socket types */
+ stype->type = SOCK_CUSTOM;
+
+ ED_init_node_socket_type_virtual(stype);
+
+ stype->use_link_limits_of_type = true;
+ stype->input_link_limit = 1;
+ stype->output_link_limit = 1;
+
+ return stype;
+}
+
+static bNodeSocketType *make_socket_type_effector(int type)
+{
+ bNodeSocketType *stype = make_standard_socket_type(type, PROP_NONE);
+ stype->input_link_limit = 0xFFF;
+ return stype;
+}
+
+static bNodeSocketType *make_socket_type_control_flow(int type)
+{
+ bNodeSocketType *stype = make_standard_socket_type(type, PROP_NONE);
+ return stype;
+}
+
+void register_standard_node_socket_types(void)
+{
+ /* draw callbacks are set in drawnode.c to avoid bad-level calls */
+
+ nodeRegisterSocketType(make_standard_socket_type(SOCK_FLOAT, PROP_NONE));
+ nodeRegisterSocketType(make_standard_socket_type(SOCK_FLOAT, PROP_UNSIGNED));
+ nodeRegisterSocketType(make_standard_socket_type(SOCK_FLOAT, PROP_PERCENTAGE));
+ nodeRegisterSocketType(make_standard_socket_type(SOCK_FLOAT, PROP_FACTOR));
+ nodeRegisterSocketType(make_standard_socket_type(SOCK_FLOAT, PROP_ANGLE));
+ nodeRegisterSocketType(make_standard_socket_type(SOCK_FLOAT, PROP_TIME));
+
+ nodeRegisterSocketType(make_standard_socket_type(SOCK_INT, PROP_NONE));
+ nodeRegisterSocketType(make_standard_socket_type(SOCK_INT, PROP_UNSIGNED));
+ nodeRegisterSocketType(make_standard_socket_type(SOCK_INT, PROP_PERCENTAGE));
+ nodeRegisterSocketType(make_standard_socket_type(SOCK_INT, PROP_FACTOR));
+
+ nodeRegisterSocketType(make_standard_socket_type(SOCK_BOOLEAN, PROP_NONE));
+
+ nodeRegisterSocketType(make_standard_socket_type(SOCK_VECTOR, PROP_NONE));
+ nodeRegisterSocketType(make_standard_socket_type(SOCK_VECTOR, PROP_TRANSLATION));
+ nodeRegisterSocketType(make_standard_socket_type(SOCK_VECTOR, PROP_DIRECTION));
+ nodeRegisterSocketType(make_standard_socket_type(SOCK_VECTOR, PROP_VELOCITY));
+ nodeRegisterSocketType(make_standard_socket_type(SOCK_VECTOR, PROP_ACCELERATION));
+ nodeRegisterSocketType(make_standard_socket_type(SOCK_VECTOR, PROP_EULER));
+ nodeRegisterSocketType(make_standard_socket_type(SOCK_VECTOR, PROP_XYZ));
+
+ nodeRegisterSocketType(make_standard_socket_type(SOCK_RGBA, PROP_NONE));
+
+ nodeRegisterSocketType(make_standard_socket_type(SOCK_STRING, PROP_NONE));
+
+ nodeRegisterSocketType(make_standard_socket_type(SOCK_SHADER, PROP_NONE));
+
+ nodeRegisterSocketType(make_standard_socket_type(SOCK_OBJECT, PROP_NONE));
+
+ nodeRegisterSocketType(make_standard_socket_type(SOCK_IMAGE, PROP_NONE));
+
+ nodeRegisterSocketType(make_socket_type_effector(SOCK_EMITTERS));
+ nodeRegisterSocketType(make_socket_type_effector(SOCK_EVENTS));
+ nodeRegisterSocketType(make_socket_type_effector(SOCK_FORCES));
+
+ nodeRegisterSocketType(make_socket_type_control_flow(SOCK_CONTROL_FLOW));
+
+ nodeRegisterSocketType(make_socket_type_virtual());
+}