Merge branch 'blender-v2.93-release'
[blender.git] / source / blender / modifiers / intern / MOD_nodes.cc
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software  Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  *
16  * The Original Code is Copyright (C) 2005 by the Blender Foundation.
17  * All rights reserved.
18  */
19
20 /** \file
21  * \ingroup modifiers
22  */
23
24 #include <cstring>
25 #include <iostream>
26 #include <string>
27
28 #include "MEM_guardedalloc.h"
29
30 #include "BLI_float3.hh"
31 #include "BLI_listbase.h"
32 #include "BLI_multi_value_map.hh"
33 #include "BLI_set.hh"
34 #include "BLI_string.h"
35 #include "BLI_utildefines.h"
36
37 #include "DNA_collection_types.h"
38 #include "DNA_defaults.h"
39 #include "DNA_mesh_types.h"
40 #include "DNA_meshdata_types.h"
41 #include "DNA_modifier_types.h"
42 #include "DNA_node_types.h"
43 #include "DNA_object_types.h"
44 #include "DNA_pointcloud_types.h"
45 #include "DNA_scene_types.h"
46 #include "DNA_screen_types.h"
47 #include "DNA_space_types.h"
48 #include "DNA_windowmanager_types.h"
49
50 #include "BKE_customdata.h"
51 #include "BKE_geometry_set_instances.hh"
52 #include "BKE_global.h"
53 #include "BKE_idprop.h"
54 #include "BKE_lib_query.h"
55 #include "BKE_main.h"
56 #include "BKE_mesh.h"
57 #include "BKE_modifier.h"
58 #include "BKE_node_ui_storage.hh"
59 #include "BKE_object.h"
60 #include "BKE_pointcloud.h"
61 #include "BKE_screen.h"
62 #include "BKE_simulation.h"
63 #include "BKE_workspace.h"
64
65 #include "BLO_read_write.h"
66
67 #include "UI_interface.h"
68 #include "UI_resources.h"
69
70 #include "RNA_access.h"
71 #include "RNA_enum_types.h"
72
73 #include "DEG_depsgraph_build.h"
74 #include "DEG_depsgraph_query.h"
75
76 #include "MOD_modifiertypes.h"
77 #include "MOD_nodes.h"
78 #include "MOD_nodes_evaluator.hh"
79 #include "MOD_ui_common.h"
80
81 #include "ED_spreadsheet.h"
82
83 #include "NOD_derived_node_tree.hh"
84 #include "NOD_geometry.h"
85 #include "NOD_node_tree_multi_function.hh"
86
87 using blender::float3;
88 using blender::FunctionRef;
89 using blender::IndexRange;
90 using blender::Map;
91 using blender::Set;
92 using blender::Span;
93 using blender::StringRef;
94 using blender::StringRefNull;
95 using blender::Vector;
96 using blender::fn::GMutablePointer;
97 using blender::fn::GPointer;
98 using blender::nodes::GeoNodeExecParams;
99 using namespace blender::fn::multi_function_types;
100 using namespace blender::nodes::derived_node_tree_types;
101
102 static void initData(ModifierData *md)
103 {
104   NodesModifierData *nmd = (NodesModifierData *)md;
105
106   BLI_assert(MEMCMP_STRUCT_AFTER_IS_ZERO(nmd, modifier));
107
108   MEMCPY_STRUCT_AFTER(nmd, DNA_struct_default_get(NodesModifierData), modifier);
109 }
110
111 static void addIdsUsedBySocket(const ListBase *sockets, Set<ID *> &ids)
112 {
113   LISTBASE_FOREACH (const bNodeSocket *, socket, sockets) {
114     if (socket->type == SOCK_OBJECT) {
115       Object *object = ((bNodeSocketValueObject *)socket->default_value)->value;
116       if (object != nullptr) {
117         ids.add(&object->id);
118       }
119     }
120     else if (socket->type == SOCK_COLLECTION) {
121       Collection *collection = ((bNodeSocketValueCollection *)socket->default_value)->value;
122       if (collection != nullptr) {
123         ids.add(&collection->id);
124       }
125     }
126   }
127 }
128
129 static void find_used_ids_from_nodes(const bNodeTree &tree, Set<ID *> &ids)
130 {
131   Set<const bNodeTree *> handled_groups;
132
133   LISTBASE_FOREACH (const bNode *, node, &tree.nodes) {
134     addIdsUsedBySocket(&node->inputs, ids);
135     addIdsUsedBySocket(&node->outputs, ids);
136
137     if (ELEM(node->type, NODE_GROUP, NODE_CUSTOM_GROUP)) {
138       const bNodeTree *group = (bNodeTree *)node->id;
139       if (group != nullptr && handled_groups.add(group)) {
140         find_used_ids_from_nodes(*group, ids);
141       }
142     }
143   }
144 }
145
146 static void find_used_ids_from_settings(const NodesModifierSettings &settings, Set<ID *> &ids)
147 {
148   IDP_foreach_property(
149       settings.properties,
150       IDP_TYPE_FILTER_ID,
151       [](IDProperty *property, void *user_data) {
152         Set<ID *> *ids = (Set<ID *> *)user_data;
153         ID *id = IDP_Id(property);
154         if (id != nullptr) {
155           ids->add(id);
156         }
157       },
158       &ids);
159 }
160
161 /* We don't know exactly what attributes from the other object we will need. */
162 static const CustomData_MeshMasks dependency_data_mask{CD_MASK_PROP_ALL | CD_MASK_MDEFORMVERT,
163                                                        CD_MASK_PROP_ALL,
164                                                        CD_MASK_PROP_ALL,
165                                                        CD_MASK_PROP_ALL,
166                                                        CD_MASK_PROP_ALL};
167
168 static void add_collection_relation(const ModifierUpdateDepsgraphContext *ctx,
169                                     Collection &collection)
170 {
171   DEG_add_collection_geometry_relation(ctx->node, &collection, "Nodes Modifier");
172   DEG_add_collection_geometry_customdata_mask(ctx->node, &collection, &dependency_data_mask);
173 }
174
175 static void add_object_relation(const ModifierUpdateDepsgraphContext *ctx, Object &object)
176 {
177   DEG_add_object_relation(ctx->node, &object, DEG_OB_COMP_TRANSFORM, "Nodes Modifier");
178   if (&(ID &)object != &ctx->object->id) {
179     if (object.type == OB_EMPTY && object.instance_collection != nullptr) {
180       add_collection_relation(ctx, *object.instance_collection);
181     }
182     else if (DEG_object_has_geometry_component(&object)) {
183       DEG_add_object_relation(ctx->node, &object, DEG_OB_COMP_GEOMETRY, "Nodes Modifier");
184       DEG_add_customdata_mask(ctx->node, &object, &dependency_data_mask);
185     }
186   }
187 }
188
189 static void updateDepsgraph(ModifierData *md, const ModifierUpdateDepsgraphContext *ctx)
190 {
191   NodesModifierData *nmd = reinterpret_cast<NodesModifierData *>(md);
192   DEG_add_modifier_to_transform_relation(ctx->node, "Nodes Modifier");
193   if (nmd->node_group != nullptr) {
194     DEG_add_node_tree_relation(ctx->node, nmd->node_group, "Nodes Modifier");
195
196     Set<ID *> used_ids;
197     find_used_ids_from_settings(nmd->settings, used_ids);
198     find_used_ids_from_nodes(*nmd->node_group, used_ids);
199     for (ID *id : used_ids) {
200       if (GS(id->name) == ID_OB) {
201         Object *object = reinterpret_cast<Object *>(id);
202         add_object_relation(ctx, *object);
203       }
204       if (GS(id->name) == ID_GR) {
205         Collection *collection = reinterpret_cast<Collection *>(id);
206         add_collection_relation(ctx, *collection);
207       }
208     }
209   }
210
211   /* TODO: Add dependency for adding and removing objects in collections. */
212 }
213
214 static void foreachIDLink(ModifierData *md, Object *ob, IDWalkFunc walk, void *userData)
215 {
216   NodesModifierData *nmd = reinterpret_cast<NodesModifierData *>(md);
217   walk(userData, ob, (ID **)&nmd->node_group, IDWALK_CB_USER);
218
219   struct ForeachSettingData {
220     IDWalkFunc walk;
221     void *userData;
222     Object *ob;
223   } settings = {walk, userData, ob};
224
225   IDP_foreach_property(
226       nmd->settings.properties,
227       IDP_TYPE_FILTER_ID,
228       [](IDProperty *id_prop, void *user_data) {
229         ForeachSettingData *settings = (ForeachSettingData *)user_data;
230         settings->walk(
231             settings->userData, settings->ob, (ID **)&id_prop->data.pointer, IDWALK_CB_USER);
232       },
233       &settings);
234 }
235
236 static void foreachTexLink(ModifierData *md, Object *ob, TexWalkFunc walk, void *userData)
237 {
238   walk(userData, ob, md, "texture");
239 }
240
241 static bool isDisabled(const struct Scene *UNUSED(scene),
242                        ModifierData *md,
243                        bool UNUSED(useRenderParams))
244 {
245   NodesModifierData *nmd = reinterpret_cast<NodesModifierData *>(md);
246
247   if (nmd->node_group == nullptr) {
248     return true;
249   }
250
251   return false;
252 }
253
254 static bool logging_enabled(const ModifierEvalContext *ctx)
255 {
256   if (!DEG_is_active(ctx->depsgraph)) {
257     return false;
258   }
259   if ((ctx->flag & MOD_APPLY_ORCO) != 0) {
260     return false;
261   }
262   return true;
263 }
264
265 /**
266  * This code is responsible for creating the new property and also creating the group of
267  * properties in the prop_ui_container group for the UI info, the mapping for which is
268  * scattered about in RNA_access.c.
269  *
270  * TODO(Hans): Codify this with some sort of table or refactor IDProperty use in RNA_access.c.
271  */
272 struct SocketPropertyType {
273   /* Create the actual property used to store the data for the modifier. */
274   IDProperty *(*create_prop)(const bNodeSocket &socket, const char *name);
275   /* Reused to build the "soft_min" property too. */
276   IDProperty *(*create_min_ui_prop)(const bNodeSocket &socket, const char *name);
277   /* Reused to build the "soft_max" property too. */
278   IDProperty *(*create_max_ui_prop)(const bNodeSocket &socket, const char *name);
279   /* This uses the same values as #create_prop, but sometimes the type is different, so it can't
280    * be the same function. */
281   IDProperty *(*create_default_ui_prop)(const bNodeSocket &socket, const char *name);
282   PropertyType (*rna_subtype_get)(const bNodeSocket &socket);
283   bool (*is_correct_type)(const IDProperty &property);
284   void (*init_cpp_value)(const IDProperty &property, void *r_value);
285 };
286
287 static IDProperty *socket_add_property(IDProperty *settings_prop_group,
288                                        IDProperty *ui_container,
289                                        const SocketPropertyType &property_type,
290                                        const bNodeSocket &socket)
291 {
292   const char *new_prop_name = socket.identifier;
293   /* Add the property actually storing the data to the modifier's group. */
294   IDProperty *prop = property_type.create_prop(socket, new_prop_name);
295   IDP_AddToGroup(settings_prop_group, prop);
296
297   prop->flag |= IDP_FLAG_OVERRIDABLE_LIBRARY;
298
299   /* Make the group in the UI container group to hold the property's UI settings. */
300   IDProperty *prop_ui_group;
301   {
302     IDPropertyTemplate idprop = {0};
303     prop_ui_group = IDP_New(IDP_GROUP, &idprop, new_prop_name);
304     IDP_AddToGroup(ui_container, prop_ui_group);
305   }
306
307   /* Set property description (tooltip). */
308   IDPropertyTemplate property_description_template;
309   property_description_template.string.str = socket.description;
310   property_description_template.string.len = BLI_strnlen(socket.description, MAX_NAME) + 1;
311   property_description_template.string.subtype = IDP_STRING_SUB_UTF8;
312   IDProperty *description = IDP_New(IDP_STRING, &property_description_template, "description");
313   IDP_AddToGroup(prop_ui_group, description);
314
315   /* Create the properties for the socket's UI settings. */
316   if (property_type.create_min_ui_prop != nullptr) {
317     IDP_AddToGroup(prop_ui_group, property_type.create_min_ui_prop(socket, "min"));
318     IDP_AddToGroup(prop_ui_group, property_type.create_min_ui_prop(socket, "soft_min"));
319   }
320   if (property_type.create_max_ui_prop != nullptr) {
321     IDP_AddToGroup(prop_ui_group, property_type.create_max_ui_prop(socket, "max"));
322     IDP_AddToGroup(prop_ui_group, property_type.create_max_ui_prop(socket, "soft_max"));
323   }
324   if (property_type.create_default_ui_prop != nullptr) {
325     IDP_AddToGroup(prop_ui_group, property_type.create_default_ui_prop(socket, "default"));
326   }
327   if (property_type.rna_subtype_get != nullptr) {
328     const char *subtype_identifier = nullptr;
329     RNA_enum_identifier(rna_enum_property_subtype_items,
330                         property_type.rna_subtype_get(socket),
331                         &subtype_identifier);
332
333     if (subtype_identifier != nullptr) {
334       IDPropertyTemplate idprop = {0};
335       idprop.string.str = subtype_identifier;
336       idprop.string.len = BLI_strnlen(subtype_identifier, MAX_NAME) + 1;
337       IDP_AddToGroup(prop_ui_group, IDP_New(IDP_STRING, &idprop, "subtype"));
338     }
339   }
340
341   return prop;
342 }
343
344 static const SocketPropertyType *get_socket_property_type(const bNodeSocket &bsocket)
345 {
346   switch (bsocket.type) {
347     case SOCK_FLOAT: {
348       static const SocketPropertyType float_type = {
349           [](const bNodeSocket &socket, const char *name) {
350             bNodeSocketValueFloat *value = (bNodeSocketValueFloat *)socket.default_value;
351             IDPropertyTemplate idprop = {0};
352             idprop.f = value->value;
353             return IDP_New(IDP_FLOAT, &idprop, name);
354           },
355           [](const bNodeSocket &socket, const char *name) {
356             bNodeSocketValueFloat *value = (bNodeSocketValueFloat *)socket.default_value;
357             IDPropertyTemplate idprop = {0};
358             idprop.d = value->min;
359             return IDP_New(IDP_DOUBLE, &idprop, name);
360           },
361           [](const bNodeSocket &socket, const char *name) {
362             bNodeSocketValueFloat *value = (bNodeSocketValueFloat *)socket.default_value;
363             IDPropertyTemplate idprop = {0};
364             idprop.d = value->max;
365             return IDP_New(IDP_DOUBLE, &idprop, name);
366           },
367           [](const bNodeSocket &socket, const char *name) {
368             bNodeSocketValueFloat *value = (bNodeSocketValueFloat *)socket.default_value;
369             IDPropertyTemplate idprop = {0};
370             idprop.d = value->value;
371             return IDP_New(IDP_DOUBLE, &idprop, name);
372           },
373           [](const bNodeSocket &socket) {
374             return (PropertyType)((bNodeSocketValueFloat *)socket.default_value)->subtype;
375           },
376           [](const IDProperty &property) { return ELEM(property.type, IDP_FLOAT, IDP_DOUBLE); },
377           [](const IDProperty &property, void *r_value) {
378             if (property.type == IDP_FLOAT) {
379               *(float *)r_value = IDP_Float(&property);
380             }
381             else if (property.type == IDP_DOUBLE) {
382               *(float *)r_value = (float)IDP_Double(&property);
383             }
384           },
385       };
386       return &float_type;
387     }
388     case SOCK_INT: {
389       static const SocketPropertyType int_type = {
390           [](const bNodeSocket &socket, const char *name) {
391             bNodeSocketValueInt *value = (bNodeSocketValueInt *)socket.default_value;
392             IDPropertyTemplate idprop = {0};
393             idprop.i = value->value;
394             return IDP_New(IDP_INT, &idprop, name);
395           },
396           [](const bNodeSocket &socket, const char *name) {
397             bNodeSocketValueInt *value = (bNodeSocketValueInt *)socket.default_value;
398             IDPropertyTemplate idprop = {0};
399             idprop.i = value->min;
400             return IDP_New(IDP_INT, &idprop, name);
401           },
402           [](const bNodeSocket &socket, const char *name) {
403             bNodeSocketValueInt *value = (bNodeSocketValueInt *)socket.default_value;
404             IDPropertyTemplate idprop = {0};
405             idprop.i = value->max;
406             return IDP_New(IDP_INT, &idprop, name);
407           },
408           [](const bNodeSocket &socket, const char *name) {
409             bNodeSocketValueInt *value = (bNodeSocketValueInt *)socket.default_value;
410             IDPropertyTemplate idprop = {0};
411             idprop.i = value->value;
412             return IDP_New(IDP_INT, &idprop, name);
413           },
414           [](const bNodeSocket &socket) {
415             return (PropertyType)((bNodeSocketValueInt *)socket.default_value)->subtype;
416           },
417           [](const IDProperty &property) { return property.type == IDP_INT; },
418           [](const IDProperty &property, void *r_value) { *(int *)r_value = IDP_Int(&property); },
419       };
420       return &int_type;
421     }
422     case SOCK_VECTOR: {
423       static const SocketPropertyType vector_type = {
424           [](const bNodeSocket &socket, const char *name) {
425             bNodeSocketValueVector *value = (bNodeSocketValueVector *)socket.default_value;
426             IDPropertyTemplate idprop = {0};
427             idprop.array.len = 3;
428             idprop.array.type = IDP_FLOAT;
429             IDProperty *property = IDP_New(IDP_ARRAY, &idprop, name);
430             copy_v3_v3((float *)IDP_Array(property), value->value);
431             return property;
432           },
433           [](const bNodeSocket &socket, const char *name) {
434             bNodeSocketValueVector *value = (bNodeSocketValueVector *)socket.default_value;
435             IDPropertyTemplate idprop = {0};
436             idprop.d = value->min;
437             return IDP_New(IDP_DOUBLE, &idprop, name);
438           },
439           [](const bNodeSocket &socket, const char *name) {
440             bNodeSocketValueVector *value = (bNodeSocketValueVector *)socket.default_value;
441             IDPropertyTemplate idprop = {0};
442             idprop.d = value->max;
443             return IDP_New(IDP_DOUBLE, &idprop, name);
444           },
445           [](const bNodeSocket &socket, const char *name) {
446             bNodeSocketValueVector *value = (bNodeSocketValueVector *)socket.default_value;
447             IDPropertyTemplate idprop = {0};
448             idprop.array.len = 3;
449             idprop.array.type = IDP_FLOAT;
450             IDProperty *property = IDP_New(IDP_ARRAY, &idprop, name);
451             copy_v3_v3((float *)IDP_Array(property), value->value);
452             return property;
453           },
454           [](const bNodeSocket &socket) {
455             return (PropertyType)((bNodeSocketValueVector *)socket.default_value)->subtype;
456           },
457           [](const IDProperty &property) {
458             return property.type == IDP_ARRAY && property.subtype == IDP_FLOAT &&
459                    property.len == 3;
460           },
461           [](const IDProperty &property, void *r_value) {
462             copy_v3_v3((float *)r_value, (const float *)IDP_Array(&property));
463           },
464       };
465       return &vector_type;
466     }
467     case SOCK_BOOLEAN: {
468       static const SocketPropertyType boolean_type = {
469           [](const bNodeSocket &socket, const char *name) {
470             bNodeSocketValueBoolean *value = (bNodeSocketValueBoolean *)socket.default_value;
471             IDPropertyTemplate idprop = {0};
472             idprop.i = value->value != 0;
473             return IDP_New(IDP_INT, &idprop, name);
474           },
475           [](const bNodeSocket &UNUSED(socket), const char *name) {
476             IDPropertyTemplate idprop = {0};
477             idprop.i = 0;
478             return IDP_New(IDP_INT, &idprop, name);
479           },
480           [](const bNodeSocket &UNUSED(socket), const char *name) {
481             IDPropertyTemplate idprop = {0};
482             idprop.i = 1;
483             return IDP_New(IDP_INT, &idprop, name);
484           },
485           [](const bNodeSocket &socket, const char *name) {
486             bNodeSocketValueBoolean *value = (bNodeSocketValueBoolean *)socket.default_value;
487             IDPropertyTemplate idprop = {0};
488             idprop.i = value->value != 0;
489             return IDP_New(IDP_INT, &idprop, name);
490           },
491           nullptr,
492           [](const IDProperty &property) { return property.type == IDP_INT; },
493           [](const IDProperty &property, void *r_value) {
494             *(bool *)r_value = IDP_Int(&property) != 0;
495           },
496       };
497       return &boolean_type;
498     }
499     case SOCK_STRING: {
500       static const SocketPropertyType string_type = {
501           [](const bNodeSocket &socket, const char *name) {
502             bNodeSocketValueString *value = (bNodeSocketValueString *)socket.default_value;
503             return IDP_NewString(
504                 value->value, name, BLI_strnlen(value->value, sizeof(value->value)) + 1);
505           },
506           nullptr,
507           nullptr,
508           [](const bNodeSocket &socket, const char *name) {
509             bNodeSocketValueString *value = (bNodeSocketValueString *)socket.default_value;
510             return IDP_NewString(
511                 value->value, name, BLI_strnlen(value->value, sizeof(value->value)) + 1);
512           },
513           nullptr,
514           [](const IDProperty &property) { return property.type == IDP_STRING; },
515           [](const IDProperty &property, void *r_value) {
516             new (r_value) std::string(IDP_String(&property));
517           },
518       };
519       return &string_type;
520     }
521     case SOCK_OBJECT: {
522       static const SocketPropertyType object_type = {
523           [](const bNodeSocket &socket, const char *name) {
524             bNodeSocketValueObject *value = (bNodeSocketValueObject *)socket.default_value;
525             IDPropertyTemplate idprop = {0};
526             idprop.id = (ID *)value->value;
527             return IDP_New(IDP_ID, &idprop, name);
528           },
529           nullptr,
530           nullptr,
531           nullptr,
532           nullptr,
533           [](const IDProperty &property) { return property.type == IDP_ID; },
534           [](const IDProperty &property, void *r_value) {
535             ID *id = IDP_Id(&property);
536             Object *object = (id && GS(id->name) == ID_OB) ? (Object *)id : nullptr;
537             *(Object **)r_value = object;
538           },
539       };
540       return &object_type;
541     }
542     case SOCK_COLLECTION: {
543       static const SocketPropertyType collection_type = {
544           [](const bNodeSocket &socket, const char *name) {
545             bNodeSocketValueCollection *value = (bNodeSocketValueCollection *)socket.default_value;
546             IDPropertyTemplate idprop = {0};
547             idprop.id = (ID *)value->value;
548             return IDP_New(IDP_ID, &idprop, name);
549           },
550           nullptr,
551           nullptr,
552           nullptr,
553           nullptr,
554           [](const IDProperty &property) { return property.type == IDP_ID; },
555           [](const IDProperty &property, void *r_value) {
556             ID *id = IDP_Id(&property);
557             Collection *collection = (id && GS(id->name) == ID_GR) ? (Collection *)id : nullptr;
558             *(Collection **)r_value = collection;
559           },
560       };
561       return &collection_type;
562     }
563     default: {
564       return nullptr;
565     }
566   }
567 }
568
569 /**
570  * Rebuild the list of properties based on the sockets exposed as the modifier's node group
571  * inputs. If any properties correspond to the old properties by name and type, carry over
572  * the values.
573  */
574 void MOD_nodes_update_interface(Object *object, NodesModifierData *nmd)
575 {
576   if (nmd->node_group == nullptr) {
577     return;
578   }
579
580   IDProperty *old_properties = nmd->settings.properties;
581
582   {
583     IDPropertyTemplate idprop = {0};
584     nmd->settings.properties = IDP_New(IDP_GROUP, &idprop, "Nodes Modifier Settings");
585   }
586
587   IDProperty *ui_container_group;
588   {
589     IDPropertyTemplate idprop = {0};
590     ui_container_group = IDP_New(IDP_GROUP, &idprop, "_RNA_UI");
591     IDP_AddToGroup(nmd->settings.properties, ui_container_group);
592   }
593
594   LISTBASE_FOREACH (bNodeSocket *, socket, &nmd->node_group->inputs) {
595     const SocketPropertyType *property_type = get_socket_property_type(*socket);
596     if (property_type == nullptr) {
597       continue;
598     }
599
600     IDProperty *new_prop = socket_add_property(
601         nmd->settings.properties, ui_container_group, *property_type, *socket);
602
603     if (old_properties != nullptr) {
604       IDProperty *old_prop = IDP_GetPropertyFromGroup(old_properties, socket->identifier);
605       if (old_prop != nullptr && property_type->is_correct_type(*old_prop)) {
606         IDP_CopyPropertyContent(new_prop, old_prop);
607       }
608     }
609   }
610
611   if (old_properties != nullptr) {
612     IDP_FreeProperty(old_properties);
613   }
614
615   DEG_id_tag_update(&object->id, ID_RECALC_GEOMETRY);
616 }
617
618 void MOD_nodes_init(Main *bmain, NodesModifierData *nmd)
619 {
620   bNodeTree *ntree = ntreeAddTree(bmain, "Geometry Nodes", ntreeType_Geometry->idname);
621   nmd->node_group = ntree;
622
623   ntreeAddSocketInterface(ntree, SOCK_IN, "NodeSocketGeometry", "Geometry");
624   ntreeAddSocketInterface(ntree, SOCK_OUT, "NodeSocketGeometry", "Geometry");
625
626   bNode *group_input_node = nodeAddStaticNode(nullptr, ntree, NODE_GROUP_INPUT);
627   bNode *group_output_node = nodeAddStaticNode(nullptr, ntree, NODE_GROUP_OUTPUT);
628
629   nodeSetSelected(group_input_node, false);
630   nodeSetSelected(group_output_node, false);
631
632   group_input_node->locx = -200 - group_input_node->width;
633   group_output_node->locx = 200;
634   group_output_node->flag |= NODE_DO_OUTPUT;
635
636   nodeAddLink(ntree,
637               group_output_node,
638               (bNodeSocket *)group_output_node->inputs.first,
639               group_input_node,
640               (bNodeSocket *)group_input_node->outputs.first);
641
642   ntreeUpdateTree(bmain, ntree);
643 }
644
645 static void initialize_group_input(NodesModifierData &nmd,
646                                    const bNodeSocket &socket,
647                                    const CPPType &cpp_type,
648                                    void *r_value)
649 {
650   const SocketPropertyType *property_type = get_socket_property_type(socket);
651   if (property_type == nullptr) {
652     cpp_type.copy_to_uninitialized(cpp_type.default_value(), r_value);
653     return;
654   }
655   if (nmd.settings.properties == nullptr) {
656     blender::nodes::socket_cpp_value_get(socket, r_value);
657     return;
658   }
659   const IDProperty *property = IDP_GetPropertyFromGroup(nmd.settings.properties,
660                                                         socket.identifier);
661   if (property == nullptr) {
662     blender::nodes::socket_cpp_value_get(socket, r_value);
663     return;
664   }
665   if (!property_type->is_correct_type(*property)) {
666     blender::nodes::socket_cpp_value_get(socket, r_value);
667     return;
668   }
669   property_type->init_cpp_value(*property, r_value);
670 }
671
672 static void reset_tree_ui_storage(Span<const blender::nodes::NodeTreeRef *> trees,
673                                   const Object &object,
674                                   const ModifierData &modifier)
675 {
676   const NodeTreeEvaluationContext context = {object, modifier};
677
678   for (const blender::nodes::NodeTreeRef *tree : trees) {
679     bNodeTree *btree_cow = tree->btree();
680     bNodeTree *btree_original = (bNodeTree *)DEG_get_original_id((ID *)btree_cow);
681     BKE_nodetree_ui_storage_free_for_context(*btree_original, context);
682   }
683 }
684
685 static Vector<SpaceSpreadsheet *> find_spreadsheet_editors(Main *bmain)
686 {
687   wmWindowManager *wm = (wmWindowManager *)bmain->wm.first;
688   if (wm == nullptr) {
689     return {};
690   }
691   Vector<SpaceSpreadsheet *> spreadsheets;
692   LISTBASE_FOREACH (wmWindow *, window, &wm->windows) {
693     bScreen *screen = BKE_workspace_active_screen_get(window->workspace_hook);
694     LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
695       SpaceLink *sl = (SpaceLink *)area->spacedata.first;
696       if (sl->spacetype == SPACE_SPREADSHEET) {
697         spreadsheets.append((SpaceSpreadsheet *)sl);
698       }
699     }
700   }
701   return spreadsheets;
702 }
703
704 using PreviewSocketMap = blender::MultiValueMap<DSocket, uint64_t>;
705
706 static DSocket try_find_preview_socket_in_node(const DNode node)
707 {
708   for (const SocketRef *socket : node->outputs()) {
709     if (socket->bsocket()->type == SOCK_GEOMETRY) {
710       return {node.context(), socket};
711     }
712   }
713   for (const SocketRef *socket : node->inputs()) {
714     if (socket->bsocket()->type == SOCK_GEOMETRY &&
715         (socket->bsocket()->flag & SOCK_MULTI_INPUT) == 0) {
716       return {node.context(), socket};
717     }
718   }
719   return {};
720 }
721
722 static DSocket try_get_socket_to_preview_for_spreadsheet(SpaceSpreadsheet *sspreadsheet,
723                                                          NodesModifierData *nmd,
724                                                          const ModifierEvalContext *ctx,
725                                                          const DerivedNodeTree &tree)
726 {
727   Vector<SpreadsheetContext *> context_path = sspreadsheet->context_path;
728   if (context_path.size() < 3) {
729     return {};
730   }
731   if (context_path[0]->type != SPREADSHEET_CONTEXT_OBJECT) {
732     return {};
733   }
734   if (context_path[1]->type != SPREADSHEET_CONTEXT_MODIFIER) {
735     return {};
736   }
737   SpreadsheetContextObject *object_context = (SpreadsheetContextObject *)context_path[0];
738   if (object_context->object != DEG_get_original_object(ctx->object)) {
739     return {};
740   }
741   SpreadsheetContextModifier *modifier_context = (SpreadsheetContextModifier *)context_path[1];
742   if (StringRef(modifier_context->modifier_name) != nmd->modifier.name) {
743     return {};
744   }
745   for (SpreadsheetContext *context : context_path.as_span().drop_front(2)) {
746     if (context->type != SPREADSHEET_CONTEXT_NODE) {
747       return {};
748     }
749   }
750
751   Span<SpreadsheetContextNode *> nested_group_contexts =
752       context_path.as_span().drop_front(2).drop_back(1).cast<SpreadsheetContextNode *>();
753   SpreadsheetContextNode *last_context = (SpreadsheetContextNode *)context_path.last();
754
755   const DTreeContext *context = &tree.root_context();
756   for (SpreadsheetContextNode *node_context : nested_group_contexts) {
757     const NodeTreeRef &tree_ref = context->tree();
758     const NodeRef *found_node = nullptr;
759     for (const NodeRef *node_ref : tree_ref.nodes()) {
760       if (node_ref->name() == node_context->node_name) {
761         found_node = node_ref;
762         break;
763       }
764     }
765     if (found_node == nullptr) {
766       return {};
767     }
768     context = context->child_context(*found_node);
769     if (context == nullptr) {
770       return {};
771     }
772   }
773
774   const NodeTreeRef &tree_ref = context->tree();
775   for (const NodeRef *node_ref : tree_ref.nodes()) {
776     if (node_ref->name() == last_context->node_name) {
777       return try_find_preview_socket_in_node({context, node_ref});
778     }
779   }
780   return {};
781 }
782
783 static void find_sockets_to_preview(NodesModifierData *nmd,
784                                     const ModifierEvalContext *ctx,
785                                     const DerivedNodeTree &tree,
786                                     PreviewSocketMap &r_sockets_to_preview)
787 {
788   Main *bmain = DEG_get_bmain(ctx->depsgraph);
789
790   /* Based on every visible spreadsheet context path, get a list of sockets that need to have their
791    * intermediate geometries cached for display. */
792   Vector<SpaceSpreadsheet *> spreadsheets = find_spreadsheet_editors(bmain);
793   for (SpaceSpreadsheet *sspreadsheet : spreadsheets) {
794     const DSocket socket = try_get_socket_to_preview_for_spreadsheet(sspreadsheet, nmd, ctx, tree);
795     if (socket) {
796       const uint64_t key = ED_spreadsheet_context_path_hash(sspreadsheet);
797       r_sockets_to_preview.add_non_duplicates(socket, key);
798     }
799   }
800 }
801
802 static void log_preview_socket_value(const Span<GPointer> values,
803                                      Object *object,
804                                      Span<uint64_t> keys)
805 {
806   GeometrySet geometry_set = *(const GeometrySet *)values[0].get();
807   geometry_set.ensure_owns_direct_data();
808   for (uint64_t key : keys) {
809     BKE_object_preview_geometry_set_add(object, key, new GeometrySet(geometry_set));
810   }
811 }
812
813 static void log_ui_hints(const DSocket socket,
814                          const Span<GPointer> values,
815                          Object *self_object,
816                          NodesModifierData *nmd)
817 {
818   const DNode node = socket.node();
819   if (node->is_reroute_node() || socket->typeinfo()->type != SOCK_GEOMETRY) {
820     return;
821   }
822   bNodeTree *btree_cow = node->btree();
823   bNodeTree *btree_original = (bNodeTree *)DEG_get_original_id((ID *)btree_cow);
824   const NodeTreeEvaluationContext context{*self_object, nmd->modifier};
825   for (const GPointer &data : values) {
826     if (data.type() == &CPPType::get<GeometrySet>()) {
827       const GeometrySet &geometry_set = *(const GeometrySet *)data.get();
828       blender::bke::geometry_set_instances_attribute_foreach(
829           geometry_set,
830           [&](StringRefNull attribute_name, const AttributeMetaData &meta_data) {
831             BKE_nodetree_attribute_hint_add(*btree_original,
832                                             context,
833                                             *node->bnode(),
834                                             attribute_name,
835                                             meta_data.domain,
836                                             meta_data.data_type);
837             return true;
838           },
839           8);
840     }
841   }
842 }
843
844 /**
845  * Evaluate a node group to compute the output geometry.
846  * Currently, this uses a fairly basic and inefficient algorithm that might compute things more
847  * often than necessary. It's going to be replaced soon.
848  */
849 static GeometrySet compute_geometry(const DerivedNodeTree &tree,
850                                     Span<const NodeRef *> group_input_nodes,
851                                     const InputSocketRef &socket_to_compute,
852                                     GeometrySet input_geometry_set,
853                                     NodesModifierData *nmd,
854                                     const ModifierEvalContext *ctx)
855 {
856   blender::ResourceScope scope;
857   blender::LinearAllocator<> &allocator = scope.linear_allocator();
858   blender::nodes::MultiFunctionByNode mf_by_node = get_multi_function_per_node(tree, scope);
859
860   Map<DOutputSocket, GMutablePointer> group_inputs;
861
862   const DTreeContext *root_context = &tree.root_context();
863   for (const NodeRef *group_input_node : group_input_nodes) {
864     Span<const OutputSocketRef *> group_input_sockets = group_input_node->outputs().drop_back(1);
865     if (group_input_sockets.is_empty()) {
866       continue;
867     }
868
869     Span<const OutputSocketRef *> remaining_input_sockets = group_input_sockets;
870
871     /* If the group expects a geometry as first input, use the geometry that has been passed to
872      * modifier. */
873     const OutputSocketRef *first_input_socket = group_input_sockets[0];
874     if (first_input_socket->bsocket()->type == SOCK_GEOMETRY) {
875       GeometrySet *geometry_set_in =
876           allocator.construct<GeometrySet>(input_geometry_set).release();
877       group_inputs.add_new({root_context, first_input_socket}, geometry_set_in);
878       remaining_input_sockets = remaining_input_sockets.drop_front(1);
879     }
880
881     /* Initialize remaining group inputs. */
882     for (const OutputSocketRef *socket : remaining_input_sockets) {
883       const CPPType &cpp_type = *blender::nodes::socket_cpp_type_get(*socket->typeinfo());
884       void *value_in = allocator.allocate(cpp_type.size(), cpp_type.alignment());
885       initialize_group_input(*nmd, *socket->bsocket(), cpp_type, value_in);
886       group_inputs.add_new({root_context, socket}, {cpp_type, value_in});
887     }
888   }
889
890   /* Don't keep a reference to the input geometry components to avoid copies during evaluation. */
891   input_geometry_set.clear();
892
893   Vector<DInputSocket> group_outputs;
894   group_outputs.append({root_context, &socket_to_compute});
895
896   PreviewSocketMap preview_sockets;
897   find_sockets_to_preview(nmd, ctx, tree, preview_sockets);
898
899   auto log_socket_value = [&](const DSocket socket, const Span<GPointer> values) {
900     if (!logging_enabled(ctx)) {
901       return;
902     }
903     Span<uint64_t> keys = preview_sockets.lookup(socket);
904     if (!keys.is_empty()) {
905       log_preview_socket_value(values, ctx->object, keys);
906     }
907     log_ui_hints(socket, values, ctx->object, nmd);
908   };
909
910   blender::modifiers::geometry_nodes::GeometryNodesEvaluationParams eval_params;
911   eval_params.input_values = group_inputs;
912   eval_params.output_sockets = group_outputs;
913   eval_params.mf_by_node = &mf_by_node;
914   eval_params.modifier_ = nmd;
915   eval_params.depsgraph = ctx->depsgraph;
916   eval_params.self_object = ctx->object;
917   eval_params.log_socket_value_fn = log_socket_value;
918   blender::modifiers::geometry_nodes::evaluate_geometry_nodes(eval_params);
919
920   BLI_assert(eval_params.r_output_values.size() == 1);
921   GMutablePointer result = eval_params.r_output_values[0];
922   return result.relocate_out<GeometrySet>();
923 }
924
925 /**
926  * \note This could be done in #initialize_group_input, though that would require adding the
927  * the object as a parameter, so it's likely better to this check as a separate step.
928  */
929 static void check_property_socket_sync(const Object *ob, ModifierData *md)
930 {
931   NodesModifierData *nmd = reinterpret_cast<NodesModifierData *>(md);
932
933   int i = 0;
934   LISTBASE_FOREACH_INDEX (const bNodeSocket *, socket, &nmd->node_group->inputs, i) {
935     /* The first socket is the special geometry socket for the modifier object. */
936     if (i == 0 && socket->type == SOCK_GEOMETRY) {
937       continue;
938     }
939
940     IDProperty *property = IDP_GetPropertyFromGroup(nmd->settings.properties, socket->identifier);
941     if (property == nullptr) {
942       if (socket->type == SOCK_GEOMETRY) {
943         BKE_modifier_set_error(ob, md, "Node group can only have one geometry input");
944       }
945       else {
946         BKE_modifier_set_error(ob, md, "Missing property for input socket \"%s\"", socket->name);
947       }
948       continue;
949     }
950
951     const SocketPropertyType *property_type = get_socket_property_type(*socket);
952     if (!property_type->is_correct_type(*property)) {
953       BKE_modifier_set_error(
954           ob, md, "Property type does not match input socket \"(%s)\"", socket->name);
955       continue;
956     }
957   }
958
959   bool has_geometry_output = false;
960   LISTBASE_FOREACH (const bNodeSocket *, socket, &nmd->node_group->outputs) {
961     if (socket->type == SOCK_GEOMETRY) {
962       has_geometry_output = true;
963     }
964   }
965
966   if (!has_geometry_output) {
967     BKE_modifier_set_error(ob, md, "Node group must have a geometry output");
968   }
969 }
970
971 static void modifyGeometry(ModifierData *md,
972                            const ModifierEvalContext *ctx,
973                            GeometrySet &geometry_set)
974 {
975   NodesModifierData *nmd = reinterpret_cast<NodesModifierData *>(md);
976   if (nmd->node_group == nullptr) {
977     return;
978   }
979
980   check_property_socket_sync(ctx->object, md);
981
982   NodeTreeRefMap tree_refs;
983   DerivedNodeTree tree{*nmd->node_group, tree_refs};
984
985   if (tree.has_link_cycles()) {
986     BKE_modifier_set_error(ctx->object, md, "Node group has cycles");
987     return;
988   }
989
990   const NodeTreeRef &root_tree_ref = tree.root_context().tree();
991   Span<const NodeRef *> input_nodes = root_tree_ref.nodes_by_type("NodeGroupInput");
992   Span<const NodeRef *> output_nodes = root_tree_ref.nodes_by_type("NodeGroupOutput");
993
994   if (output_nodes.size() != 1) {
995     return;
996   }
997
998   Span<const InputSocketRef *> group_outputs = output_nodes[0]->inputs().drop_back(1);
999
1000   if (group_outputs.size() == 0) {
1001     return;
1002   }
1003
1004   const InputSocketRef *group_output = group_outputs[0];
1005   if (group_output->idname() != "NodeSocketGeometry") {
1006     return;
1007   }
1008
1009   if (logging_enabled(ctx)) {
1010     reset_tree_ui_storage(tree.used_node_tree_refs(), *ctx->object, *md);
1011   }
1012
1013   geometry_set = compute_geometry(
1014       tree, input_nodes, *group_outputs[0], std::move(geometry_set), nmd, ctx);
1015 }
1016
1017 static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh)
1018 {
1019   GeometrySet geometry_set = GeometrySet::create_with_mesh(mesh, GeometryOwnershipType::Editable);
1020   geometry_set.get_component_for_write<MeshComponent>().copy_vertex_group_names_from_object(
1021       *ctx->object);
1022   modifyGeometry(md, ctx, geometry_set);
1023
1024   /* This function is only called when applying modifiers. In this case it makes sense to realize
1025    * instances, otherwise in some cases there might be no results when applying the modifier. */
1026   geometry_set = blender::bke::geometry_set_realize_mesh_for_modifier(geometry_set);
1027
1028   Mesh *new_mesh = geometry_set.get_component_for_write<MeshComponent>().release();
1029   if (new_mesh == nullptr) {
1030     return BKE_mesh_new_nomain(0, 0, 0, 0, 0);
1031   }
1032   return new_mesh;
1033 }
1034
1035 static void modifyGeometrySet(ModifierData *md,
1036                               const ModifierEvalContext *ctx,
1037                               GeometrySet *geometry_set)
1038 {
1039   modifyGeometry(md, ctx, *geometry_set);
1040 }
1041
1042 /* Drawing the properties manually with #uiItemR instead of #uiDefAutoButsRNA allows using
1043  * the node socket identifier for the property names, since they are unique, but also having
1044  * the correct label displayed in the UI.  */
1045 static void draw_property_for_socket(uiLayout *layout,
1046                                      PointerRNA *bmain_ptr,
1047                                      PointerRNA *md_ptr,
1048                                      const IDProperty *modifier_props,
1049                                      const bNodeSocket &socket)
1050 {
1051   const SocketPropertyType *property_type = get_socket_property_type(socket);
1052   if (property_type == nullptr) {
1053     return;
1054   }
1055
1056   /* The property should be created in #MOD_nodes_update_interface with the correct type. */
1057   IDProperty *property = IDP_GetPropertyFromGroup(modifier_props, socket.identifier);
1058
1059   /* IDProperties can be removed with python, so there could be a situation where
1060    * there isn't a property for a socket or it doesn't have the correct type. */
1061   if (property == nullptr || !property_type->is_correct_type(*property)) {
1062     return;
1063   }
1064
1065   char socket_id_esc[sizeof(socket.identifier) * 2];
1066   BLI_str_escape(socket_id_esc, socket.identifier, sizeof(socket_id_esc));
1067
1068   char rna_path[sizeof(socket_id_esc) + 4];
1069   BLI_snprintf(rna_path, ARRAY_SIZE(rna_path), "[\"%s\"]", socket_id_esc);
1070
1071   /* Use #uiItemPointerR to draw pointer properties because #uiItemR would not have enough
1072    * information about what type of ID to select for editing the values. This is because
1073    * pointer IDProperties contain no information about their type. */
1074   switch (socket.type) {
1075     case SOCK_OBJECT: {
1076       uiItemPointerR(
1077           layout, md_ptr, rna_path, bmain_ptr, "objects", socket.name, ICON_OBJECT_DATA);
1078       break;
1079     }
1080     case SOCK_COLLECTION: {
1081       uiItemPointerR(layout,
1082                      md_ptr,
1083                      rna_path,
1084                      bmain_ptr,
1085                      "collections",
1086                      socket.name,
1087                      ICON_OUTLINER_COLLECTION);
1088       break;
1089     }
1090     default:
1091       uiItemR(layout, md_ptr, rna_path, 0, socket.name, ICON_NONE);
1092   }
1093 }
1094
1095 static void panel_draw(const bContext *C, Panel *panel)
1096 {
1097   uiLayout *layout = panel->layout;
1098   Main *bmain = CTX_data_main(C);
1099
1100   PointerRNA *ptr = modifier_panel_get_property_pointers(panel, nullptr);
1101   NodesModifierData *nmd = static_cast<NodesModifierData *>(ptr->data);
1102
1103   uiLayoutSetPropSep(layout, true);
1104   uiLayoutSetPropDecorate(layout, true);
1105
1106   uiTemplateID(layout,
1107                C,
1108                ptr,
1109                "node_group",
1110                "node.new_geometry_node_group_assign",
1111                nullptr,
1112                nullptr,
1113                0,
1114                false,
1115                nullptr);
1116
1117   if (nmd->node_group != nullptr && nmd->settings.properties != nullptr) {
1118     PointerRNA bmain_ptr;
1119     RNA_main_pointer_create(bmain, &bmain_ptr);
1120
1121     LISTBASE_FOREACH (bNodeSocket *, socket, &nmd->node_group->inputs) {
1122       draw_property_for_socket(layout, &bmain_ptr, ptr, nmd->settings.properties, *socket);
1123     }
1124   }
1125
1126   modifier_panel_end(layout, ptr);
1127 }
1128
1129 static void panelRegister(ARegionType *region_type)
1130 {
1131   modifier_panel_register(region_type, eModifierType_Nodes, panel_draw);
1132 }
1133
1134 static void blendWrite(BlendWriter *writer, const ModifierData *md)
1135 {
1136   const NodesModifierData *nmd = reinterpret_cast<const NodesModifierData *>(md);
1137   if (nmd->settings.properties != nullptr) {
1138     /* Note that the property settings are based on the socket type info
1139      * and don't necessarily need to be written, but we can't just free them. */
1140     IDP_BlendWrite(writer, nmd->settings.properties);
1141   }
1142 }
1143
1144 static void blendRead(BlendDataReader *reader, ModifierData *md)
1145 {
1146   NodesModifierData *nmd = reinterpret_cast<NodesModifierData *>(md);
1147   BLO_read_data_address(reader, &nmd->settings.properties);
1148   IDP_BlendDataRead(reader, &nmd->settings.properties);
1149 }
1150
1151 static void copyData(const ModifierData *md, ModifierData *target, const int flag)
1152 {
1153   const NodesModifierData *nmd = reinterpret_cast<const NodesModifierData *>(md);
1154   NodesModifierData *tnmd = reinterpret_cast<NodesModifierData *>(target);
1155
1156   BKE_modifier_copydata_generic(md, target, flag);
1157
1158   if (nmd->settings.properties != nullptr) {
1159     tnmd->settings.properties = IDP_CopyProperty_ex(nmd->settings.properties, flag);
1160   }
1161 }
1162
1163 static void freeData(ModifierData *md)
1164 {
1165   NodesModifierData *nmd = reinterpret_cast<NodesModifierData *>(md);
1166   if (nmd->settings.properties != nullptr) {
1167     IDP_FreeProperty_ex(nmd->settings.properties, false);
1168     nmd->settings.properties = nullptr;
1169   }
1170 }
1171
1172 static void requiredDataMask(Object *UNUSED(ob),
1173                              ModifierData *UNUSED(md),
1174                              CustomData_MeshMasks *r_cddata_masks)
1175 {
1176   /* We don't know what the node tree will need. If there are vertex groups, it is likely that the
1177    * node tree wants to access them. */
1178   r_cddata_masks->vmask |= CD_MASK_MDEFORMVERT;
1179   r_cddata_masks->vmask |= CD_MASK_PROP_ALL;
1180 }
1181
1182 ModifierTypeInfo modifierType_Nodes = {
1183     /* name */ "GeometryNodes",
1184     /* structName */ "NodesModifierData",
1185     /* structSize */ sizeof(NodesModifierData),
1186     /* srna */ &RNA_NodesModifier,
1187     /* type */ eModifierTypeType_Constructive,
1188     /* flags */
1189     static_cast<ModifierTypeFlag>(
1190         eModifierTypeFlag_AcceptsMesh | eModifierTypeFlag_SupportsEditmode |
1191         eModifierTypeFlag_EnableInEditmode | eModifierTypeFlag_SupportsMapping),
1192     /* icon */ ICON_NODETREE,
1193
1194     /* copyData */ copyData,
1195
1196     /* deformVerts */ nullptr,
1197     /* deformMatrices */ nullptr,
1198     /* deformVertsEM */ nullptr,
1199     /* deformMatricesEM */ nullptr,
1200     /* modifyMesh */ modifyMesh,
1201     /* modifyHair */ nullptr,
1202     /* modifyGeometrySet */ modifyGeometrySet,
1203
1204     /* initData */ initData,
1205     /* requiredDataMask */ requiredDataMask,
1206     /* freeData */ freeData,
1207     /* isDisabled */ isDisabled,
1208     /* updateDepsgraph */ updateDepsgraph,
1209     /* dependsOnTime */ nullptr,
1210     /* dependsOnNormals */ nullptr,
1211     /* foreachIDLink */ foreachIDLink,
1212     /* foreachTexLink */ foreachTexLink,
1213     /* freeRuntimeData */ nullptr,
1214     /* panelRegister */ panelRegister,
1215     /* blendWrite */ blendWrite,
1216     /* blendRead */ blendRead,
1217 };