Nodes: New Object and Image socket types
authorJacques Lucke <jacques@blender.org>
Mon, 20 Apr 2020 11:22:20 +0000 (13:22 +0200)
committerJacques Lucke <jacques@blender.org>
Mon, 20 Apr 2020 11:27:45 +0000 (13:27 +0200)
Those new socket types will be necessary for particle nodes.

The main difficulty with adding these socket types is that they
are the first that reference ID data in their `value`.
Therefore, user counting code had to be added in a couple new places.

Reviewers: brecht, mont29

Differential Revision: https://developer.blender.org/D7347

source/blender/blenkernel/intern/lib_query.c
source/blender/blenkernel/intern/node.c
source/blender/blenloader/intern/readfile.c
source/blender/blenloader/intern/writefile.c
source/blender/editors/space_node/drawnode.c
source/blender/makesdna/DNA_node_types.h
source/blender/makesrna/intern/rna_nodetree.c
source/blender/nodes/intern/node_socket.c

index 17d26e777b64407ec6eb1d0b42f26d0853e5a548..804d7f2b4d652d005877f283fbb6c729faa34ea1 100644 (file)
@@ -205,6 +205,36 @@ static void library_foreach_idproperty_ID_link(LibraryForeachIDData *data,
   FOREACH_FINALIZE_VOID;
 }
 
+static void library_foreach_node_socket(LibraryForeachIDData *data, bNodeSocket *sock)
+{
+  library_foreach_idproperty_ID_link(data, sock->prop, IDWALK_CB_USER);
+
+  switch ((eNodeSocketDatatype)sock->type) {
+    case SOCK_OBJECT: {
+      bNodeSocketValueObject *default_value = sock->default_value;
+      FOREACH_CALLBACK_INVOKE_ID_PP(data, (ID **)&default_value->value, IDWALK_CB_USER);
+      break;
+    }
+    case SOCK_IMAGE: {
+      bNodeSocketValueImage *default_value = sock->default_value;
+      FOREACH_CALLBACK_INVOKE_ID_PP(data, (ID **)&default_value->value, IDWALK_CB_USER);
+      break;
+    }
+    case SOCK_FLOAT:
+    case SOCK_VECTOR:
+    case SOCK_RGBA:
+    case SOCK_BOOLEAN:
+    case SOCK_INT:
+    case SOCK_STRING:
+    case __SOCK_MESH:
+    case SOCK_CUSTOM:
+    case SOCK_SHADER:
+      break;
+  }
+
+  FOREACH_FINALIZE_VOID;
+}
+
 static void library_foreach_rigidbodyworldSceneLooper(struct RigidBodyWorld *UNUSED(rbw),
                                                       ID **id_pointer,
                                                       void *user_data,
@@ -1018,7 +1048,6 @@ static void library_foreach_ID_link(Main *bmain,
       case ID_NT: {
         bNodeTree *ntree = (bNodeTree *)id;
         bNode *node;
-        bNodeSocket *sock;
 
         CALLBACK_INVOKE(ntree->gpd, IDWALK_CB_USER);
 
@@ -1026,19 +1055,19 @@ static void library_foreach_ID_link(Main *bmain,
           CALLBACK_INVOKE_ID(node->id, IDWALK_CB_USER);
 
           library_foreach_idproperty_ID_link(&data, node->prop, IDWALK_CB_USER);
-          for (sock = node->inputs.first; sock; sock = sock->next) {
-            library_foreach_idproperty_ID_link(&data, sock->prop, IDWALK_CB_USER);
+          LISTBASE_FOREACH (bNodeSocket *, sock, &node->inputs) {
+            library_foreach_node_socket(&data, sock);
           }
-          for (sock = node->outputs.first; sock; sock = sock->next) {
-            library_foreach_idproperty_ID_link(&data, sock->prop, IDWALK_CB_USER);
+          LISTBASE_FOREACH (bNodeSocket *, sock, &node->outputs) {
+            library_foreach_node_socket(&data, sock);
           }
         }
 
-        for (sock = ntree->inputs.first; sock; sock = sock->next) {
-          library_foreach_idproperty_ID_link(&data, sock->prop, IDWALK_CB_USER);
+        LISTBASE_FOREACH (bNodeSocket *, sock, &ntree->inputs) {
+          library_foreach_node_socket(&data, sock);
         }
-        for (sock = ntree->outputs.first; sock; sock = sock->next) {
-          library_foreach_idproperty_ID_link(&data, sock->prop, IDWALK_CB_USER);
+        LISTBASE_FOREACH (bNodeSocket *, sock, &ntree->outputs) {
+          library_foreach_node_socket(&data, sock);
         }
         break;
       }
index ec12cd9b83fc17cbb99a215be61358aa5b1d2a20..e3eb25297df57a765552ac42b49f5c03ee7aa821 100644 (file)
@@ -88,7 +88,9 @@ static void ntree_set_typeinfo(bNodeTree *ntree, bNodeTreeType *typeinfo);
 static void node_socket_copy(bNodeSocket *sock_dst, const bNodeSocket *sock_src, const int flag);
 static void free_localized_node_groups(bNodeTree *ntree);
 static void node_free_node(bNodeTree *ntree, bNode *node);
-static void node_socket_interface_free(bNodeTree *UNUSED(ntree), bNodeSocket *sock);
+static void node_socket_interface_free(bNodeTree *UNUSED(ntree),
+                                       bNodeSocket *sock,
+                                       const bool do_id_user);
 
 static void ntree_init_data(ID *id)
 {
@@ -231,12 +233,12 @@ static void ntree_free_data(ID *id)
   /* free interface sockets */
   for (sock = ntree->inputs.first; sock; sock = nextsock) {
     nextsock = sock->next;
-    node_socket_interface_free(ntree, sock);
+    node_socket_interface_free(ntree, sock, false);
     MEM_freeN(sock);
   }
   for (sock = ntree->outputs.first; sock; sock = nextsock) {
     nextsock = sock->next;
-    node_socket_interface_free(ntree, sock);
+    node_socket_interface_free(ntree, sock, false);
     MEM_freeN(sock);
   }
 
@@ -746,6 +748,58 @@ static bNodeSocket *make_socket(bNodeTree *ntree,
   return sock;
 }
 
+static void socket_id_user_increment(bNodeSocket *sock)
+{
+  switch ((eNodeSocketDatatype)sock->type) {
+    case SOCK_OBJECT: {
+      bNodeSocketValueObject *default_value = sock->default_value;
+      id_us_plus(&default_value->value->id);
+      break;
+    }
+    case SOCK_IMAGE: {
+      bNodeSocketValueImage *default_value = sock->default_value;
+      id_us_plus(&default_value->value->id);
+      break;
+    }
+    case SOCK_FLOAT:
+    case SOCK_VECTOR:
+    case SOCK_RGBA:
+    case SOCK_BOOLEAN:
+    case SOCK_INT:
+    case SOCK_STRING:
+    case __SOCK_MESH:
+    case SOCK_CUSTOM:
+    case SOCK_SHADER:
+      break;
+  }
+}
+
+static void socket_id_user_decrement(bNodeSocket *sock)
+{
+  switch ((eNodeSocketDatatype)sock->type) {
+    case SOCK_OBJECT: {
+      bNodeSocketValueObject *default_value = sock->default_value;
+      id_us_min(&default_value->value->id);
+      break;
+    }
+    case SOCK_IMAGE: {
+      bNodeSocketValueImage *default_value = sock->default_value;
+      id_us_min(&default_value->value->id);
+      break;
+    }
+    case SOCK_FLOAT:
+    case SOCK_VECTOR:
+    case SOCK_RGBA:
+    case SOCK_BOOLEAN:
+    case SOCK_INT:
+    case SOCK_STRING:
+    case __SOCK_MESH:
+    case SOCK_CUSTOM:
+    case SOCK_SHADER:
+      break;
+  }
+}
+
 void nodeModifySocketType(
     bNodeTree *ntree, bNode *UNUSED(node), bNodeSocket *sock, int type, int subtype)
 {
@@ -757,6 +811,7 @@ void nodeModifySocketType(
   }
 
   if (sock->default_value) {
+    socket_id_user_decrement(sock);
     MEM_freeN(sock->default_value);
     sock->default_value = NULL;
   }
@@ -860,6 +915,10 @@ const char *nodeStaticSocketType(int type, int subtype)
       return "NodeSocketString";
     case SOCK_SHADER:
       return "NodeSocketShader";
+    case SOCK_OBJECT:
+      return "NodeSocketObject";
+    case SOCK_IMAGE:
+      return "NodeSocketImage";
   }
   return NULL;
 }
@@ -921,6 +980,10 @@ const char *nodeStaticSocketInterfaceType(int type, int subtype)
       return "NodeSocketInterfaceString";
     case SOCK_SHADER:
       return "NodeSocketInterfaceShader";
+    case SOCK_OBJECT:
+      return "NodeSocketInterfaceObject";
+    case SOCK_IMAGE:
+      return "NodeSocketInterfaceImage";
   }
   return NULL;
 }
@@ -979,6 +1042,9 @@ static void node_socket_free(bNodeTree *UNUSED(ntree),
   }
 
   if (sock->default_value) {
+    if (do_id_user) {
+      socket_id_user_decrement(sock);
+    }
     MEM_freeN(sock->default_value);
   }
 }
@@ -1265,6 +1331,10 @@ static void node_socket_copy(bNodeSocket *sock_dst, const bNodeSocket *sock_src,
 
   if (sock_src->default_value) {
     sock_dst->default_value = MEM_dupallocN(sock_src->default_value);
+
+    if ((flag & LIB_ID_CREATE_NO_USER_REFCOUNT) == 0) {
+      socket_id_user_increment(sock_dst);
+    }
   }
 
   sock_dst->stack_index = 0;
@@ -2085,6 +2155,13 @@ void nodeRemoveNode(Main *bmain, bNodeTree *ntree, bNode *node, bool do_id_user)
     if (node->id) {
       id_us_min(node->id);
     }
+
+    LISTBASE_FOREACH (bNodeSocket *, sock, &node->inputs) {
+      socket_id_user_decrement(sock);
+    }
+    LISTBASE_FOREACH (bNodeSocket *, sock, &node->outputs) {
+      socket_id_user_decrement(sock);
+    }
   }
 
   /* Remove animation data. */
@@ -2104,13 +2181,18 @@ void nodeRemoveNode(Main *bmain, bNodeTree *ntree, bNode *node, bool do_id_user)
   node_free_node(ntree, node);
 }
 
-static void node_socket_interface_free(bNodeTree *UNUSED(ntree), bNodeSocket *sock)
+static void node_socket_interface_free(bNodeTree *UNUSED(ntree),
+                                       bNodeSocket *sock,
+                                       const bool do_id_user)
 {
   if (sock->prop) {
-    IDP_FreeProperty(sock->prop);
+    IDP_FreeProperty_ex(sock->prop, do_id_user);
   }
 
   if (sock->default_value) {
+    if (do_id_user) {
+      socket_id_user_decrement(sock);
+    }
     MEM_freeN(sock->default_value);
   }
 }
@@ -2533,7 +2615,7 @@ void ntreeRemoveSocketInterface(bNodeTree *ntree, bNodeSocket *sock)
   BLI_remlink(&ntree->inputs, sock);
   BLI_remlink(&ntree->outputs, sock);
 
-  node_socket_interface_free(ntree, sock);
+  node_socket_interface_free(ntree, sock, true);
   MEM_freeN(sock);
 
   ntree->update |= NTREE_UPDATE_GROUP;
index a57e14a22b70103ca8de3d260a40e167a68669e1..e4977718103893b6f78fab9faf03fed5ba9bddbc 100644 (file)
@@ -3602,6 +3602,41 @@ static void lib_link_workspace_instance_hook(FileData *fd, WorkSpaceInstanceHook
 /** \name Read ID: Node Tree
  * \{ */
 
+static void lib_link_node_socket(FileData *fd, Library *lib, bNodeSocket *sock)
+{
+  IDP_LibLinkProperty(sock->prop, fd);
+
+  switch ((eNodeSocketDatatype)sock->type) {
+    case SOCK_OBJECT: {
+      bNodeSocketValueObject *default_value = sock->default_value;
+      default_value->value = newlibadr(fd, lib, default_value->value);
+      break;
+    }
+    case SOCK_IMAGE: {
+      bNodeSocketValueImage *default_value = sock->default_value;
+      default_value->value = newlibadr(fd, lib, default_value->value);
+      break;
+    }
+    case SOCK_FLOAT:
+    case SOCK_VECTOR:
+    case SOCK_RGBA:
+    case SOCK_BOOLEAN:
+    case SOCK_INT:
+    case SOCK_STRING:
+    case __SOCK_MESH:
+    case SOCK_CUSTOM:
+    case SOCK_SHADER:
+      break;
+  }
+}
+
+static void lib_link_node_sockets(FileData *fd, Library *lib, ListBase *sockets)
+{
+  LISTBASE_FOREACH (bNodeSocket *, sock, sockets) {
+    lib_link_node_socket(fd, lib, sock);
+  }
+}
+
 /* Single node tree (also used for material/scene trees), ntree is not NULL */
 static void lib_link_ntree(FileData *fd, Library *lib, bNodeTree *ntree)
 {
@@ -3616,20 +3651,12 @@ static void lib_link_ntree(FileData *fd, Library *lib, bNodeTree *ntree)
 
     node->id = newlibadr(fd, lib, node->id);
 
-    LISTBASE_FOREACH (bNodeSocket *, sock, &node->inputs) {
-      IDP_LibLinkProperty(sock->prop, fd);
-    }
-    LISTBASE_FOREACH (bNodeSocket *, sock, &node->outputs) {
-      IDP_LibLinkProperty(sock->prop, fd);
-    }
+    lib_link_node_sockets(fd, lib, &node->inputs);
+    lib_link_node_sockets(fd, lib, &node->outputs);
   }
 
-  LISTBASE_FOREACH (bNodeSocket *, sock, &ntree->inputs) {
-    IDP_LibLinkProperty(sock->prop, fd);
-  }
-  LISTBASE_FOREACH (bNodeSocket *, sock, &ntree->outputs) {
-    IDP_LibLinkProperty(sock->prop, fd);
-  }
+  lib_link_node_sockets(fd, lib, &ntree->inputs);
+  lib_link_node_sockets(fd, lib, &ntree->outputs);
 
   /* Set node->typeinfo pointers. This is done in lib linking, after the
    * first versioning that can change types still without functions that
@@ -10959,10 +10986,47 @@ static void expand_key(FileData *fd, Main *mainvar, Key *key)
   expand_doit(fd, mainvar, key->ipo);  // XXX deprecated - old animation system
 }
 
+static void expand_node_socket(FileData *fd, Main *mainvar, bNodeSocket *sock)
+{
+  expand_idprops(fd, mainvar, sock->prop);
+
+  if (sock->default_value != NULL) {
+
+    switch ((eNodeSocketDatatype)sock->type) {
+      case SOCK_OBJECT: {
+        bNodeSocketValueObject *default_value = sock->default_value;
+        expand_doit(fd, mainvar, default_value->value);
+        break;
+      }
+      case SOCK_IMAGE: {
+        bNodeSocketValueImage *default_value = sock->default_value;
+        expand_doit(fd, mainvar, default_value->value);
+        break;
+      }
+      case SOCK_FLOAT:
+      case SOCK_VECTOR:
+      case SOCK_RGBA:
+      case SOCK_BOOLEAN:
+      case SOCK_INT:
+      case SOCK_STRING:
+      case __SOCK_MESH:
+      case SOCK_CUSTOM:
+      case SOCK_SHADER:
+        break;
+    }
+  }
+}
+
+static void expand_node_sockets(FileData *fd, Main *mainvar, ListBase *sockets)
+{
+  LISTBASE_FOREACH (bNodeSocket *, sock, sockets) {
+    expand_node_socket(fd, mainvar, sock);
+  }
+}
+
 static void expand_nodetree(FileData *fd, Main *mainvar, bNodeTree *ntree)
 {
   bNode *node;
-  bNodeSocket *sock;
 
   if (ntree->gpd) {
     expand_doit(fd, mainvar, ntree->gpd);
@@ -10975,20 +11039,12 @@ static void expand_nodetree(FileData *fd, Main *mainvar, bNodeTree *ntree)
 
     expand_idprops(fd, mainvar, node->prop);
 
-    for (sock = node->inputs.first; sock; sock = sock->next) {
-      expand_idprops(fd, mainvar, sock->prop);
-    }
-    for (sock = node->outputs.first; sock; sock = sock->next) {
-      expand_idprops(fd, mainvar, sock->prop);
-    }
+    expand_node_sockets(fd, mainvar, &node->inputs);
+    expand_node_sockets(fd, mainvar, &node->outputs);
   }
 
-  for (sock = ntree->inputs.first; sock; sock = sock->next) {
-    expand_idprops(fd, mainvar, sock->prop);
-  }
-  for (sock = ntree->outputs.first; sock; sock = sock->next) {
-    expand_idprops(fd, mainvar, sock->prop);
-  }
+  expand_node_sockets(fd, mainvar, &ntree->inputs);
+  expand_node_sockets(fd, mainvar, &ntree->outputs);
 }
 
 static void expand_texture(FileData *fd, Main *mainvar, Tex *tex)
index 9b721ae30ffa833dbea5e71bbcde65cb90ab115c..258b0b5c3269dda632a942c129cbfdd5e96e0731 100644 (file)
@@ -991,6 +991,12 @@ static void write_node_socket_default_value(WriteData *wd, bNodeSocket *sock)
     case SOCK_STRING:
       writestruct(wd, DATA, bNodeSocketValueString, 1, sock->default_value);
       break;
+    case SOCK_OBJECT:
+      writestruct(wd, DATA, bNodeSocketValueObject, 1, sock->default_value);
+      break;
+    case SOCK_IMAGE:
+      writestruct(wd, DATA, bNodeSocketValueImage, 1, sock->default_value);
+      break;
     case __SOCK_MESH:
     case SOCK_CUSTOM:
     case SOCK_SHADER:
index 01fbafe6176763f186011ac360719f3211658f33..202e2f2940f059fbdb944858f1b01f1de9210105 100644 (file)
@@ -3277,6 +3277,8 @@ static const float std_node_socket_colors[][4] = {
     {0.0, 0.0, 0.0, 1.0},    /*__SOCK_MESH (deprecated) */
     {0.06, 0.52, 0.15, 1.0}, /* SOCK_INT */
     {0.39, 0.39, 0.39, 1.0}, /* SOCK_STRING */
+    {0.40, 0.10, 0.10, 1.0}, /* SOCK_OBJECT */
+    {0.10, 0.40, 0.10, 1.0}, /* SOCK_IMAGE */
 };
 
 /* common color callbacks for standard types */
@@ -3394,6 +3396,14 @@ static void std_node_socket_draw(
       uiItemR(row, ptr, "default_value", 0, "", 0);
       break;
     }
+    case SOCK_OBJECT: {
+      uiItemR(layout, ptr, "default_value", 0, text, 0);
+      break;
+    }
+    case SOCK_IMAGE: {
+      uiItemR(layout, ptr, "default_value", 0, text, 0);
+      break;
+    }
     default:
       node_socket_button_label(C, layout, ptr, node_ptr, text);
       break;
index 069449fcba7f735ea6fa9bfd0a01e1ec4ccf381a..bf4d3d2e88649e2a009a6d8e08b9f6c5db9a70d2 100644 (file)
@@ -154,6 +154,8 @@ typedef enum eNodeSocketDatatype {
   __SOCK_MESH = 5, /* deprecated */
   SOCK_INT = 6,
   SOCK_STRING = 7,
+  SOCK_OBJECT = 8,
+  SOCK_IMAGE = 9,
 } eNodeSocketDatatype;
 
 /* socket shape */
@@ -566,6 +568,14 @@ typedef struct bNodeSocketValueString {
   char value[1024];
 } bNodeSocketValueString;
 
+typedef struct bNodeSocketValueObject {
+  struct Object *value;
+} bNodeSocketValueObject;
+
+typedef struct bNodeSocketValueImage {
+  struct Image *value;
+} bNodeSocketValueImage;
+
 /* data structs, for node->storage */
 enum {
   CMP_NODE_MASKTYPE_ADD = 0,
index 104423322e659e78489ba22b74f7ce36c8b1bf49..9832b126cb7e57dd278ceeb855c3b8a38438a493 100644 (file)
@@ -81,6 +81,8 @@ static const EnumPropertyItem node_socket_type_items[] = {
     {SOCK_STRING, "STRING", 0, "String", ""},
     {SOCK_RGBA, "RGBA", 0, "RGBA", ""},
     {SOCK_SHADER, "SHADER", 0, "Shader", ""},
+    {SOCK_OBJECT, "OBJECT", 0, "Object", ""},
+    {SOCK_IMAGE, "IMAGE", 0, "Image", ""},
     {0, NULL, 0, NULL, NULL},
 };
 
@@ -8538,6 +8540,74 @@ static void rna_def_node_socket_virtual(BlenderRNA *brna, const char *identifier
   RNA_def_struct_sdna(srna, "bNodeSocket");
 }
 
+static void rna_def_node_socket_object(BlenderRNA *brna,
+                                       const char *identifier,
+                                       const char *interface_idname)
+{
+  StructRNA *srna;
+  PropertyRNA *prop;
+
+  srna = RNA_def_struct(brna, identifier, "NodeSocketStandard");
+  RNA_def_struct_ui_text(srna, "Object Node Socket", "Object socket of a node");
+  RNA_def_struct_sdna(srna, "bNodeSocket");
+
+  RNA_def_struct_sdna_from(srna, "bNodeSocketValueObject", "default_value");
+
+  prop = RNA_def_property(srna, "default_value", PROP_POINTER, PROP_NONE);
+  RNA_def_property_pointer_sdna(prop, NULL, "value");
+  RNA_def_property_struct_type(prop, "Object");
+  RNA_def_property_ui_text(prop, "Default Value", "Input value used for unconnected socket");
+  RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_NodeSocketStandard_value_update");
+  RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_REFCOUNT | PROP_CONTEXT_UPDATE);
+
+  /* socket interface */
+  srna = RNA_def_struct(brna, interface_idname, "NodeSocketInterfaceStandard");
+  RNA_def_struct_ui_text(srna, "Object Node Socket Interface", "Object socket of a node");
+  RNA_def_struct_sdna(srna, "bNodeSocket");
+
+  RNA_def_struct_sdna_from(srna, "bNodeSocketValueObject", "default_value");
+
+  prop = RNA_def_property(srna, "default_value", PROP_POINTER, PROP_NONE);
+  RNA_def_property_pointer_sdna(prop, NULL, "value");
+  RNA_def_property_struct_type(prop, "Object");
+  RNA_def_property_ui_text(prop, "Default Value", "Input value used for unconnected socket");
+  RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_NodeSocketInterface_update");
+}
+
+static void rna_def_node_socket_image(BlenderRNA *brna,
+                                      const char *identifier,
+                                      const char *interface_idname)
+{
+  StructRNA *srna;
+  PropertyRNA *prop;
+
+  srna = RNA_def_struct(brna, identifier, "NodeSocketStandard");
+  RNA_def_struct_ui_text(srna, "Image Node Socket", "Image socket of a node");
+  RNA_def_struct_sdna(srna, "bNodeSocket");
+
+  RNA_def_struct_sdna_from(srna, "bNodeSocketValueImage", "default_value");
+
+  prop = RNA_def_property(srna, "default_value", PROP_POINTER, PROP_NONE);
+  RNA_def_property_pointer_sdna(prop, NULL, "value");
+  RNA_def_property_struct_type(prop, "Image");
+  RNA_def_property_ui_text(prop, "Default Value", "Input value used for unconnected socket");
+  RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_NodeSocketStandard_value_update");
+  RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_REFCOUNT | PROP_CONTEXT_UPDATE);
+
+  /* socket interface */
+  srna = RNA_def_struct(brna, interface_idname, "NodeSocketInterfaceStandard");
+  RNA_def_struct_ui_text(srna, "Image Node Socket Interface", "Image socket of a node");
+  RNA_def_struct_sdna(srna, "bNodeSocket");
+
+  RNA_def_struct_sdna_from(srna, "bNodeSocketValueImage", "default_value");
+
+  prop = RNA_def_property(srna, "default_value", PROP_POINTER, PROP_NONE);
+  RNA_def_property_pointer_sdna(prop, NULL, "value");
+  RNA_def_property_struct_type(prop, "Image");
+  RNA_def_property_ui_text(prop, "Default Value", "Input value used for unconnected socket");
+  RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_NodeSocketInterface_update");
+}
+
 static void rna_def_node_socket_standard_types(BlenderRNA *brna)
 {
   /* XXX Workaround: Registered functions are not exposed in python by bpy,
@@ -8672,6 +8742,10 @@ static void rna_def_node_socket_standard_types(BlenderRNA *brna)
   rna_def_node_socket_shader(brna, "NodeSocketShader", "NodeSocketInterfaceShader");
 
   rna_def_node_socket_virtual(brna, "NodeSocketVirtual");
+
+  rna_def_node_socket_object(brna, "NodeSocketObject", "NodeSocketInterfaceObject");
+
+  rna_def_node_socket_image(brna, "NodeSocketImage", "NodeSocketInterfaceImage");
 }
 
 static void rna_def_internal_node(BlenderRNA *brna)
index 199b469781d25ffe35becfda885e220e1839299c..4433038acf903064945ac8912942524ea213ee82 100644 (file)
@@ -30,6 +30,7 @@
 #include "BLI_string.h"
 #include "BLI_utildefines.h"
 
+#include "BKE_lib_id.h"
 #include "BKE_node.h"
 
 #include "RNA_access.h"
@@ -256,6 +257,22 @@ void node_socket_init_default_value(bNodeSocket *sock)
       dval->subtype = subtype;
       dval->value[0] = '\0';
 
+      sock->default_value = dval;
+      break;
+    }
+    case SOCK_OBJECT: {
+      bNodeSocketValueObject *dval = MEM_callocN(sizeof(bNodeSocketValueObject),
+                                                 "node socket value object");
+      dval->value = NULL;
+
+      sock->default_value = dval;
+      break;
+    }
+    case SOCK_IMAGE: {
+      bNodeSocketValueImage *dval = MEM_callocN(sizeof(bNodeSocketValueImage),
+                                                "node socket value image");
+      dval->value = NULL;
+
       sock->default_value = dval;
       break;
     }
@@ -317,6 +334,20 @@ void node_socket_copy_default_value(bNodeSocket *to, const bNodeSocket *from)
       *toval = *fromval;
       break;
     }
+    case SOCK_OBJECT: {
+      bNodeSocketValueObject *toval = to->default_value;
+      bNodeSocketValueObject *fromval = from->default_value;
+      *toval = *fromval;
+      id_us_plus(&toval->value->id);
+      break;
+    }
+    case SOCK_IMAGE: {
+      bNodeSocketValueImage *toval = to->default_value;
+      bNodeSocketValueImage *fromval = from->default_value;
+      *toval = *fromval;
+      id_us_plus(&toval->value->id);
+      break;
+    }
   }
 
   to->flag |= (from->flag & SOCK_HIDE_VALUE);
@@ -499,5 +530,9 @@ void register_standard_node_socket_types(void)
 
   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_virtual());
 }