Files
test/source/blender/blenkernel/intern/node.cc

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

5423 lines
178 KiB
C++
Raw Normal View History

/* SPDX-FileCopyrightText: 2005 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup bke
2011-02-27 20:40:57 +00:00
*/
#include "CLG_log.h"
#include "MEM_guardedalloc.h"
#include <cstddef>
#include <cstdlib>
#include <cstring>
#include <optional>
/* Allow using deprecated functionality for .blend file I/O. */
#define DNA_DEPRECATED_ALLOW
#include "DNA_collection_types.h"
#include "DNA_gpencil_legacy_types.h"
2019-02-27 12:34:56 +11:00
#include "DNA_light_types.h"
#include "DNA_linestyle_types.h"
#include "DNA_material_types.h"
#include "DNA_node_types.h"
#include "DNA_scene_types.h"
#include "DNA_texture_types.h"
#include "DNA_userdef_types.h"
#include "DNA_world_types.h"
2021-12-06 16:50:44 -05:00
#include "BLI_color.hh"
#include "BLI_ghash.h"
#include "BLI_listbase.h"
#include "BLI_map.hh"
#include "BLI_math_rotation_types.hh"
#include "BLI_math_vector.h"
#include "BLI_rand.hh"
#include "BLI_set.hh"
#include "BLI_string.h"
#include "BLI_string_utf8.h"
#include "BLI_string_utils.hh"
#include "BLI_time.h"
#include "BLI_utildefines.h"
#include "BLI_vector_set.hh"
#include "BLT_translation.hh"
2024-01-18 22:50:23 +02:00
#include "IMB_imbuf.hh"
#include "BKE_anim_data.hh"
#include "BKE_animsys.h"
#include "BKE_asset.hh"
#include "BKE_bpath.hh"
#include "BKE_colortools.hh"
#include "BKE_context.hh"
#include "BKE_global.hh"
2024-03-26 12:57:30 -04:00
#include "BKE_idprop.hh"
#include "BKE_idtype.hh"
#include "BKE_image_format.hh"
2024-01-15 12:44:04 -05:00
#include "BKE_lib_id.hh"
#include "BKE_lib_query.hh"
#include "BKE_main.hh"
#include "BKE_node.hh"
Geometry Nodes: Menu Switch Node This patch adds support for _Menu Switch_ nodes and enum definitions in node trees more generally. The design is based on the outcome of the [2022 Nodes Workshop](https://code.blender.org/2022/11/geometry-nodes-workshop-2022/#menu-switch). The _Menu Switch_ node is an advanced version of the _Switch_ node which has a customizable **menu input socket** instead of a simple boolean. The _items_ of this menu are owned by the node itself. Each item has a name and description and unique identifier that is used internally. A menu _socket_ represents a concrete value out of the list of items. To enable selection of an enum value for unconnected sockets the menu is presented as a dropdown list like built-in enums. When the socket is connected a shared pointer to the enum definition is propagated along links and stored in socket default values. This allows node groups to expose a menu from an internal menu switch as a parameter. The enum definition is a runtime copy of the enum items in DNA that allows sharing. A menu socket can have multiple connections, which can lead to ambiguity. If two or more different menu source nodes are connected to a socket it gets marked as _undefined_. Any connection to an undefined menu socket is invalid as a hint to users that there is a problem. A warning/error is also shown on nodes with undefined menu sockets. At runtime the value of a menu socket is the simple integer identifier. This can also be a field in geometry nodes. The identifier is unique within each enum definition, and it is persistent even when items are added, removed, or changed. Changing the name of an item does not affect the internal identifier, so users can rename enum items without breaking existing input values. This also persists if, for example, a linked node group is temporarily unavailable. Pull Request: https://projects.blender.org/blender/blender/pulls/113445
2024-01-26 12:40:01 +01:00
#include "BKE_node_enum.hh"
#include "BKE_node_legacy_types.hh"
#include "BKE_node_runtime.hh"
Nodes: Panels integration with blend files and UI Part 3/3 of #109135, #110272 Switch to new node group interfaces and deprecate old DNA and API. This completes support for panels in node drawing and in node group interface declarations in particular. The new node group interface DNA and RNA code has been added in parts 1 and 2 (#110885, #110952) but has not be enabled yet. This commit completes the integration by * enabling the new RNA API * using the new API in UI * read/write new interfaces from blend files * add versioning for backward compatibility * add forward-compatible writing code to reconstruct old interfaces All places accessing node group interface declarations should now be using the new API. A runtime cache has been added that allows simple linear access to socket inputs and outputs even when a panel hierarchy is used. Old DNA has been deprecated and should only be accessed for versioning (inputs/outputs renamed to inputs_legacy/outputs_legacy to catch errors). Versioning code ensures both backward and forward compatibility of existing files. The API for old interfaces is removed. The new API is very similar but is defined on the `ntree.interface` instead of the `ntree` directly. Breaking change notifications and detailed instructions for migrating will be added. A python test has been added for the node group API functions. This includes new functionality such as creating panels and moving items between different levels. This patch does not yet contain panel representations in the modifier UI. This has been tested in a separate branch and will be added with a later PR (#108565). Pull Request: https://projects.blender.org/blender/blender/pulls/111348
2023-08-30 12:37:21 +02:00
#include "BKE_node_tree_interface.hh"
Refactor: Geometry Nodes: improve lifetime analysis for anonymous attributes This refactors the lifetime analysis of anonymous attributes in geometry nodes. The refactor has a couple of goals: * Use a better and simpler abstraction that can be used when building the lazy-function graph. We currently have a bunch of duplicate code to handle "field source" and "caller propagation" attributes. This is now unified so that one only has to worry about one kind of "reference sets". * Make the abstraction compatible with handling bundles and closures in case we want to support them in the future. Both types can contain geometries and fields so they need to be taken into account when determining lifetimes. * Make more parts independent of the concept of "anonymous attributes". In theory, there could be more kinds of referenced data whose lifetimes need to be managed. I don't have any concrete plans for adding any though. At its core, deterministic anonymous attributes still work the same they have been since they became deterministic [0]. Even the generated lazy-function graph is still pretty much or even exactly the same as before. The patch renames `AnonymousAttributeSet` to the more general `GeometryNodesReferenceSet` which is more. This also makes more places independent of the concept of anonymous attributes. Functionally, this still the same though. It's only used in the internals of geometry nodes nowadays. Most code just gets an `AttributeFilter` that is based on it. [0]: https://archive.blender.org/developer/D16858 Pull Request: https://projects.blender.org/blender/blender/pulls/128667
2024-10-07 12:59:39 +02:00
#include "BKE_node_tree_reference_lifetimes.hh"
#include "BKE_node_tree_update.hh"
#include "BKE_preview_image.hh"
#include "BKE_type_conversions.hh"
Geometry Nodes: add Closures and Bundles behind experimental feature flag This implements bundles and closures which are described in more detail in this blog post: https://code.blender.org/2024/11/geometry-nodes-workshop-october-2024/ tl;dr: * Bundles are containers that allow storing multiple socket values in a single value. Each value in the bundle is identified by a name. Bundles can be nested. * Closures are functions that are created with the Closure Zone and can be evaluated with the Evaluate Closure node. To use the patch, the `Bundle and Closure Nodes` experimental feature has to be enabled. This is necessary, because these features are not fully done yet and still need iterations to improve the workflow before they can be officially released. These iterations are easier to do in `main` than in a separate branch though. That's because this patch is quite large and somewhat prone to merge conflicts. Also other work we want to do, depends on this. This adds the following new nodes: * Combine Bundle: can pack multiple values into one. * Separate Bundle: extracts values from a bundle. * Closure Zone: outputs a closure zone for use in the `Evaluate Closure` node. * Evaluate Closure: evaluates the passed in closure. Things that will be added soon after this lands: * Fields in bundles and closures. The way this is done changes with #134811, so I rather implement this once both are in `main`. * UI features for keeping sockets in sync (right now there are warnings only). One bigger issue is the limited support for lazyness. For example, all inputs of a Combine Bundle node will be evaluated, even if they are not all needed. The same is true for all captured values of a closure. This is a deeper limitation that needs to be resolved at some point. This will likely be done after an initial version of this patch is done. Pull Request: https://projects.blender.org/blender/blender/pulls/128340
2025-04-03 15:44:06 +02:00
#include "NOD_geometry_nodes_bundle.hh"
#include "NOD_geometry_nodes_closure.hh"
Three-in-one commit: - Compositor now is threaded Enable it with the Scene buttons "Threads". This will handle over nodes to individual threads to be calculated. However, if nodes depend on others they have to wait. The current system only threads per entire node, not for calculating results in parts. I've reshuffled the node execution code to evaluate 'changed' events, and prepare the entire tree to become simply parsed for open jobs with a call to node = getExecutableNode() By default, even without 'thread' option active, all node execution is done within a separate thread. Also fixed issues in yesterdays commit for 'event based' calculations, it didn't do animated images, or execute (on rendering) the correct nodes when you don't have Render-Result nodes included. - Added generic Thread support in blenlib/ module The renderer and the node system now both use same code for controlling the threads. This has been moved to a new C file in blenlib/intern/threads.c. Check this c file for an extensive doc and example how to use it. The current implementation for Compositing allows unlimited amount of threads. For rendering it is still tied to two threads, although it is pretty easy to extend to 4 already. People with giant amounts of cpus can poke me once for tests. :) - Bugfix in creating group nodes Group node definitions demand a clear separation of 'internal sockets' and 'external sockets'. The first are sockets being linked internally, the latter are sockets exposed as sockets for the group itself. When sockets were linked both internal and external, Blender crashed. It is solved now by removing the external link(s).
2006-01-29 11:36:33 +00:00
#include "RNA_access.hh"
#include "RNA_define.hh"
#include "RNA_enum_types.hh"
#include "RNA_prototypes.hh"
2025-01-10 14:34:51 -05:00
#include "NOD_common.hh"
#include "NOD_composite.hh"
#include "NOD_geo_bake.hh"
Geometry Nodes: add Closures and Bundles behind experimental feature flag This implements bundles and closures which are described in more detail in this blog post: https://code.blender.org/2024/11/geometry-nodes-workshop-october-2024/ tl;dr: * Bundles are containers that allow storing multiple socket values in a single value. Each value in the bundle is identified by a name. Bundles can be nested. * Closures are functions that are created with the Closure Zone and can be evaluated with the Evaluate Closure node. To use the patch, the `Bundle and Closure Nodes` experimental feature has to be enabled. This is necessary, because these features are not fully done yet and still need iterations to improve the workflow before they can be officially released. These iterations are easier to do in `main` than in a separate branch though. That's because this patch is quite large and somewhat prone to merge conflicts. Also other work we want to do, depends on this. This adds the following new nodes: * Combine Bundle: can pack multiple values into one. * Separate Bundle: extracts values from a bundle. * Closure Zone: outputs a closure zone for use in the `Evaluate Closure` node. * Evaluate Closure: evaluates the passed in closure. Things that will be added soon after this lands: * Fields in bundles and closures. The way this is done changes with #134811, so I rather implement this once both are in `main`. * UI features for keeping sockets in sync (right now there are warnings only). One bigger issue is the limited support for lazyness. For example, all inputs of a Combine Bundle node will be evaluated, even if they are not all needed. The same is true for all captured values of a closure. This is a deeper limitation that needs to be resolved at some point. This will likely be done after an initial version of this patch is done. Pull Request: https://projects.blender.org/blender/blender/pulls/128340
2025-04-03 15:44:06 +02:00
#include "NOD_geo_bundle.hh"
#include "NOD_geo_capture_attribute.hh"
Geometry Nodes: add Closures and Bundles behind experimental feature flag This implements bundles and closures which are described in more detail in this blog post: https://code.blender.org/2024/11/geometry-nodes-workshop-october-2024/ tl;dr: * Bundles are containers that allow storing multiple socket values in a single value. Each value in the bundle is identified by a name. Bundles can be nested. * Closures are functions that are created with the Closure Zone and can be evaluated with the Evaluate Closure node. To use the patch, the `Bundle and Closure Nodes` experimental feature has to be enabled. This is necessary, because these features are not fully done yet and still need iterations to improve the workflow before they can be officially released. These iterations are easier to do in `main` than in a separate branch though. That's because this patch is quite large and somewhat prone to merge conflicts. Also other work we want to do, depends on this. This adds the following new nodes: * Combine Bundle: can pack multiple values into one. * Separate Bundle: extracts values from a bundle. * Closure Zone: outputs a closure zone for use in the `Evaluate Closure` node. * Evaluate Closure: evaluates the passed in closure. Things that will be added soon after this lands: * Fields in bundles and closures. The way this is done changes with #134811, so I rather implement this once both are in `main`. * UI features for keeping sockets in sync (right now there are warnings only). One bigger issue is the limited support for lazyness. For example, all inputs of a Combine Bundle node will be evaluated, even if they are not all needed. The same is true for all captured values of a closure. This is a deeper limitation that needs to be resolved at some point. This will likely be done after an initial version of this patch is done. Pull Request: https://projects.blender.org/blender/blender/pulls/128340
2025-04-03 15:44:06 +02:00
#include "NOD_geo_closure.hh"
Geometry Nodes: new For Each Geometry Element zone This adds a new type of zone to Geometry Nodes that allows executing some nodes for each element in a geometry. ## Features * The `Selection` input allows iterating over a subset of elements on the set domain. * Fields passed into the input node are available as single values inside of the zone. * The input geometry can be split up into separate (completely independent) geometries for each element (on all domains except face corner). * New attributes can be created on the input geometry by outputting a single value from each iteration. * New geometries can be generated in each iteration. * All of these geometries are joined to form the final output. * Attributes from the input geometry are propagated to the output geometries. ## Evaluation The evaluation strategy is similar to the one used for repeat zones. Namely, it dynamically builds a `lazy_function::Graph` once it knows how many iterations are necessary. It contains a separate node for each iteration. The inputs for each iteration are hardcoded into the graph. The outputs of each iteration a passed to a separate lazy-function that reduces all the values down to the final outputs. This final output can have a huge number of inputs and that is not ideal for multi-threading yet, but that can still be improved in the future. ## Performance There is a non-neglilible amount of overhead for each iteration. The overhead is way larger than the per-element overhead when just doing field evaluation. Therefore, normal field evaluation should be preferred when possible. That can partially still be optimized if there is only some number crunching going on in the zone but that optimization is not implemented yet. However, processing many small geometries (e.g. each hair of a character separately) will likely **always be slower** than working on fewer larger geoemtries. The additional flexibility you get by processing each element separately comes at the cost that Blender can't optimize the operation as well. For node groups that need to handle lots of geometry elements, we recommend trying to design the node setup so that iteration over tiny sub-geometries is not required. An opposite point is true as well though. It can be faster to process more medium sized geometries in parallel than fewer very large geometries because of more multi-threading opportunities. The exact threshold between tiny, medium and large geometries depends on a lot of factors though. Overall, this initial version of the new zone does not implement all optimization opportunities yet, but the points mentioned above will still hold true later. Pull Request: https://projects.blender.org/blender/blender/pulls/127331
2024-09-24 11:52:02 +02:00
#include "NOD_geo_foreach_geometry_element.hh"
#include "NOD_geo_index_switch.hh"
Geometry Nodes: unify menu switch with other nodes with dynamic sockets This changes the menu switch socket to use the socket-items system (`NOD_socket_items.hh`) that is already used by the simulation zone, repeat zone, bake node and index switch node. By using this system, the per-node boilerplate can be removed significantly. This is especially important as we plan to have dynamic socket amounts in more nodes in the future. There are some user visible changes which make the node more consistent with others: * Move the menu items list into the properties panel as in 0c585a1b8af. * Add an extend socket. * Duplicating a menu item keeps the name of the old one. There is also a (backward compatible) change in the Python API: It's now possible to directly access `node.enum_items` and `node.active_index` instead of having to use `node.enum_definition.enum_items`. This is consistent with the other nodes. For backward compatibility, `node.enum_definition` still exists, but simply returns the node itself. Many API functions from `NodeEnumDefinition` like `NodeEnumDefinition::remove_item` have been removed. Those are not used anymore and are unnecessary boilerplate. If ever necessary, they can be implemented back in terms of the socket-items system. The socket-items system had to be extended a little bit to support the case for the menu switch node where each socket item has a name but no type. Previously, there was the case without name and type in the index switch node, and the case with both in the bake node and zones. The system was trivial to extend to this case. Pull Request: https://projects.blender.org/blender/blender/pulls/121234
2024-04-30 10:19:32 +02:00
#include "NOD_geo_menu_switch.hh"
#include "NOD_geo_repeat.hh"
#include "NOD_geo_simulation.hh"
Geometry Nodes: improve detecting data-block dependencies Previously, the data-block dependencies were always detected in `update_depsgraph` in `MOD_nodes.cc`. This would only be called when something called `DEG_relations_tag_update` before. We don't want to trigger a depsgraph rebuild after each operation in the node editor, as that would be expensive. However, that also meant that we often had to add data-block dependencies that are not actually used, but might be used if the user changed e.g. a link. A typical example for that is a object socket that has a default value, but the socket is also linked. Now, the dependencies referenced by the node tree are collected by the node tree update code which runs after all changes. This way we can detect whether the dependencies have changed. Only if they have changed, a depsgraph rebuild is triggered. This now allows also taking into account the mute status of nodes and whether an input is linked. There are still more things that could be taken into account. Most obviously whether a node is connected to an output. This can be done later. The most tricky aspect here is probably that we also have to consider all viewer nodes as output, because at the time the node runs, it's not known which viewer will actually be used (which depends on other editors). This also cleans up some special cases we had for e.g. the scene time node where we always had to trigger a depsgraph rebuild when it was added/removed because of its time dependence. This is now part of a more general system. This fixes #109219. Pull Request: https://projects.blender.org/blender/blender/pulls/131446
2024-12-05 18:02:14 +01:00
#include "NOD_geometry_nodes_dependencies.hh"
Geometry Nodes: support attaching gizmos to input values This adds support for attaching gizmos for input values. The goal is to make it easier for users to set input values intuitively in the 3D viewport. We went through multiple different possible designs until we settled on the one implemented here. We picked it for it's flexibility and ease of use when using geometry node assets. The core principle in the design is that **gizmos are attached to existing input values instead of being the input value themselves**. This actually fits the existing concept of gizmos in Blender well, but may be a bit unintutitive in a node setup at first. The attachment is done using links in the node editor. The most basic usage of the node is to link a Value node to the new Linear Gizmo node. This attaches the gizmo to the input value and allows you to change it from the 3D view. The attachment is indicated by the gizmo icon in the sockets which are controlled by a gizmo as well as the back-link (notice the double link) when the gizmo is active. The core principle makes it straight forward to control the same node setup from the 3D view with gizmos, or by manually changing input values, or by driving the input values procedurally. If the input value is controlled indirectly by other inputs, it's often possible to **automatically propagate** the gizmo to the actual input. Backpropagation does not work for all nodes, although more nodes can be supported over time. This patch adds the first three gizmo nodes which cover common use cases: * **Linear Gizmo**: Creates a gizmo that controls a float or integer value using a linear movement of e.g. an arrow in the 3D viewport. * **Dial Gizmo**: Creates a circular gizmo in the 3D viewport that can be rotated to change the attached angle input. * **Transform Gizmo**: Creates a simple gizmo for location, rotation and scale. In the future, more built-in gizmos and potentially the ability for custom gizmos could be added. All gizmo nodes have a **Transform** geometry output. Using it is optional but it is recommended when the gizmo is used to control inputs that affect a geometry. When it is used, Blender will automatically transform the gizmos together with the geometry that they control. To achieve this, the output should be merged with the generated geometry using the *Join Geometry* node. The data contained in *Transform* output is not visible geometry, but just internal information that helps Blender to give a better user experience when using gizmos. The gizmo nodes have a multi-input socket. This allows **controlling multiple values** with the same gizmo. Only a small set of **gizmo shapes** is supported initially. It might be extended in the future but one goal is to give the gizmos used by different node group assets a familiar look and feel. A similar constraint exists for **colors**. Currently, one can choose from a fixed set of colors which can be modified in the theme settings. The set of **visible gizmos** is determined by a multiple factors because it's not really feasible to show all possible gizmos at all times. To see any of the geometry nodes gizmos, the "Active Modifier" option has to be enabled in the "Viewport Gizmos" popover. Then all gizmos are drawn for which at least one of the following is true: * The gizmo controls an input of the active modifier of the active object. * The gizmo controls a value in a selected node in an open node editor. * The gizmo controls a pinned value in an open node editor. Pinning works by clicking the gizmo icon next to the value. Pull Request: https://projects.blender.org/blender/blender/pulls/112677
2024-07-10 16:18:47 +02:00
#include "NOD_geometry_nodes_gizmos.hh"
Geometry Nodes: new evaluation system This refactors the geometry nodes evaluation system. No changes for the user are expected. At a high level the goals are: * Support using geometry nodes outside of the geometry nodes modifier. * Support using the evaluator infrastructure for other purposes like field evaluation. * Support more nodes, especially when many of them are disabled behind switch nodes. * Support doing preprocessing on node groups. For more details see T98492. There are fairly detailed comments in the code, but here is a high level overview for how it works now: * There is a new "lazy-function" system. It is similar in spirit to the multi-function system but with different goals. Instead of optimizing throughput for highly parallelizable work, this system is designed to compute only the data that is actually necessary. What data is necessary can be determined dynamically during evaluation. Many lazy-functions can be composed in a graph to form a new lazy-function, which can again be used in a graph etc. * Each geometry node group is converted into a lazy-function graph prior to evaluation. To evaluate geometry nodes, one then just has to evaluate that graph. Node groups are no longer inlined into their parents. Next steps for the evaluation system is to reduce the use of threads in some situations to avoid overhead. Many small node groups don't benefit from multi-threading at all. This is much easier to do now because not everything has to be inlined in one huge node tree anymore. Differential Revision: https://developer.blender.org/D15914
2022-09-13 08:44:26 +02:00
#include "NOD_geometry_nodes_lazy_function.hh"
#include "NOD_node_declaration.hh"
#include "NOD_register.hh"
#include "NOD_shader.h"
#include "NOD_socket.hh"
#include "NOD_socket_items_blend.hh"
#include "NOD_texture.h"
Christmas coding work! ********* Node editor work: - To enable Nodes for Materials, you have to set the "Use Nodes" button, in the new Material buttons "Nodes" Panel or in header of the Node editor. Doing this will disable Material-Layers. - Nodes now execute materials ("shaders"), but still only using the previewrender code. - Nodes have (optional) previews for rendered images. - Node headers allow to hide buttons and/or preview image - Nodes can be dragged larger/smaller (right-bottom corner) - Nodes can be hidden (minimized) with hotkey H - CTRL+click on an Input Socket gives a popup with default values. - Changing Material/Texture or Mix node will adjust Node title. - Click-drag outside of a Node changes cursor to "Knife' and allows to draw a rect where to cut Links. - Added new node types RGBtoBW, Texture, In/Output, ColorRamp - Material Nodes have options to ouput diffuse or specular, or to use a negative normal. The input socket 'Normal' will force the material to use that normal, otherwise it uses the normal from the Material that has the node tree. - When drawing a link between two not-matching sockets, Blender inserts a converting node (now only for value/rgb combos) - When drawing a link to an input socket that's already in use, the old link will either disappear or flip to another unused socket. - A click on a Material Node will activate it, and show all its settings in the Material Buttons. Active Material Nodes draw the material icon in red. - A click on any node will show its options in the Node Panel in the Material buttons. - Multiple Output Nodes can be used, to sample contents of a tree, but only one Output is the real one, which is indicated in a different color and red material icon. - Added ThemeColors for node types - ALT+C will convert existing Material-Layers to Node... this currently only adds the material/mix nodes and connects them. Dunno if this is worth a lot of coding work to make perfect? - Press C to call another "Solve order", which will show all possible cyclic conflicts (if there are). - Technical: nodes now use "Type" structs which define the structure of nodes and in/output sockets. The Type structs store all fixed info, callbacks, and allow to reconstruct saved Nodes to match what is required by Blender. - Defining (new) nodes now is as simple as filling in a fixed Type struct, plus code some callbacks. A doc will be made! - Node preview images are by default float ********* Icon drawing: - Cleanup of how old icons were implemented in new system, making them 16x16 too, correctly centered *and* scaled. - Made drawing Icons use float coordinates - Moved BIF_calcpreview_image() into interface_icons.c, renamed it icon_from_image(). Removed a lot of unneeded Imbuf magic here! :) - Skipped scaling and imbuf copying when icons are OK size ********* Preview render: - Huge cleanup of code.... - renaming BIF_xxx calls that only were used internally - BIF_previewrender() now accepts an argument for rendering method, so it supports icons, buttonwindow previewrender and node editor - Only a single BIF_preview_changed() call now exists, supporting all signals as needed for buttos and node editor ********* More stuff: - glutil.c, glaDrawPixelsSafe() and glaDrawPixelsTex() now accept format argument for GL_FLOAT rects - Made the ColorBand become a built-in button for interface.c Was a load of cleanup work in buttons_shading.c... - removed a load of unneeded glBlendFunc() calls - Fixed bug in calculating text length for buttons (ancient!)
2005-12-28 15:42:51 +00:00
#include "DEG_depsgraph.hh"
#include "DEG_depsgraph_build.hh"
2018-03-16 11:17:45 +01:00
#include "BLO_read_write.hh"
using blender::nodes::FieldInferencingInterface;
using blender::nodes::InputSocketFieldType;
using blender::nodes::NodeDeclaration;
using blender::nodes::OutputFieldDependency;
using blender::nodes::OutputSocketFieldType;
using blender::nodes::SocketDeclaration;
static CLG_LogRef LOG = {"bke.node"};
namespace blender::bke {
/* Forward declaration. */
static void write_node_socket_default_value(BlendWriter *writer, const bNodeSocket *sock);
/* Fallback types for undefined tree, nodes, sockets. */
bNodeTreeType NodeTreeTypeUndefined;
bNodeType NodeTypeUndefined;
bNodeSocketType NodeSocketTypeUndefined;
static void ntree_set_typeinfo(bNodeTree *ntree, bNodeTreeType *typeinfo);
Nodes: Panels integration with blend files and UI Part 3/3 of #109135, #110272 Switch to new node group interfaces and deprecate old DNA and API. This completes support for panels in node drawing and in node group interface declarations in particular. The new node group interface DNA and RNA code has been added in parts 1 and 2 (#110885, #110952) but has not be enabled yet. This commit completes the integration by * enabling the new RNA API * using the new API in UI * read/write new interfaces from blend files * add versioning for backward compatibility * add forward-compatible writing code to reconstruct old interfaces All places accessing node group interface declarations should now be using the new API. A runtime cache has been added that allows simple linear access to socket inputs and outputs even when a panel hierarchy is used. Old DNA has been deprecated and should only be accessed for versioning (inputs/outputs renamed to inputs_legacy/outputs_legacy to catch errors). Versioning code ensures both backward and forward compatibility of existing files. The API for old interfaces is removed. The new API is very similar but is defined on the `ntree.interface` instead of the `ntree` directly. Breaking change notifications and detailed instructions for migrating will be added. A python test has been added for the node group API functions. This includes new functionality such as creating panels and moving items between different levels. This patch does not yet contain panel representations in the modifier UI. This has been tested in a separate branch and will be added with a later PR (#108565). Pull Request: https://projects.blender.org/blender/blender/pulls/111348
2023-08-30 12:37:21 +02:00
static void node_socket_set_typeinfo(bNodeTree *ntree,
bNodeSocket *sock,
bNodeSocketType *typeinfo);
static void node_socket_copy(bNodeSocket *sock_dst, const bNodeSocket *sock_src, const int flag);
static void free_localized_node_groups(bNodeTree *ntree);
Nodes: Panels integration with blend files and UI Part 3/3 of #109135, #110272 Switch to new node group interfaces and deprecate old DNA and API. This completes support for panels in node drawing and in node group interface declarations in particular. The new node group interface DNA and RNA code has been added in parts 1 and 2 (#110885, #110952) but has not be enabled yet. This commit completes the integration by * enabling the new RNA API * using the new API in UI * read/write new interfaces from blend files * add versioning for backward compatibility * add forward-compatible writing code to reconstruct old interfaces All places accessing node group interface declarations should now be using the new API. A runtime cache has been added that allows simple linear access to socket inputs and outputs even when a panel hierarchy is used. Old DNA has been deprecated and should only be accessed for versioning (inputs/outputs renamed to inputs_legacy/outputs_legacy to catch errors). Versioning code ensures both backward and forward compatibility of existing files. The API for old interfaces is removed. The new API is very similar but is defined on the `ntree.interface` instead of the `ntree` directly. Breaking change notifications and detailed instructions for migrating will be added. A python test has been added for the node group API functions. This includes new functionality such as creating panels and moving items between different levels. This patch does not yet contain panel representations in the modifier UI. This has been tested in a separate branch and will be added with a later PR (#108565). Pull Request: https://projects.blender.org/blender/blender/pulls/111348
2023-08-30 12:37:21 +02:00
static bool socket_id_user_decrement(bNodeSocket *sock);
static void ntree_init_data(ID *id)
{
bNodeTree *ntree = reinterpret_cast<bNodeTree *>(id);
Nodes: Panels integration with blend files and UI Part 3/3 of #109135, #110272 Switch to new node group interfaces and deprecate old DNA and API. This completes support for panels in node drawing and in node group interface declarations in particular. The new node group interface DNA and RNA code has been added in parts 1 and 2 (#110885, #110952) but has not be enabled yet. This commit completes the integration by * enabling the new RNA API * using the new API in UI * read/write new interfaces from blend files * add versioning for backward compatibility * add forward-compatible writing code to reconstruct old interfaces All places accessing node group interface declarations should now be using the new API. A runtime cache has been added that allows simple linear access to socket inputs and outputs even when a panel hierarchy is used. Old DNA has been deprecated and should only be accessed for versioning (inputs/outputs renamed to inputs_legacy/outputs_legacy to catch errors). Versioning code ensures both backward and forward compatibility of existing files. The API for old interfaces is removed. The new API is very similar but is defined on the `ntree.interface` instead of the `ntree` directly. Breaking change notifications and detailed instructions for migrating will be added. A python test has been added for the node group API functions. This includes new functionality such as creating panels and moving items between different levels. This patch does not yet contain panel representations in the modifier UI. This has been tested in a separate branch and will be added with a later PR (#108565). Pull Request: https://projects.blender.org/blender/blender/pulls/111348
2023-08-30 12:37:21 +02:00
ntree->tree_interface.init_data();
ntree->runtime = MEM_new<bNodeTreeRuntime>(__func__);
ntree->default_group_node_width = GROUP_NODE_DEFAULT_WIDTH;
ntree_set_typeinfo(ntree, nullptr);
}
static void ntree_copy_data(Main * /*bmain*/,
std::optional<Library *> /*owner_library*/,
ID *id_dst,
const ID *id_src,
const int flag)
{
bNodeTree *ntree_dst = reinterpret_cast<bNodeTree *>(id_dst);
const bNodeTree *ntree_src = reinterpret_cast<const bNodeTree *>(id_src);
/* We never handle user-count here for owned data. */
const int flag_subdata = flag | LIB_ID_CREATE_NO_USER_REFCOUNT;
ntree_dst->runtime = MEM_new<bNodeTreeRuntime>(__func__);
bNodeTreeRuntime &dst_runtime = *ntree_dst->runtime;
Map<const bNodeSocket *, bNodeSocket *> socket_map;
dst_runtime.nodes_by_id.reserve(ntree_src->all_nodes().size());
BLI_listbase_clear(&ntree_dst->nodes);
int i;
LISTBASE_FOREACH_INDEX (const bNode *, src_node, &ntree_src->nodes, i) {
/* Don't find a unique name for every node, since they should have valid names already. */
bNode *new_node = node_copy_with_mapping(
ntree_dst, *src_node, flag_subdata, false, socket_map);
dst_runtime.nodes_by_id.add_new(new_node);
new_node->runtime->index_in_tree = i;
Geometry Nodes: add simulation support This adds support for building simulations with geometry nodes. A new `Simulation Input` and `Simulation Output` node allow maintaining a simulation state across multiple frames. Together these two nodes form a `simulation zone` which contains all the nodes that update the simulation state from one frame to the next. A new simulation zone can be added via the menu (`Simulation > Simulation Zone`) or with the node add search. The simulation state contains a geometry by default. However, it is possible to add multiple geometry sockets as well as other socket types. Currently, field inputs are evaluated and stored for the preceding geometry socket in the order that the sockets are shown. Simulation state items can be added by linking one of the empty sockets to something else. In the sidebar, there is a new panel that allows adding, removing and reordering these sockets. The simulation nodes behave as follows: * On the first frame, the inputs of the `Simulation Input` node are evaluated to initialize the simulation state. In later frames these sockets are not evaluated anymore. The `Delta Time` at the first frame is zero, but the simulation zone is still evaluated. * On every next frame, the `Simulation Input` node outputs the simulation state of the previous frame. Nodes in the simulation zone can edit that data in arbitrary ways, also taking into account the `Delta Time`. The new simulation state has to be passed to the `Simulation Output` node where it is cached and forwarded. * On a frame that is already cached or baked, the nodes in the simulation zone are not evaluated, because the `Simulation Output` node can return the previously cached data directly. It is not allowed to connect sockets from inside the simulation zone to the outside without going through the `Simulation Output` node. This is a necessary restriction to make caching and sub-frame interpolation work. Links can go into the simulation zone without problems though. Anonymous attributes are not propagated by the simulation nodes unless they are explicitly stored in the simulation state. This is unfortunate, but currently there is no practical and reliable alternative. The core problem is detecting which anonymous attributes will be required for the simulation and afterwards. While we can detect this for the current evaluation, we can't look into the future in time to see what data will be necessary. We intend to make it easier to explicitly pass data through a simulation in the future, even if the simulation is in a nested node group. There is a new `Simulation Nodes` panel in the physics tab in the properties editor. It allows baking all simulation zones on the selected objects. The baking options are intentially kept at a minimum for this MVP. More features for simulation baking as well as baking in general can be expected to be added separately. All baked data is stored on disk in a folder next to the .blend file. #106937 describes how baking is implemented in more detail. Volumes can not be baked yet and materials are lost during baking for now. Packing the baked data into the .blend file is not yet supported. The timeline indicates which frames are currently cached, baked or cached but invalidated by user-changes. Simulation input and output nodes are internally linked together by their `bNode.identifier` which stays the same even if the node name changes. They are generally added and removed together. However, there are still cases where "dangling" simulation nodes can be created currently. Those generally don't cause harm, but would be nice to avoid this in more cases in the future. Co-authored-by: Hans Goudey <h.goudey@me.com> Co-authored-by: Lukas Tönne <lukas@blender.org> Pull Request: https://projects.blender.org/blender/blender/pulls/104924
2023-05-03 13:18:51 +02:00
}
/* copy links */
BLI_listbase_clear(&ntree_dst->links);
LISTBASE_FOREACH (const bNodeLink *, src_link, &ntree_src->links) {
bNodeLink *dst_link = static_cast<bNodeLink *>(MEM_dupallocN(src_link));
dst_link->fromnode = dst_runtime.nodes_by_id.lookup_key_as(src_link->fromnode->identifier);
dst_link->fromsock = socket_map.lookup(src_link->fromsock);
dst_link->tonode = dst_runtime.nodes_by_id.lookup_key_as(src_link->tonode->identifier);
dst_link->tosock = socket_map.lookup(src_link->tosock);
BLI_assert(dst_link->tosock);
dst_link->tosock->link = dst_link;
BLI_addtail(&ntree_dst->links, dst_link);
}
/* update node->parent pointers */
for (bNode *node : ntree_dst->all_nodes()) {
if (node->parent) {
node->parent = dst_runtime.nodes_by_id.lookup_key_as(node->parent->identifier);
}
}
for (bNode *node : ntree_dst->all_nodes()) {
node_declaration_ensure(*ntree_dst, *node);
}
Nodes: Panels integration with blend files and UI Part 3/3 of #109135, #110272 Switch to new node group interfaces and deprecate old DNA and API. This completes support for panels in node drawing and in node group interface declarations in particular. The new node group interface DNA and RNA code has been added in parts 1 and 2 (#110885, #110952) but has not be enabled yet. This commit completes the integration by * enabling the new RNA API * using the new API in UI * read/write new interfaces from blend files * add versioning for backward compatibility * add forward-compatible writing code to reconstruct old interfaces All places accessing node group interface declarations should now be using the new API. A runtime cache has been added that allows simple linear access to socket inputs and outputs even when a panel hierarchy is used. Old DNA has been deprecated and should only be accessed for versioning (inputs/outputs renamed to inputs_legacy/outputs_legacy to catch errors). Versioning code ensures both backward and forward compatibility of existing files. The API for old interfaces is removed. The new API is very similar but is defined on the `ntree.interface` instead of the `ntree` directly. Breaking change notifications and detailed instructions for migrating will be added. A python test has been added for the node group API functions. This includes new functionality such as creating panels and moving items between different levels. This patch does not yet contain panel representations in the modifier UI. This has been tested in a separate branch and will be added with a later PR (#108565). Pull Request: https://projects.blender.org/blender/blender/pulls/111348
2023-08-30 12:37:21 +02:00
ntree_dst->tree_interface.copy_data(ntree_src->tree_interface, flag);
/* copy preview hash */
if ((flag & LIB_ID_COPY_NO_PREVIEW) == 0) {
for (const auto &item : ntree_src->runtime->previews.items()) {
dst_runtime.previews.add_new(item.key, item.value);
}
}
if (ntree_src->runtime->field_inferencing_interface) {
dst_runtime.field_inferencing_interface = std::make_unique<FieldInferencingInterface>(
*ntree_src->runtime->field_inferencing_interface);
}
Refactor: Geometry Nodes: improve lifetime analysis for anonymous attributes This refactors the lifetime analysis of anonymous attributes in geometry nodes. The refactor has a couple of goals: * Use a better and simpler abstraction that can be used when building the lazy-function graph. We currently have a bunch of duplicate code to handle "field source" and "caller propagation" attributes. This is now unified so that one only has to worry about one kind of "reference sets". * Make the abstraction compatible with handling bundles and closures in case we want to support them in the future. Both types can contain geometries and fields so they need to be taken into account when determining lifetimes. * Make more parts independent of the concept of "anonymous attributes". In theory, there could be more kinds of referenced data whose lifetimes need to be managed. I don't have any concrete plans for adding any though. At its core, deterministic anonymous attributes still work the same they have been since they became deterministic [0]. Even the generated lazy-function graph is still pretty much or even exactly the same as before. The patch renames `AnonymousAttributeSet` to the more general `GeometryNodesReferenceSet` which is more. This also makes more places independent of the concept of anonymous attributes. Functionally, this still the same though. It's only used in the internals of geometry nodes nowadays. Most code just gets an `AttributeFilter` that is based on it. [0]: https://archive.blender.org/developer/D16858 Pull Request: https://projects.blender.org/blender/blender/pulls/128667
2024-10-07 12:59:39 +02:00
if (ntree_src->runtime->reference_lifetimes_info) {
using namespace node_tree_reference_lifetimes;
dst_runtime.reference_lifetimes_info = std::make_unique<ReferenceLifetimesInfo>(
*ntree_src->runtime->reference_lifetimes_info);
for (ReferenceSetInfo &reference_set : dst_runtime.reference_lifetimes_info->reference_sets) {
Geometry Nodes: add Closures and Bundles behind experimental feature flag This implements bundles and closures which are described in more detail in this blog post: https://code.blender.org/2024/11/geometry-nodes-workshop-october-2024/ tl;dr: * Bundles are containers that allow storing multiple socket values in a single value. Each value in the bundle is identified by a name. Bundles can be nested. * Closures are functions that are created with the Closure Zone and can be evaluated with the Evaluate Closure node. To use the patch, the `Bundle and Closure Nodes` experimental feature has to be enabled. This is necessary, because these features are not fully done yet and still need iterations to improve the workflow before they can be officially released. These iterations are easier to do in `main` than in a separate branch though. That's because this patch is quite large and somewhat prone to merge conflicts. Also other work we want to do, depends on this. This adds the following new nodes: * Combine Bundle: can pack multiple values into one. * Separate Bundle: extracts values from a bundle. * Closure Zone: outputs a closure zone for use in the `Evaluate Closure` node. * Evaluate Closure: evaluates the passed in closure. Things that will be added soon after this lands: * Fields in bundles and closures. The way this is done changes with #134811, so I rather implement this once both are in `main`. * UI features for keeping sockets in sync (right now there are warnings only). One bigger issue is the limited support for lazyness. For example, all inputs of a Combine Bundle node will be evaluated, even if they are not all needed. The same is true for all captured values of a closure. This is a deeper limitation that needs to be resolved at some point. This will likely be done after an initial version of this patch is done. Pull Request: https://projects.blender.org/blender/blender/pulls/128340
2025-04-03 15:44:06 +02:00
if (ELEM(reference_set.type,
ReferenceSetType::LocalReferenceSet,
ReferenceSetType::ClosureInputReferenceSet,
ReferenceSetType::ClosureOutputData))
{
Refactor: Geometry Nodes: improve lifetime analysis for anonymous attributes This refactors the lifetime analysis of anonymous attributes in geometry nodes. The refactor has a couple of goals: * Use a better and simpler abstraction that can be used when building the lazy-function graph. We currently have a bunch of duplicate code to handle "field source" and "caller propagation" attributes. This is now unified so that one only has to worry about one kind of "reference sets". * Make the abstraction compatible with handling bundles and closures in case we want to support them in the future. Both types can contain geometries and fields so they need to be taken into account when determining lifetimes. * Make more parts independent of the concept of "anonymous attributes". In theory, there could be more kinds of referenced data whose lifetimes need to be managed. I don't have any concrete plans for adding any though. At its core, deterministic anonymous attributes still work the same they have been since they became deterministic [0]. Even the generated lazy-function graph is still pretty much or even exactly the same as before. The patch renames `AnonymousAttributeSet` to the more general `GeometryNodesReferenceSet` which is more. This also makes more places independent of the concept of anonymous attributes. Functionally, this still the same though. It's only used in the internals of geometry nodes nowadays. Most code just gets an `AttributeFilter` that is based on it. [0]: https://archive.blender.org/developer/D16858 Pull Request: https://projects.blender.org/blender/blender/pulls/128667
2024-10-07 12:59:39 +02:00
reference_set.socket = socket_map.lookup(reference_set.socket);
}
Refactor: Geometry Nodes: improve lifetime analysis for anonymous attributes This refactors the lifetime analysis of anonymous attributes in geometry nodes. The refactor has a couple of goals: * Use a better and simpler abstraction that can be used when building the lazy-function graph. We currently have a bunch of duplicate code to handle "field source" and "caller propagation" attributes. This is now unified so that one only has to worry about one kind of "reference sets". * Make the abstraction compatible with handling bundles and closures in case we want to support them in the future. Both types can contain geometries and fields so they need to be taken into account when determining lifetimes. * Make more parts independent of the concept of "anonymous attributes". In theory, there could be more kinds of referenced data whose lifetimes need to be managed. I don't have any concrete plans for adding any though. At its core, deterministic anonymous attributes still work the same they have been since they became deterministic [0]. Even the generated lazy-function graph is still pretty much or even exactly the same as before. The patch renames `AnonymousAttributeSet` to the more general `GeometryNodesReferenceSet` which is more. This also makes more places independent of the concept of anonymous attributes. Functionally, this still the same though. It's only used in the internals of geometry nodes nowadays. Most code just gets an `AttributeFilter` that is based on it. [0]: https://archive.blender.org/developer/D16858 Pull Request: https://projects.blender.org/blender/blender/pulls/128667
2024-10-07 12:59:39 +02:00
for (auto &socket : reference_set.potential_data_origins) {
socket = socket_map.lookup(socket);
}
}
}
if (ntree_src->geometry_node_asset_traits) {
ntree_dst->geometry_node_asset_traits = MEM_dupallocN<GeometryNodeAssetTraits>(
__func__, *ntree_src->geometry_node_asset_traits);
}
Nodes: add nested node ids and use them for simulation state The simulation state used by simulation nodes is owned by the modifier. Since a geometry nodes setup can contain an arbitrary number of simulations, the modifier has a mapping from `SimulationZoneID` to `SimulationZoneState`. This patch changes what is used as `SimulationZoneID`. Previously, the `SimulationZoneID` contained a list of `bNode::identifier` that described the path from the root node tree to the simulation output node. This works ok in many cases, but also has a significant problem: The `SimulationZoneID` changes when moving the simulation zone into or out of a node group. This implies that any of these operations loses the mapping from zone to simulation state, invalidating the cache or even baked data. The goal of this patch is to introduce a single-integer ID that identifies a (nested) simulation zone and is stable even when grouping and un-grouping. The ID should be stable even if the node group containing the (nested) simulation zone is in a separate linked .blend file and that linked file is changed. In the future, the same kind of ID can be used to store e.g. checkpoint/baked/frozen data in the modifier. To achieve the described goal, node trees can now store an arbitrary number of nested node references (an array of `bNestedNodeRef`). Each nested node reference has an ID that is unique within the current node tree. The node tree does not store the entire path to the nested node. Instead it only know which group node the nested node is in, and what the nested node ID of the node is within that group. Grouping and un-grouping operations have to update the nested node references to keep the IDs stable. Importantly though, these operations only have to care about the two node groups that are affected. IDs in higher level node groups remain unchanged by design. A consequence of this design is that every `bNodeTree` now has a `bNestedNodeRef` for every (nested) simulation zone. Two instances of the same simulation zone (because a node group is reused) are referenced by two separate `bNestedNodeRef`. This is important to keep in mind, because it also means that this solution doesn't scale well if we wanted to use it to keep stable references to *all* nested nodes. I can't think of a solution that fulfills the described requirements but scales better with more nodes. For that reason, this solution should only be used when we want to store data for each referenced nested node at the top level (like we do for simulations). This is not a replacement for `ViewerPath` which can store a path to data in a node tree without changing the node tree. Also `ViewerPath` can contain information like the loop iteration that should be viewed (#109164). `bNestedNodeRef` can't differentiate between different iterations of a loop. This also means that simulations can't be used inside of a loop (loops inside of a simulation work fine though). When baking, the new stable ID is now written to disk, which means that baked data is not invalidated by grouping/un-grouping operations. Backward compatibility for baked data is provided, but only works as long as the simulation zone has not been moved to a different node group yet. Forward compatibility for the baked data is not provided (so older versions can't load the data baked with a newer version of Blender). Pull Request: https://projects.blender.org/blender/blender/pulls/109444
2023-07-01 11:54:32 +02:00
if (ntree_src->nested_node_refs) {
ntree_dst->nested_node_refs = MEM_malloc_arrayN<bNestedNodeRef>(
size_t(ntree_src->nested_node_refs_num), __func__);
Nodes: add nested node ids and use them for simulation state The simulation state used by simulation nodes is owned by the modifier. Since a geometry nodes setup can contain an arbitrary number of simulations, the modifier has a mapping from `SimulationZoneID` to `SimulationZoneState`. This patch changes what is used as `SimulationZoneID`. Previously, the `SimulationZoneID` contained a list of `bNode::identifier` that described the path from the root node tree to the simulation output node. This works ok in many cases, but also has a significant problem: The `SimulationZoneID` changes when moving the simulation zone into or out of a node group. This implies that any of these operations loses the mapping from zone to simulation state, invalidating the cache or even baked data. The goal of this patch is to introduce a single-integer ID that identifies a (nested) simulation zone and is stable even when grouping and un-grouping. The ID should be stable even if the node group containing the (nested) simulation zone is in a separate linked .blend file and that linked file is changed. In the future, the same kind of ID can be used to store e.g. checkpoint/baked/frozen data in the modifier. To achieve the described goal, node trees can now store an arbitrary number of nested node references (an array of `bNestedNodeRef`). Each nested node reference has an ID that is unique within the current node tree. The node tree does not store the entire path to the nested node. Instead it only know which group node the nested node is in, and what the nested node ID of the node is within that group. Grouping and un-grouping operations have to update the nested node references to keep the IDs stable. Importantly though, these operations only have to care about the two node groups that are affected. IDs in higher level node groups remain unchanged by design. A consequence of this design is that every `bNodeTree` now has a `bNestedNodeRef` for every (nested) simulation zone. Two instances of the same simulation zone (because a node group is reused) are referenced by two separate `bNestedNodeRef`. This is important to keep in mind, because it also means that this solution doesn't scale well if we wanted to use it to keep stable references to *all* nested nodes. I can't think of a solution that fulfills the described requirements but scales better with more nodes. For that reason, this solution should only be used when we want to store data for each referenced nested node at the top level (like we do for simulations). This is not a replacement for `ViewerPath` which can store a path to data in a node tree without changing the node tree. Also `ViewerPath` can contain information like the loop iteration that should be viewed (#109164). `bNestedNodeRef` can't differentiate between different iterations of a loop. This also means that simulations can't be used inside of a loop (loops inside of a simulation work fine though). When baking, the new stable ID is now written to disk, which means that baked data is not invalidated by grouping/un-grouping operations. Backward compatibility for baked data is provided, but only works as long as the simulation zone has not been moved to a different node group yet. Forward compatibility for the baked data is not provided (so older versions can't load the data baked with a newer version of Blender). Pull Request: https://projects.blender.org/blender/blender/pulls/109444
2023-07-01 11:54:32 +02:00
uninitialized_copy_n(
ntree_src->nested_node_refs, ntree_src->nested_node_refs_num, ntree_dst->nested_node_refs);
}
if (flag & LIB_ID_COPY_NO_PREVIEW) {
ntree_dst->preview = nullptr;
}
else {
BKE_previewimg_id_copy(&ntree_dst->id, &ntree_src->id);
}
ntree_dst->description = BLI_strdup_null(ntree_src->description);
}
static void ntree_free_data(ID *id)
{
bNodeTree *ntree = reinterpret_cast<bNodeTree *>(id);
/* XXX hack! node trees should not store execution graphs at all.
* This should be removed when old tree types no longer require it.
* Currently the execution data for texture nodes remains in the tree
* after execution, until the node tree is updated or freed. */
if (ntree->runtime->execdata) {
switch (ntree->type) {
case NTREE_SHADER:
ntreeShaderEndExecTree(ntree->runtime->execdata);
break;
case NTREE_TEXTURE:
ntreeTexEndExecTree(ntree->runtime->execdata);
ntree->runtime->execdata = nullptr;
break;
}
}
/* XXX not nice, but needed to free localized node groups properly */
free_localized_node_groups(ntree);
BLI_freelistN(&ntree->links);
LISTBASE_FOREACH_MUTABLE (bNode *, node, &ntree->nodes) {
node_free_node(ntree, *node);
}
Nodes: Panels integration with blend files and UI Part 3/3 of #109135, #110272 Switch to new node group interfaces and deprecate old DNA and API. This completes support for panels in node drawing and in node group interface declarations in particular. The new node group interface DNA and RNA code has been added in parts 1 and 2 (#110885, #110952) but has not be enabled yet. This commit completes the integration by * enabling the new RNA API * using the new API in UI * read/write new interfaces from blend files * add versioning for backward compatibility * add forward-compatible writing code to reconstruct old interfaces All places accessing node group interface declarations should now be using the new API. A runtime cache has been added that allows simple linear access to socket inputs and outputs even when a panel hierarchy is used. Old DNA has been deprecated and should only be accessed for versioning (inputs/outputs renamed to inputs_legacy/outputs_legacy to catch errors). Versioning code ensures both backward and forward compatibility of existing files. The API for old interfaces is removed. The new API is very similar but is defined on the `ntree.interface` instead of the `ntree` directly. Breaking change notifications and detailed instructions for migrating will be added. A python test has been added for the node group API functions. This includes new functionality such as creating panels and moving items between different levels. This patch does not yet contain panel representations in the modifier UI. This has been tested in a separate branch and will be added with a later PR (#108565). Pull Request: https://projects.blender.org/blender/blender/pulls/111348
2023-08-30 12:37:21 +02:00
ntree->tree_interface.free_data();
if (ntree->id.tag & ID_TAG_LOCALIZED) {
BKE_libblock_free_data(&ntree->id, true);
}
if (ntree->geometry_node_asset_traits) {
MEM_freeN(ntree->geometry_node_asset_traits);
}
Nodes: add nested node ids and use them for simulation state The simulation state used by simulation nodes is owned by the modifier. Since a geometry nodes setup can contain an arbitrary number of simulations, the modifier has a mapping from `SimulationZoneID` to `SimulationZoneState`. This patch changes what is used as `SimulationZoneID`. Previously, the `SimulationZoneID` contained a list of `bNode::identifier` that described the path from the root node tree to the simulation output node. This works ok in many cases, but also has a significant problem: The `SimulationZoneID` changes when moving the simulation zone into or out of a node group. This implies that any of these operations loses the mapping from zone to simulation state, invalidating the cache or even baked data. The goal of this patch is to introduce a single-integer ID that identifies a (nested) simulation zone and is stable even when grouping and un-grouping. The ID should be stable even if the node group containing the (nested) simulation zone is in a separate linked .blend file and that linked file is changed. In the future, the same kind of ID can be used to store e.g. checkpoint/baked/frozen data in the modifier. To achieve the described goal, node trees can now store an arbitrary number of nested node references (an array of `bNestedNodeRef`). Each nested node reference has an ID that is unique within the current node tree. The node tree does not store the entire path to the nested node. Instead it only know which group node the nested node is in, and what the nested node ID of the node is within that group. Grouping and un-grouping operations have to update the nested node references to keep the IDs stable. Importantly though, these operations only have to care about the two node groups that are affected. IDs in higher level node groups remain unchanged by design. A consequence of this design is that every `bNodeTree` now has a `bNestedNodeRef` for every (nested) simulation zone. Two instances of the same simulation zone (because a node group is reused) are referenced by two separate `bNestedNodeRef`. This is important to keep in mind, because it also means that this solution doesn't scale well if we wanted to use it to keep stable references to *all* nested nodes. I can't think of a solution that fulfills the described requirements but scales better with more nodes. For that reason, this solution should only be used when we want to store data for each referenced nested node at the top level (like we do for simulations). This is not a replacement for `ViewerPath` which can store a path to data in a node tree without changing the node tree. Also `ViewerPath` can contain information like the loop iteration that should be viewed (#109164). `bNestedNodeRef` can't differentiate between different iterations of a loop. This also means that simulations can't be used inside of a loop (loops inside of a simulation work fine though). When baking, the new stable ID is now written to disk, which means that baked data is not invalidated by grouping/un-grouping operations. Backward compatibility for baked data is provided, but only works as long as the simulation zone has not been moved to a different node group yet. Forward compatibility for the baked data is not provided (so older versions can't load the data baked with a newer version of Blender). Pull Request: https://projects.blender.org/blender/blender/pulls/109444
2023-07-01 11:54:32 +02:00
if (ntree->nested_node_refs) {
MEM_freeN(ntree->nested_node_refs);
}
MEM_SAFE_FREE(ntree->description);
BKE_previewimg_free(&ntree->preview);
MEM_delete(ntree->runtime);
}
static void library_foreach_node_socket(bNodeSocket *sock, LibraryForeachIDData *data)
{
BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL(
data, IDP_foreach_property(sock->prop, IDP_TYPE_FILTER_ID, [&](IDProperty *prop) {
BKE_lib_query_idpropertiesForeachIDLink_callback(prop, data);
}));
switch (eNodeSocketDatatype(sock->type)) {
case SOCK_OBJECT: {
bNodeSocketValueObject &default_value = *sock->default_value_typed<bNodeSocketValueObject>();
BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, default_value.value, IDWALK_CB_USER);
break;
}
case SOCK_IMAGE: {
bNodeSocketValueImage &default_value = *sock->default_value_typed<bNodeSocketValueImage>();
BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, default_value.value, IDWALK_CB_USER);
break;
}
case SOCK_COLLECTION: {
bNodeSocketValueCollection &default_value =
*sock->default_value_typed<bNodeSocketValueCollection>();
BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, default_value.value, IDWALK_CB_USER);
break;
}
case SOCK_TEXTURE: {
bNodeSocketValueTexture &default_value =
*sock->default_value_typed<bNodeSocketValueTexture>();
BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, default_value.value, IDWALK_CB_USER);
break;
}
case SOCK_MATERIAL: {
bNodeSocketValueMaterial &default_value =
*sock->default_value_typed<bNodeSocketValueMaterial>();
BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, default_value.value, IDWALK_CB_USER);
break;
Geometry Nodes: add simulation support This adds support for building simulations with geometry nodes. A new `Simulation Input` and `Simulation Output` node allow maintaining a simulation state across multiple frames. Together these two nodes form a `simulation zone` which contains all the nodes that update the simulation state from one frame to the next. A new simulation zone can be added via the menu (`Simulation > Simulation Zone`) or with the node add search. The simulation state contains a geometry by default. However, it is possible to add multiple geometry sockets as well as other socket types. Currently, field inputs are evaluated and stored for the preceding geometry socket in the order that the sockets are shown. Simulation state items can be added by linking one of the empty sockets to something else. In the sidebar, there is a new panel that allows adding, removing and reordering these sockets. The simulation nodes behave as follows: * On the first frame, the inputs of the `Simulation Input` node are evaluated to initialize the simulation state. In later frames these sockets are not evaluated anymore. The `Delta Time` at the first frame is zero, but the simulation zone is still evaluated. * On every next frame, the `Simulation Input` node outputs the simulation state of the previous frame. Nodes in the simulation zone can edit that data in arbitrary ways, also taking into account the `Delta Time`. The new simulation state has to be passed to the `Simulation Output` node where it is cached and forwarded. * On a frame that is already cached or baked, the nodes in the simulation zone are not evaluated, because the `Simulation Output` node can return the previously cached data directly. It is not allowed to connect sockets from inside the simulation zone to the outside without going through the `Simulation Output` node. This is a necessary restriction to make caching and sub-frame interpolation work. Links can go into the simulation zone without problems though. Anonymous attributes are not propagated by the simulation nodes unless they are explicitly stored in the simulation state. This is unfortunate, but currently there is no practical and reliable alternative. The core problem is detecting which anonymous attributes will be required for the simulation and afterwards. While we can detect this for the current evaluation, we can't look into the future in time to see what data will be necessary. We intend to make it easier to explicitly pass data through a simulation in the future, even if the simulation is in a nested node group. There is a new `Simulation Nodes` panel in the physics tab in the properties editor. It allows baking all simulation zones on the selected objects. The baking options are intentially kept at a minimum for this MVP. More features for simulation baking as well as baking in general can be expected to be added separately. All baked data is stored on disk in a folder next to the .blend file. #106937 describes how baking is implemented in more detail. Volumes can not be baked yet and materials are lost during baking for now. Packing the baked data into the .blend file is not yet supported. The timeline indicates which frames are currently cached, baked or cached but invalidated by user-changes. Simulation input and output nodes are internally linked together by their `bNode.identifier` which stays the same even if the node name changes. They are generally added and removed together. However, there are still cases where "dangling" simulation nodes can be created currently. Those generally don't cause harm, but would be nice to avoid this in more cases in the future. Co-authored-by: Hans Goudey <h.goudey@me.com> Co-authored-by: Lukas Tönne <lukas@blender.org> Pull Request: https://projects.blender.org/blender/blender/pulls/104924
2023-05-03 13:18:51 +02:00
}
case SOCK_FLOAT:
case SOCK_VECTOR:
case SOCK_RGBA:
case SOCK_BOOLEAN:
case SOCK_ROTATION:
case SOCK_MATRIX:
case SOCK_INT:
case SOCK_STRING:
case SOCK_CUSTOM:
case SOCK_SHADER:
case SOCK_GEOMETRY:
Geometry Nodes: Menu Switch Node This patch adds support for _Menu Switch_ nodes and enum definitions in node trees more generally. The design is based on the outcome of the [2022 Nodes Workshop](https://code.blender.org/2022/11/geometry-nodes-workshop-2022/#menu-switch). The _Menu Switch_ node is an advanced version of the _Switch_ node which has a customizable **menu input socket** instead of a simple boolean. The _items_ of this menu are owned by the node itself. Each item has a name and description and unique identifier that is used internally. A menu _socket_ represents a concrete value out of the list of items. To enable selection of an enum value for unconnected sockets the menu is presented as a dropdown list like built-in enums. When the socket is connected a shared pointer to the enum definition is propagated along links and stored in socket default values. This allows node groups to expose a menu from an internal menu switch as a parameter. The enum definition is a runtime copy of the enum items in DNA that allows sharing. A menu socket can have multiple connections, which can lead to ambiguity. If two or more different menu source nodes are connected to a socket it gets marked as _undefined_. Any connection to an undefined menu socket is invalid as a hint to users that there is a problem. A warning/error is also shown on nodes with undefined menu sockets. At runtime the value of a menu socket is the simple integer identifier. This can also be a field in geometry nodes. The identifier is unique within each enum definition, and it is persistent even when items are added, removed, or changed. Changing the name of an item does not affect the internal identifier, so users can rename enum items without breaking existing input values. This also persists if, for example, a linked node group is temporarily unavailable. Pull Request: https://projects.blender.org/blender/blender/pulls/113445
2024-01-26 12:40:01 +01:00
case SOCK_MENU:
Geometry Nodes: add Closures and Bundles behind experimental feature flag This implements bundles and closures which are described in more detail in this blog post: https://code.blender.org/2024/11/geometry-nodes-workshop-october-2024/ tl;dr: * Bundles are containers that allow storing multiple socket values in a single value. Each value in the bundle is identified by a name. Bundles can be nested. * Closures are functions that are created with the Closure Zone and can be evaluated with the Evaluate Closure node. To use the patch, the `Bundle and Closure Nodes` experimental feature has to be enabled. This is necessary, because these features are not fully done yet and still need iterations to improve the workflow before they can be officially released. These iterations are easier to do in `main` than in a separate branch though. That's because this patch is quite large and somewhat prone to merge conflicts. Also other work we want to do, depends on this. This adds the following new nodes: * Combine Bundle: can pack multiple values into one. * Separate Bundle: extracts values from a bundle. * Closure Zone: outputs a closure zone for use in the `Evaluate Closure` node. * Evaluate Closure: evaluates the passed in closure. Things that will be added soon after this lands: * Fields in bundles and closures. The way this is done changes with #134811, so I rather implement this once both are in `main`. * UI features for keeping sockets in sync (right now there are warnings only). One bigger issue is the limited support for lazyness. For example, all inputs of a Combine Bundle node will be evaluated, even if they are not all needed. The same is true for all captured values of a closure. This is a deeper limitation that needs to be resolved at some point. This will likely be done after an initial version of this patch is done. Pull Request: https://projects.blender.org/blender/blender/pulls/128340
2025-04-03 15:44:06 +02:00
case SOCK_BUNDLE:
case SOCK_CLOSURE:
break;
}
}
void node_node_foreach_id(bNode *node, LibraryForeachIDData *data)
{
BKE_LIB_FOREACHID_PROCESS_ID(data, node->id, IDWALK_CB_USER);
BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL(
data, IDP_foreach_property(node->prop, IDP_TYPE_FILTER_ID, [&](IDProperty *prop) {
BKE_lib_query_idpropertiesForeachIDLink_callback(prop, data);
}));
LISTBASE_FOREACH (bNodeSocket *, sock, &node->inputs) {
BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL(data, library_foreach_node_socket(sock, data));
}
LISTBASE_FOREACH (bNodeSocket *, sock, &node->outputs) {
BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL(data, library_foreach_node_socket(sock, data));
}
/* Note that this ID pointer is only a cache, it may be outdated. */
BKE_LIB_FOREACHID_PROCESS_ID(data, node->runtime->owner_tree, IDWALK_CB_LOOPBACK);
}
static void node_foreach_id(ID *id, LibraryForeachIDData *data)
{
bNodeTree *ntree = reinterpret_cast<bNodeTree *>(id);
BKE_LIB_FOREACHID_PROCESS_ID(
data,
ntree->owner_id,
(IDWALK_CB_LOOPBACK | IDWALK_CB_NEVER_SELF | IDWALK_CB_READFILE_IGNORE));
BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, ntree->gpd, IDWALK_CB_USER);
for (bNode *node : ntree->all_nodes()) {
node_node_foreach_id(node, data);
}
Nodes: Panels integration with blend files and UI Part 3/3 of #109135, #110272 Switch to new node group interfaces and deprecate old DNA and API. This completes support for panels in node drawing and in node group interface declarations in particular. The new node group interface DNA and RNA code has been added in parts 1 and 2 (#110885, #110952) but has not be enabled yet. This commit completes the integration by * enabling the new RNA API * using the new API in UI * read/write new interfaces from blend files * add versioning for backward compatibility * add forward-compatible writing code to reconstruct old interfaces All places accessing node group interface declarations should now be using the new API. A runtime cache has been added that allows simple linear access to socket inputs and outputs even when a panel hierarchy is used. Old DNA has been deprecated and should only be accessed for versioning (inputs/outputs renamed to inputs_legacy/outputs_legacy to catch errors). Versioning code ensures both backward and forward compatibility of existing files. The API for old interfaces is removed. The new API is very similar but is defined on the `ntree.interface` instead of the `ntree` directly. Breaking change notifications and detailed instructions for migrating will be added. A python test has been added for the node group API functions. This includes new functionality such as creating panels and moving items between different levels. This patch does not yet contain panel representations in the modifier UI. This has been tested in a separate branch and will be added with a later PR (#108565). Pull Request: https://projects.blender.org/blender/blender/pulls/111348
2023-08-30 12:37:21 +02:00
ntree->tree_interface.foreach_id(data);
Geometry Nodes: improve detecting data-block dependencies Previously, the data-block dependencies were always detected in `update_depsgraph` in `MOD_nodes.cc`. This would only be called when something called `DEG_relations_tag_update` before. We don't want to trigger a depsgraph rebuild after each operation in the node editor, as that would be expensive. However, that also meant that we often had to add data-block dependencies that are not actually used, but might be used if the user changed e.g. a link. A typical example for that is a object socket that has a default value, but the socket is also linked. Now, the dependencies referenced by the node tree are collected by the node tree update code which runs after all changes. This way we can detect whether the dependencies have changed. Only if they have changed, a depsgraph rebuild is triggered. This now allows also taking into account the mute status of nodes and whether an input is linked. There are still more things that could be taken into account. Most obviously whether a node is connected to an output. This can be done later. The most tricky aspect here is probably that we also have to consider all viewer nodes as output, because at the time the node runs, it's not known which viewer will actually be used (which depends on other editors). This also cleans up some special cases we had for e.g. the scene time node where we always had to trigger a depsgraph rebuild when it was added/removed because of its time dependence. This is now part of a more general system. This fixes #109219. Pull Request: https://projects.blender.org/blender/blender/pulls/131446
2024-12-05 18:02:14 +01:00
if (ntree->runtime->geometry_nodes_eval_dependencies) {
for (ID *&id_ref : ntree->runtime->geometry_nodes_eval_dependencies->ids.values()) {
BKE_LIB_FOREACHID_PROCESS_ID(data, id_ref, IDWALK_CB_NOP);
}
}
}
static void node_foreach_cache(ID *id,
IDTypeForeachCacheFunctionCallback function_callback,
void *user_data)
{
bNodeTree *nodetree = reinterpret_cast<bNodeTree *>(id);
IDCacheKey key = {0};
key.id_session_uid = id->session_uid;
if (nodetree->type == NTREE_COMPOSIT) {
for (bNode *node : nodetree->all_nodes()) {
if (node->type_legacy == CMP_NODE_MOVIEDISTORTION) {
key.identifier = size_t(BLI_ghashutil_strhash_p(node->name));
function_callback(id, &key, (&node->storage), 0, user_data);
}
}
}
}
static void node_foreach_path(ID *id, BPathForeachPathData *bpath_data)
{
bNodeTree *ntree = reinterpret_cast<bNodeTree *>(id);
Geometry Nodes: add simulation support This adds support for building simulations with geometry nodes. A new `Simulation Input` and `Simulation Output` node allow maintaining a simulation state across multiple frames. Together these two nodes form a `simulation zone` which contains all the nodes that update the simulation state from one frame to the next. A new simulation zone can be added via the menu (`Simulation > Simulation Zone`) or with the node add search. The simulation state contains a geometry by default. However, it is possible to add multiple geometry sockets as well as other socket types. Currently, field inputs are evaluated and stored for the preceding geometry socket in the order that the sockets are shown. Simulation state items can be added by linking one of the empty sockets to something else. In the sidebar, there is a new panel that allows adding, removing and reordering these sockets. The simulation nodes behave as follows: * On the first frame, the inputs of the `Simulation Input` node are evaluated to initialize the simulation state. In later frames these sockets are not evaluated anymore. The `Delta Time` at the first frame is zero, but the simulation zone is still evaluated. * On every next frame, the `Simulation Input` node outputs the simulation state of the previous frame. Nodes in the simulation zone can edit that data in arbitrary ways, also taking into account the `Delta Time`. The new simulation state has to be passed to the `Simulation Output` node where it is cached and forwarded. * On a frame that is already cached or baked, the nodes in the simulation zone are not evaluated, because the `Simulation Output` node can return the previously cached data directly. It is not allowed to connect sockets from inside the simulation zone to the outside without going through the `Simulation Output` node. This is a necessary restriction to make caching and sub-frame interpolation work. Links can go into the simulation zone without problems though. Anonymous attributes are not propagated by the simulation nodes unless they are explicitly stored in the simulation state. This is unfortunate, but currently there is no practical and reliable alternative. The core problem is detecting which anonymous attributes will be required for the simulation and afterwards. While we can detect this for the current evaluation, we can't look into the future in time to see what data will be necessary. We intend to make it easier to explicitly pass data through a simulation in the future, even if the simulation is in a nested node group. There is a new `Simulation Nodes` panel in the physics tab in the properties editor. It allows baking all simulation zones on the selected objects. The baking options are intentially kept at a minimum for this MVP. More features for simulation baking as well as baking in general can be expected to be added separately. All baked data is stored on disk in a folder next to the .blend file. #106937 describes how baking is implemented in more detail. Volumes can not be baked yet and materials are lost during baking for now. Packing the baked data into the .blend file is not yet supported. The timeline indicates which frames are currently cached, baked or cached but invalidated by user-changes. Simulation input and output nodes are internally linked together by their `bNode.identifier` which stays the same even if the node name changes. They are generally added and removed together. However, there are still cases where "dangling" simulation nodes can be created currently. Those generally don't cause harm, but would be nice to avoid this in more cases in the future. Co-authored-by: Hans Goudey <h.goudey@me.com> Co-authored-by: Lukas Tönne <lukas@blender.org> Pull Request: https://projects.blender.org/blender/blender/pulls/104924
2023-05-03 13:18:51 +02:00
switch (ntree->type) {
case NTREE_SHADER: {
for (bNode *node : ntree->all_nodes()) {
if (node->type_legacy == SH_NODE_SCRIPT) {
NodeShaderScript *nss = static_cast<NodeShaderScript *>(node->storage);
if (nss->mode == NODE_SCRIPT_EXTERNAL && nss->filepath[0]) {
BKE_bpath_foreach_path_fixed_process(bpath_data, nss->filepath, sizeof(nss->filepath));
}
}
else if (node->type_legacy == SH_NODE_TEX_IES) {
NodeShaderTexIES *ies = static_cast<NodeShaderTexIES *>(node->storage);
if (ies->mode == NODE_IES_EXTERNAL && ies->filepath[0]) {
BKE_bpath_foreach_path_fixed_process(bpath_data, ies->filepath, sizeof(ies->filepath));
}
}
}
break;
}
default:
break;
}
}
static ID **node_owner_pointer_get(ID *id, const bool debug_relationship_assert)
{
if ((id->flag & ID_FLAG_EMBEDDED_DATA) == 0) {
return nullptr;
}
/* TODO: Sort this NO_MAIN or not for embedded node trees. See #86119. */
// BLI_assert((id->tag & ID_TAG_NO_MAIN) == 0);
bNodeTree *ntree = reinterpret_cast<bNodeTree *>(id);
if (debug_relationship_assert) {
BLI_assert(ntree->owner_id != nullptr);
BLI_assert(node_tree_from_id(ntree->owner_id) == ntree);
}
return &ntree->owner_id;
}
namespace forward_compat {
Nodes: Panels integration with blend files and UI Part 3/3 of #109135, #110272 Switch to new node group interfaces and deprecate old DNA and API. This completes support for panels in node drawing and in node group interface declarations in particular. The new node group interface DNA and RNA code has been added in parts 1 and 2 (#110885, #110952) but has not be enabled yet. This commit completes the integration by * enabling the new RNA API * using the new API in UI * read/write new interfaces from blend files * add versioning for backward compatibility * add forward-compatible writing code to reconstruct old interfaces All places accessing node group interface declarations should now be using the new API. A runtime cache has been added that allows simple linear access to socket inputs and outputs even when a panel hierarchy is used. Old DNA has been deprecated and should only be accessed for versioning (inputs/outputs renamed to inputs_legacy/outputs_legacy to catch errors). Versioning code ensures both backward and forward compatibility of existing files. The API for old interfaces is removed. The new API is very similar but is defined on the `ntree.interface` instead of the `ntree` directly. Breaking change notifications and detailed instructions for migrating will be added. A python test has been added for the node group API functions. This includes new functionality such as creating panels and moving items between different levels. This patch does not yet contain panel representations in the modifier UI. This has been tested in a separate branch and will be added with a later PR (#108565). Pull Request: https://projects.blender.org/blender/blender/pulls/111348
2023-08-30 12:37:21 +02:00
static void write_node_socket_interface(BlendWriter *writer, const bNodeSocket *sock)
{
BLO_write_struct(writer, bNodeSocket, sock);
if (sock->prop) {
IDP_BlendWrite(writer, sock->prop);
}
BLO_write_string(writer, sock->default_attribute_name);
write_node_socket_default_value(writer, sock);
}
/* Construct a bNodeSocket that represents a node group socket the old way. */
static bNodeSocket *make_socket(bNodeTree *ntree,
const eNodeSocketInOut in_out,
const StringRef idname,
const StringRef name,
const StringRef identifier)
{
bNodeSocketType *stype = node_socket_type_find(idname);
Nodes: Panels integration with blend files and UI Part 3/3 of #109135, #110272 Switch to new node group interfaces and deprecate old DNA and API. This completes support for panels in node drawing and in node group interface declarations in particular. The new node group interface DNA and RNA code has been added in parts 1 and 2 (#110885, #110952) but has not be enabled yet. This commit completes the integration by * enabling the new RNA API * using the new API in UI * read/write new interfaces from blend files * add versioning for backward compatibility * add forward-compatible writing code to reconstruct old interfaces All places accessing node group interface declarations should now be using the new API. A runtime cache has been added that allows simple linear access to socket inputs and outputs even when a panel hierarchy is used. Old DNA has been deprecated and should only be accessed for versioning (inputs/outputs renamed to inputs_legacy/outputs_legacy to catch errors). Versioning code ensures both backward and forward compatibility of existing files. The API for old interfaces is removed. The new API is very similar but is defined on the `ntree.interface` instead of the `ntree` directly. Breaking change notifications and detailed instructions for migrating will be added. A python test has been added for the node group API functions. This includes new functionality such as creating panels and moving items between different levels. This patch does not yet contain panel representations in the modifier UI. This has been tested in a separate branch and will be added with a later PR (#108565). Pull Request: https://projects.blender.org/blender/blender/pulls/111348
2023-08-30 12:37:21 +02:00
if (stype == nullptr) {
return nullptr;
}
bNodeSocket *sock = MEM_callocN<bNodeSocket>(__func__);
Nodes: Panels integration with blend files and UI Part 3/3 of #109135, #110272 Switch to new node group interfaces and deprecate old DNA and API. This completes support for panels in node drawing and in node group interface declarations in particular. The new node group interface DNA and RNA code has been added in parts 1 and 2 (#110885, #110952) but has not be enabled yet. This commit completes the integration by * enabling the new RNA API * using the new API in UI * read/write new interfaces from blend files * add versioning for backward compatibility * add forward-compatible writing code to reconstruct old interfaces All places accessing node group interface declarations should now be using the new API. A runtime cache has been added that allows simple linear access to socket inputs and outputs even when a panel hierarchy is used. Old DNA has been deprecated and should only be accessed for versioning (inputs/outputs renamed to inputs_legacy/outputs_legacy to catch errors). Versioning code ensures both backward and forward compatibility of existing files. The API for old interfaces is removed. The new API is very similar but is defined on the `ntree.interface` instead of the `ntree` directly. Breaking change notifications and detailed instructions for migrating will be added. A python test has been added for the node group API functions. This includes new functionality such as creating panels and moving items between different levels. This patch does not yet contain panel representations in the modifier UI. This has been tested in a separate branch and will be added with a later PR (#108565). Pull Request: https://projects.blender.org/blender/blender/pulls/111348
2023-08-30 12:37:21 +02:00
sock->runtime = MEM_new<bNodeSocketRuntime>(__func__);
StringRef(stype->idname).copy_utf8_truncated(sock->idname);
Nodes: Panels integration with blend files and UI Part 3/3 of #109135, #110272 Switch to new node group interfaces and deprecate old DNA and API. This completes support for panels in node drawing and in node group interface declarations in particular. The new node group interface DNA and RNA code has been added in parts 1 and 2 (#110885, #110952) but has not be enabled yet. This commit completes the integration by * enabling the new RNA API * using the new API in UI * read/write new interfaces from blend files * add versioning for backward compatibility * add forward-compatible writing code to reconstruct old interfaces All places accessing node group interface declarations should now be using the new API. A runtime cache has been added that allows simple linear access to socket inputs and outputs even when a panel hierarchy is used. Old DNA has been deprecated and should only be accessed for versioning (inputs/outputs renamed to inputs_legacy/outputs_legacy to catch errors). Versioning code ensures both backward and forward compatibility of existing files. The API for old interfaces is removed. The new API is very similar but is defined on the `ntree.interface` instead of the `ntree` directly. Breaking change notifications and detailed instructions for migrating will be added. A python test has been added for the node group API functions. This includes new functionality such as creating panels and moving items between different levels. This patch does not yet contain panel representations in the modifier UI. This has been tested in a separate branch and will be added with a later PR (#108565). Pull Request: https://projects.blender.org/blender/blender/pulls/111348
2023-08-30 12:37:21 +02:00
sock->in_out = int(in_out);
sock->type = int(SOCK_CUSTOM); /* int type undefined by default */
node_socket_set_typeinfo(ntree, sock, stype);
sock->limit = (in_out == SOCK_IN ? 1 : 0xFFF);
identifier.copy_utf8_truncated(sock->identifier);
name.copy_utf8_truncated(sock->name);
Nodes: Panels integration with blend files and UI Part 3/3 of #109135, #110272 Switch to new node group interfaces and deprecate old DNA and API. This completes support for panels in node drawing and in node group interface declarations in particular. The new node group interface DNA and RNA code has been added in parts 1 and 2 (#110885, #110952) but has not be enabled yet. This commit completes the integration by * enabling the new RNA API * using the new API in UI * read/write new interfaces from blend files * add versioning for backward compatibility * add forward-compatible writing code to reconstruct old interfaces All places accessing node group interface declarations should now be using the new API. A runtime cache has been added that allows simple linear access to socket inputs and outputs even when a panel hierarchy is used. Old DNA has been deprecated and should only be accessed for versioning (inputs/outputs renamed to inputs_legacy/outputs_legacy to catch errors). Versioning code ensures both backward and forward compatibility of existing files. The API for old interfaces is removed. The new API is very similar but is defined on the `ntree.interface` instead of the `ntree` directly. Breaking change notifications and detailed instructions for migrating will be added. A python test has been added for the node group API functions. This includes new functionality such as creating panels and moving items between different levels. This patch does not yet contain panel representations in the modifier UI. This has been tested in a separate branch and will be added with a later PR (#108565). Pull Request: https://projects.blender.org/blender/blender/pulls/111348
2023-08-30 12:37:21 +02:00
sock->storage = nullptr;
sock->flag |= SOCK_COLLAPSED;
return sock;
}
/* Include the subtype suffix for old socket idnames. */
static StringRef get_legacy_socket_subtype_idname(StringRef idname, const void *socket_data)
{
if (idname == "NodeSocketFloat") {
const bNodeSocketValueFloat &float_data = *static_cast<const bNodeSocketValueFloat *>(
socket_data);
switch (float_data.subtype) {
case PROP_UNSIGNED:
return "NodeSocketFloatUnsigned";
case PROP_PERCENTAGE:
return "NodeSocketFloatPercentage";
case PROP_FACTOR:
return "NodeSocketFloatFactor";
case PROP_ANGLE:
return "NodeSocketFloatAngle";
case PROP_TIME:
return "NodeSocketFloatTime";
case PROP_TIME_ABSOLUTE:
return "NodeSocketFloatTimeAbsolute";
case PROP_DISTANCE:
return "NodeSocketFloatDistance";
case PROP_WAVELENGTH:
return "NodeSocketFloatWavelength";
case PROP_COLOR_TEMPERATURE:
return "NodeSocketFloatColorTemperature";
case PROP_FREQUENCY:
return "NodeSocketFloatFrequency";
}
}
if (idname == "NodeSocketInt") {
const bNodeSocketValueInt &int_data = *static_cast<const bNodeSocketValueInt *>(socket_data);
switch (int_data.subtype) {
case PROP_UNSIGNED:
return "NodeSocketIntUnsigned";
case PROP_PERCENTAGE:
return "NodeSocketIntPercentage";
case PROP_FACTOR:
return "NodeSocketIntFactor";
}
}
if (idname == "NodeSocketVector") {
const bNodeSocketValueVector &vector_data = *static_cast<const bNodeSocketValueVector *>(
socket_data);
switch (vector_data.subtype) {
case PROP_FACTOR:
return "NodeSocketVectorFactor";
case PROP_PERCENTAGE:
return "NodeSocketVectorPercentage";
case PROP_TRANSLATION:
return "NodeSocketVectorTranslation";
case PROP_DIRECTION:
return "NodeSocketVectorDirection";
case PROP_VELOCITY:
return "NodeSocketVectorVelocity";
case PROP_ACCELERATION:
return "NodeSocketVectorAcceleration";
case PROP_EULER:
return "NodeSocketVectorEuler";
}
}
return idname;
}
Nodes: Panels integration with blend files and UI Part 3/3 of #109135, #110272 Switch to new node group interfaces and deprecate old DNA and API. This completes support for panels in node drawing and in node group interface declarations in particular. The new node group interface DNA and RNA code has been added in parts 1 and 2 (#110885, #110952) but has not be enabled yet. This commit completes the integration by * enabling the new RNA API * using the new API in UI * read/write new interfaces from blend files * add versioning for backward compatibility * add forward-compatible writing code to reconstruct old interfaces All places accessing node group interface declarations should now be using the new API. A runtime cache has been added that allows simple linear access to socket inputs and outputs even when a panel hierarchy is used. Old DNA has been deprecated and should only be accessed for versioning (inputs/outputs renamed to inputs_legacy/outputs_legacy to catch errors). Versioning code ensures both backward and forward compatibility of existing files. The API for old interfaces is removed. The new API is very similar but is defined on the `ntree.interface` instead of the `ntree` directly. Breaking change notifications and detailed instructions for migrating will be added. A python test has been added for the node group API functions. This includes new functionality such as creating panels and moving items between different levels. This patch does not yet contain panel representations in the modifier UI. This has been tested in a separate branch and will be added with a later PR (#108565). Pull Request: https://projects.blender.org/blender/blender/pulls/111348
2023-08-30 12:37:21 +02:00
/**
* Socket interface reconstruction for forward compatibility.
* To enable previous Blender versions to read the new interface DNA data,
* construct the bNodeSocket inputs/outputs lists.
* This discards any information about panels and alternating input/output order,
* but all functional information is preserved for executing node trees.
*/
static void construct_interface_as_legacy_sockets(bNodeTree *ntree)
{
BLI_assert(BLI_listbase_is_empty(&ntree->inputs_legacy));
BLI_assert(BLI_listbase_is_empty(&ntree->outputs_legacy));
auto make_legacy_socket = [&](const bNodeTreeInterfaceSocket &socket,
eNodeSocketInOut in_out) -> bNodeSocket * {
bNodeSocket *iosock = make_socket(
ntree,
in_out,
get_legacy_socket_subtype_idname(socket.socket_type, socket.socket_data),
socket.name ? socket.name : "",
socket.identifier);
Nodes: Panels integration with blend files and UI Part 3/3 of #109135, #110272 Switch to new node group interfaces and deprecate old DNA and API. This completes support for panels in node drawing and in node group interface declarations in particular. The new node group interface DNA and RNA code has been added in parts 1 and 2 (#110885, #110952) but has not be enabled yet. This commit completes the integration by * enabling the new RNA API * using the new API in UI * read/write new interfaces from blend files * add versioning for backward compatibility * add forward-compatible writing code to reconstruct old interfaces All places accessing node group interface declarations should now be using the new API. A runtime cache has been added that allows simple linear access to socket inputs and outputs even when a panel hierarchy is used. Old DNA has been deprecated and should only be accessed for versioning (inputs/outputs renamed to inputs_legacy/outputs_legacy to catch errors). Versioning code ensures both backward and forward compatibility of existing files. The API for old interfaces is removed. The new API is very similar but is defined on the `ntree.interface` instead of the `ntree` directly. Breaking change notifications and detailed instructions for migrating will be added. A python test has been added for the node group API functions. This includes new functionality such as creating panels and moving items between different levels. This patch does not yet contain panel representations in the modifier UI. This has been tested in a separate branch and will be added with a later PR (#108565). Pull Request: https://projects.blender.org/blender/blender/pulls/111348
2023-08-30 12:37:21 +02:00
if (!iosock) {
return nullptr;
}
if (socket.description) {
STRNCPY(iosock->description, socket.description);
Nodes: Panels integration with blend files and UI Part 3/3 of #109135, #110272 Switch to new node group interfaces and deprecate old DNA and API. This completes support for panels in node drawing and in node group interface declarations in particular. The new node group interface DNA and RNA code has been added in parts 1 and 2 (#110885, #110952) but has not be enabled yet. This commit completes the integration by * enabling the new RNA API * using the new API in UI * read/write new interfaces from blend files * add versioning for backward compatibility * add forward-compatible writing code to reconstruct old interfaces All places accessing node group interface declarations should now be using the new API. A runtime cache has been added that allows simple linear access to socket inputs and outputs even when a panel hierarchy is used. Old DNA has been deprecated and should only be accessed for versioning (inputs/outputs renamed to inputs_legacy/outputs_legacy to catch errors). Versioning code ensures both backward and forward compatibility of existing files. The API for old interfaces is removed. The new API is very similar but is defined on the `ntree.interface` instead of the `ntree` directly. Breaking change notifications and detailed instructions for migrating will be added. A python test has been added for the node group API functions. This includes new functionality such as creating panels and moving items between different levels. This patch does not yet contain panel representations in the modifier UI. This has been tested in a separate branch and will be added with a later PR (#108565). Pull Request: https://projects.blender.org/blender/blender/pulls/111348
2023-08-30 12:37:21 +02:00
}
node_socket_copy_default_value_data(
eNodeSocketDatatype(iosock->typeinfo->type), iosock->default_value, socket.socket_data);
if (socket.properties) {
iosock->prop = IDP_CopyProperty(socket.properties);
}
SET_FLAG_FROM_TEST(
iosock->flag, socket.flag & NODE_INTERFACE_SOCKET_HIDE_VALUE, SOCK_HIDE_VALUE);
SET_FLAG_FROM_TEST(
iosock->flag, socket.flag & NODE_INTERFACE_SOCKET_HIDE_IN_MODIFIER, SOCK_HIDE_IN_MODIFIER);
iosock->attribute_domain = socket.attribute_domain;
iosock->default_attribute_name = BLI_strdup_null(socket.default_attribute_name);
Nodes: Panels integration with blend files and UI Part 3/3 of #109135, #110272 Switch to new node group interfaces and deprecate old DNA and API. This completes support for panels in node drawing and in node group interface declarations in particular. The new node group interface DNA and RNA code has been added in parts 1 and 2 (#110885, #110952) but has not be enabled yet. This commit completes the integration by * enabling the new RNA API * using the new API in UI * read/write new interfaces from blend files * add versioning for backward compatibility * add forward-compatible writing code to reconstruct old interfaces All places accessing node group interface declarations should now be using the new API. A runtime cache has been added that allows simple linear access to socket inputs and outputs even when a panel hierarchy is used. Old DNA has been deprecated and should only be accessed for versioning (inputs/outputs renamed to inputs_legacy/outputs_legacy to catch errors). Versioning code ensures both backward and forward compatibility of existing files. The API for old interfaces is removed. The new API is very similar but is defined on the `ntree.interface` instead of the `ntree` directly. Breaking change notifications and detailed instructions for migrating will be added. A python test has been added for the node group API functions. This includes new functionality such as creating panels and moving items between different levels. This patch does not yet contain panel representations in the modifier UI. This has been tested in a separate branch and will be added with a later PR (#108565). Pull Request: https://projects.blender.org/blender/blender/pulls/111348
2023-08-30 12:37:21 +02:00
return iosock;
};
/* Construct inputs/outputs socket lists in the node tree. */
ntree->tree_interface.foreach_item([&](const bNodeTreeInterfaceItem &item) {
if (const bNodeTreeInterfaceSocket *socket =
node_interface::get_item_as<bNodeTreeInterfaceSocket>(&item))
{
if (socket->flag & NODE_INTERFACE_SOCKET_INPUT) {
if (bNodeSocket *legacy_socket = make_legacy_socket(*socket, SOCK_IN)) {
BLI_addtail(&ntree->inputs_legacy, legacy_socket);
}
}
if (socket->flag & NODE_INTERFACE_SOCKET_OUTPUT) {
if (bNodeSocket *legacy_socket = make_legacy_socket(*socket, SOCK_OUT)) {
BLI_addtail(&ntree->outputs_legacy, legacy_socket);
}
}
}
return true;
});
}
static void write_legacy_sockets(BlendWriter *writer, bNodeTree *ntree)
{
/* Write inputs/outputs */
LISTBASE_FOREACH (bNodeSocket *, sock, &ntree->inputs_legacy) {
write_node_socket_interface(writer, sock);
}
LISTBASE_FOREACH (bNodeSocket *, sock, &ntree->outputs_legacy) {
write_node_socket_interface(writer, sock);
}
}
static void legacy_socket_interface_free(bNodeSocket *sock)
{
if (sock->prop) {
IDP_FreeProperty_ex(sock->prop, false);
}
if (sock->default_value) {
MEM_freeN(sock->default_value);
}
if (sock->default_attribute_name) {
MEM_freeN(sock->default_attribute_name);
}
MEM_delete(sock->runtime);
}
static void cleanup_legacy_sockets(bNodeTree *ntree)
{
/* Clean up temporary inputs/outputs. */
LISTBASE_FOREACH_MUTABLE (bNodeSocket *, socket, &ntree->inputs_legacy) {
legacy_socket_interface_free(socket);
MEM_freeN(socket);
}
LISTBASE_FOREACH_MUTABLE (bNodeSocket *, socket, &ntree->outputs_legacy) {
legacy_socket_interface_free(socket);
MEM_freeN(socket);
}
BLI_listbase_clear(&ntree->inputs_legacy);
BLI_listbase_clear(&ntree->outputs_legacy);
}
static void update_node_location_legacy(bNodeTree &ntree)
{
for (bNode *node : ntree.all_nodes()) {
node->locx_legacy = node->location[0];
node->locy_legacy = node->location[1];
if (const bNode *parent = node->parent) {
node->locx_legacy -= parent->location[0];
node->locy_legacy -= parent->location[1];
}
}
}
/* Some node properties were turned into inputs, so we write the input values back to the
* properties upon write to maintain forward compatibility. */
static void write_compositor_legacy_properties(bNodeTree &node_tree)
{
if (node_tree.type != NTREE_COMPOSIT) {
return;
}
for (bNode *node : node_tree.all_nodes()) {
auto write_input_to_property_bool_char = [&](const char *identifier, char &property) {
const bNodeSocket *input = blender::bke::node_find_socket(*node, SOCK_IN, identifier);
property = input->default_value_typed<bNodeSocketValueBoolean>()->value;
};
auto write_input_to_property_bool_short = [&](const char *identifier, short &property) {
const bNodeSocket *input = blender::bke::node_find_socket(*node, SOCK_IN, identifier);
property = input->default_value_typed<bNodeSocketValueBoolean>()->value;
};
auto write_input_to_property_bool_int16_flag = [&](const char *identifier,
int16_t &property,
const int flag,
const bool negative = false) {
const bNodeSocket *input = blender::bke::node_find_socket(*node, SOCK_IN, identifier);
if (bool(input->default_value_typed<bNodeSocketValueBoolean>()->value) != negative) {
property |= flag;
}
else {
property &= ~flag;
}
};
auto write_input_to_property_int = [&](const char *identifier, int &property) {
const bNodeSocket *input = blender::bke::node_find_socket(*node, SOCK_IN, identifier);
property = input->default_value_typed<bNodeSocketValueInt>()->value;
};
auto write_input_to_property_short = [&](const char *identifier, short &property) {
const bNodeSocket *input = blender::bke::node_find_socket(*node, SOCK_IN, identifier);
property = input->default_value_typed<bNodeSocketValueInt>()->value;
};
auto write_input_to_property_char = [&](const char *identifier, char &property) {
const bNodeSocket *input = blender::bke::node_find_socket(*node, SOCK_IN, identifier);
property = input->default_value_typed<bNodeSocketValueInt>()->value;
};
auto write_input_to_property_int16 = [&](const char *identifier, int16_t &property) {
const bNodeSocket *input = blender::bke::node_find_socket(*node, SOCK_IN, identifier);
property = int16_t(input->default_value_typed<bNodeSocketValueInt>()->value);
};
auto write_input_to_property_float = [&](const char *identifier, float &property) {
const bNodeSocket *input = blender::bke::node_find_socket(*node, SOCK_IN, identifier);
property = input->default_value_typed<bNodeSocketValueFloat>()->value;
};
auto write_input_to_property_float_vector =
[&](const char *identifier, const int index, float &property) {
const bNodeSocket *input = blender::bke::node_find_socket(*node, SOCK_IN, identifier);
property = input->default_value_typed<bNodeSocketValueVector>()->value[index];
};
auto write_input_to_property_float_color =
[&](const char *identifier, const int index, float &property) {
const bNodeSocket *input = blender::bke::node_find_socket(*node, SOCK_IN, identifier);
property = input->default_value_typed<bNodeSocketValueRGBA>()->value[index];
};
if (node->type_legacy == CMP_NODE_GLARE) {
NodeGlare *storage = static_cast<NodeGlare *>(node->storage);
write_input_to_property_bool_char("Diagonal Star", storage->star_45);
}
if (node->type_legacy == CMP_NODE_BOKEHIMAGE) {
NodeBokehImage *storage = static_cast<NodeBokehImage *>(node->storage);
write_input_to_property_int("Flaps", storage->flaps);
write_input_to_property_float("Angle", storage->angle);
write_input_to_property_float("Roundness", storage->rounding);
write_input_to_property_float("Catadioptric Size", storage->catadioptric);
write_input_to_property_float("Color Shift", storage->lensshift);
}
if (node->type_legacy == CMP_NODE_TIME) {
write_input_to_property_int16("Start Frame", node->custom1);
write_input_to_property_int16("End Frame", node->custom2);
}
if (node->type_legacy == CMP_NODE_MASK) {
NodeMask *storage = static_cast<NodeMask *>(node->storage);
write_input_to_property_int("Size X", storage->size_x);
write_input_to_property_int("Size Y", storage->size_y);
write_input_to_property_bool_int16_flag(
"Feather", node->custom1, CMP_NODE_MASK_FLAG_NO_FEATHER, true);
write_input_to_property_bool_int16_flag(
"Motion Blur", node->custom1, CMP_NODE_MASK_FLAG_MOTION_BLUR);
write_input_to_property_int16("Motion Blur Samples", node->custom2);
write_input_to_property_float("Motion Blur Shutter", node->custom3);
}
if (node->type_legacy == CMP_NODE_SWITCH) {
write_input_to_property_bool_int16_flag("Switch", node->custom1, 1 << 0);
}
if (node->type_legacy == CMP_NODE_SPLIT) {
const bNodeSocket *input = blender::bke::node_find_socket(*node, SOCK_IN, "Factor");
node->custom1 = int(input->default_value_typed<bNodeSocketValueFloat>()->value * 100.0f);
}
if (node->type_legacy == CMP_NODE_INVERT) {
write_input_to_property_bool_int16_flag("Invert Color", node->custom1, CMP_CHAN_RGB);
write_input_to_property_bool_int16_flag("Invert Alpha", node->custom1, CMP_CHAN_A);
}
if (node->type_legacy == CMP_NODE_ZCOMBINE) {
write_input_to_property_bool_int16_flag("Use Alpha", node->custom1, 1 << 0);
write_input_to_property_bool_int16_flag("Anti-Alias", node->custom2, 1 << 0, true);
}
if (node->type_legacy == CMP_NODE_TONEMAP) {
NodeTonemap *storage = static_cast<NodeTonemap *>(node->storage);
write_input_to_property_float("Key", storage->key);
write_input_to_property_float("Balance", storage->offset);
write_input_to_property_float("Gamma", storage->gamma);
write_input_to_property_float("Intensity", storage->f);
write_input_to_property_float("Contrast", storage->m);
write_input_to_property_float("Light Adaptation", storage->a);
write_input_to_property_float("Chromatic Adaptation", storage->c);
}
if (node->type_legacy == CMP_NODE_DILATEERODE) {
write_input_to_property_int16("Size", node->custom2);
write_input_to_property_float("Falloff Size", node->custom3);
}
if (node->type_legacy == CMP_NODE_INPAINT) {
write_input_to_property_int16("Size", node->custom2);
}
if (node->type_legacy == CMP_NODE_PIXELATE) {
write_input_to_property_int16("Size", node->custom1);
}
if (node->type_legacy == CMP_NODE_KUWAHARA) {
NodeKuwaharaData *storage = static_cast<NodeKuwaharaData *>(node->storage);
write_input_to_property_bool_char("High Precision", storage->high_precision);
write_input_to_property_int("Uniformity", storage->uniformity);
write_input_to_property_float("Sharpness", storage->sharpness);
write_input_to_property_float("Eccentricity", storage->eccentricity);
}
if (node->type_legacy == CMP_NODE_DESPECKLE) {
write_input_to_property_float("Color Threshold", node->custom3);
write_input_to_property_float("Neighbor Threshold", node->custom4);
}
if (node->type_legacy == CMP_NODE_DENOISE) {
NodeDenoise *storage = static_cast<NodeDenoise *>(node->storage);
write_input_to_property_bool_char("HDR", storage->hdr);
}
if (node->type_legacy == CMP_NODE_ANTIALIASING) {
NodeAntiAliasingData *storage = static_cast<NodeAntiAliasingData *>(node->storage);
write_input_to_property_float("Threshold", storage->threshold);
write_input_to_property_float("Corner Rounding", storage->corner_rounding);
/* Contrast limit was previously divided by 10. */
const bNodeSocket *input = blender::bke::node_find_socket(*node, SOCK_IN, "Contrast Limit");
storage->contrast_limit = input->default_value_typed<bNodeSocketValueFloat>()->value / 10.0f;
}
if (node->type_legacy == CMP_NODE_VECBLUR) {
NodeBlurData *storage = static_cast<NodeBlurData *>(node->storage);
write_input_to_property_short("Samples", storage->samples);
/* Shutter was previously divided by 2. */
const bNodeSocket *input = blender::bke::node_find_socket(*node, SOCK_IN, "Shutter");
storage->fac = input->default_value_typed<bNodeSocketValueFloat>()->value / 2.0f;
}
if (node->type_legacy == CMP_NODE_CHANNEL_MATTE) {
NodeChroma *storage = static_cast<NodeChroma *>(node->storage);
write_input_to_property_float("Minimum", storage->t2);
write_input_to_property_float("Maximum", storage->t1);
}
if (node->type_legacy == CMP_NODE_CHROMA_MATTE) {
NodeChroma *storage = static_cast<NodeChroma *>(node->storage);
write_input_to_property_float("Minimum", storage->t2);
write_input_to_property_float("Maximum", storage->t1);
write_input_to_property_float("Falloff", storage->fstrength);
}
if (node->type_legacy == CMP_NODE_COLOR_MATTE) {
NodeChroma *storage = static_cast<NodeChroma *>(node->storage);
write_input_to_property_float("Hue", storage->t1);
write_input_to_property_float("Saturation", storage->t2);
write_input_to_property_float("Value", storage->t3);
}
if (node->type_legacy == CMP_NODE_DIFF_MATTE) {
NodeChroma *storage = static_cast<NodeChroma *>(node->storage);
write_input_to_property_float("Tolerance", storage->t1);
write_input_to_property_float("Falloff", storage->t2);
}
if (node->type_legacy == CMP_NODE_DIST_MATTE) {
NodeChroma *storage = static_cast<NodeChroma *>(node->storage);
write_input_to_property_float("Tolerance", storage->t1);
write_input_to_property_float("Falloff", storage->t2);
}
if (node->type_legacy == CMP_NODE_LUMA_MATTE) {
NodeChroma *storage = static_cast<NodeChroma *>(node->storage);
write_input_to_property_float("Minimum", storage->t2);
write_input_to_property_float("Maximum", storage->t1);
}
if (node->type_legacy == CMP_NODE_COLOR_SPILL) {
NodeColorspill *storage = static_cast<NodeColorspill *>(node->storage);
write_input_to_property_float("Limit Strength", storage->limscale);
write_input_to_property_bool_short("Use Spill Strength", storage->unspill);
write_input_to_property_float_color("Spill Strength", 0, storage->uspillr);
write_input_to_property_float_color("Spill Strength", 1, storage->uspillg);
write_input_to_property_float_color("Spill Strength", 2, storage->uspillb);
}
if (node->type_legacy == CMP_NODE_KEYINGSCREEN) {
NodeKeyingScreenData *storage = static_cast<NodeKeyingScreenData *>(node->storage);
write_input_to_property_float("Smoothness", storage->smoothness);
}
if (node->type_legacy == CMP_NODE_KEYING) {
NodeKeyingData *storage = static_cast<NodeKeyingData *>(node->storage);
write_input_to_property_int("Preprocess Blur Size", storage->blur_pre);
write_input_to_property_float("Key Balance", storage->screen_balance);
write_input_to_property_int("Edge Search Size", storage->edge_kernel_radius);
write_input_to_property_float("Edge Tolerance", storage->edge_kernel_tolerance);
write_input_to_property_float("Black Level", storage->clip_black);
write_input_to_property_float("White Level", storage->clip_white);
write_input_to_property_int("Postprocess Blur Size", storage->blur_post);
write_input_to_property_int("Postprocess Dilate Size", storage->dilate_distance);
write_input_to_property_int("Postprocess Feather Size", storage->feather_distance);
write_input_to_property_float("Despill Strength", storage->despill_factor);
write_input_to_property_float("Despill Balance", storage->despill_balance);
}
if (node->type_legacy == CMP_NODE_ID_MASK) {
write_input_to_property_short("Index", node->custom1);
write_input_to_property_bool_short("Anti-Alias", node->custom2);
}
if (node->type_legacy == CMP_NODE_STABILIZE2D) {
write_input_to_property_bool_short("Invert", node->custom2);
}
if (node->type_legacy == CMP_NODE_PLANETRACKDEFORM) {
NodePlaneTrackDeformData *storage = static_cast<NodePlaneTrackDeformData *>(node->storage);
write_input_to_property_bool_char("Motion Blur", storage->flag);
write_input_to_property_char("Motion Blur Samples", storage->motion_blur_samples);
write_input_to_property_float("Motion Blur Shutter", storage->motion_blur_shutter);
}
if (node->type_legacy == CMP_NODE_COLORCORRECTION) {
NodeColorCorrection *storage = static_cast<NodeColorCorrection *>(node->storage);
write_input_to_property_float("Master Saturation", storage->master.saturation);
write_input_to_property_float("Master Contrast", storage->master.contrast);
write_input_to_property_float("Master Gamma", storage->master.gamma);
write_input_to_property_float("Master Gain", storage->master.gain);
write_input_to_property_float("Master Lift", storage->master.lift);
write_input_to_property_float("Shadows Saturation", storage->shadows.saturation);
write_input_to_property_float("Shadows Contrast", storage->shadows.contrast);
write_input_to_property_float("Shadows Gamma", storage->shadows.gamma);
write_input_to_property_float("Shadows Gain", storage->shadows.gain);
write_input_to_property_float("Shadows Lift", storage->shadows.lift);
write_input_to_property_float("Midtones Saturation", storage->midtones.saturation);
write_input_to_property_float("Midtones Contrast", storage->midtones.contrast);
write_input_to_property_float("Midtones Gamma", storage->midtones.gamma);
write_input_to_property_float("Midtones Gain", storage->midtones.gain);
write_input_to_property_float("Midtones Lift", storage->midtones.lift);
write_input_to_property_float("Highlights Saturation", storage->highlights.saturation);
write_input_to_property_float("Highlights Contrast", storage->highlights.contrast);
write_input_to_property_float("Highlights Gamma", storage->highlights.gamma);
write_input_to_property_float("Highlights Gain", storage->highlights.gain);
write_input_to_property_float("Highlights Lift", storage->highlights.lift);
write_input_to_property_float("Midtones Start", storage->startmidtones);
write_input_to_property_float("Midtones End", storage->endmidtones);
write_input_to_property_bool_int16_flag("Apply On Red", node->custom1, 1 << 0);
write_input_to_property_bool_int16_flag("Apply On Green", node->custom1, 1 << 1);
write_input_to_property_bool_int16_flag("Apply On Blue", node->custom1, 1 << 2);
}
if (node->type_legacy == CMP_NODE_LENSDIST) {
NodeLensDist *storage = static_cast<NodeLensDist *>(node->storage);
write_input_to_property_bool_short("Jitter", storage->jit);
write_input_to_property_bool_short("Fit", storage->fit);
storage->proj = storage->distortion_type == CMP_NODE_LENS_DISTORTION_HORIZONTAL;
}
if (node->type_legacy == CMP_NODE_MASK_BOX) {
NodeBoxMask *storage = static_cast<NodeBoxMask *>(node->storage);
write_input_to_property_float_vector("Position", 0, storage->x);
write_input_to_property_float_vector("Position", 1, storage->y);
write_input_to_property_float_vector("Size", 0, storage->width);
write_input_to_property_float_vector("Size", 1, storage->height);
write_input_to_property_float("Rotation", storage->rotation);
}
if (node->type_legacy == CMP_NODE_MASK_ELLIPSE) {
NodeEllipseMask *storage = static_cast<NodeEllipseMask *>(node->storage);
write_input_to_property_float_vector("Position", 0, storage->x);
write_input_to_property_float_vector("Position", 1, storage->y);
write_input_to_property_float_vector("Size", 0, storage->width);
write_input_to_property_float_vector("Size", 1, storage->height);
write_input_to_property_float("Rotation", storage->rotation);
}
if (node->type_legacy == CMP_NODE_SUNBEAMS) {
NodeSunBeams *storage = static_cast<NodeSunBeams *>(node->storage);
write_input_to_property_float_vector("Source", 0, storage->source[0]);
write_input_to_property_float_vector("Source", 1, storage->source[1]);
write_input_to_property_float("Length", storage->ray_length);
}
if (node->type_legacy == CMP_NODE_DBLUR) {
NodeDBlurData *storage = static_cast<NodeDBlurData *>(node->storage);
write_input_to_property_short("Samples", storage->iter);
write_input_to_property_float_vector("Center", 0, storage->center_x);
write_input_to_property_float_vector("Center", 1, storage->center_y);
write_input_to_property_float("Translation Amount", storage->distance);
write_input_to_property_float("Translation Direction", storage->angle);
write_input_to_property_float("Rotation", storage->spin);
/* Scale was previously minus 1. */
const bNodeSocket *input = blender::bke::node_find_socket(*node, SOCK_IN, "Scale");
storage->zoom = input->default_value_typed<bNodeSocketValueFloat>()->value - 1.0f;
}
if (node->type_legacy == CMP_NODE_BILATERALBLUR) {
NodeBilateralBlurData *storage = static_cast<NodeBilateralBlurData *>(node->storage);
/* The size input is `ceil(iterations + sigma_space)`. */
const bNodeSocket *size_input = blender::bke::node_find_socket(*node, SOCK_IN, "Size");
storage->iter = size_input->default_value_typed<bNodeSocketValueInt>()->value - 1;
storage->sigma_space = 1.0f;
/* Threshold was previously multiplied by 3. */
const bNodeSocket *threshold_input = blender::bke::node_find_socket(
*node, SOCK_IN, "Threshold");
storage->sigma_color = threshold_input->default_value_typed<bNodeSocketValueFloat>()->value *
3.0f;
}
if (node->type_legacy == CMP_NODE_ALPHAOVER) {
write_input_to_property_bool_short("Straight Alpha", node->custom1);
}
if (node->type_legacy == CMP_NODE_BOKEHBLUR) {
write_input_to_property_bool_int16_flag("Extend Bounds", node->custom1, (1 << 1));
}
if (node->type_legacy == CMP_NODE_CROP) {
write_input_to_property_bool_int16_flag("Alpha Crop", node->custom1, (1 << 0), true);
NodeTwoXYs *storage = static_cast<NodeTwoXYs *>(node->storage);
write_input_to_property_int16("X", storage->x1);
write_input_to_property_int16("Y", storage->y2);
const bNodeSocket *x_input = blender::bke::node_find_socket(*node, SOCK_IN, "X");
const bNodeSocket *width_input = blender::bke::node_find_socket(*node, SOCK_IN, "Width");
storage->x2 = x_input->default_value_typed<bNodeSocketValueInt>()->value +
width_input->default_value_typed<bNodeSocketValueInt>()->value;
const bNodeSocket *y_input = blender::bke::node_find_socket(*node, SOCK_IN, "Y");
const bNodeSocket *height_input = blender::bke::node_find_socket(*node, SOCK_IN, "Height");
storage->y1 = y_input->default_value_typed<bNodeSocketValueInt>()->value +
height_input->default_value_typed<bNodeSocketValueInt>()->value;
}
if (node->type_legacy == CMP_NODE_COLORBALANCE) {
NodeColorBalance *storage = static_cast<NodeColorBalance *>(node->storage);
{
const bNodeSocket *base_input = blender::bke::node_find_socket(
*node, SOCK_IN, "Base Lift");
const bNodeSocket *color_input = blender::bke::node_find_socket(
*node, SOCK_IN, "Color Lift");
const float3 value = base_input->default_value_typed<bNodeSocketValueFloat>()->value +
float3(
color_input->default_value_typed<bNodeSocketValueRGBA>()->value);
copy_v3_v3(storage->lift, value);
}
{
const bNodeSocket *base_input = blender::bke::node_find_socket(
*node, SOCK_IN, "Base Gamma");
const bNodeSocket *color_input = blender::bke::node_find_socket(
*node, SOCK_IN, "Color Gamma");
const float3 value = base_input->default_value_typed<bNodeSocketValueFloat>()->value *
float3(
color_input->default_value_typed<bNodeSocketValueRGBA>()->value);
copy_v3_v3(storage->gamma, value);
}
{
const bNodeSocket *base_input = blender::bke::node_find_socket(
*node, SOCK_IN, "Base Gain");
const bNodeSocket *color_input = blender::bke::node_find_socket(
*node, SOCK_IN, "Color Gain");
const float3 value = base_input->default_value_typed<bNodeSocketValueFloat>()->value *
float3(
color_input->default_value_typed<bNodeSocketValueRGBA>()->value);
copy_v3_v3(storage->gain, value);
}
{
const bNodeSocket *base_input = blender::bke::node_find_socket(
*node, SOCK_IN, "Base Power");
const bNodeSocket *color_input = blender::bke::node_find_socket(
*node, SOCK_IN, "Color Power");
const float3 value = base_input->default_value_typed<bNodeSocketValueFloat>()->value *
float3(
color_input->default_value_typed<bNodeSocketValueRGBA>()->value);
copy_v3_v3(storage->power, value);
}
{
const bNodeSocket *base_input = blender::bke::node_find_socket(
*node, SOCK_IN, "Base Slope");
const bNodeSocket *color_input = blender::bke::node_find_socket(
*node, SOCK_IN, "Color Slope");
const float3 value = base_input->default_value_typed<bNodeSocketValueFloat>()->value *
float3(
color_input->default_value_typed<bNodeSocketValueRGBA>()->value);
copy_v3_v3(storage->slope, value);
}
{
const bNodeSocket *base_input = blender::bke::node_find_socket(
*node, SOCK_IN, "Base Offset");
const bNodeSocket *color_input = blender::bke::node_find_socket(
*node, SOCK_IN, "Color Offset");
storage->offset_basis = base_input->default_value_typed<bNodeSocketValueFloat>()->value;
copy_v3_v3(storage->offset,
color_input->default_value_typed<bNodeSocketValueRGBA>()->value);
}
write_input_to_property_float("Input Temperature", storage->input_temperature);
write_input_to_property_float("Input Tint", storage->input_tint);
write_input_to_property_float("Output Temperature", storage->output_temperature);
write_input_to_property_float("Output Tint", storage->output_tint);
}
}
}
} // namespace forward_compat
Nodes: Panels integration with blend files and UI Part 3/3 of #109135, #110272 Switch to new node group interfaces and deprecate old DNA and API. This completes support for panels in node drawing and in node group interface declarations in particular. The new node group interface DNA and RNA code has been added in parts 1 and 2 (#110885, #110952) but has not be enabled yet. This commit completes the integration by * enabling the new RNA API * using the new API in UI * read/write new interfaces from blend files * add versioning for backward compatibility * add forward-compatible writing code to reconstruct old interfaces All places accessing node group interface declarations should now be using the new API. A runtime cache has been added that allows simple linear access to socket inputs and outputs even when a panel hierarchy is used. Old DNA has been deprecated and should only be accessed for versioning (inputs/outputs renamed to inputs_legacy/outputs_legacy to catch errors). Versioning code ensures both backward and forward compatibility of existing files. The API for old interfaces is removed. The new API is very similar but is defined on the `ntree.interface` instead of the `ntree` directly. Breaking change notifications and detailed instructions for migrating will be added. A python test has been added for the node group API functions. This includes new functionality such as creating panels and moving items between different levels. This patch does not yet contain panel representations in the modifier UI. This has been tested in a separate branch and will be added with a later PR (#108565). Pull Request: https://projects.blender.org/blender/blender/pulls/111348
2023-08-30 12:37:21 +02:00
static void write_node_socket_default_value(BlendWriter *writer, const bNodeSocket *sock)
{
if (sock->default_value == nullptr) {
return;
}
switch (eNodeSocketDatatype(sock->type)) {
case SOCK_FLOAT:
BLO_write_struct(writer, bNodeSocketValueFloat, sock->default_value);
break;
case SOCK_VECTOR:
BLO_write_struct(writer, bNodeSocketValueVector, sock->default_value);
break;
case SOCK_RGBA:
BLO_write_struct(writer, bNodeSocketValueRGBA, sock->default_value);
break;
case SOCK_BOOLEAN:
BLO_write_struct(writer, bNodeSocketValueBoolean, sock->default_value);
break;
case SOCK_INT:
BLO_write_struct(writer, bNodeSocketValueInt, sock->default_value);
break;
case SOCK_STRING:
BLO_write_struct(writer, bNodeSocketValueString, sock->default_value);
break;
case SOCK_OBJECT:
BLO_write_struct(writer, bNodeSocketValueObject, sock->default_value);
break;
case SOCK_IMAGE:
BLO_write_struct(writer, bNodeSocketValueImage, sock->default_value);
break;
case SOCK_COLLECTION:
BLO_write_struct(writer, bNodeSocketValueCollection, sock->default_value);
break;
case SOCK_TEXTURE:
BLO_write_struct(writer, bNodeSocketValueTexture, sock->default_value);
break;
case SOCK_MATERIAL:
BLO_write_struct(writer, bNodeSocketValueMaterial, sock->default_value);
break;
case SOCK_ROTATION:
BLO_write_struct(writer, bNodeSocketValueRotation, sock->default_value);
break;
case SOCK_MENU:
Geometry Nodes: Menu Switch Node This patch adds support for _Menu Switch_ nodes and enum definitions in node trees more generally. The design is based on the outcome of the [2022 Nodes Workshop](https://code.blender.org/2022/11/geometry-nodes-workshop-2022/#menu-switch). The _Menu Switch_ node is an advanced version of the _Switch_ node which has a customizable **menu input socket** instead of a simple boolean. The _items_ of this menu are owned by the node itself. Each item has a name and description and unique identifier that is used internally. A menu _socket_ represents a concrete value out of the list of items. To enable selection of an enum value for unconnected sockets the menu is presented as a dropdown list like built-in enums. When the socket is connected a shared pointer to the enum definition is propagated along links and stored in socket default values. This allows node groups to expose a menu from an internal menu switch as a parameter. The enum definition is a runtime copy of the enum items in DNA that allows sharing. A menu socket can have multiple connections, which can lead to ambiguity. If two or more different menu source nodes are connected to a socket it gets marked as _undefined_. Any connection to an undefined menu socket is invalid as a hint to users that there is a problem. A warning/error is also shown on nodes with undefined menu sockets. At runtime the value of a menu socket is the simple integer identifier. This can also be a field in geometry nodes. The identifier is unique within each enum definition, and it is persistent even when items are added, removed, or changed. Changing the name of an item does not affect the internal identifier, so users can rename enum items without breaking existing input values. This also persists if, for example, a linked node group is temporarily unavailable. Pull Request: https://projects.blender.org/blender/blender/pulls/113445
2024-01-26 12:40:01 +01:00
BLO_write_struct(writer, bNodeSocketValueMenu, sock->default_value);
break;
case SOCK_MATRIX:
/* Matrix sockets currently have no default value. */
break;
case SOCK_CUSTOM:
/* Custom node sockets where default_value is defined use custom properties for storage. */
break;
case SOCK_SHADER:
case SOCK_GEOMETRY:
Geometry Nodes: add Closures and Bundles behind experimental feature flag This implements bundles and closures which are described in more detail in this blog post: https://code.blender.org/2024/11/geometry-nodes-workshop-october-2024/ tl;dr: * Bundles are containers that allow storing multiple socket values in a single value. Each value in the bundle is identified by a name. Bundles can be nested. * Closures are functions that are created with the Closure Zone and can be evaluated with the Evaluate Closure node. To use the patch, the `Bundle and Closure Nodes` experimental feature has to be enabled. This is necessary, because these features are not fully done yet and still need iterations to improve the workflow before they can be officially released. These iterations are easier to do in `main` than in a separate branch though. That's because this patch is quite large and somewhat prone to merge conflicts. Also other work we want to do, depends on this. This adds the following new nodes: * Combine Bundle: can pack multiple values into one. * Separate Bundle: extracts values from a bundle. * Closure Zone: outputs a closure zone for use in the `Evaluate Closure` node. * Evaluate Closure: evaluates the passed in closure. Things that will be added soon after this lands: * Fields in bundles and closures. The way this is done changes with #134811, so I rather implement this once both are in `main`. * UI features for keeping sockets in sync (right now there are warnings only). One bigger issue is the limited support for lazyness. For example, all inputs of a Combine Bundle node will be evaluated, even if they are not all needed. The same is true for all captured values of a closure. This is a deeper limitation that needs to be resolved at some point. This will likely be done after an initial version of this patch is done. Pull Request: https://projects.blender.org/blender/blender/pulls/128340
2025-04-03 15:44:06 +02:00
case SOCK_BUNDLE:
case SOCK_CLOSURE:
BLI_assert_unreachable();
break;
}
}
Nodes: Panels integration with blend files and UI Part 3/3 of #109135, #110272 Switch to new node group interfaces and deprecate old DNA and API. This completes support for panels in node drawing and in node group interface declarations in particular. The new node group interface DNA and RNA code has been added in parts 1 and 2 (#110885, #110952) but has not be enabled yet. This commit completes the integration by * enabling the new RNA API * using the new API in UI * read/write new interfaces from blend files * add versioning for backward compatibility * add forward-compatible writing code to reconstruct old interfaces All places accessing node group interface declarations should now be using the new API. A runtime cache has been added that allows simple linear access to socket inputs and outputs even when a panel hierarchy is used. Old DNA has been deprecated and should only be accessed for versioning (inputs/outputs renamed to inputs_legacy/outputs_legacy to catch errors). Versioning code ensures both backward and forward compatibility of existing files. The API for old interfaces is removed. The new API is very similar but is defined on the `ntree.interface` instead of the `ntree` directly. Breaking change notifications and detailed instructions for migrating will be added. A python test has been added for the node group API functions. This includes new functionality such as creating panels and moving items between different levels. This patch does not yet contain panel representations in the modifier UI. This has been tested in a separate branch and will be added with a later PR (#108565). Pull Request: https://projects.blender.org/blender/blender/pulls/111348
2023-08-30 12:37:21 +02:00
static void write_node_socket(BlendWriter *writer, const bNodeSocket *sock)
{
BLO_write_struct(writer, bNodeSocket, sock);
if (sock->prop) {
IDP_BlendWrite(writer, sock->prop);
}
/* This property should only be used for group node "interface" sockets. */
BLI_assert(sock->default_attribute_name == nullptr);
write_node_socket_default_value(writer, sock);
}
static void node_blend_write_storage(BlendWriter *writer, bNodeTree *ntree, bNode *node)
{
if (!node->storage) {
return;
}
if (node->type_legacy == CMP_NODE_GLARE) {
/* Simple forward compatibility for fix for #50736.
* Not ideal (there is no ideal solution here), but should do for now. */
NodeGlare *ndg = static_cast<NodeGlare *>(node->storage);
/* Not in undo case. */
if (!BLO_write_is_undo(writer)) {
switch (ndg->type) {
case CMP_NODE_GLARE_STREAKS:
ndg->angle = ndg->streaks;
break;
case CMP_NODE_GLARE_SIMPLE_STAR:
ndg->angle = ndg->star_45;
break;
default:
break;
}
}
}
else if (node->type_legacy == GEO_NODE_CAPTURE_ATTRIBUTE) {
auto &storage = *static_cast<NodeGeometryAttributeCapture *>(node->storage);
/* Improve forward compatibility. */
storage.data_type_legacy = CD_PROP_FLOAT;
for (const NodeGeometryAttributeCaptureItem &item :
Span{storage.capture_items, storage.capture_items_num})
{
if (item.identifier == 0) {
/* The sockets of this item have the same identifiers that have been used by older
* Blender versions before the node supported capturing multiple attributes. */
storage.data_type_legacy = item.data_type;
break;
}
}
}
const bNodeType *ntype = node->typeinfo;
if (!ntype->storagename.empty()) {
BLO_write_struct_by_name(writer, ntype->storagename.c_str(), node->storage);
}
if (ntype->blend_write_storage_content) {
ntype->blend_write_storage_content(*ntree, *node, *writer);
return;
}
/* These nodes don't use #blend_write_storage_content because their corresponding blend-read
* can't use it since they were introduced before there were node idnames. */
if (ELEM(node->type_legacy,
SH_NODE_CURVE_VEC,
SH_NODE_CURVE_RGB,
SH_NODE_CURVE_FLOAT,
CMP_NODE_TIME,
CMP_NODE_CURVE_VEC,
CMP_NODE_CURVE_RGB,
CMP_NODE_HUECORRECT,
TEX_NODE_CURVE_RGB,
TEX_NODE_CURVE_TIME))
{
BKE_curvemapping_curves_blend_write(writer, static_cast<const CurveMapping *>(node->storage));
}
else if (node->type_legacy == SH_NODE_SCRIPT) {
NodeShaderScript *nss = static_cast<NodeShaderScript *>(node->storage);
if (nss->bytecode) {
BLO_write_string(writer, nss->bytecode);
}
}
else if (node->type_legacy == CMP_NODE_MOVIEDISTORTION) {
/* pass */
}
else if (ELEM(node->type_legacy, CMP_NODE_CRYPTOMATTE, CMP_NODE_CRYPTOMATTE_LEGACY)) {
NodeCryptomatte *nc = static_cast<NodeCryptomatte *>(node->storage);
BLO_write_string(writer, nc->matte_id);
LISTBASE_FOREACH (CryptomatteEntry *, entry, &nc->entries) {
BLO_write_struct(writer, CryptomatteEntry, entry);
}
}
}
void node_tree_blend_write(BlendWriter *writer, bNodeTree *ntree)
{
BKE_id_blend_write(writer, &ntree->id);
BLO_write_string(writer, ntree->description);
if (!BLO_write_is_undo(writer)) {
forward_compat::update_node_location_legacy(*ntree);
forward_compat::write_compositor_legacy_properties(*ntree);
}
for (bNode *node : ntree->all_nodes()) {
if (ntree->type == NTREE_SHADER && node->type_legacy == SH_NODE_BSDF_HAIR_PRINCIPLED) {
Cycles: new Principled Hair BSDF variant with elliptical cross-section support Implements the paper [A Microfacet-based Hair Scattering Model](https://onlinelibrary.wiley.com/doi/full/10.1111/cgf.14588) by Weizhen Huang, Matthias B. Hullin and Johannes Hanika. ### Features: - This is a far-field model, as opposed to the previous near-field Principled Hair BSDF model. The hair is expected to be less noisy, but lower roughness values takes longer to render due to numerical integration along the hair width. The hair also appears to be flat when viewed up-close. - The longitudinal width of the scattering lobe differs along the azimuth, providing a higher contrast compared to the evenly spread scattering in the near-field Principled Hair BSDF model. For a more detailed comparison, please refer to the original paper. - Supports elliptical cross-sections, adding more realism as human hairs are usually elliptical. The orientation of the cross-section is aligned with the curve normal, which can be adjusted using geometry nodes. Default is minimal twist. During sampling, light rays that hit outside the hair width will continue propogating as if the material is transparent. - There is non-physical modulation factors for the first three lobes (Reflection, Transmission, Secondary Reflection). ### Missing: - A good default for cross-section orientation. There was an attempt (9039f76928) to default the orientation to align with the curve normal in the mathematical sense, but the stability (when animated) is unclear and it would be a hassle to generalise to all curve types. After the model is in main, we could experiment with the geometry nodes team to see what works the best as a default. Co-authored-by: Lukas Stockner <lukas.stockner@freenet.de> Pull Request: https://projects.blender.org/blender/blender/pulls/105600
2023-08-18 12:46:13 +02:00
/* For Principeld Hair BSDF, also write to `node->custom1` for forward compatibility, because
* prior to 4.0 `node->custom1` was used for color parametrization instead of
* `node->storage->parametrization`. */
NodeShaderHairPrincipled *data = static_cast<NodeShaderHairPrincipled *>(node->storage);
node->custom1 = data->parametrization;
}
BLO_write_struct(writer, bNode, node);
if (node->prop) {
IDP_BlendWrite(writer, node->prop);
}
LISTBASE_FOREACH (bNodeSocket *, sock, &node->inputs) {
write_node_socket(writer, sock);
}
LISTBASE_FOREACH (bNodeSocket *, sock, &node->outputs) {
write_node_socket(writer, sock);
}
Nodes: Panels integration with blend files and UI Part 3/3 of #109135, #110272 Switch to new node group interfaces and deprecate old DNA and API. This completes support for panels in node drawing and in node group interface declarations in particular. The new node group interface DNA and RNA code has been added in parts 1 and 2 (#110885, #110952) but has not be enabled yet. This commit completes the integration by * enabling the new RNA API * using the new API in UI * read/write new interfaces from blend files * add versioning for backward compatibility * add forward-compatible writing code to reconstruct old interfaces All places accessing node group interface declarations should now be using the new API. A runtime cache has been added that allows simple linear access to socket inputs and outputs even when a panel hierarchy is used. Old DNA has been deprecated and should only be accessed for versioning (inputs/outputs renamed to inputs_legacy/outputs_legacy to catch errors). Versioning code ensures both backward and forward compatibility of existing files. The API for old interfaces is removed. The new API is very similar but is defined on the `ntree.interface` instead of the `ntree` directly. Breaking change notifications and detailed instructions for migrating will be added. A python test has been added for the node group API functions. This includes new functionality such as creating panels and moving items between different levels. This patch does not yet contain panel representations in the modifier UI. This has been tested in a separate branch and will be added with a later PR (#108565). Pull Request: https://projects.blender.org/blender/blender/pulls/111348
2023-08-30 12:37:21 +02:00
BLO_write_struct_array(
writer, bNodePanelState, node->num_panel_states, node->panel_states_array);
if (node->storage) {
node_blend_write_storage(writer, ntree, node);
}
if (node->type_legacy == CMP_NODE_OUTPUT_FILE) {
/* Inputs have their own storage data. */
NodeImageMultiFile *nimf = (NodeImageMultiFile *)node->storage;
BKE_image_format_blend_write(writer, &nimf->format);
LISTBASE_FOREACH (bNodeSocket *, sock, &node->inputs) {
NodeImageMultiFileSocket *sockdata = static_cast<NodeImageMultiFileSocket *>(
sock->storage);
BLO_write_struct(writer, NodeImageMultiFileSocket, sockdata);
BKE_image_format_blend_write(writer, &sockdata->format);
}
}
if (ELEM(node->type_legacy, CMP_NODE_IMAGE, CMP_NODE_R_LAYERS)) {
/* Write extra socket info. */
LISTBASE_FOREACH (bNodeSocket *, sock, &node->outputs) {
BLO_write_struct(writer, NodeImageLayer, sock->storage);
}
}
}
LISTBASE_FOREACH (bNodeLink *, link, &ntree->links) {
BLO_write_struct(writer, bNodeLink, link);
}
Nodes: Panels integration with blend files and UI Part 3/3 of #109135, #110272 Switch to new node group interfaces and deprecate old DNA and API. This completes support for panels in node drawing and in node group interface declarations in particular. The new node group interface DNA and RNA code has been added in parts 1 and 2 (#110885, #110952) but has not be enabled yet. This commit completes the integration by * enabling the new RNA API * using the new API in UI * read/write new interfaces from blend files * add versioning for backward compatibility * add forward-compatible writing code to reconstruct old interfaces All places accessing node group interface declarations should now be using the new API. A runtime cache has been added that allows simple linear access to socket inputs and outputs even when a panel hierarchy is used. Old DNA has been deprecated and should only be accessed for versioning (inputs/outputs renamed to inputs_legacy/outputs_legacy to catch errors). Versioning code ensures both backward and forward compatibility of existing files. The API for old interfaces is removed. The new API is very similar but is defined on the `ntree.interface` instead of the `ntree` directly. Breaking change notifications and detailed instructions for migrating will be added. A python test has been added for the node group API functions. This includes new functionality such as creating panels and moving items between different levels. This patch does not yet contain panel representations in the modifier UI. This has been tested in a separate branch and will be added with a later PR (#108565). Pull Request: https://projects.blender.org/blender/blender/pulls/111348
2023-08-30 12:37:21 +02:00
ntree->tree_interface.write(writer);
if (!BLO_write_is_undo(writer)) {
forward_compat::write_legacy_sockets(writer, ntree);
}
BLO_write_struct(writer, GeometryNodeAssetTraits, ntree->geometry_node_asset_traits);
Nodes: add nested node ids and use them for simulation state The simulation state used by simulation nodes is owned by the modifier. Since a geometry nodes setup can contain an arbitrary number of simulations, the modifier has a mapping from `SimulationZoneID` to `SimulationZoneState`. This patch changes what is used as `SimulationZoneID`. Previously, the `SimulationZoneID` contained a list of `bNode::identifier` that described the path from the root node tree to the simulation output node. This works ok in many cases, but also has a significant problem: The `SimulationZoneID` changes when moving the simulation zone into or out of a node group. This implies that any of these operations loses the mapping from zone to simulation state, invalidating the cache or even baked data. The goal of this patch is to introduce a single-integer ID that identifies a (nested) simulation zone and is stable even when grouping and un-grouping. The ID should be stable even if the node group containing the (nested) simulation zone is in a separate linked .blend file and that linked file is changed. In the future, the same kind of ID can be used to store e.g. checkpoint/baked/frozen data in the modifier. To achieve the described goal, node trees can now store an arbitrary number of nested node references (an array of `bNestedNodeRef`). Each nested node reference has an ID that is unique within the current node tree. The node tree does not store the entire path to the nested node. Instead it only know which group node the nested node is in, and what the nested node ID of the node is within that group. Grouping and un-grouping operations have to update the nested node references to keep the IDs stable. Importantly though, these operations only have to care about the two node groups that are affected. IDs in higher level node groups remain unchanged by design. A consequence of this design is that every `bNodeTree` now has a `bNestedNodeRef` for every (nested) simulation zone. Two instances of the same simulation zone (because a node group is reused) are referenced by two separate `bNestedNodeRef`. This is important to keep in mind, because it also means that this solution doesn't scale well if we wanted to use it to keep stable references to *all* nested nodes. I can't think of a solution that fulfills the described requirements but scales better with more nodes. For that reason, this solution should only be used when we want to store data for each referenced nested node at the top level (like we do for simulations). This is not a replacement for `ViewerPath` which can store a path to data in a node tree without changing the node tree. Also `ViewerPath` can contain information like the loop iteration that should be viewed (#109164). `bNestedNodeRef` can't differentiate between different iterations of a loop. This also means that simulations can't be used inside of a loop (loops inside of a simulation work fine though). When baking, the new stable ID is now written to disk, which means that baked data is not invalidated by grouping/un-grouping operations. Backward compatibility for baked data is provided, but only works as long as the simulation zone has not been moved to a different node group yet. Forward compatibility for the baked data is not provided (so older versions can't load the data baked with a newer version of Blender). Pull Request: https://projects.blender.org/blender/blender/pulls/109444
2023-07-01 11:54:32 +02:00
BLO_write_struct_array(
writer, bNestedNodeRef, ntree->nested_node_refs_num, ntree->nested_node_refs);
BKE_previewimg_blend_write(writer, ntree->preview);
}
static void ntree_blend_write(BlendWriter *writer, ID *id, const void *id_address)
{
bNodeTree *ntree = reinterpret_cast<bNodeTree *>(id);
/* Clean up, important in undo case to reduce false detection of changed datablocks. */
ntree->typeinfo = nullptr;
ntree->runtime->execdata = nullptr;
Nodes: Panels integration with blend files and UI Part 3/3 of #109135, #110272 Switch to new node group interfaces and deprecate old DNA and API. This completes support for panels in node drawing and in node group interface declarations in particular. The new node group interface DNA and RNA code has been added in parts 1 and 2 (#110885, #110952) but has not be enabled yet. This commit completes the integration by * enabling the new RNA API * using the new API in UI * read/write new interfaces from blend files * add versioning for backward compatibility * add forward-compatible writing code to reconstruct old interfaces All places accessing node group interface declarations should now be using the new API. A runtime cache has been added that allows simple linear access to socket inputs and outputs even when a panel hierarchy is used. Old DNA has been deprecated and should only be accessed for versioning (inputs/outputs renamed to inputs_legacy/outputs_legacy to catch errors). Versioning code ensures both backward and forward compatibility of existing files. The API for old interfaces is removed. The new API is very similar but is defined on the `ntree.interface` instead of the `ntree` directly. Breaking change notifications and detailed instructions for migrating will be added. A python test has been added for the node group API functions. This includes new functionality such as creating panels and moving items between different levels. This patch does not yet contain panel representations in the modifier UI. This has been tested in a separate branch and will be added with a later PR (#108565). Pull Request: https://projects.blender.org/blender/blender/pulls/111348
2023-08-30 12:37:21 +02:00
if (!BLO_write_is_undo(writer)) {
/* Generate legacy inputs/outputs socket ListBase for forward compatibility.
* NOTE: this has to happen before writing the ntree struct itself so that the ListBase
Nodes: Panels integration with blend files and UI Part 3/3 of #109135, #110272 Switch to new node group interfaces and deprecate old DNA and API. This completes support for panels in node drawing and in node group interface declarations in particular. The new node group interface DNA and RNA code has been added in parts 1 and 2 (#110885, #110952) but has not be enabled yet. This commit completes the integration by * enabling the new RNA API * using the new API in UI * read/write new interfaces from blend files * add versioning for backward compatibility * add forward-compatible writing code to reconstruct old interfaces All places accessing node group interface declarations should now be using the new API. A runtime cache has been added that allows simple linear access to socket inputs and outputs even when a panel hierarchy is used. Old DNA has been deprecated and should only be accessed for versioning (inputs/outputs renamed to inputs_legacy/outputs_legacy to catch errors). Versioning code ensures both backward and forward compatibility of existing files. The API for old interfaces is removed. The new API is very similar but is defined on the `ntree.interface` instead of the `ntree` directly. Breaking change notifications and detailed instructions for migrating will be added. A python test has been added for the node group API functions. This includes new functionality such as creating panels and moving items between different levels. This patch does not yet contain panel representations in the modifier UI. This has been tested in a separate branch and will be added with a later PR (#108565). Pull Request: https://projects.blender.org/blender/blender/pulls/111348
2023-08-30 12:37:21 +02:00
* first/last pointers are valid. */
forward_compat::construct_interface_as_legacy_sockets(ntree);
Nodes: Panels integration with blend files and UI Part 3/3 of #109135, #110272 Switch to new node group interfaces and deprecate old DNA and API. This completes support for panels in node drawing and in node group interface declarations in particular. The new node group interface DNA and RNA code has been added in parts 1 and 2 (#110885, #110952) but has not be enabled yet. This commit completes the integration by * enabling the new RNA API * using the new API in UI * read/write new interfaces from blend files * add versioning for backward compatibility * add forward-compatible writing code to reconstruct old interfaces All places accessing node group interface declarations should now be using the new API. A runtime cache has been added that allows simple linear access to socket inputs and outputs even when a panel hierarchy is used. Old DNA has been deprecated and should only be accessed for versioning (inputs/outputs renamed to inputs_legacy/outputs_legacy to catch errors). Versioning code ensures both backward and forward compatibility of existing files. The API for old interfaces is removed. The new API is very similar but is defined on the `ntree.interface` instead of the `ntree` directly. Breaking change notifications and detailed instructions for migrating will be added. A python test has been added for the node group API functions. This includes new functionality such as creating panels and moving items between different levels. This patch does not yet contain panel representations in the modifier UI. This has been tested in a separate branch and will be added with a later PR (#108565). Pull Request: https://projects.blender.org/blender/blender/pulls/111348
2023-08-30 12:37:21 +02:00
}
BLO_write_id_struct(writer, bNodeTree, id_address, &ntree->id);
node_tree_blend_write(writer, ntree);
Nodes: Panels integration with blend files and UI Part 3/3 of #109135, #110272 Switch to new node group interfaces and deprecate old DNA and API. This completes support for panels in node drawing and in node group interface declarations in particular. The new node group interface DNA and RNA code has been added in parts 1 and 2 (#110885, #110952) but has not be enabled yet. This commit completes the integration by * enabling the new RNA API * using the new API in UI * read/write new interfaces from blend files * add versioning for backward compatibility * add forward-compatible writing code to reconstruct old interfaces All places accessing node group interface declarations should now be using the new API. A runtime cache has been added that allows simple linear access to socket inputs and outputs even when a panel hierarchy is used. Old DNA has been deprecated and should only be accessed for versioning (inputs/outputs renamed to inputs_legacy/outputs_legacy to catch errors). Versioning code ensures both backward and forward compatibility of existing files. The API for old interfaces is removed. The new API is very similar but is defined on the `ntree.interface` instead of the `ntree` directly. Breaking change notifications and detailed instructions for migrating will be added. A python test has been added for the node group API functions. This includes new functionality such as creating panels and moving items between different levels. This patch does not yet contain panel representations in the modifier UI. This has been tested in a separate branch and will be added with a later PR (#108565). Pull Request: https://projects.blender.org/blender/blender/pulls/111348
2023-08-30 12:37:21 +02:00
if (!BLO_write_is_undo(writer)) {
forward_compat::cleanup_legacy_sockets(ntree);
Nodes: Panels integration with blend files and UI Part 3/3 of #109135, #110272 Switch to new node group interfaces and deprecate old DNA and API. This completes support for panels in node drawing and in node group interface declarations in particular. The new node group interface DNA and RNA code has been added in parts 1 and 2 (#110885, #110952) but has not be enabled yet. This commit completes the integration by * enabling the new RNA API * using the new API in UI * read/write new interfaces from blend files * add versioning for backward compatibility * add forward-compatible writing code to reconstruct old interfaces All places accessing node group interface declarations should now be using the new API. A runtime cache has been added that allows simple linear access to socket inputs and outputs even when a panel hierarchy is used. Old DNA has been deprecated and should only be accessed for versioning (inputs/outputs renamed to inputs_legacy/outputs_legacy to catch errors). Versioning code ensures both backward and forward compatibility of existing files. The API for old interfaces is removed. The new API is very similar but is defined on the `ntree.interface` instead of the `ntree` directly. Breaking change notifications and detailed instructions for migrating will be added. A python test has been added for the node group API functions. This includes new functionality such as creating panels and moving items between different levels. This patch does not yet contain panel representations in the modifier UI. This has been tested in a separate branch and will be added with a later PR (#108565). Pull Request: https://projects.blender.org/blender/blender/pulls/111348
2023-08-30 12:37:21 +02:00
}
}
/**
* Sockets with default_value data must be known built-in types, otherwise reading and writing data
* correctly cannot be guaranteed. Discard any socket with default_value data that has an unknown
* type.
*/
static bool is_node_socket_supported(const bNodeSocket *sock)
{
switch (eNodeSocketDatatype(sock->type)) {
case SOCK_FLOAT:
case SOCK_VECTOR:
case SOCK_RGBA:
case SOCK_BOOLEAN:
case SOCK_INT:
case SOCK_STRING:
case SOCK_CUSTOM:
case SOCK_SHADER:
case SOCK_GEOMETRY:
case SOCK_OBJECT:
case SOCK_IMAGE:
case SOCK_COLLECTION:
case SOCK_TEXTURE:
case SOCK_MATERIAL:
case SOCK_ROTATION:
Geometry Nodes: Menu Switch Node This patch adds support for _Menu Switch_ nodes and enum definitions in node trees more generally. The design is based on the outcome of the [2022 Nodes Workshop](https://code.blender.org/2022/11/geometry-nodes-workshop-2022/#menu-switch). The _Menu Switch_ node is an advanced version of the _Switch_ node which has a customizable **menu input socket** instead of a simple boolean. The _items_ of this menu are owned by the node itself. Each item has a name and description and unique identifier that is used internally. A menu _socket_ represents a concrete value out of the list of items. To enable selection of an enum value for unconnected sockets the menu is presented as a dropdown list like built-in enums. When the socket is connected a shared pointer to the enum definition is propagated along links and stored in socket default values. This allows node groups to expose a menu from an internal menu switch as a parameter. The enum definition is a runtime copy of the enum items in DNA that allows sharing. A menu socket can have multiple connections, which can lead to ambiguity. If two or more different menu source nodes are connected to a socket it gets marked as _undefined_. Any connection to an undefined menu socket is invalid as a hint to users that there is a problem. A warning/error is also shown on nodes with undefined menu sockets. At runtime the value of a menu socket is the simple integer identifier. This can also be a field in geometry nodes. The identifier is unique within each enum definition, and it is persistent even when items are added, removed, or changed. Changing the name of an item does not affect the internal identifier, so users can rename enum items without breaking existing input values. This also persists if, for example, a linked node group is temporarily unavailable. Pull Request: https://projects.blender.org/blender/blender/pulls/113445
2024-01-26 12:40:01 +01:00
case SOCK_MENU:
case SOCK_MATRIX:
Geometry Nodes: add Closures and Bundles behind experimental feature flag This implements bundles and closures which are described in more detail in this blog post: https://code.blender.org/2024/11/geometry-nodes-workshop-october-2024/ tl;dr: * Bundles are containers that allow storing multiple socket values in a single value. Each value in the bundle is identified by a name. Bundles can be nested. * Closures are functions that are created with the Closure Zone and can be evaluated with the Evaluate Closure node. To use the patch, the `Bundle and Closure Nodes` experimental feature has to be enabled. This is necessary, because these features are not fully done yet and still need iterations to improve the workflow before they can be officially released. These iterations are easier to do in `main` than in a separate branch though. That's because this patch is quite large and somewhat prone to merge conflicts. Also other work we want to do, depends on this. This adds the following new nodes: * Combine Bundle: can pack multiple values into one. * Separate Bundle: extracts values from a bundle. * Closure Zone: outputs a closure zone for use in the `Evaluate Closure` node. * Evaluate Closure: evaluates the passed in closure. Things that will be added soon after this lands: * Fields in bundles and closures. The way this is done changes with #134811, so I rather implement this once both are in `main`. * UI features for keeping sockets in sync (right now there are warnings only). One bigger issue is the limited support for lazyness. For example, all inputs of a Combine Bundle node will be evaluated, even if they are not all needed. The same is true for all captured values of a closure. This is a deeper limitation that needs to be resolved at some point. This will likely be done after an initial version of this patch is done. Pull Request: https://projects.blender.org/blender/blender/pulls/128340
2025-04-03 15:44:06 +02:00
case SOCK_BUNDLE:
case SOCK_CLOSURE:
return true;
}
return false;
}
namespace versioning_internal {
/* Specific code required to properly handle older blend-files (pre-2.83), where some node data
* (like the sockets default values) were written as raw bytes buffer, without any DNA type
* information. */
/* Node socket default values were historically written and read as raw bytes buffers, without any
* DNA typing information.
*
* The writing code was fixed in commit `50d5050e9c`, which is included in the 2.83 release.
* However the matching reading code was only fixed in the 4.5 release.
*
* So currently, reading code assumes that any blend-file >= 3.0 has correct DNA info for these
* default values, and it keeps previous 'raw buffer' reading code for older ones.
*
* This means that special care must be taken when the various DNA types used for these default
* values are modified, as a 'manual' version of DNA internal versioning must be performed on data
* from older blend-files (see also #direct_link_node_socket_default_value).
*/
constexpr int MIN_BLENDFILE_VERSION_FOR_MODERN_NODE_SOCKET_DEFAULT_VALUE_READING = 300;
/* The `_404` structs below are copies of DNA structs as they were in Blender 4.4 and before. Their
* data layout should never have to be modified in any way, as it matches the expected data layout
* in the raw bytes buffers read from older blend-files.
*
* NOTE: There is _no_ need to protect DNA structs definition in any way to ensure forward
* compatibility, for the following reasons:
* - The DNA struct info _is_ properly written in blend-files since 2.83.
* - When there is DNA info for a #BHead in the blend-file, even if that #BHead is ultimately
* 'read'/used as raw bytes buffer through a call to `BLO_read_data_address`, the actual
* reading of that #BHead from the blend-file will have already gone through the lower-level
* 'DNA versioning' process, which means that DNA struct changes (like adding new properties,
* increasing an array size, etc.) will be handled properly.
* - Blender versions prior to 3.6 will not be able to load any 4.0+ blend-files without
* immediate crash, so trying to preserve forward compatibility for versions older than
* 2.83 would be totally pointless.
*/
typedef struct bNodeSocketValueInt_404 {
/** RNA subtype. */
int subtype;
int value;
int min, max;
} bNodeSocketValueInt_404;
typedef struct bNodeSocketValueFloat_404 {
/** RNA subtype. */
int subtype;
float value;
float min, max;
} bNodeSocketValueFloat_404;
typedef struct bNodeSocketValueBoolean_404 {
char value;
} bNodeSocketValueBoolean_404;
typedef struct bNodeSocketValueVector_404 {
/** RNA subtype. */
int subtype;
float value[3];
float min, max;
} bNodeSocketValueVector_404;
typedef struct bNodeSocketValueRotation_404 {
float value_euler[3];
} bNodeSocketValueRotation_404;
typedef struct bNodeSocketValueRGBA_404 {
float value[4];
} bNodeSocketValueRGBA_404;
typedef struct bNodeSocketValueString_404 {
int subtype;
char _pad[4];
char value[/*FILE_MAX*/ 1024];
} bNodeSocketValueString_404;
typedef struct bNodeSocketValueObject_404 {
Object *value;
} bNodeSocketValueObject_404;
typedef struct bNodeSocketValueImage_404 {
Image *value;
} bNodeSocketValueImage_404;
typedef struct bNodeSocketValueCollection_404 {
Collection *value;
} bNodeSocketValueCollection_404;
typedef struct bNodeSocketValueTexture_404 {
Tex *value;
} bNodeSocketValueTexture_404;
typedef struct bNodeSocketValueMaterial_404 {
Material *value;
} bNodeSocketValueMaterial_404;
typedef struct bNodeSocketValueMenu_404 {
/* Default input enum identifier. */
int value;
/* #NodeSocketValueMenuRuntimeFlag */
int runtime_flag;
/* Immutable runtime enum definition. */
const RuntimeNodeEnumItemsHandle *enum_items;
} bNodeSocketValueMenu_404;
/* Generic code handling the conversion between a legacy (pre-2.83) socket data, and its current
* data. Currently used for `bNodeSocket.default_value`. */
template<typename T, typename T_404>
static void direct_link_node_socket_legacy_data_version_do(
void **dest_data, void **raw_data, blender::FunctionRef<void(T &dest, T_404 &source)> copy_fn)
{
/* Cannot check for equality because of potential alignment offset. */
BLI_assert(MEM_allocN_len(*raw_data) >= sizeof(T_404));
T_404 *orig_data = static_cast<T_404 *>(*raw_data);
*raw_data = nullptr;
T *final_data = MEM_callocN<T>(__func__);
/* Could use `memcpy` here, since we also require historic members of these DNA structs to
* never be moved or re-ordered. But better be verbose and explicit here. */
copy_fn(*final_data, *orig_data);
*dest_data = final_data;
MEM_freeN(orig_data);
}
} // namespace versioning_internal
static void direct_link_node_socket_default_value(BlendDataReader *reader, bNodeSocket *sock)
{
if (sock->default_value == nullptr) {
return;
}
if (BLO_read_fileversion_get(reader) >=
versioning_internal::MIN_BLENDFILE_VERSION_FOR_MODERN_NODE_SOCKET_DEFAULT_VALUE_READING)
{
/* Modern, standard DNA-typed reading of sockets default values. */
switch (eNodeSocketDatatype(sock->type)) {
case SOCK_FLOAT:
BLO_read_struct(reader, bNodeSocketValueFloat, &sock->default_value);
break;
case SOCK_VECTOR:
BLO_read_struct(reader, bNodeSocketValueVector, &sock->default_value);
break;
case SOCK_RGBA:
BLO_read_struct(reader, bNodeSocketValueRGBA, &sock->default_value);
break;
case SOCK_BOOLEAN:
BLO_read_struct(reader, bNodeSocketValueBoolean, &sock->default_value);
break;
case SOCK_INT:
BLO_read_struct(reader, bNodeSocketValueInt, &sock->default_value);
break;
case SOCK_STRING:
BLO_read_struct(reader, bNodeSocketValueString, &sock->default_value);
break;
case SOCK_OBJECT:
BLO_read_struct(reader, bNodeSocketValueObject, &sock->default_value);
break;
case SOCK_IMAGE:
BLO_read_struct(reader, bNodeSocketValueImage, &sock->default_value);
break;
case SOCK_COLLECTION:
BLO_read_struct(reader, bNodeSocketValueCollection, &sock->default_value);
break;
case SOCK_TEXTURE:
BLO_read_struct(reader, bNodeSocketValueTexture, &sock->default_value);
break;
case SOCK_MATERIAL:
BLO_read_struct(reader, bNodeSocketValueMaterial, &sock->default_value);
break;
case SOCK_ROTATION:
BLO_read_struct(reader, bNodeSocketValueRotation, &sock->default_value);
break;
case SOCK_MENU:
BLO_read_struct(reader, bNodeSocketValueMenu, &sock->default_value);
break;
case SOCK_MATRIX:
/* Matrix sockets currently have no default value. */
case SOCK_CUSTOM:
/* Custom node sockets where default_value is defined use custom properties for storage. */
case SOCK_SHADER:
case SOCK_GEOMETRY:
case SOCK_BUNDLE:
case SOCK_CLOSURE:
BLI_assert_unreachable();
break;
}
}
else {
/* Legacy-compatible, raw-buffer-based reading of sockets default values. */
void *temp_data = sock->default_value;
BLO_read_data_address(reader, &temp_data);
if (!temp_data) {
sock->default_value = nullptr;
return;
}
switch (eNodeSocketDatatype(sock->type)) {
case SOCK_FLOAT:
versioning_internal::direct_link_node_socket_legacy_data_version_do<
bNodeSocketValueFloat,
versioning_internal::bNodeSocketValueFloat_404>(
&sock->default_value,
&temp_data,
[](bNodeSocketValueFloat &dest, versioning_internal::bNodeSocketValueFloat_404 &src) {
dest.subtype = src.subtype;
dest.value = src.value;
dest.min = src.min;
dest.max = src.max;
});
break;
case SOCK_VECTOR:
versioning_internal::direct_link_node_socket_legacy_data_version_do<
bNodeSocketValueVector,
versioning_internal::bNodeSocketValueVector_404>(
&sock->default_value,
&temp_data,
[](bNodeSocketValueVector &dest,
versioning_internal::bNodeSocketValueVector_404 &src) {
dest.subtype = src.subtype;
copy_v3_v3(dest.value, src.value);
dest.min = src.min;
dest.max = src.max;
});
break;
case SOCK_RGBA:
versioning_internal::direct_link_node_socket_legacy_data_version_do<
bNodeSocketValueRGBA,
versioning_internal::bNodeSocketValueRGBA_404>(
&sock->default_value,
&temp_data,
[](bNodeSocketValueRGBA &dest, versioning_internal::bNodeSocketValueRGBA_404 &src) {
copy_v4_v4(dest.value, src.value);
});
break;
case SOCK_BOOLEAN:
versioning_internal::direct_link_node_socket_legacy_data_version_do<
bNodeSocketValueBoolean,
versioning_internal::bNodeSocketValueBoolean_404>(
&sock->default_value,
&temp_data,
[](bNodeSocketValueBoolean &dest,
versioning_internal::bNodeSocketValueBoolean_404 &src) { dest.value = src.value; });
break;
case SOCK_INT:
versioning_internal::direct_link_node_socket_legacy_data_version_do<
bNodeSocketValueInt,
versioning_internal::bNodeSocketValueInt_404>(
&sock->default_value,
&temp_data,
[](bNodeSocketValueInt &dest, versioning_internal::bNodeSocketValueInt_404 &src) {
dest.subtype = src.subtype;
dest.value = src.value;
dest.min = src.min;
dest.max = src.max;
});
break;
case SOCK_STRING:
versioning_internal::direct_link_node_socket_legacy_data_version_do<
bNodeSocketValueString,
versioning_internal::bNodeSocketValueString_404>(
&sock->default_value,
&temp_data,
[](bNodeSocketValueString &dest,
versioning_internal::bNodeSocketValueString_404 &src) {
dest.subtype = src.subtype;
STRNCPY(dest.value, src.value);
});
break;
case SOCK_OBJECT:
versioning_internal::direct_link_node_socket_legacy_data_version_do<
bNodeSocketValueObject,
versioning_internal::bNodeSocketValueObject_404>(
&sock->default_value,
&temp_data,
[](bNodeSocketValueObject &dest,
versioning_internal::bNodeSocketValueObject_404 &src) { dest.value = src.value; });
break;
case SOCK_IMAGE:
versioning_internal::direct_link_node_socket_legacy_data_version_do<
bNodeSocketValueImage,
versioning_internal::bNodeSocketValueImage_404>(
&sock->default_value,
&temp_data,
[](bNodeSocketValueImage &dest, versioning_internal::bNodeSocketValueImage_404 &src) {
dest.value = src.value;
});
break;
case SOCK_COLLECTION:
versioning_internal::direct_link_node_socket_legacy_data_version_do<
bNodeSocketValueCollection,
versioning_internal::bNodeSocketValueCollection_404>(
&sock->default_value,
&temp_data,
[](bNodeSocketValueCollection &dest,
versioning_internal::bNodeSocketValueCollection_404 &src) {
dest.value = src.value;
});
break;
case SOCK_TEXTURE:
versioning_internal::direct_link_node_socket_legacy_data_version_do<
bNodeSocketValueTexture,
versioning_internal::bNodeSocketValueTexture_404>(
&sock->default_value,
&temp_data,
[](bNodeSocketValueTexture &dest,
versioning_internal::bNodeSocketValueTexture_404 &src) { dest.value = src.value; });
break;
case SOCK_MATERIAL:
versioning_internal::direct_link_node_socket_legacy_data_version_do<
bNodeSocketValueMaterial,
versioning_internal::bNodeSocketValueMaterial_404>(
&sock->default_value,
&temp_data,
[](bNodeSocketValueMaterial &dest,
versioning_internal::bNodeSocketValueMaterial_404 &src) {
dest.value = src.value;
});
break;
case SOCK_ROTATION:
versioning_internal::direct_link_node_socket_legacy_data_version_do<
bNodeSocketValueRotation,
versioning_internal::bNodeSocketValueRotation_404>(
&sock->default_value,
&temp_data,
[](bNodeSocketValueRotation &dest,
versioning_internal::bNodeSocketValueRotation_404 &src) {
copy_v3_v3(dest.value_euler, src.value_euler);
});
break;
case SOCK_MENU:
versioning_internal::direct_link_node_socket_legacy_data_version_do<
bNodeSocketValueMenu,
versioning_internal::bNodeSocketValueMenu_404>(
&sock->default_value,
&temp_data,
[](bNodeSocketValueMenu &dest, versioning_internal::bNodeSocketValueMenu_404 &src) {
dest.value = src.value;
/* Other members are runtime-only. */
});
break;
case SOCK_MATRIX:
/* Matrix sockets had no default value. */
case SOCK_CUSTOM:
/* Custom node sockets where default_value is defined were using custom properties for
* storage. */
case SOCK_SHADER:
case SOCK_GEOMETRY:
case SOCK_BUNDLE:
case SOCK_CLOSURE:
BLI_assert_unreachable();
break;
}
}
Geometry Nodes: Menu Switch Node This patch adds support for _Menu Switch_ nodes and enum definitions in node trees more generally. The design is based on the outcome of the [2022 Nodes Workshop](https://code.blender.org/2022/11/geometry-nodes-workshop-2022/#menu-switch). The _Menu Switch_ node is an advanced version of the _Switch_ node which has a customizable **menu input socket** instead of a simple boolean. The _items_ of this menu are owned by the node itself. Each item has a name and description and unique identifier that is used internally. A menu _socket_ represents a concrete value out of the list of items. To enable selection of an enum value for unconnected sockets the menu is presented as a dropdown list like built-in enums. When the socket is connected a shared pointer to the enum definition is propagated along links and stored in socket default values. This allows node groups to expose a menu from an internal menu switch as a parameter. The enum definition is a runtime copy of the enum items in DNA that allows sharing. A menu socket can have multiple connections, which can lead to ambiguity. If two or more different menu source nodes are connected to a socket it gets marked as _undefined_. Any connection to an undefined menu socket is invalid as a hint to users that there is a problem. A warning/error is also shown on nodes with undefined menu sockets. At runtime the value of a menu socket is the simple integer identifier. This can also be a field in geometry nodes. The identifier is unique within each enum definition, and it is persistent even when items are added, removed, or changed. Changing the name of an item does not affect the internal identifier, so users can rename enum items without breaking existing input values. This also persists if, for example, a linked node group is temporarily unavailable. Pull Request: https://projects.blender.org/blender/blender/pulls/113445
2024-01-26 12:40:01 +01:00
/* Post-reading processing. */
Geometry Nodes: Menu Switch Node This patch adds support for _Menu Switch_ nodes and enum definitions in node trees more generally. The design is based on the outcome of the [2022 Nodes Workshop](https://code.blender.org/2022/11/geometry-nodes-workshop-2022/#menu-switch). The _Menu Switch_ node is an advanced version of the _Switch_ node which has a customizable **menu input socket** instead of a simple boolean. The _items_ of this menu are owned by the node itself. Each item has a name and description and unique identifier that is used internally. A menu _socket_ represents a concrete value out of the list of items. To enable selection of an enum value for unconnected sockets the menu is presented as a dropdown list like built-in enums. When the socket is connected a shared pointer to the enum definition is propagated along links and stored in socket default values. This allows node groups to expose a menu from an internal menu switch as a parameter. The enum definition is a runtime copy of the enum items in DNA that allows sharing. A menu socket can have multiple connections, which can lead to ambiguity. If two or more different menu source nodes are connected to a socket it gets marked as _undefined_. Any connection to an undefined menu socket is invalid as a hint to users that there is a problem. A warning/error is also shown on nodes with undefined menu sockets. At runtime the value of a menu socket is the simple integer identifier. This can also be a field in geometry nodes. The identifier is unique within each enum definition, and it is persistent even when items are added, removed, or changed. Changing the name of an item does not affect the internal identifier, so users can rename enum items without breaking existing input values. This also persists if, for example, a linked node group is temporarily unavailable. Pull Request: https://projects.blender.org/blender/blender/pulls/113445
2024-01-26 12:40:01 +01:00
switch (eNodeSocketDatatype(sock->type)) {
case SOCK_MENU: {
bNodeSocketValueMenu &default_value = *sock->default_value_typed<bNodeSocketValueMenu>();
/* Clear runtime data. */
default_value.enum_items = nullptr;
default_value.runtime_flag = 0;
break;
}
default:
break;
}
}
static void direct_link_node_socket_storage(BlendDataReader *reader,
const bNode *node,
bNodeSocket *sock)
{
if (!sock->storage) {
return;
}
if (!node) {
/* Sockets not owned by a node should never have storage data. */
BLI_assert_unreachable();
sock->storage = nullptr;
return;
}
/* Sockets storage data seem to have always been written with correct DNA type info (see
* 3bae60d0c9 and 9d91bc38d3). So no need to use the same versioning work-around for old files as
* done for default values. */
switch (node->type_legacy) {
case CMP_NODE_OUTPUT_FILE:
BLO_read_struct(reader, NodeImageMultiFileSocket, &sock->storage);
if (sock->storage) {
NodeImageMultiFileSocket *sockdata = static_cast<NodeImageMultiFileSocket *>(
sock->storage);
BKE_image_format_blend_read_data(reader, &sockdata->format);
}
break;
case CMP_NODE_IMAGE:
case CMP_NODE_R_LAYERS:
BLO_read_struct(reader, NodeImageLayer, &sock->storage);
break;
default:
BLI_assert_unreachable();
sock->storage = nullptr;
break;
}
}
static void direct_link_node_socket(BlendDataReader *reader, const bNode *node, bNodeSocket *sock)
{
BLO_read_struct(reader, IDProperty, &sock->prop);
IDP_BlendDataRead(reader, &sock->prop);
BLO_read_struct(reader, bNodeLink, &sock->link);
sock->typeinfo = nullptr;
direct_link_node_socket_storage(reader, node, sock);
direct_link_node_socket_default_value(reader, sock);
BLO_read_string(reader, &sock->default_attribute_name);
sock->runtime = MEM_new<bNodeSocketRuntime>(__func__);
}
static void remove_unsupported_sockets(ListBase *sockets, ListBase *links)
{
LISTBASE_FOREACH_MUTABLE (bNodeSocket *, sock, sockets) {
if (is_node_socket_supported(sock)) {
continue;
}
/* First remove any link pointing to the socket. */
if (links) {
LISTBASE_FOREACH_MUTABLE (bNodeLink *, link, links) {
if (link->fromsock == sock || link->tosock == sock) {
BLI_remlink(links, link);
if (link->tosock) {
link->tosock->link = nullptr;
}
MEM_freeN(link);
}
}
}
BLI_remlink(sockets, sock);
MEM_delete(sock->runtime);
MEM_freeN(sock);
}
}
static void node_blend_read_data_storage(BlendDataReader *reader, bNodeTree *ntree, bNode *node)
{
if (!node->storage) {
return;
}
if (node->type_legacy == CMP_NODE_MOVIEDISTORTION) {
/* Do nothing, this is a runtime cache and hence handled by generic code using
* `IDTypeInfo.foreach_cache` callback. */
return;
}
/* This may not always find the type for legacy nodes when the idname did not exist yet or it was
* changed. Versioning code will update the nodes with unknown types. */
const bNodeType *ntype = node_type_find(node->idname);
if (ntype && !ntype->storagename.empty()) {
node->storage = BLO_read_struct_by_name_array(
reader, ntype->storagename.c_str(), 1, node->storage);
}
else {
/* Untyped read because we don't know the type yet. */
BLO_read_data_address(reader, &node->storage);
}
if (ntype && ntype->blend_data_read_storage_content) {
ntype->blend_data_read_storage_content(*ntree, *node, *reader);
return;
}
/* Some nodes don't use the callback above, because they were introduced before there were node
* idnames. Therefore, we can't rely on the idname to lookup the node type. */
switch (node->type_legacy) {
case SH_NODE_CURVE_VEC:
case SH_NODE_CURVE_RGB:
case SH_NODE_CURVE_FLOAT:
case CMP_NODE_TIME:
case CMP_NODE_CURVE_VEC:
case CMP_NODE_CURVE_RGB:
case CMP_NODE_HUECORRECT:
case TEX_NODE_CURVE_RGB:
case TEX_NODE_CURVE_TIME: {
BKE_curvemapping_blend_read(reader, static_cast<CurveMapping *>(node->storage));
break;
}
case SH_NODE_SCRIPT: {
NodeShaderScript *nss = static_cast<NodeShaderScript *>(node->storage);
BLO_read_string(reader, &nss->bytecode);
break;
}
case SH_NODE_TEX_POINTDENSITY: {
NodeShaderTexPointDensity *npd = static_cast<NodeShaderTexPointDensity *>(node->storage);
npd->pd = dna::shallow_zero_initialize();
break;
}
case SH_NODE_TEX_IMAGE: {
NodeTexImage *tex = static_cast<NodeTexImage *>(node->storage);
tex->iuser.scene = nullptr;
break;
}
case SH_NODE_TEX_ENVIRONMENT: {
NodeTexEnvironment *tex = static_cast<NodeTexEnvironment *>(node->storage);
tex->iuser.scene = nullptr;
break;
}
case CMP_NODE_IMAGE:
case CMP_NODE_VIEWER: {
ImageUser *iuser = static_cast<ImageUser *>(node->storage);
iuser->scene = nullptr;
break;
}
case CMP_NODE_CRYPTOMATTE_LEGACY:
case CMP_NODE_CRYPTOMATTE: {
NodeCryptomatte *nc = static_cast<NodeCryptomatte *>(node->storage);
BLO_read_string(reader, &nc->matte_id);
BLO_read_struct_list(reader, CryptomatteEntry, &nc->entries);
BLI_listbase_clear(&nc->runtime.layers);
break;
}
case TEX_NODE_IMAGE: {
ImageUser *iuser = static_cast<ImageUser *>(node->storage);
iuser->scene = nullptr;
break;
}
case CMP_NODE_OUTPUT_FILE: {
NodeImageMultiFile *nimf = static_cast<NodeImageMultiFile *>(node->storage);
BKE_image_format_blend_read_data(reader, &nimf->format);
break;
}
default:
break;
}
}
void node_tree_blend_read_data(BlendDataReader *reader, ID *owner_id, bNodeTree *ntree)
{
/* Special case for this pointer, do not rely on regular `lib_link` process here. Avoids needs
* for do_versioning, and ensures coherence of data in any case.
*
* NOTE: Old versions are very often 'broken' here, just fix it silently in these cases.
*/
if (BLO_read_fileversion_get(reader) > 300) {
BLI_assert((ntree->id.flag & ID_FLAG_EMBEDDED_DATA) != 0 || owner_id == nullptr);
}
BLI_assert(owner_id == nullptr || owner_id->lib == ntree->id.lib);
if (owner_id != nullptr && (ntree->id.flag & ID_FLAG_EMBEDDED_DATA) == 0) {
/* This is unfortunate, but currently a lot of existing files (including startup ones) have
* missing `ID_FLAG_EMBEDDED_DATA` flag.
*
* NOTE: Using do_version is not a solution here, since this code will be called before any
* do_version takes place. Keeping it here also ensures future (or unknown existing) similar
* bugs won't go easily unnoticed. */
if (BLO_read_fileversion_get(reader) > 300) {
CLOG_WARN(&LOG,
"Fixing root node tree '%s' owned by '%s' missing EMBEDDED tag, please consider "
"re-saving your (startup) file",
ntree->id.name,
owner_id->name);
}
ntree->id.flag |= ID_FLAG_EMBEDDED_DATA;
}
ntree->owner_id = owner_id;
/* NOTE: writing and reading goes in sync, for speed. */
ntree->typeinfo = nullptr;
ntree->runtime = MEM_new<bNodeTreeRuntime>(__func__);
BKE_ntree_update_tag_missing_runtime_data(ntree);
BLO_read_string(reader, &ntree->description);
BLO_read_struct_list(reader, bNode, &ntree->nodes);
int i;
LISTBASE_FOREACH_INDEX (bNode *, node, &ntree->nodes, i) {
node->runtime = MEM_new<bNodeRuntime>(__func__);
node->typeinfo = nullptr;
node->runtime->index_in_tree = i;
Merge of the PyNodes branch (aka "custom nodes") into trunk. PyNodes opens up the node system in Blender to scripters and adds a number of UI-level improvements. === Dynamic node type registration === Node types can now be added at runtime, using the RNA registration mechanism from python. This enables addons such as render engines to create a complete user interface with nodes. Examples of how such nodes can be defined can be found in my personal wiki docs atm [1] and as a script template in release/scripts/templates_py/custom_nodes.py [2]. === Node group improvements === Each node editor now has a tree history of edited node groups, which allows opening and editing nested node groups. The node editor also supports pinning now, so that different spaces can be used to edit different node groups simultaneously. For more ramblings and rationale see (really old) blog post on code.blender.org [3]. The interface of node groups has been overhauled. Sockets of a node group are no longer displayed in columns on either side, but instead special input/output nodes are used to mirror group sockets inside a node tree. This solves the problem of long node lines in groups and allows more adaptable node layout. Internal sockets can be exposed from a group by either connecting to the extension sockets in input/output nodes (shown as empty circle) or by adding sockets from the node property bar in the "Interface" panel. Further details such as the socket name can also be changed there. [1] http://wiki.blender.org/index.php/User:Phonybone/Python_Nodes [2] http://projects.blender.org/scm/viewvc.php/trunk/blender/release/scripts/templates_py/custom_nodes.py?view=markup&root=bf-blender [3] http://code.blender.org/index.php/2012/01/improving-node-group-interface-editing/
2013-03-18 16:34:57 +00:00
/* Create the `nodes_by_id` cache eagerly so it can be expected to be valid. Because
* we create it here we also have to check for zero identifiers from previous versions. */
if (node->identifier == 0 || ntree->runtime->nodes_by_id.contains_as(node->identifier)) {
node_unique_id(*ntree, *node);
}
else {
ntree->runtime->nodes_by_id.add_new(node);
Merge of the PyNodes branch (aka "custom nodes") into trunk. PyNodes opens up the node system in Blender to scripters and adds a number of UI-level improvements. === Dynamic node type registration === Node types can now be added at runtime, using the RNA registration mechanism from python. This enables addons such as render engines to create a complete user interface with nodes. Examples of how such nodes can be defined can be found in my personal wiki docs atm [1] and as a script template in release/scripts/templates_py/custom_nodes.py [2]. === Node group improvements === Each node editor now has a tree history of edited node groups, which allows opening and editing nested node groups. The node editor also supports pinning now, so that different spaces can be used to edit different node groups simultaneously. For more ramblings and rationale see (really old) blog post on code.blender.org [3]. The interface of node groups has been overhauled. Sockets of a node group are no longer displayed in columns on either side, but instead special input/output nodes are used to mirror group sockets inside a node tree. This solves the problem of long node lines in groups and allows more adaptable node layout. Internal sockets can be exposed from a group by either connecting to the extension sockets in input/output nodes (shown as empty circle) or by adding sockets from the node property bar in the "Interface" panel. Further details such as the socket name can also be changed there. [1] http://wiki.blender.org/index.php/User:Phonybone/Python_Nodes [2] http://projects.blender.org/scm/viewvc.php/trunk/blender/release/scripts/templates_py/custom_nodes.py?view=markup&root=bf-blender [3] http://code.blender.org/index.php/2012/01/improving-node-group-interface-editing/
2013-03-18 16:34:57 +00:00
}
BLO_read_struct_list(reader, bNodeSocket, &node->inputs);
BLO_read_struct_list(reader, bNodeSocket, &node->outputs);
BLO_read_struct_array(
reader, bNodePanelState, node->num_panel_states, &node->panel_states_array);
Merge of the PyNodes branch (aka "custom nodes") into trunk. PyNodes opens up the node system in Blender to scripters and adds a number of UI-level improvements. === Dynamic node type registration === Node types can now be added at runtime, using the RNA registration mechanism from python. This enables addons such as render engines to create a complete user interface with nodes. Examples of how such nodes can be defined can be found in my personal wiki docs atm [1] and as a script template in release/scripts/templates_py/custom_nodes.py [2]. === Node group improvements === Each node editor now has a tree history of edited node groups, which allows opening and editing nested node groups. The node editor also supports pinning now, so that different spaces can be used to edit different node groups simultaneously. For more ramblings and rationale see (really old) blog post on code.blender.org [3]. The interface of node groups has been overhauled. Sockets of a node group are no longer displayed in columns on either side, but instead special input/output nodes are used to mirror group sockets inside a node tree. This solves the problem of long node lines in groups and allows more adaptable node layout. Internal sockets can be exposed from a group by either connecting to the extension sockets in input/output nodes (shown as empty circle) or by adding sockets from the node property bar in the "Interface" panel. Further details such as the socket name can also be changed there. [1] http://wiki.blender.org/index.php/User:Phonybone/Python_Nodes [2] http://projects.blender.org/scm/viewvc.php/trunk/blender/release/scripts/templates_py/custom_nodes.py?view=markup&root=bf-blender [3] http://code.blender.org/index.php/2012/01/improving-node-group-interface-editing/
2013-03-18 16:34:57 +00:00
BLO_read_struct(reader, IDProperty, &node->prop);
IDP_BlendDataRead(reader, &node->prop);
2018-06-17 17:05:51 +02:00
node_blend_read_data_storage(reader, ntree, node);
Geometry Nodes: add simulation support This adds support for building simulations with geometry nodes. A new `Simulation Input` and `Simulation Output` node allow maintaining a simulation state across multiple frames. Together these two nodes form a `simulation zone` which contains all the nodes that update the simulation state from one frame to the next. A new simulation zone can be added via the menu (`Simulation > Simulation Zone`) or with the node add search. The simulation state contains a geometry by default. However, it is possible to add multiple geometry sockets as well as other socket types. Currently, field inputs are evaluated and stored for the preceding geometry socket in the order that the sockets are shown. Simulation state items can be added by linking one of the empty sockets to something else. In the sidebar, there is a new panel that allows adding, removing and reordering these sockets. The simulation nodes behave as follows: * On the first frame, the inputs of the `Simulation Input` node are evaluated to initialize the simulation state. In later frames these sockets are not evaluated anymore. The `Delta Time` at the first frame is zero, but the simulation zone is still evaluated. * On every next frame, the `Simulation Input` node outputs the simulation state of the previous frame. Nodes in the simulation zone can edit that data in arbitrary ways, also taking into account the `Delta Time`. The new simulation state has to be passed to the `Simulation Output` node where it is cached and forwarded. * On a frame that is already cached or baked, the nodes in the simulation zone are not evaluated, because the `Simulation Output` node can return the previously cached data directly. It is not allowed to connect sockets from inside the simulation zone to the outside without going through the `Simulation Output` node. This is a necessary restriction to make caching and sub-frame interpolation work. Links can go into the simulation zone without problems though. Anonymous attributes are not propagated by the simulation nodes unless they are explicitly stored in the simulation state. This is unfortunate, but currently there is no practical and reliable alternative. The core problem is detecting which anonymous attributes will be required for the simulation and afterwards. While we can detect this for the current evaluation, we can't look into the future in time to see what data will be necessary. We intend to make it easier to explicitly pass data through a simulation in the future, even if the simulation is in a nested node group. There is a new `Simulation Nodes` panel in the physics tab in the properties editor. It allows baking all simulation zones on the selected objects. The baking options are intentially kept at a minimum for this MVP. More features for simulation baking as well as baking in general can be expected to be added separately. All baked data is stored on disk in a folder next to the .blend file. #106937 describes how baking is implemented in more detail. Volumes can not be baked yet and materials are lost during baking for now. Packing the baked data into the .blend file is not yet supported. The timeline indicates which frames are currently cached, baked or cached but invalidated by user-changes. Simulation input and output nodes are internally linked together by their `bNode.identifier` which stays the same even if the node name changes. They are generally added and removed together. However, there are still cases where "dangling" simulation nodes can be created currently. Those generally don't cause harm, but would be nice to avoid this in more cases in the future. Co-authored-by: Hans Goudey <h.goudey@me.com> Co-authored-by: Lukas Tönne <lukas@blender.org> Pull Request: https://projects.blender.org/blender/blender/pulls/104924
2023-05-03 13:18:51 +02:00
}
BLO_read_struct_list(reader, bNodeLink, &ntree->links);
BLI_assert(ntree->all_nodes().size() == BLI_listbase_count(&ntree->nodes));
/* and we connect the rest */
LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
BLO_read_struct(reader, bNode, &node->parent);
LISTBASE_FOREACH_MUTABLE (bNodeSocket *, sock, &node->inputs) {
direct_link_node_socket(reader, node, sock);
}
LISTBASE_FOREACH_MUTABLE (bNodeSocket *, sock, &node->outputs) {
direct_link_node_socket(reader, node, sock);
}
}
Geometry Nodes: add simulation support This adds support for building simulations with geometry nodes. A new `Simulation Input` and `Simulation Output` node allow maintaining a simulation state across multiple frames. Together these two nodes form a `simulation zone` which contains all the nodes that update the simulation state from one frame to the next. A new simulation zone can be added via the menu (`Simulation > Simulation Zone`) or with the node add search. The simulation state contains a geometry by default. However, it is possible to add multiple geometry sockets as well as other socket types. Currently, field inputs are evaluated and stored for the preceding geometry socket in the order that the sockets are shown. Simulation state items can be added by linking one of the empty sockets to something else. In the sidebar, there is a new panel that allows adding, removing and reordering these sockets. The simulation nodes behave as follows: * On the first frame, the inputs of the `Simulation Input` node are evaluated to initialize the simulation state. In later frames these sockets are not evaluated anymore. The `Delta Time` at the first frame is zero, but the simulation zone is still evaluated. * On every next frame, the `Simulation Input` node outputs the simulation state of the previous frame. Nodes in the simulation zone can edit that data in arbitrary ways, also taking into account the `Delta Time`. The new simulation state has to be passed to the `Simulation Output` node where it is cached and forwarded. * On a frame that is already cached or baked, the nodes in the simulation zone are not evaluated, because the `Simulation Output` node can return the previously cached data directly. It is not allowed to connect sockets from inside the simulation zone to the outside without going through the `Simulation Output` node. This is a necessary restriction to make caching and sub-frame interpolation work. Links can go into the simulation zone without problems though. Anonymous attributes are not propagated by the simulation nodes unless they are explicitly stored in the simulation state. This is unfortunate, but currently there is no practical and reliable alternative. The core problem is detecting which anonymous attributes will be required for the simulation and afterwards. While we can detect this for the current evaluation, we can't look into the future in time to see what data will be necessary. We intend to make it easier to explicitly pass data through a simulation in the future, even if the simulation is in a nested node group. There is a new `Simulation Nodes` panel in the physics tab in the properties editor. It allows baking all simulation zones on the selected objects. The baking options are intentially kept at a minimum for this MVP. More features for simulation baking as well as baking in general can be expected to be added separately. All baked data is stored on disk in a folder next to the .blend file. #106937 describes how baking is implemented in more detail. Volumes can not be baked yet and materials are lost during baking for now. Packing the baked data into the .blend file is not yet supported. The timeline indicates which frames are currently cached, baked or cached but invalidated by user-changes. Simulation input and output nodes are internally linked together by their `bNode.identifier` which stays the same even if the node name changes. They are generally added and removed together. However, there are still cases where "dangling" simulation nodes can be created currently. Those generally don't cause harm, but would be nice to avoid this in more cases in the future. Co-authored-by: Hans Goudey <h.goudey@me.com> Co-authored-by: Lukas Tönne <lukas@blender.org> Pull Request: https://projects.blender.org/blender/blender/pulls/104924
2023-05-03 13:18:51 +02:00
Nodes: Panels integration with blend files and UI Part 3/3 of #109135, #110272 Switch to new node group interfaces and deprecate old DNA and API. This completes support for panels in node drawing and in node group interface declarations in particular. The new node group interface DNA and RNA code has been added in parts 1 and 2 (#110885, #110952) but has not be enabled yet. This commit completes the integration by * enabling the new RNA API * using the new API in UI * read/write new interfaces from blend files * add versioning for backward compatibility * add forward-compatible writing code to reconstruct old interfaces All places accessing node group interface declarations should now be using the new API. A runtime cache has been added that allows simple linear access to socket inputs and outputs even when a panel hierarchy is used. Old DNA has been deprecated and should only be accessed for versioning (inputs/outputs renamed to inputs_legacy/outputs_legacy to catch errors). Versioning code ensures both backward and forward compatibility of existing files. The API for old interfaces is removed. The new API is very similar but is defined on the `ntree.interface` instead of the `ntree` directly. Breaking change notifications and detailed instructions for migrating will be added. A python test has been added for the node group API functions. This includes new functionality such as creating panels and moving items between different levels. This patch does not yet contain panel representations in the modifier UI. This has been tested in a separate branch and will be added with a later PR (#108565). Pull Request: https://projects.blender.org/blender/blender/pulls/111348
2023-08-30 12:37:21 +02:00
/* Read legacy interface socket lists for versioning. */
BLO_read_struct_list(reader, bNodeSocket, &ntree->inputs_legacy);
BLO_read_struct_list(reader, bNodeSocket, &ntree->outputs_legacy);
LISTBASE_FOREACH_MUTABLE (bNodeSocket *, sock, &ntree->inputs_legacy) {
direct_link_node_socket(reader, nullptr, sock);
}
LISTBASE_FOREACH_MUTABLE (bNodeSocket *, sock, &ntree->outputs_legacy) {
direct_link_node_socket(reader, nullptr, sock);
}
2018-06-17 17:05:51 +02:00
Nodes: Panels integration with blend files and UI Part 3/3 of #109135, #110272 Switch to new node group interfaces and deprecate old DNA and API. This completes support for panels in node drawing and in node group interface declarations in particular. The new node group interface DNA and RNA code has been added in parts 1 and 2 (#110885, #110952) but has not be enabled yet. This commit completes the integration by * enabling the new RNA API * using the new API in UI * read/write new interfaces from blend files * add versioning for backward compatibility * add forward-compatible writing code to reconstruct old interfaces All places accessing node group interface declarations should now be using the new API. A runtime cache has been added that allows simple linear access to socket inputs and outputs even when a panel hierarchy is used. Old DNA has been deprecated and should only be accessed for versioning (inputs/outputs renamed to inputs_legacy/outputs_legacy to catch errors). Versioning code ensures both backward and forward compatibility of existing files. The API for old interfaces is removed. The new API is very similar but is defined on the `ntree.interface` instead of the `ntree` directly. Breaking change notifications and detailed instructions for migrating will be added. A python test has been added for the node group API functions. This includes new functionality such as creating panels and moving items between different levels. This patch does not yet contain panel representations in the modifier UI. This has been tested in a separate branch and will be added with a later PR (#108565). Pull Request: https://projects.blender.org/blender/blender/pulls/111348
2023-08-30 12:37:21 +02:00
ntree->tree_interface.read_data(reader);
LISTBASE_FOREACH (bNodeLink *, link, &ntree->links) {
BLO_read_struct(reader, bNode, &link->fromnode);
BLO_read_struct(reader, bNode, &link->tonode);
BLO_read_struct(reader, bNodeSocket, &link->fromsock);
BLO_read_struct(reader, bNodeSocket, &link->tosock);
}
2018-06-17 17:05:51 +02:00
LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
remove_unsupported_sockets(&node->inputs, &ntree->links);
remove_unsupported_sockets(&node->outputs, &ntree->links);
}
remove_unsupported_sockets(&ntree->inputs_legacy, nullptr);
remove_unsupported_sockets(&ntree->outputs_legacy, nullptr);
BLO_read_struct(reader, GeometryNodeAssetTraits, &ntree->geometry_node_asset_traits);
BLO_read_struct_array(
reader, bNestedNodeRef, ntree->nested_node_refs_num, &ntree->nested_node_refs);
Nodes: add nested node ids and use them for simulation state The simulation state used by simulation nodes is owned by the modifier. Since a geometry nodes setup can contain an arbitrary number of simulations, the modifier has a mapping from `SimulationZoneID` to `SimulationZoneState`. This patch changes what is used as `SimulationZoneID`. Previously, the `SimulationZoneID` contained a list of `bNode::identifier` that described the path from the root node tree to the simulation output node. This works ok in many cases, but also has a significant problem: The `SimulationZoneID` changes when moving the simulation zone into or out of a node group. This implies that any of these operations loses the mapping from zone to simulation state, invalidating the cache or even baked data. The goal of this patch is to introduce a single-integer ID that identifies a (nested) simulation zone and is stable even when grouping and un-grouping. The ID should be stable even if the node group containing the (nested) simulation zone is in a separate linked .blend file and that linked file is changed. In the future, the same kind of ID can be used to store e.g. checkpoint/baked/frozen data in the modifier. To achieve the described goal, node trees can now store an arbitrary number of nested node references (an array of `bNestedNodeRef`). Each nested node reference has an ID that is unique within the current node tree. The node tree does not store the entire path to the nested node. Instead it only know which group node the nested node is in, and what the nested node ID of the node is within that group. Grouping and un-grouping operations have to update the nested node references to keep the IDs stable. Importantly though, these operations only have to care about the two node groups that are affected. IDs in higher level node groups remain unchanged by design. A consequence of this design is that every `bNodeTree` now has a `bNestedNodeRef` for every (nested) simulation zone. Two instances of the same simulation zone (because a node group is reused) are referenced by two separate `bNestedNodeRef`. This is important to keep in mind, because it also means that this solution doesn't scale well if we wanted to use it to keep stable references to *all* nested nodes. I can't think of a solution that fulfills the described requirements but scales better with more nodes. For that reason, this solution should only be used when we want to store data for each referenced nested node at the top level (like we do for simulations). This is not a replacement for `ViewerPath` which can store a path to data in a node tree without changing the node tree. Also `ViewerPath` can contain information like the loop iteration that should be viewed (#109164). `bNestedNodeRef` can't differentiate between different iterations of a loop. This also means that simulations can't be used inside of a loop (loops inside of a simulation work fine though). When baking, the new stable ID is now written to disk, which means that baked data is not invalidated by grouping/un-grouping operations. Backward compatibility for baked data is provided, but only works as long as the simulation zone has not been moved to a different node group yet. Forward compatibility for the baked data is not provided (so older versions can't load the data baked with a newer version of Blender). Pull Request: https://projects.blender.org/blender/blender/pulls/109444
2023-07-01 11:54:32 +02:00
BLO_read_struct(reader, PreviewImage, &ntree->preview);
BKE_previewimg_blend_read(reader, ntree->preview);
Orange: more noodle updates! **** NEW: Group Nodes Node trees usually become messy and confusing quickly, so we need not only a way to collapse Nodes into single 'groups', but also a way to re-use that data to create libraries of effects. This has been done by making a new Library data type, the NodeTree. Everything that has been grouped is stored here, and available for re-use, appending or linking. These NodeTrees are fully generic, i.e. can store shader trees, composit trees, and so on. The 'type' value as stored in the NodeTree will keep track of internal type definitions and execute/drawing callbacks. Needless to say, re-using shader trees in a composit tree is a bit useless, and will be prevented in the browsing code. :) So; any NodeTree can become a "Goup Node" inside in a NodeTree. This Group Node then works just like any Node. To prevent the current code to become too complex, I've disabled the possibility to insert Groups inside of Groups. That might be enabled later, but is a real nasty piece of code to get OK. Since Group Nodes are a dynamic Node type, a lot of work has been done to ensure Node definitions can be dynamic too, but still allow to be stored in files, and allow to be verified for type-definition changes on reloading. This system needs a little bit maturing still, so the Python gurus should better wait a little bit! (Also for me to write the definite API docs for it). What works now: - Press CTRL+G to create a new Group. The grouping code checks for impossible selections (like an unselected node between selected nodes). Everthing that's selected then gets removed from the current tree, and inserted in a new NodeTree library data block. A Group Node then is added which links to this new NodeTree. - Press ALT+G to ungroup. This will not delete the NodeTree library data, but just duplicate the Group into the current tree. - Press TAB, or click on the NodeTree icon to edit Groups. Note that NodeTrees are instances, so editing one Group will also change the other users. This also means that when removing nodes in a Group (or hiding sockets or changing internal links) this is immediately corrected for all users of this Group, also in other Materials. - While editing Groups, only the internal Nodes can be edited. A single click outside of the Group boundary will close this 'edit mode'. What needs to be done: - SHIFT+A menu in toolbox style, also including a list of Groups - Enable the single-user button in the Group Node - Displaying all (visible) internal group UI elements in the Node Panel - Enable Library linking and prevent editing of Groups then. **** NEW: Socket Visibility control Node types will be generated with a lot of possible inputs or outputs, and drawing all sockets all the time isn't very useful then. A new option in the Node header ('plus' icon) allows to either hide all unused sockets (first keypress) or to reveil them (when there are hidden sockets, the icon displays black, otherwise it's blended). Hidden sockets in Nodes also are not exported to a Group, so this way you can control what options (in/outputs) exactly are available. To be done: - a way to hide individual sockets, like with a RMB click on it. **** NEW: Nodes now render! This is still quite primitive, more on a level to replace the (now obsolete and disabled) Material Layers. What needs to be done: - make the "Geometry" node work properly, also for AA textures - make the Texture Node work (does very little at the moment) - give Material Nodes all inputs as needed (like Map-to Panel) - find a way to export more data from a Material Node, like the shadow value, or light intensity only, etc Very important also to separate from the Material Buttons the "global" options, like "Ztransp" or "Wire" or "Halo". These can not be set for each Material-Node individually. Also note that the Preview Render (Buttons window) now renders a bit differently. This was a horrid piece of antique code, using a totally incompatible way of rendering. Target is to fully re-use internal render code for previews. OK... that's it mostly. Now test!
2006-01-02 13:06:05 +00:00
/* type verification is in lib-link */
}
2018-06-17 17:05:51 +02:00
static void ntree_blend_read_data(BlendDataReader *reader, ID *id)
{
bNodeTree *ntree = reinterpret_cast<bNodeTree *>(id);
node_tree_blend_read_data(reader, nullptr, ntree);
Merge of the PyNodes branch (aka "custom nodes") into trunk. PyNodes opens up the node system in Blender to scripters and adds a number of UI-level improvements. === Dynamic node type registration === Node types can now be added at runtime, using the RNA registration mechanism from python. This enables addons such as render engines to create a complete user interface with nodes. Examples of how such nodes can be defined can be found in my personal wiki docs atm [1] and as a script template in release/scripts/templates_py/custom_nodes.py [2]. === Node group improvements === Each node editor now has a tree history of edited node groups, which allows opening and editing nested node groups. The node editor also supports pinning now, so that different spaces can be used to edit different node groups simultaneously. For more ramblings and rationale see (really old) blog post on code.blender.org [3]. The interface of node groups has been overhauled. Sockets of a node group are no longer displayed in columns on either side, but instead special input/output nodes are used to mirror group sockets inside a node tree. This solves the problem of long node lines in groups and allows more adaptable node layout. Internal sockets can be exposed from a group by either connecting to the extension sockets in input/output nodes (shown as empty circle) or by adding sockets from the node property bar in the "Interface" panel. Further details such as the socket name can also be changed there. [1] http://wiki.blender.org/index.php/User:Phonybone/Python_Nodes [2] http://projects.blender.org/scm/viewvc.php/trunk/blender/release/scripts/templates_py/custom_nodes.py?view=markup&root=bf-blender [3] http://code.blender.org/index.php/2012/01/improving-node-group-interface-editing/
2013-03-18 16:34:57 +00:00
}
static void ntree_blend_read_after_liblink(BlendLibReader *reader, ID *id)
Merge of the PyNodes branch (aka "custom nodes") into trunk. PyNodes opens up the node system in Blender to scripters and adds a number of UI-level improvements. === Dynamic node type registration === Node types can now be added at runtime, using the RNA registration mechanism from python. This enables addons such as render engines to create a complete user interface with nodes. Examples of how such nodes can be defined can be found in my personal wiki docs atm [1] and as a script template in release/scripts/templates_py/custom_nodes.py [2]. === Node group improvements === Each node editor now has a tree history of edited node groups, which allows opening and editing nested node groups. The node editor also supports pinning now, so that different spaces can be used to edit different node groups simultaneously. For more ramblings and rationale see (really old) blog post on code.blender.org [3]. The interface of node groups has been overhauled. Sockets of a node group are no longer displayed in columns on either side, but instead special input/output nodes are used to mirror group sockets inside a node tree. This solves the problem of long node lines in groups and allows more adaptable node layout. Internal sockets can be exposed from a group by either connecting to the extension sockets in input/output nodes (shown as empty circle) or by adding sockets from the node property bar in the "Interface" panel. Further details such as the socket name can also be changed there. [1] http://wiki.blender.org/index.php/User:Phonybone/Python_Nodes [2] http://projects.blender.org/scm/viewvc.php/trunk/blender/release/scripts/templates_py/custom_nodes.py?view=markup&root=bf-blender [3] http://code.blender.org/index.php/2012/01/improving-node-group-interface-editing/
2013-03-18 16:34:57 +00:00
{
bNodeTree *ntree = reinterpret_cast<bNodeTree *>(id);
/* Set `node->typeinfo` pointers. This is done in lib linking, after the
* first versioning that can change types still without functions that
* update the `typeinfo` pointers. Versioning after lib linking needs
* these top be valid. */
node_tree_set_type(nullptr, *ntree);
/* For nodes with static socket layout, add/remove sockets as needed
* to match the static layout. */
if (!BLO_read_lib_is_undo(reader)) {
LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
/* Don't update node groups here because they may depend on other node groups which are not
* fully versioned yet and don't have `typeinfo` pointers set. */
if (!node->is_group()) {
node_verify_sockets(ntree, node, false);
}
}
}
}
void node_update_asset_metadata(bNodeTree &node_tree)
Merge of the PyNodes branch (aka "custom nodes") into trunk. PyNodes opens up the node system in Blender to scripters and adds a number of UI-level improvements. === Dynamic node type registration === Node types can now be added at runtime, using the RNA registration mechanism from python. This enables addons such as render engines to create a complete user interface with nodes. Examples of how such nodes can be defined can be found in my personal wiki docs atm [1] and as a script template in release/scripts/templates_py/custom_nodes.py [2]. === Node group improvements === Each node editor now has a tree history of edited node groups, which allows opening and editing nested node groups. The node editor also supports pinning now, so that different spaces can be used to edit different node groups simultaneously. For more ramblings and rationale see (really old) blog post on code.blender.org [3]. The interface of node groups has been overhauled. Sockets of a node group are no longer displayed in columns on either side, but instead special input/output nodes are used to mirror group sockets inside a node tree. This solves the problem of long node lines in groups and allows more adaptable node layout. Internal sockets can be exposed from a group by either connecting to the extension sockets in input/output nodes (shown as empty circle) or by adding sockets from the node property bar in the "Interface" panel. Further details such as the socket name can also be changed there. [1] http://wiki.blender.org/index.php/User:Phonybone/Python_Nodes [2] http://projects.blender.org/scm/viewvc.php/trunk/blender/release/scripts/templates_py/custom_nodes.py?view=markup&root=bf-blender [3] http://code.blender.org/index.php/2012/01/improving-node-group-interface-editing/
2013-03-18 16:34:57 +00:00
{
AssetMetaData *asset_data = node_tree.id.asset_data;
if (!asset_data) {
return;
}
Merge of the PyNodes branch (aka "custom nodes") into trunk. PyNodes opens up the node system in Blender to scripters and adds a number of UI-level improvements. === Dynamic node type registration === Node types can now be added at runtime, using the RNA registration mechanism from python. This enables addons such as render engines to create a complete user interface with nodes. Examples of how such nodes can be defined can be found in my personal wiki docs atm [1] and as a script template in release/scripts/templates_py/custom_nodes.py [2]. === Node group improvements === Each node editor now has a tree history of edited node groups, which allows opening and editing nested node groups. The node editor also supports pinning now, so that different spaces can be used to edit different node groups simultaneously. For more ramblings and rationale see (really old) blog post on code.blender.org [3]. The interface of node groups has been overhauled. Sockets of a node group are no longer displayed in columns on either side, but instead special input/output nodes are used to mirror group sockets inside a node tree. This solves the problem of long node lines in groups and allows more adaptable node layout. Internal sockets can be exposed from a group by either connecting to the extension sockets in input/output nodes (shown as empty circle) or by adding sockets from the node property bar in the "Interface" panel. Further details such as the socket name can also be changed there. [1] http://wiki.blender.org/index.php/User:Phonybone/Python_Nodes [2] http://projects.blender.org/scm/viewvc.php/trunk/blender/release/scripts/templates_py/custom_nodes.py?view=markup&root=bf-blender [3] http://code.blender.org/index.php/2012/01/improving-node-group-interface-editing/
2013-03-18 16:34:57 +00:00
BKE_asset_metadata_idprop_ensure(asset_data, idprop::create("type", node_tree.type).release());
auto inputs = idprop::create_group("inputs");
auto outputs = idprop::create_group("outputs");
node_tree.ensure_interface_cache();
Nodes: Panels integration with blend files and UI Part 3/3 of #109135, #110272 Switch to new node group interfaces and deprecate old DNA and API. This completes support for panels in node drawing and in node group interface declarations in particular. The new node group interface DNA and RNA code has been added in parts 1 and 2 (#110885, #110952) but has not be enabled yet. This commit completes the integration by * enabling the new RNA API * using the new API in UI * read/write new interfaces from blend files * add versioning for backward compatibility * add forward-compatible writing code to reconstruct old interfaces All places accessing node group interface declarations should now be using the new API. A runtime cache has been added that allows simple linear access to socket inputs and outputs even when a panel hierarchy is used. Old DNA has been deprecated and should only be accessed for versioning (inputs/outputs renamed to inputs_legacy/outputs_legacy to catch errors). Versioning code ensures both backward and forward compatibility of existing files. The API for old interfaces is removed. The new API is very similar but is defined on the `ntree.interface` instead of the `ntree` directly. Breaking change notifications and detailed instructions for migrating will be added. A python test has been added for the node group API functions. This includes new functionality such as creating panels and moving items between different levels. This patch does not yet contain panel representations in the modifier UI. This has been tested in a separate branch and will be added with a later PR (#108565). Pull Request: https://projects.blender.org/blender/blender/pulls/111348
2023-08-30 12:37:21 +02:00
for (const bNodeTreeInterfaceSocket *socket : node_tree.interface_inputs()) {
auto *prop = idprop::create(socket->name ? socket->name : "", socket->socket_type).release();
if (!IDP_AddToGroup(inputs.get(), prop)) {
IDP_FreeProperty(prop);
}
}
Nodes: Panels integration with blend files and UI Part 3/3 of #109135, #110272 Switch to new node group interfaces and deprecate old DNA and API. This completes support for panels in node drawing and in node group interface declarations in particular. The new node group interface DNA and RNA code has been added in parts 1 and 2 (#110885, #110952) but has not be enabled yet. This commit completes the integration by * enabling the new RNA API * using the new API in UI * read/write new interfaces from blend files * add versioning for backward compatibility * add forward-compatible writing code to reconstruct old interfaces All places accessing node group interface declarations should now be using the new API. A runtime cache has been added that allows simple linear access to socket inputs and outputs even when a panel hierarchy is used. Old DNA has been deprecated and should only be accessed for versioning (inputs/outputs renamed to inputs_legacy/outputs_legacy to catch errors). Versioning code ensures both backward and forward compatibility of existing files. The API for old interfaces is removed. The new API is very similar but is defined on the `ntree.interface` instead of the `ntree` directly. Breaking change notifications and detailed instructions for migrating will be added. A python test has been added for the node group API functions. This includes new functionality such as creating panels and moving items between different levels. This patch does not yet contain panel representations in the modifier UI. This has been tested in a separate branch and will be added with a later PR (#108565). Pull Request: https://projects.blender.org/blender/blender/pulls/111348
2023-08-30 12:37:21 +02:00
for (const bNodeTreeInterfaceSocket *socket : node_tree.interface_outputs()) {
auto *prop = idprop::create(socket->name ? socket->name : "", socket->socket_type).release();
if (!IDP_AddToGroup(outputs.get(), prop)) {
IDP_FreeProperty(prop);
}
Merge of the PyNodes branch (aka "custom nodes") into trunk. PyNodes opens up the node system in Blender to scripters and adds a number of UI-level improvements. === Dynamic node type registration === Node types can now be added at runtime, using the RNA registration mechanism from python. This enables addons such as render engines to create a complete user interface with nodes. Examples of how such nodes can be defined can be found in my personal wiki docs atm [1] and as a script template in release/scripts/templates_py/custom_nodes.py [2]. === Node group improvements === Each node editor now has a tree history of edited node groups, which allows opening and editing nested node groups. The node editor also supports pinning now, so that different spaces can be used to edit different node groups simultaneously. For more ramblings and rationale see (really old) blog post on code.blender.org [3]. The interface of node groups has been overhauled. Sockets of a node group are no longer displayed in columns on either side, but instead special input/output nodes are used to mirror group sockets inside a node tree. This solves the problem of long node lines in groups and allows more adaptable node layout. Internal sockets can be exposed from a group by either connecting to the extension sockets in input/output nodes (shown as empty circle) or by adding sockets from the node property bar in the "Interface" panel. Further details such as the socket name can also be changed there. [1] http://wiki.blender.org/index.php/User:Phonybone/Python_Nodes [2] http://projects.blender.org/scm/viewvc.php/trunk/blender/release/scripts/templates_py/custom_nodes.py?view=markup&root=bf-blender [3] http://code.blender.org/index.php/2012/01/improving-node-group-interface-editing/
2013-03-18 16:34:57 +00:00
}
BKE_asset_metadata_idprop_ensure(asset_data, inputs.release());
BKE_asset_metadata_idprop_ensure(asset_data, outputs.release());
if (node_tree.geometry_node_asset_traits) {
auto property = idprop::create("geometry_node_asset_traits_flag",
node_tree.geometry_node_asset_traits->flag);
BKE_asset_metadata_idprop_ensure(asset_data, property.release());
}
}
static void node_tree_asset_pre_save(void *asset_ptr, AssetMetaData * /*asset_data*/)
{
bNodeTree &ntree = *static_cast<bNodeTree *>(asset_ptr);
node_update_asset_metadata(ntree);
}
static void node_tree_asset_on_mark_asset(void *asset_ptr, AssetMetaData *asset_data)
{
bNodeTree &ntree = *static_cast<bNodeTree *>(asset_ptr);
node_update_asset_metadata(ntree);
/* Copy node tree description to asset description so that the user does not have to write it
* again. */
if (!asset_data->description) {
asset_data->description = BLI_strdup_null(ntree.description);
}
}
static void node_tree_asset_on_clear_asset(void *asset_ptr, AssetMetaData *asset_data)
{
bNodeTree &ntree = *static_cast<bNodeTree *>(asset_ptr);
/* Copy asset description to node tree description so that it is not lost when the asset data is
* removed. */
if (asset_data->description) {
MEM_SAFE_FREE(ntree.description);
ntree.description = BLI_strdup_null(asset_data->description);
}
}
} // namespace blender::bke
static AssetTypeInfo AssetType_NT = {
/*pre_save_fn*/ blender::bke::node_tree_asset_pre_save,
/*on_mark_asset_fn*/ blender::bke::node_tree_asset_on_mark_asset,
/*on_clear_asset_fn*/ blender::bke::node_tree_asset_on_clear_asset,
};
IDTypeInfo IDType_ID_NT = {
/*id_code*/ bNodeTree::id_type,
/*id_filter*/ FILTER_ID_NT,
/* IDProps of nodes, and #bNode.id, can use any type of ID. */
/*dependencies_id_types*/ FILTER_ID_ALL,
/*main_listbase_index*/ INDEX_ID_NT,
/*struct_size*/ sizeof(bNodeTree),
/*name*/ "NodeTree",
/*name_plural*/ N_("node_groups"),
/*translation_context*/ BLT_I18NCONTEXT_ID_NODETREE,
/*flags*/ IDTYPE_FLAGS_APPEND_IS_REUSABLE,
/*asset_type_info*/ &AssetType_NT,
/*init_data*/ blender::bke::ntree_init_data,
/*copy_data*/ blender::bke::ntree_copy_data,
/*free_data*/ blender::bke::ntree_free_data,
/*make_local*/ nullptr,
/*foreach_id*/ blender::bke::node_foreach_id,
/*foreach_cache*/ blender::bke::node_foreach_cache,
/*foreach_path*/ blender::bke::node_foreach_path,
/*owner_pointer_get*/ blender::bke::node_owner_pointer_get,
/*blend_write*/ blender::bke::ntree_blend_write,
/*blend_read_data*/ blender::bke::ntree_blend_read_data,
/*blend_read_after_liblink*/ blender::bke::ntree_blend_read_after_liblink,
/*blend_read_undo_preserve*/ nullptr,
/*lib_override_apply_post*/ nullptr,
};
namespace blender::bke {
static void node_add_sockets_from_type(bNodeTree *ntree, bNode *node, bNodeType *ntype)
{
Nodes: unify static and dynamic declarations This helps solving the problem encountered in #113553. The problem is that we currently can't support link-drag-search for nodes which have a dynamic declaration. With this patch, there is only a single `declare` function per node type, instead of the separate `declare` and `declare_dynamic` functions. The new `declare` function has access to the node and tree. However, both are allowed to be null. The final node declaration has a flag for whether it depends on the node context or not. Nodes that previously had a dynamic declaration should now create as much of the declaration as possible that does not depend on the node. This allows code like for link-drag-search to take those sockets into account even if the other sockets are dynamic. For node declarations that have dynamic types (e.g. Switch node), we can also add extra information to the static node declaration, like the identifier of the socket with the dynamic type. This is not part of this patch though. I can think of two main alternatives to the approach implemented here: * Define two separate functions for dynamic nodes. One that creates the "static declaration" without node context, and on that creates the actual declaration with node context. * Have a single declare function that generates "build instructions" for the actual node declaration. So instead of building the final declaration directly, one can for example add a socket whose type depends on a specific rna path in the node. The actual node declaration is then automatically generated based on the build instructions. This becomes quite a bit more tricky with dynamic amounts of sockets and introduces another indirection between declarations and what sockets the node actually has. I found the approach implemented in this patch to lead to the least amount of boilerplate (doesn't require a seperate "build instructions" data structure) and code duplication (socket properties are still only defined in one place). At the same time, it offers more flexibility to how nodes can be dynamic. Pull Request: https://projects.blender.org/blender/blender/pulls/113742
2023-10-15 20:28:23 +02:00
if (ntype->declare) {
node_verify_sockets(ntree, node, true);
return;
}
bNodeSocketTemplate *sockdef;
if (ntype->inputs) {
sockdef = ntype->inputs;
while (sockdef->type != -1) {
node_add_socket_from_template(ntree, node, sockdef, SOCK_IN);
sockdef++;
}
}
if (ntype->outputs) {
sockdef = ntype->outputs;
while (sockdef->type != -1) {
node_add_socket_from_template(ntree, node, sockdef, SOCK_OUT);
sockdef++;
}
Merge of the PyNodes branch (aka "custom nodes") into trunk. PyNodes opens up the node system in Blender to scripters and adds a number of UI-level improvements. === Dynamic node type registration === Node types can now be added at runtime, using the RNA registration mechanism from python. This enables addons such as render engines to create a complete user interface with nodes. Examples of how such nodes can be defined can be found in my personal wiki docs atm [1] and as a script template in release/scripts/templates_py/custom_nodes.py [2]. === Node group improvements === Each node editor now has a tree history of edited node groups, which allows opening and editing nested node groups. The node editor also supports pinning now, so that different spaces can be used to edit different node groups simultaneously. For more ramblings and rationale see (really old) blog post on code.blender.org [3]. The interface of node groups has been overhauled. Sockets of a node group are no longer displayed in columns on either side, but instead special input/output nodes are used to mirror group sockets inside a node tree. This solves the problem of long node lines in groups and allows more adaptable node layout. Internal sockets can be exposed from a group by either connecting to the extension sockets in input/output nodes (shown as empty circle) or by adding sockets from the node property bar in the "Interface" panel. Further details such as the socket name can also be changed there. [1] http://wiki.blender.org/index.php/User:Phonybone/Python_Nodes [2] http://projects.blender.org/scm/viewvc.php/trunk/blender/release/scripts/templates_py/custom_nodes.py?view=markup&root=bf-blender [3] http://code.blender.org/index.php/2012/01/improving-node-group-interface-editing/
2013-03-18 16:34:57 +00:00
}
Christmas coding work! ********* Node editor work: - To enable Nodes for Materials, you have to set the "Use Nodes" button, in the new Material buttons "Nodes" Panel or in header of the Node editor. Doing this will disable Material-Layers. - Nodes now execute materials ("shaders"), but still only using the previewrender code. - Nodes have (optional) previews for rendered images. - Node headers allow to hide buttons and/or preview image - Nodes can be dragged larger/smaller (right-bottom corner) - Nodes can be hidden (minimized) with hotkey H - CTRL+click on an Input Socket gives a popup with default values. - Changing Material/Texture or Mix node will adjust Node title. - Click-drag outside of a Node changes cursor to "Knife' and allows to draw a rect where to cut Links. - Added new node types RGBtoBW, Texture, In/Output, ColorRamp - Material Nodes have options to ouput diffuse or specular, or to use a negative normal. The input socket 'Normal' will force the material to use that normal, otherwise it uses the normal from the Material that has the node tree. - When drawing a link between two not-matching sockets, Blender inserts a converting node (now only for value/rgb combos) - When drawing a link to an input socket that's already in use, the old link will either disappear or flip to another unused socket. - A click on a Material Node will activate it, and show all its settings in the Material Buttons. Active Material Nodes draw the material icon in red. - A click on any node will show its options in the Node Panel in the Material buttons. - Multiple Output Nodes can be used, to sample contents of a tree, but only one Output is the real one, which is indicated in a different color and red material icon. - Added ThemeColors for node types - ALT+C will convert existing Material-Layers to Node... this currently only adds the material/mix nodes and connects them. Dunno if this is worth a lot of coding work to make perfect? - Press C to call another "Solve order", which will show all possible cyclic conflicts (if there are). - Technical: nodes now use "Type" structs which define the structure of nodes and in/output sockets. The Type structs store all fixed info, callbacks, and allow to reconstruct saved Nodes to match what is required by Blender. - Defining (new) nodes now is as simple as filling in a fixed Type struct, plus code some callbacks. A doc will be made! - Node preview images are by default float ********* Icon drawing: - Cleanup of how old icons were implemented in new system, making them 16x16 too, correctly centered *and* scaled. - Made drawing Icons use float coordinates - Moved BIF_calcpreview_image() into interface_icons.c, renamed it icon_from_image(). Removed a lot of unneeded Imbuf magic here! :) - Skipped scaling and imbuf copying when icons are OK size ********* Preview render: - Huge cleanup of code.... - renaming BIF_xxx calls that only were used internally - BIF_previewrender() now accepts an argument for rendering method, so it supports icons, buttonwindow previewrender and node editor - Only a single BIF_preview_changed() call now exists, supporting all signals as needed for buttos and node editor ********* More stuff: - glutil.c, glaDrawPixelsSafe() and glaDrawPixelsTex() now accept format argument for GL_FLOAT rects - Made the ColorBand become a built-in button for interface.c Was a load of cleanup work in buttons_shading.c... - removed a load of unneeded glBlendFunc() calls - Fixed bug in calculating text length for buttons (ancient!)
2005-12-28 15:42:51 +00:00
}
/* NOTE: This function is called to initialize node data based on the type.
* The #bNodeType may not be registered at creation time of the node,
* so this can be delayed until the node type gets registered.
*/
static void node_init(const bContext *C, bNodeTree *ntree, bNode *node)
{
BLI_assert(ntree != nullptr);
bNodeType *ntype = node->typeinfo;
if (ntype == &NodeTypeUndefined) {
return;
}
2018-06-17 17:05:51 +02:00
/* only do this once */
if (node->flag & NODE_INIT) {
return;
Merge of the PyNodes branch (aka "custom nodes") into trunk. PyNodes opens up the node system in Blender to scripters and adds a number of UI-level improvements. === Dynamic node type registration === Node types can now be added at runtime, using the RNA registration mechanism from python. This enables addons such as render engines to create a complete user interface with nodes. Examples of how such nodes can be defined can be found in my personal wiki docs atm [1] and as a script template in release/scripts/templates_py/custom_nodes.py [2]. === Node group improvements === Each node editor now has a tree history of edited node groups, which allows opening and editing nested node groups. The node editor also supports pinning now, so that different spaces can be used to edit different node groups simultaneously. For more ramblings and rationale see (really old) blog post on code.blender.org [3]. The interface of node groups has been overhauled. Sockets of a node group are no longer displayed in columns on either side, but instead special input/output nodes are used to mirror group sockets inside a node tree. This solves the problem of long node lines in groups and allows more adaptable node layout. Internal sockets can be exposed from a group by either connecting to the extension sockets in input/output nodes (shown as empty circle) or by adding sockets from the node property bar in the "Interface" panel. Further details such as the socket name can also be changed there. [1] http://wiki.blender.org/index.php/User:Phonybone/Python_Nodes [2] http://projects.blender.org/scm/viewvc.php/trunk/blender/release/scripts/templates_py/custom_nodes.py?view=markup&root=bf-blender [3] http://code.blender.org/index.php/2012/01/improving-node-group-interface-editing/
2013-03-18 16:34:57 +00:00
}
node->flag = NODE_SELECT | NODE_OPTIONS | ntype->flag;
node->width = ntype->width;
node->height = ntype->height;
node->color[0] = node->color[1] = node->color[2] = 0.608; /* default theme color */
/* initialize the node name with the node label.
* NOTE: do this after the initfunc so nodes get their data set which may be used in naming
* (node groups for example) */
/* XXX Do not use nodeLabel() here, it returns translated content for UI,
* which should *only* be used in UI, *never* in data...
* Data have their own translation option!
* This solution may be a bit rougher than nodeLabel()'s returned string, but it's simpler
* than adding "do_translate" flags to this func (and labelfunc() as well). */
DATA_(ntype->ui_name).copy_utf8_truncated(node->name);
node_unique_name(*ntree, *node);
/* Generally sockets should be added after the initialization, because the set of sockets might
* depend on node properties. */
const bool add_sockets_before_init = node->type_legacy == CMP_NODE_R_LAYERS;
if (add_sockets_before_init) {
node_add_sockets_from_type(ntree, node, ntype);
Merge of the PyNodes branch (aka "custom nodes") into trunk. PyNodes opens up the node system in Blender to scripters and adds a number of UI-level improvements. === Dynamic node type registration === Node types can now be added at runtime, using the RNA registration mechanism from python. This enables addons such as render engines to create a complete user interface with nodes. Examples of how such nodes can be defined can be found in my personal wiki docs atm [1] and as a script template in release/scripts/templates_py/custom_nodes.py [2]. === Node group improvements === Each node editor now has a tree history of edited node groups, which allows opening and editing nested node groups. The node editor also supports pinning now, so that different spaces can be used to edit different node groups simultaneously. For more ramblings and rationale see (really old) blog post on code.blender.org [3]. The interface of node groups has been overhauled. Sockets of a node group are no longer displayed in columns on either side, but instead special input/output nodes are used to mirror group sockets inside a node tree. This solves the problem of long node lines in groups and allows more adaptable node layout. Internal sockets can be exposed from a group by either connecting to the extension sockets in input/output nodes (shown as empty circle) or by adding sockets from the node property bar in the "Interface" panel. Further details such as the socket name can also be changed there. [1] http://wiki.blender.org/index.php/User:Phonybone/Python_Nodes [2] http://projects.blender.org/scm/viewvc.php/trunk/blender/release/scripts/templates_py/custom_nodes.py?view=markup&root=bf-blender [3] http://code.blender.org/index.php/2012/01/improving-node-group-interface-editing/
2013-03-18 16:34:57 +00:00
}
2018-06-17 17:05:51 +02:00
if (ntype->initfunc != nullptr) {
ntype->initfunc(ntree, node);
}
2018-06-17 17:05:51 +02:00
if (ntree->typeinfo && ntree->typeinfo->node_add_init) {
ntree->typeinfo->node_add_init(ntree, node);
}
2018-06-17 17:05:51 +02:00
if (!add_sockets_before_init) {
node_add_sockets_from_type(ntree, node, ntype);
}
2018-06-17 17:05:51 +02:00
if (node->id) {
id_us_plus(node->id);
}
2018-06-17 17:05:51 +02:00
if (ntype->initfunc_api) {
PointerRNA ptr = RNA_pointer_create_discrete(&ntree->id, &RNA_Node, node);
/* XXX WARNING: context can be nullptr in case nodes are added in do_versions.
* Delayed init is not supported for nodes with context-based `initfunc_api` at the moment. */
BLI_assert(C != nullptr);
ntype->initfunc_api(C, &ptr);
}
node->flag |= NODE_INIT;
}
static void ntree_set_typeinfo(bNodeTree *ntree, bNodeTreeType *typeinfo)
{
if (typeinfo) {
ntree->typeinfo = typeinfo;
}
else {
ntree->typeinfo = &NodeTreeTypeUndefined;
}
/* Deprecated integer type. */
ntree->type = ntree->typeinfo->type;
BKE_ntree_update_tag_all(ntree);
}
static void node_set_typeinfo(const bContext *C,
bNodeTree *ntree,
bNode *node,
bNodeType *typeinfo)
{
/* for nodes saved in older versions storage can get lost, make undefined then */
if (node->flag & NODE_INIT) {
if (typeinfo && typeinfo->storagename[0] && !node->storage) {
typeinfo = nullptr;
}
}
if (typeinfo) {
node->typeinfo = typeinfo;
/* deprecated integer type */
node->type_legacy = typeinfo->type_legacy;
/* initialize the node if necessary */
node_init(C, ntree, node);
}
else {
node->typeinfo = &NodeTypeUndefined;
}
2025-02-11 17:25:10 +01:00
BKE_ntree_update_tag_node_type(ntree, node);
}
/* WARNING: default_value must either be null or match the typeinfo at this point.
* This function is called both for initializing new sockets and after loading files.
*/
static void node_socket_set_typeinfo(bNodeTree *ntree,
bNodeSocket *sock,
bNodeSocketType *typeinfo)
{
if (typeinfo) {
sock->typeinfo = typeinfo;
/* deprecated integer type */
sock->type = typeinfo->type;
if (sock->default_value == nullptr) {
/* initialize the default_value pointer used by standard socket types */
node_socket_init_default_value(sock);
}
}
else {
sock->typeinfo = &NodeSocketTypeUndefined;
}
BKE_ntree_update_tag_socket_type(ntree, sock);
Nodes: Adds button to groups to change type of sockets. The menu lists all socket types that are valid for the node tree. Changing a socket type updates all instances of the group and keeps existing links to the socket. If changing the socket type leads to incorrect node connections the links are flagged as invalid (red) and ignored but not removed. This is so users don't lose information and can then fix resulting issues. For example: Changing a Color socket to a Shader socket can cause an invalid Shader-to-Color connection. Implementation details: The new `NODE_OT_tree_socket_change_type` operator uses the generic `rna_node_socket_type_itemf` function to list all eligible socket types. It uses the tree type's `valid_socket_type` callback to test for valid types. In addition it also checks the subtype, because multiple RNA types are registered for the same base type. The `valid_socket_type` callback has been modified slightly to accept full socket types instead of just the base type enum, so that custom (python) socket types can be used by this operator. The `nodeModifySocketType` function is now called when group nodes encounter a socket type mismatch, instead of replacing the socket entirely. This ensures that links are kept to/from group nodes as well as group input/output nodes. The `nodeModifySocketType` function now also takes a full `bNodeSocketType` instead of just the base and subtype enum (a shortcut `nodeModifySocketTypeStatic` exists for when only static types are used). Differential Revision: https://developer.blender.org/D10912
2021-07-06 18:36:11 +01:00
}
/* Set specific typeinfo pointers in all node trees on register/unregister */
static void update_typeinfo(Main *bmain,
const bContext *C,
bNodeTreeType *treetype,
bNodeType *nodetype,
bNodeSocketType *socktype,
const bool unregister)
Nodes: Adds button to groups to change type of sockets. The menu lists all socket types that are valid for the node tree. Changing a socket type updates all instances of the group and keeps existing links to the socket. If changing the socket type leads to incorrect node connections the links are flagged as invalid (red) and ignored but not removed. This is so users don't lose information and can then fix resulting issues. For example: Changing a Color socket to a Shader socket can cause an invalid Shader-to-Color connection. Implementation details: The new `NODE_OT_tree_socket_change_type` operator uses the generic `rna_node_socket_type_itemf` function to list all eligible socket types. It uses the tree type's `valid_socket_type` callback to test for valid types. In addition it also checks the subtype, because multiple RNA types are registered for the same base type. The `valid_socket_type` callback has been modified slightly to accept full socket types instead of just the base type enum, so that custom (python) socket types can be used by this operator. The `nodeModifySocketType` function is now called when group nodes encounter a socket type mismatch, instead of replacing the socket entirely. This ensures that links are kept to/from group nodes as well as group input/output nodes. The `nodeModifySocketType` function now also takes a full `bNodeSocketType` instead of just the base and subtype enum (a shortcut `nodeModifySocketTypeStatic` exists for when only static types are used). Differential Revision: https://developer.blender.org/D10912
2021-07-06 18:36:11 +01:00
{
if (!bmain) {
return;
}
FOREACH_NODETREE_BEGIN (bmain, ntree, id) {
if (treetype && ntree->idname == treetype->idname) {
ntree_set_typeinfo(ntree, unregister ? nullptr : treetype);
}
/* initialize nodes */
for (bNode *node : ntree->all_nodes()) {
if (nodetype && node->idname == nodetype->idname) {
node_set_typeinfo(C, ntree, node, unregister ? nullptr : nodetype);
}
/* initialize node sockets */
LISTBASE_FOREACH (bNodeSocket *, sock, &node->inputs) {
if (socktype && sock->idname == socktype->idname) {
node_socket_set_typeinfo(ntree, sock, unregister ? nullptr : socktype);
}
}
LISTBASE_FOREACH (bNodeSocket *, sock, &node->outputs) {
if (socktype && sock->idname == socktype->idname) {
node_socket_set_typeinfo(ntree, sock, unregister ? nullptr : socktype);
}
}
}
}
FOREACH_NODETREE_END;
}
void node_tree_set_type(const bContext *C, bNodeTree &ntree)
Christmas coding work! ********* Node editor work: - To enable Nodes for Materials, you have to set the "Use Nodes" button, in the new Material buttons "Nodes" Panel or in header of the Node editor. Doing this will disable Material-Layers. - Nodes now execute materials ("shaders"), but still only using the previewrender code. - Nodes have (optional) previews for rendered images. - Node headers allow to hide buttons and/or preview image - Nodes can be dragged larger/smaller (right-bottom corner) - Nodes can be hidden (minimized) with hotkey H - CTRL+click on an Input Socket gives a popup with default values. - Changing Material/Texture or Mix node will adjust Node title. - Click-drag outside of a Node changes cursor to "Knife' and allows to draw a rect where to cut Links. - Added new node types RGBtoBW, Texture, In/Output, ColorRamp - Material Nodes have options to ouput diffuse or specular, or to use a negative normal. The input socket 'Normal' will force the material to use that normal, otherwise it uses the normal from the Material that has the node tree. - When drawing a link between two not-matching sockets, Blender inserts a converting node (now only for value/rgb combos) - When drawing a link to an input socket that's already in use, the old link will either disappear or flip to another unused socket. - A click on a Material Node will activate it, and show all its settings in the Material Buttons. Active Material Nodes draw the material icon in red. - A click on any node will show its options in the Node Panel in the Material buttons. - Multiple Output Nodes can be used, to sample contents of a tree, but only one Output is the real one, which is indicated in a different color and red material icon. - Added ThemeColors for node types - ALT+C will convert existing Material-Layers to Node... this currently only adds the material/mix nodes and connects them. Dunno if this is worth a lot of coding work to make perfect? - Press C to call another "Solve order", which will show all possible cyclic conflicts (if there are). - Technical: nodes now use "Type" structs which define the structure of nodes and in/output sockets. The Type structs store all fixed info, callbacks, and allow to reconstruct saved Nodes to match what is required by Blender. - Defining (new) nodes now is as simple as filling in a fixed Type struct, plus code some callbacks. A doc will be made! - Node preview images are by default float ********* Icon drawing: - Cleanup of how old icons were implemented in new system, making them 16x16 too, correctly centered *and* scaled. - Made drawing Icons use float coordinates - Moved BIF_calcpreview_image() into interface_icons.c, renamed it icon_from_image(). Removed a lot of unneeded Imbuf magic here! :) - Skipped scaling and imbuf copying when icons are OK size ********* Preview render: - Huge cleanup of code.... - renaming BIF_xxx calls that only were used internally - BIF_previewrender() now accepts an argument for rendering method, so it supports icons, buttonwindow previewrender and node editor - Only a single BIF_preview_changed() call now exists, supporting all signals as needed for buttos and node editor ********* More stuff: - glutil.c, glaDrawPixelsSafe() and glaDrawPixelsTex() now accept format argument for GL_FLOAT rects - Made the ColorBand become a built-in button for interface.c Was a load of cleanup work in buttons_shading.c... - removed a load of unneeded glBlendFunc() calls - Fixed bug in calculating text length for buttons (ancient!)
2005-12-28 15:42:51 +00:00
{
ntree_set_typeinfo(&ntree, node_tree_type_find(ntree.idname));
for (bNode *node : ntree.all_nodes()) {
Nodes: Fix versioning 2.6 groups, causing dangling link pointers In 2.6 the old method of using bNodeSocket lists in bNodeTree directly as group sockets was replaced with new group input/output nodes. This required versioning to create those input/output nodes and then redirect links to the new node sockets. Because creating nodes relies heavily on node typeinfo this versioning was done in the `_after_linking` section of the 2.6 versioning code, running after _all other versioning_ (including for much newer versions!) has already happended. While typinfo is available at that point, doing such late versioning causes severe problems when the data structure changes, as is the case with the recent node panels patch (#111348). The new node group interface also has versioning code for 4.0, but this runs _before_ the `_after_linking` code for 2.6! Versioning for node panels expects sockets in bNodeTree to not have any links pointing at them, but this is not true for old 2.6 files which have not yet been fully versioned at that point, because of the late versioning stage. Subsequently 2.6 `_after_linking` code crashes when trying to modify node links with dangling pointers. The solution here is to move the old versioning code out of the `after_linking` stage to restore the expected versioning chain. This requires creating nodes and node sockets without any typeinfo, but luckily we only need to create simple known group input/output nodes which don't have much complicated behavior. Pull Request: https://projects.blender.org/blender/blender/pulls/111704
2023-09-05 12:37:05 +02:00
/* Set socket typeinfo first because node initialization may rely on socket typeinfo for
* generating declarations. */
LISTBASE_FOREACH (bNodeSocket *, sock, &node->inputs) {
node_socket_set_typeinfo(&ntree, sock, node_socket_type_find(sock->idname));
}
LISTBASE_FOREACH (bNodeSocket *, sock, &node->outputs) {
node_socket_set_typeinfo(&ntree, sock, node_socket_type_find(sock->idname));
}
Nodes: Fix versioning 2.6 groups, causing dangling link pointers In 2.6 the old method of using bNodeSocket lists in bNodeTree directly as group sockets was replaced with new group input/output nodes. This required versioning to create those input/output nodes and then redirect links to the new node sockets. Because creating nodes relies heavily on node typeinfo this versioning was done in the `_after_linking` section of the 2.6 versioning code, running after _all other versioning_ (including for much newer versions!) has already happended. While typinfo is available at that point, doing such late versioning causes severe problems when the data structure changes, as is the case with the recent node panels patch (#111348). The new node group interface also has versioning code for 4.0, but this runs _before_ the `_after_linking` code for 2.6! Versioning for node panels expects sockets in bNodeTree to not have any links pointing at them, but this is not true for old 2.6 files which have not yet been fully versioned at that point, because of the late versioning stage. Subsequently 2.6 `_after_linking` code crashes when trying to modify node links with dangling pointers. The solution here is to move the old versioning code out of the `after_linking` stage to restore the expected versioning chain. This requires creating nodes and node sockets without any typeinfo, but luckily we only need to create simple known group input/output nodes which don't have much complicated behavior. Pull Request: https://projects.blender.org/blender/blender/pulls/111704
2023-09-05 12:37:05 +02:00
node_set_typeinfo(C, &ntree, node, node_type_find(node->idname));
}
Christmas coding work! ********* Node editor work: - To enable Nodes for Materials, you have to set the "Use Nodes" button, in the new Material buttons "Nodes" Panel or in header of the Node editor. Doing this will disable Material-Layers. - Nodes now execute materials ("shaders"), but still only using the previewrender code. - Nodes have (optional) previews for rendered images. - Node headers allow to hide buttons and/or preview image - Nodes can be dragged larger/smaller (right-bottom corner) - Nodes can be hidden (minimized) with hotkey H - CTRL+click on an Input Socket gives a popup with default values. - Changing Material/Texture or Mix node will adjust Node title. - Click-drag outside of a Node changes cursor to "Knife' and allows to draw a rect where to cut Links. - Added new node types RGBtoBW, Texture, In/Output, ColorRamp - Material Nodes have options to ouput diffuse or specular, or to use a negative normal. The input socket 'Normal' will force the material to use that normal, otherwise it uses the normal from the Material that has the node tree. - When drawing a link between two not-matching sockets, Blender inserts a converting node (now only for value/rgb combos) - When drawing a link to an input socket that's already in use, the old link will either disappear or flip to another unused socket. - A click on a Material Node will activate it, and show all its settings in the Material Buttons. Active Material Nodes draw the material icon in red. - A click on any node will show its options in the Node Panel in the Material buttons. - Multiple Output Nodes can be used, to sample contents of a tree, but only one Output is the real one, which is indicated in a different color and red material icon. - Added ThemeColors for node types - ALT+C will convert existing Material-Layers to Node... this currently only adds the material/mix nodes and connects them. Dunno if this is worth a lot of coding work to make perfect? - Press C to call another "Solve order", which will show all possible cyclic conflicts (if there are). - Technical: nodes now use "Type" structs which define the structure of nodes and in/output sockets. The Type structs store all fixed info, callbacks, and allow to reconstruct saved Nodes to match what is required by Blender. - Defining (new) nodes now is as simple as filling in a fixed Type struct, plus code some callbacks. A doc will be made! - Node preview images are by default float ********* Icon drawing: - Cleanup of how old icons were implemented in new system, making them 16x16 too, correctly centered *and* scaled. - Made drawing Icons use float coordinates - Moved BIF_calcpreview_image() into interface_icons.c, renamed it icon_from_image(). Removed a lot of unneeded Imbuf magic here! :) - Skipped scaling and imbuf copying when icons are OK size ********* Preview render: - Huge cleanup of code.... - renaming BIF_xxx calls that only were used internally - BIF_previewrender() now accepts an argument for rendering method, so it supports icons, buttonwindow previewrender and node editor - Only a single BIF_preview_changed() call now exists, supporting all signals as needed for buttos and node editor ********* More stuff: - glutil.c, glaDrawPixelsSafe() and glaDrawPixelsTex() now accept format argument for GL_FLOAT rects - Made the ColorBand become a built-in button for interface.c Was a load of cleanup work in buttons_shading.c... - removed a load of unneeded glBlendFunc() calls - Fixed bug in calculating text length for buttons (ancient!)
2005-12-28 15:42:51 +00:00
}
template<typename T> struct NodeStructIDNameGetter {
StringRef operator()(const T *value) const
{
return StringRef(value->idname);
}
};
static auto &get_node_tree_type_map()
{
static CustomIDVectorSet<bNodeTreeType *, NodeStructIDNameGetter<bNodeTreeType>> map;
return map;
}
static auto &get_node_type_map()
{
static CustomIDVectorSet<bNodeType *, NodeStructIDNameGetter<bNodeType>> map;
return map;
}
static auto &get_node_type_alias_map()
{
static Map<std::string, std::string> map;
return map;
}
static auto &get_socket_type_map()
{
static CustomIDVectorSet<bNodeSocketType *, NodeStructIDNameGetter<bNodeSocketType>> map;
return map;
}
bNodeTreeType *node_tree_type_find(const StringRef idname)
{
bNodeTreeType *const *value = get_node_tree_type_map().lookup_key_ptr_as(idname);
if (!value) {
return nullptr;
}
return *value;
Nodes: Adds button to groups to change type of sockets. The menu lists all socket types that are valid for the node tree. Changing a socket type updates all instances of the group and keeps existing links to the socket. If changing the socket type leads to incorrect node connections the links are flagged as invalid (red) and ignored but not removed. This is so users don't lose information and can then fix resulting issues. For example: Changing a Color socket to a Shader socket can cause an invalid Shader-to-Color connection. Implementation details: The new `NODE_OT_tree_socket_change_type` operator uses the generic `rna_node_socket_type_itemf` function to list all eligible socket types. It uses the tree type's `valid_socket_type` callback to test for valid types. In addition it also checks the subtype, because multiple RNA types are registered for the same base type. The `valid_socket_type` callback has been modified slightly to accept full socket types instead of just the base type enum, so that custom (python) socket types can be used by this operator. The `nodeModifySocketType` function is now called when group nodes encounter a socket type mismatch, instead of replacing the socket entirely. This ensures that links are kept to/from group nodes as well as group input/output nodes. The `nodeModifySocketType` function now also takes a full `bNodeSocketType` instead of just the base and subtype enum (a shortcut `nodeModifySocketTypeStatic` exists for when only static types are used). Differential Revision: https://developer.blender.org/D10912
2021-07-06 18:36:11 +01:00
}
2025-02-11 17:25:10 +01:00
static void defer_free_tree_type(bNodeTreeType *tree_type)
{
static ResourceScope scope;
scope.add_destruct_call([tree_type]() { MEM_delete(tree_type); });
}
static void defer_free_node_type(bNodeType *ntype)
{
static ResourceScope scope;
scope.add_destruct_call([ntype]() {
/* May be null if the type is statically allocated. */
if (ntype->free_self) {
ntype->free_self(ntype);
}
});
}
static void defer_free_socket_type(bNodeSocketType *stype)
{
static ResourceScope scope;
scope.add_destruct_call([stype]() {
/* May be null if the type is statically allocated. */
if (stype->free_self) {
stype->free_self(stype);
}
});
}
void node_tree_type_add(bNodeTreeType &nt)
Merge of the PyNodes branch (aka "custom nodes") into trunk. PyNodes opens up the node system in Blender to scripters and adds a number of UI-level improvements. === Dynamic node type registration === Node types can now be added at runtime, using the RNA registration mechanism from python. This enables addons such as render engines to create a complete user interface with nodes. Examples of how such nodes can be defined can be found in my personal wiki docs atm [1] and as a script template in release/scripts/templates_py/custom_nodes.py [2]. === Node group improvements === Each node editor now has a tree history of edited node groups, which allows opening and editing nested node groups. The node editor also supports pinning now, so that different spaces can be used to edit different node groups simultaneously. For more ramblings and rationale see (really old) blog post on code.blender.org [3]. The interface of node groups has been overhauled. Sockets of a node group are no longer displayed in columns on either side, but instead special input/output nodes are used to mirror group sockets inside a node tree. This solves the problem of long node lines in groups and allows more adaptable node layout. Internal sockets can be exposed from a group by either connecting to the extension sockets in input/output nodes (shown as empty circle) or by adding sockets from the node property bar in the "Interface" panel. Further details such as the socket name can also be changed there. [1] http://wiki.blender.org/index.php/User:Phonybone/Python_Nodes [2] http://projects.blender.org/scm/viewvc.php/trunk/blender/release/scripts/templates_py/custom_nodes.py?view=markup&root=bf-blender [3] http://code.blender.org/index.php/2012/01/improving-node-group-interface-editing/
2013-03-18 16:34:57 +00:00
{
get_node_tree_type_map().add(&nt);
/* XXX pass Main to register function? */
/* Probably not. It is pretty much expected we want to update G_MAIN here I think -
* or we'd want to update *all* active Mains, which we cannot do anyway currently. */
update_typeinfo(G_MAIN, nullptr, &nt, nullptr, nullptr, false);
}
static void ntree_free_type(void *treetype_v)
{
bNodeTreeType *treetype = static_cast<bNodeTreeType *>(treetype_v);
/* XXX pass Main to unregister function? */
/* Probably not. It is pretty much expected we want to update G_MAIN here I think -
* or we'd want to update *all* active Mains, which we cannot do anyway currently. */
update_typeinfo(G_MAIN, nullptr, treetype, nullptr, nullptr, true);
2025-02-11 17:25:10 +01:00
/* Defer freeing the tree type, because it may still be referenced by trees in depsgraph
* copies. We can't just remove these tree types, because the depsgraph may exist completely
* separate from original data. */
defer_free_tree_type(treetype);
}
void node_tree_type_free_link(const bNodeTreeType &nt)
{
get_node_tree_type_map().remove(const_cast<bNodeTreeType *>(&nt));
ntree_free_type(const_cast<bNodeTreeType *>(&nt));
}
bool node_tree_is_registered(const bNodeTree &ntree)
{
return (ntree.typeinfo != &NodeTreeTypeUndefined);
}
Span<bNodeTreeType *> node_tree_types_get()
{
return get_node_tree_type_map().as_span();
}
bNodeType *node_type_find(const StringRef idname)
{
bNodeType *const *value = get_node_type_map().lookup_key_ptr_as(idname);
if (!value) {
return nullptr;
}
return *value;
}
StringRefNull node_type_find_alias(const StringRefNull alias)
{
const std::string *idname = get_node_type_alias_map().lookup_ptr_as(alias);
if (!idname) {
return alias;
}
return *idname;
}
static void node_free_type(void *nodetype_v)
{
bNodeType *nodetype = static_cast<bNodeType *>(nodetype_v);
/* XXX pass Main to unregister function? */
/* Probably not. It is pretty much expected we want to update G_MAIN here I think -
* or we'd want to update *all* active Mains, which we cannot do anyway currently. */
update_typeinfo(G_MAIN, nullptr, nullptr, nodetype, nullptr, true);
2025-02-11 17:25:10 +01:00
/* Setting this to null is necessary for the case of static node types. When running tests,
* they may be registered and unregistered multiple times. */
Nodes: unify static and dynamic declarations This helps solving the problem encountered in #113553. The problem is that we currently can't support link-drag-search for nodes which have a dynamic declaration. With this patch, there is only a single `declare` function per node type, instead of the separate `declare` and `declare_dynamic` functions. The new `declare` function has access to the node and tree. However, both are allowed to be null. The final node declaration has a flag for whether it depends on the node context or not. Nodes that previously had a dynamic declaration should now create as much of the declaration as possible that does not depend on the node. This allows code like for link-drag-search to take those sockets into account even if the other sockets are dynamic. For node declarations that have dynamic types (e.g. Switch node), we can also add extra information to the static node declaration, like the identifier of the socket with the dynamic type. This is not part of this patch though. I can think of two main alternatives to the approach implemented here: * Define two separate functions for dynamic nodes. One that creates the "static declaration" without node context, and on that creates the actual declaration with node context. * Have a single declare function that generates "build instructions" for the actual node declaration. So instead of building the final declaration directly, one can for example add a socket whose type depends on a specific rna path in the node. The actual node declaration is then automatically generated based on the build instructions. This becomes quite a bit more tricky with dynamic amounts of sockets and introduces another indirection between declarations and what sockets the node actually has. I found the approach implemented in this patch to lead to the least amount of boilerplate (doesn't require a seperate "build instructions" data structure) and code duplication (socket properties are still only defined in one place). At the same time, it offers more flexibility to how nodes can be dynamic. Pull Request: https://projects.blender.org/blender/blender/pulls/113742
2023-10-15 20:28:23 +02:00
delete nodetype->static_declaration;
nodetype->static_declaration = nullptr;
2025-02-11 17:25:10 +01:00
/* Defer freeing the node type, because it may still be referenced by nodes in depsgraph
* copies. We can't just remove these node types, because the depsgraph may exist completely
* separate from original data. */
defer_free_node_type(nodetype);
}
void node_register_type(bNodeType &nt)
{
/* debug only: basic verification of registered types */
BLI_assert(!nt.idname.empty());
BLI_assert(nt.poll != nullptr);
RNA_def_struct_ui_text(nt.rna_ext.srna, nt.ui_name.c_str(), nt.ui_description.c_str());
if (!nt.enum_name_legacy) {
/* For new nodes, use the idname as a unique identifier. */
nt.enum_name_legacy = nt.idname.c_str();
}
if (nt.declare) {
nt.static_declaration = new nodes::NodeDeclaration();
nodes::build_node_declaration(nt, *nt.static_declaration, nullptr, nullptr);
}
get_node_type_map().add_new(&nt);
/* XXX pass Main to register function? */
/* Probably not. It is pretty much expected we want to update G_MAIN here I think -
* or we'd want to update *all* active Mains, which we cannot do anyway currently. */
update_typeinfo(G_MAIN, nullptr, nullptr, &nt, nullptr, false);
}
void node_unregister_type(bNodeType &nt)
{
get_node_type_map().remove(&nt);
node_free_type(&nt);
}
Span<bNodeType *> node_types_get()
{
return get_node_type_map().as_span();
}
void node_register_alias(bNodeType &nt, const StringRef alias)
{
get_node_type_alias_map().add_new(alias, nt.idname);
}
Span<bNodeSocketType *> node_socket_types_get()
{
return get_socket_type_map().as_span();
}
bNodeSocketType *node_socket_type_find(const StringRef idname)
{
bNodeSocketType *const *value = get_socket_type_map().lookup_key_ptr_as(idname);
if (!value) {
return nullptr;
}
return *value;
}
bNodeSocketType *node_socket_type_find_static(const int type, const int subtype)
{
const std::optional<StringRefNull> idname = node_static_socket_type(type, subtype);
if (!idname) {
return nullptr;
}
return node_socket_type_find(*idname);
}
static void node_free_socket_type(void *socktype_v)
{
bNodeSocketType *socktype = static_cast<bNodeSocketType *>(socktype_v);
/* XXX pass Main to unregister function? */
/* Probably not. It is pretty much expected we want to update G_MAIN here I think -
* or we'd want to update *all* active Mains, which we cannot do anyway currently. */
update_typeinfo(G_MAIN, nullptr, nullptr, nullptr, socktype, true);
2025-02-11 17:25:10 +01:00
/* Defer freeing the socket type, because it may still be referenced by nodes in depsgraph
* copies. We can't just remove these socket types, because the depsgraph may exist completely
* separate from original data. */
defer_free_socket_type(socktype);
}
void node_register_socket_type(bNodeSocketType &st)
{
get_socket_type_map().add(&st);
/* XXX pass Main to register function? */
/* Probably not. It is pretty much expected we want to update G_MAIN here I think -
* or we'd want to update *all* active Mains, which we cannot do anyway currently. */
update_typeinfo(G_MAIN, nullptr, nullptr, nullptr, &st, false);
}
void node_unregister_socket_type(bNodeSocketType &st)
{
get_socket_type_map().remove(&st);
node_free_socket_type(&st);
}
bool node_socket_is_registered(const bNodeSocket &sock)
{
return (sock.typeinfo != &NodeSocketTypeUndefined);
}
StringRefNull node_socket_type_label(const bNodeSocketType &stype)
{
/* Use socket type name as a fallback if label is undefined. */
if (stype.label[0] == '\0') {
return RNA_struct_ui_name(stype.ext_socket.srna);
}
return stype.label;
}
StringRefNull node_socket_sub_type_label(int subtype)
{
const char *name;
if (RNA_enum_name(rna_enum_property_subtype_items, subtype, &name)) {
return name;
}
return "";
}
bNodeSocket *node_find_socket(bNode &node,
const eNodeSocketInOut in_out,
const StringRef identifier)
{
const ListBase *sockets = (in_out == SOCK_IN) ? &node.inputs : &node.outputs;
LISTBASE_FOREACH (bNodeSocket *, sock, sockets) {
if (sock->identifier == identifier) {
return sock;
}
}
return nullptr;
}
const bNodeSocket *node_find_socket(const bNode &node,
const eNodeSocketInOut in_out,
const StringRef identifier)
{
/* Reuse the implementation of the mutable accessor. */
return node_find_socket(*const_cast<bNode *>(&node), in_out, identifier);
}
bNodeSocket *node_find_enabled_socket(bNode &node,
const eNodeSocketInOut in_out,
const StringRef name)
{
ListBase *sockets = (in_out == SOCK_IN) ? &node.inputs : &node.outputs;
LISTBASE_FOREACH (bNodeSocket *, socket, sockets) {
if (socket->is_available() && socket->name == name) {
return socket;
}
}
return nullptr;
}
bNodeSocket *node_find_enabled_input_socket(bNode &node, const StringRef name)
{
return node_find_enabled_socket(node, SOCK_IN, name);
}
bNodeSocket *node_find_enabled_output_socket(bNode &node, const StringRef name)
{
return node_find_enabled_socket(node, SOCK_OUT, name);
}
static bNodeSocket *make_socket(bNodeTree *ntree,
bNode * /*node*/,
const int in_out,
ListBase *lb,
const StringRefNull idname,
const StringRefNull identifier,
const StringRefNull name)
{
char auto_identifier[MAX_NAME];
if (identifier[0] != '\0') {
/* use explicit identifier */
identifier.copy_utf8_truncated(auto_identifier);
}
else {
/* if no explicit identifier is given, assign a unique identifier based on the name */
name.copy_utf8_truncated(auto_identifier);
}
/* Make the identifier unique. */
BLI_uniquename_cb(
[&](const StringRef check_name) {
LISTBASE_FOREACH (bNodeSocket *, sock, lb) {
if (sock->identifier == check_name) {
return true;
}
}
return false;
},
"socket",
'_',
auto_identifier,
sizeof(auto_identifier));
bNodeSocket *sock = MEM_callocN<bNodeSocket>(__func__);
sock->runtime = MEM_new<bNodeSocketRuntime>(__func__);
sock->in_out = in_out;
STRNCPY(sock->identifier, auto_identifier);
sock->limit = (in_out == SOCK_IN ? 1 : 0xFFF);
name.copy_utf8_truncated(sock->name);
sock->storage = nullptr;
sock->flag |= SOCK_COLLAPSED;
sock->type = SOCK_CUSTOM; /* int type undefined by default */
idname.copy_utf8_truncated(sock->idname);
node_socket_set_typeinfo(ntree, sock, node_socket_type_find(idname));
return sock;
}
static void socket_id_user_increment(bNodeSocket *sock)
{
switch (eNodeSocketDatatype(sock->type)) {
case SOCK_OBJECT: {
bNodeSocketValueObject &default_value = *sock->default_value_typed<bNodeSocketValueObject>();
id_us_plus(reinterpret_cast<ID *>(default_value.value));
break;
}
case SOCK_IMAGE: {
bNodeSocketValueImage &default_value = *sock->default_value_typed<bNodeSocketValueImage>();
id_us_plus(reinterpret_cast<ID *>(default_value.value));
break;
}
case SOCK_COLLECTION: {
bNodeSocketValueCollection &default_value =
*sock->default_value_typed<bNodeSocketValueCollection>();
id_us_plus(reinterpret_cast<ID *>(default_value.value));
break;
}
case SOCK_TEXTURE: {
bNodeSocketValueTexture &default_value =
*sock->default_value_typed<bNodeSocketValueTexture>();
id_us_plus(reinterpret_cast<ID *>(default_value.value));
break;
}
case SOCK_MATERIAL: {
bNodeSocketValueMaterial &default_value =
*sock->default_value_typed<bNodeSocketValueMaterial>();
id_us_plus(reinterpret_cast<ID *>(default_value.value));
break;
}
case SOCK_FLOAT:
case SOCK_VECTOR:
case SOCK_RGBA:
case SOCK_BOOLEAN:
case SOCK_ROTATION:
case SOCK_MATRIX:
case SOCK_INT:
case SOCK_STRING:
Geometry Nodes: Menu Switch Node This patch adds support for _Menu Switch_ nodes and enum definitions in node trees more generally. The design is based on the outcome of the [2022 Nodes Workshop](https://code.blender.org/2022/11/geometry-nodes-workshop-2022/#menu-switch). The _Menu Switch_ node is an advanced version of the _Switch_ node which has a customizable **menu input socket** instead of a simple boolean. The _items_ of this menu are owned by the node itself. Each item has a name and description and unique identifier that is used internally. A menu _socket_ represents a concrete value out of the list of items. To enable selection of an enum value for unconnected sockets the menu is presented as a dropdown list like built-in enums. When the socket is connected a shared pointer to the enum definition is propagated along links and stored in socket default values. This allows node groups to expose a menu from an internal menu switch as a parameter. The enum definition is a runtime copy of the enum items in DNA that allows sharing. A menu socket can have multiple connections, which can lead to ambiguity. If two or more different menu source nodes are connected to a socket it gets marked as _undefined_. Any connection to an undefined menu socket is invalid as a hint to users that there is a problem. A warning/error is also shown on nodes with undefined menu sockets. At runtime the value of a menu socket is the simple integer identifier. This can also be a field in geometry nodes. The identifier is unique within each enum definition, and it is persistent even when items are added, removed, or changed. Changing the name of an item does not affect the internal identifier, so users can rename enum items without breaking existing input values. This also persists if, for example, a linked node group is temporarily unavailable. Pull Request: https://projects.blender.org/blender/blender/pulls/113445
2024-01-26 12:40:01 +01:00
case SOCK_MENU:
case SOCK_CUSTOM:
case SOCK_SHADER:
case SOCK_GEOMETRY:
Geometry Nodes: add Closures and Bundles behind experimental feature flag This implements bundles and closures which are described in more detail in this blog post: https://code.blender.org/2024/11/geometry-nodes-workshop-october-2024/ tl;dr: * Bundles are containers that allow storing multiple socket values in a single value. Each value in the bundle is identified by a name. Bundles can be nested. * Closures are functions that are created with the Closure Zone and can be evaluated with the Evaluate Closure node. To use the patch, the `Bundle and Closure Nodes` experimental feature has to be enabled. This is necessary, because these features are not fully done yet and still need iterations to improve the workflow before they can be officially released. These iterations are easier to do in `main` than in a separate branch though. That's because this patch is quite large and somewhat prone to merge conflicts. Also other work we want to do, depends on this. This adds the following new nodes: * Combine Bundle: can pack multiple values into one. * Separate Bundle: extracts values from a bundle. * Closure Zone: outputs a closure zone for use in the `Evaluate Closure` node. * Evaluate Closure: evaluates the passed in closure. Things that will be added soon after this lands: * Fields in bundles and closures. The way this is done changes with #134811, so I rather implement this once both are in `main`. * UI features for keeping sockets in sync (right now there are warnings only). One bigger issue is the limited support for lazyness. For example, all inputs of a Combine Bundle node will be evaluated, even if they are not all needed. The same is true for all captured values of a closure. This is a deeper limitation that needs to be resolved at some point. This will likely be done after an initial version of this patch is done. Pull Request: https://projects.blender.org/blender/blender/pulls/128340
2025-04-03 15:44:06 +02:00
case SOCK_BUNDLE:
case SOCK_CLOSURE:
break;
}
}
/** \return True if the socket had an ID default value. */
static bool socket_id_user_decrement(bNodeSocket *sock)
{
switch (eNodeSocketDatatype(sock->type)) {
case SOCK_OBJECT: {
bNodeSocketValueObject &default_value = *sock->default_value_typed<bNodeSocketValueObject>();
id_us_min(reinterpret_cast<ID *>(default_value.value));
return default_value.value != nullptr;
}
case SOCK_IMAGE: {
bNodeSocketValueImage &default_value = *sock->default_value_typed<bNodeSocketValueImage>();
id_us_min(reinterpret_cast<ID *>(default_value.value));
return default_value.value != nullptr;
}
case SOCK_COLLECTION: {
bNodeSocketValueCollection &default_value =
*sock->default_value_typed<bNodeSocketValueCollection>();
id_us_min(reinterpret_cast<ID *>(default_value.value));
return default_value.value != nullptr;
}
case SOCK_TEXTURE: {
bNodeSocketValueTexture &default_value =
*sock->default_value_typed<bNodeSocketValueTexture>();
id_us_min(reinterpret_cast<ID *>(default_value.value));
return default_value.value != nullptr;
}
case SOCK_MATERIAL: {
bNodeSocketValueMaterial &default_value =
*sock->default_value_typed<bNodeSocketValueMaterial>();
id_us_min(reinterpret_cast<ID *>(default_value.value));
return default_value.value != nullptr;
}
case SOCK_FLOAT:
case SOCK_VECTOR:
case SOCK_RGBA:
case SOCK_BOOLEAN:
case SOCK_ROTATION:
case SOCK_MATRIX:
case SOCK_INT:
case SOCK_STRING:
Geometry Nodes: Menu Switch Node This patch adds support for _Menu Switch_ nodes and enum definitions in node trees more generally. The design is based on the outcome of the [2022 Nodes Workshop](https://code.blender.org/2022/11/geometry-nodes-workshop-2022/#menu-switch). The _Menu Switch_ node is an advanced version of the _Switch_ node which has a customizable **menu input socket** instead of a simple boolean. The _items_ of this menu are owned by the node itself. Each item has a name and description and unique identifier that is used internally. A menu _socket_ represents a concrete value out of the list of items. To enable selection of an enum value for unconnected sockets the menu is presented as a dropdown list like built-in enums. When the socket is connected a shared pointer to the enum definition is propagated along links and stored in socket default values. This allows node groups to expose a menu from an internal menu switch as a parameter. The enum definition is a runtime copy of the enum items in DNA that allows sharing. A menu socket can have multiple connections, which can lead to ambiguity. If two or more different menu source nodes are connected to a socket it gets marked as _undefined_. Any connection to an undefined menu socket is invalid as a hint to users that there is a problem. A warning/error is also shown on nodes with undefined menu sockets. At runtime the value of a menu socket is the simple integer identifier. This can also be a field in geometry nodes. The identifier is unique within each enum definition, and it is persistent even when items are added, removed, or changed. Changing the name of an item does not affect the internal identifier, so users can rename enum items without breaking existing input values. This also persists if, for example, a linked node group is temporarily unavailable. Pull Request: https://projects.blender.org/blender/blender/pulls/113445
2024-01-26 12:40:01 +01:00
case SOCK_MENU:
case SOCK_CUSTOM:
case SOCK_SHADER:
case SOCK_GEOMETRY:
Geometry Nodes: add Closures and Bundles behind experimental feature flag This implements bundles and closures which are described in more detail in this blog post: https://code.blender.org/2024/11/geometry-nodes-workshop-october-2024/ tl;dr: * Bundles are containers that allow storing multiple socket values in a single value. Each value in the bundle is identified by a name. Bundles can be nested. * Closures are functions that are created with the Closure Zone and can be evaluated with the Evaluate Closure node. To use the patch, the `Bundle and Closure Nodes` experimental feature has to be enabled. This is necessary, because these features are not fully done yet and still need iterations to improve the workflow before they can be officially released. These iterations are easier to do in `main` than in a separate branch though. That's because this patch is quite large and somewhat prone to merge conflicts. Also other work we want to do, depends on this. This adds the following new nodes: * Combine Bundle: can pack multiple values into one. * Separate Bundle: extracts values from a bundle. * Closure Zone: outputs a closure zone for use in the `Evaluate Closure` node. * Evaluate Closure: evaluates the passed in closure. Things that will be added soon after this lands: * Fields in bundles and closures. The way this is done changes with #134811, so I rather implement this once both are in `main`. * UI features for keeping sockets in sync (right now there are warnings only). One bigger issue is the limited support for lazyness. For example, all inputs of a Combine Bundle node will be evaluated, even if they are not all needed. The same is true for all captured values of a closure. This is a deeper limitation that needs to be resolved at some point. This will likely be done after an initial version of this patch is done. Pull Request: https://projects.blender.org/blender/blender/pulls/128340
2025-04-03 15:44:06 +02:00
case SOCK_BUNDLE:
case SOCK_CLOSURE:
break;
}
return false;
}
void node_modify_socket_type(bNodeTree &ntree,
bNode & /*node*/,
bNodeSocket &sock,
const StringRefNull idname)
{
bNodeSocketType *socktype = node_socket_type_find(idname);
if (!socktype) {
CLOG_ERROR(&LOG, "node socket type %s undefined", idname.c_str());
return;
}
if (sock.default_value) {
if (sock.type != socktype->type) {
/* Only reallocate the default value if the type changed so that UI data like min and max
* isn't removed. This assumes that the default value is stored in the same format for all
* socket types with the same #eNodeSocketDatatype. */
socket_id_user_decrement(&sock);
MEM_freeN(sock.default_value);
sock.default_value = nullptr;
}
else {
/* Update the socket subtype when the storage isn't freed and recreated. */
switch (eNodeSocketDatatype(sock.type)) {
case SOCK_FLOAT: {
sock.default_value_typed<bNodeSocketValueFloat>()->subtype = socktype->subtype;
break;
}
case SOCK_VECTOR: {
sock.default_value_typed<bNodeSocketValueVector>()->subtype = socktype->subtype;
break;
}
case SOCK_INT: {
sock.default_value_typed<bNodeSocketValueInt>()->subtype = socktype->subtype;
break;
}
case SOCK_STRING: {
sock.default_value_typed<bNodeSocketValueString>()->subtype = socktype->subtype;
break;
}
case SOCK_RGBA:
case SOCK_SHADER:
case SOCK_BOOLEAN:
case SOCK_ROTATION:
case SOCK_MATRIX:
case SOCK_CUSTOM:
case SOCK_OBJECT:
case SOCK_IMAGE:
case SOCK_GEOMETRY:
case SOCK_COLLECTION:
case SOCK_TEXTURE:
case SOCK_MATERIAL:
Geometry Nodes: Menu Switch Node This patch adds support for _Menu Switch_ nodes and enum definitions in node trees more generally. The design is based on the outcome of the [2022 Nodes Workshop](https://code.blender.org/2022/11/geometry-nodes-workshop-2022/#menu-switch). The _Menu Switch_ node is an advanced version of the _Switch_ node which has a customizable **menu input socket** instead of a simple boolean. The _items_ of this menu are owned by the node itself. Each item has a name and description and unique identifier that is used internally. A menu _socket_ represents a concrete value out of the list of items. To enable selection of an enum value for unconnected sockets the menu is presented as a dropdown list like built-in enums. When the socket is connected a shared pointer to the enum definition is propagated along links and stored in socket default values. This allows node groups to expose a menu from an internal menu switch as a parameter. The enum definition is a runtime copy of the enum items in DNA that allows sharing. A menu socket can have multiple connections, which can lead to ambiguity. If two or more different menu source nodes are connected to a socket it gets marked as _undefined_. Any connection to an undefined menu socket is invalid as a hint to users that there is a problem. A warning/error is also shown on nodes with undefined menu sockets. At runtime the value of a menu socket is the simple integer identifier. This can also be a field in geometry nodes. The identifier is unique within each enum definition, and it is persistent even when items are added, removed, or changed. Changing the name of an item does not affect the internal identifier, so users can rename enum items without breaking existing input values. This also persists if, for example, a linked node group is temporarily unavailable. Pull Request: https://projects.blender.org/blender/blender/pulls/113445
2024-01-26 12:40:01 +01:00
case SOCK_MENU:
Geometry Nodes: add Closures and Bundles behind experimental feature flag This implements bundles and closures which are described in more detail in this blog post: https://code.blender.org/2024/11/geometry-nodes-workshop-october-2024/ tl;dr: * Bundles are containers that allow storing multiple socket values in a single value. Each value in the bundle is identified by a name. Bundles can be nested. * Closures are functions that are created with the Closure Zone and can be evaluated with the Evaluate Closure node. To use the patch, the `Bundle and Closure Nodes` experimental feature has to be enabled. This is necessary, because these features are not fully done yet and still need iterations to improve the workflow before they can be officially released. These iterations are easier to do in `main` than in a separate branch though. That's because this patch is quite large and somewhat prone to merge conflicts. Also other work we want to do, depends on this. This adds the following new nodes: * Combine Bundle: can pack multiple values into one. * Separate Bundle: extracts values from a bundle. * Closure Zone: outputs a closure zone for use in the `Evaluate Closure` node. * Evaluate Closure: evaluates the passed in closure. Things that will be added soon after this lands: * Fields in bundles and closures. The way this is done changes with #134811, so I rather implement this once both are in `main`. * UI features for keeping sockets in sync (right now there are warnings only). One bigger issue is the limited support for lazyness. For example, all inputs of a Combine Bundle node will be evaluated, even if they are not all needed. The same is true for all captured values of a closure. This is a deeper limitation that needs to be resolved at some point. This will likely be done after an initial version of this patch is done. Pull Request: https://projects.blender.org/blender/blender/pulls/128340
2025-04-03 15:44:06 +02:00
case SOCK_BUNDLE:
case SOCK_CLOSURE:
break;
}
}
}
idname.copy_utf8_truncated(sock.idname);
node_socket_set_typeinfo(&ntree, &sock, socktype);
}
void node_modify_socket_type_static(
bNodeTree *ntree, bNode *node, bNodeSocket *sock, const int type, const int subtype)
{
const std::optional<StringRefNull> idname = node_static_socket_type(type, subtype);
if (!idname.has_value()) {
CLOG_ERROR(&LOG, "static node socket type %d undefined", type);
return;
}
node_modify_socket_type(*ntree, *node, *sock, *idname);
}
bNodeSocket *node_add_socket(bNodeTree &ntree,
bNode &node,
const eNodeSocketInOut in_out,
const StringRefNull idname,
const StringRefNull identifier,
const StringRefNull name)
{
BLI_assert(!node.is_frame());
BLI_assert(!(in_out == SOCK_IN && node.is_group_input()));
BLI_assert(!(in_out == SOCK_OUT && node.is_group_output()));
ListBase *lb = (in_out == SOCK_IN ? &node.inputs : &node.outputs);
bNodeSocket *sock = make_socket(&ntree, &node, in_out, lb, idname, identifier, name);
BLI_remlink(lb, sock); /* does nothing for new socket */
BLI_addtail(lb, sock);
BKE_ntree_update_tag_socket_new(&ntree, sock);
return sock;
}
bool node_is_static_socket_type(const bNodeSocketType &stype)
{
/*
* Cannot rely on type==SOCK_CUSTOM here, because type is 0 by default
* and can be changed on custom sockets.
*/
return RNA_struct_is_a(stype.ext_socket.srna, &RNA_NodeSocketStandard);
}
std::optional<StringRefNull> node_static_socket_type(const int type, const int subtype)
{
switch (eNodeSocketDatatype(type)) {
case SOCK_FLOAT:
switch (PropertySubType(subtype)) {
case PROP_UNSIGNED:
return "NodeSocketFloatUnsigned";
case PROP_PERCENTAGE:
return "NodeSocketFloatPercentage";
case PROP_FACTOR:
return "NodeSocketFloatFactor";
case PROP_ANGLE:
return "NodeSocketFloatAngle";
case PROP_TIME:
return "NodeSocketFloatTime";
case PROP_TIME_ABSOLUTE:
return "NodeSocketFloatTimeAbsolute";
case PROP_DISTANCE:
return "NodeSocketFloatDistance";
case PROP_WAVELENGTH:
return "NodeSocketFloatWavelength";
case PROP_COLOR_TEMPERATURE:
return "NodeSocketFloatColorTemperature";
case PROP_FREQUENCY:
return "NodeSocketFloatFrequency";
case PROP_NONE:
default:
return "NodeSocketFloat";
}
case SOCK_INT:
switch (PropertySubType(subtype)) {
case PROP_UNSIGNED:
return "NodeSocketIntUnsigned";
case PROP_PERCENTAGE:
return "NodeSocketIntPercentage";
case PROP_FACTOR:
return "NodeSocketIntFactor";
case PROP_NONE:
default:
return "NodeSocketInt";
}
case SOCK_BOOLEAN:
return "NodeSocketBool";
case SOCK_ROTATION:
return "NodeSocketRotation";
case SOCK_MATRIX:
return "NodeSocketMatrix";
case SOCK_VECTOR:
switch (PropertySubType(subtype)) {
case PROP_FACTOR:
return "NodeSocketVectorFactor";
case PROP_PERCENTAGE:
return "NodeSocketVectorPercentage";
case PROP_TRANSLATION:
return "NodeSocketVectorTranslation";
case PROP_DIRECTION:
return "NodeSocketVectorDirection";
case PROP_VELOCITY:
return "NodeSocketVectorVelocity";
case PROP_ACCELERATION:
return "NodeSocketVectorAcceleration";
case PROP_EULER:
return "NodeSocketVectorEuler";
case PROP_XYZ:
return "NodeSocketVectorXYZ";
case PROP_NONE:
default:
return "NodeSocketVector";
}
case SOCK_RGBA:
return "NodeSocketColor";
case SOCK_STRING:
switch (PropertySubType(subtype)) {
case PROP_FILEPATH:
return "NodeSocketStringFilePath";
default:
return "NodeSocketString";
}
case SOCK_SHADER:
return "NodeSocketShader";
case SOCK_OBJECT:
return "NodeSocketObject";
case SOCK_IMAGE:
return "NodeSocketImage";
case SOCK_GEOMETRY:
return "NodeSocketGeometry";
case SOCK_COLLECTION:
return "NodeSocketCollection";
case SOCK_TEXTURE:
return "NodeSocketTexture";
case SOCK_MATERIAL:
return "NodeSocketMaterial";
Geometry Nodes: Menu Switch Node This patch adds support for _Menu Switch_ nodes and enum definitions in node trees more generally. The design is based on the outcome of the [2022 Nodes Workshop](https://code.blender.org/2022/11/geometry-nodes-workshop-2022/#menu-switch). The _Menu Switch_ node is an advanced version of the _Switch_ node which has a customizable **menu input socket** instead of a simple boolean. The _items_ of this menu are owned by the node itself. Each item has a name and description and unique identifier that is used internally. A menu _socket_ represents a concrete value out of the list of items. To enable selection of an enum value for unconnected sockets the menu is presented as a dropdown list like built-in enums. When the socket is connected a shared pointer to the enum definition is propagated along links and stored in socket default values. This allows node groups to expose a menu from an internal menu switch as a parameter. The enum definition is a runtime copy of the enum items in DNA that allows sharing. A menu socket can have multiple connections, which can lead to ambiguity. If two or more different menu source nodes are connected to a socket it gets marked as _undefined_. Any connection to an undefined menu socket is invalid as a hint to users that there is a problem. A warning/error is also shown on nodes with undefined menu sockets. At runtime the value of a menu socket is the simple integer identifier. This can also be a field in geometry nodes. The identifier is unique within each enum definition, and it is persistent even when items are added, removed, or changed. Changing the name of an item does not affect the internal identifier, so users can rename enum items without breaking existing input values. This also persists if, for example, a linked node group is temporarily unavailable. Pull Request: https://projects.blender.org/blender/blender/pulls/113445
2024-01-26 12:40:01 +01:00
case SOCK_MENU:
return "NodeSocketMenu";
Geometry Nodes: add Closures and Bundles behind experimental feature flag This implements bundles and closures which are described in more detail in this blog post: https://code.blender.org/2024/11/geometry-nodes-workshop-october-2024/ tl;dr: * Bundles are containers that allow storing multiple socket values in a single value. Each value in the bundle is identified by a name. Bundles can be nested. * Closures are functions that are created with the Closure Zone and can be evaluated with the Evaluate Closure node. To use the patch, the `Bundle and Closure Nodes` experimental feature has to be enabled. This is necessary, because these features are not fully done yet and still need iterations to improve the workflow before they can be officially released. These iterations are easier to do in `main` than in a separate branch though. That's because this patch is quite large and somewhat prone to merge conflicts. Also other work we want to do, depends on this. This adds the following new nodes: * Combine Bundle: can pack multiple values into one. * Separate Bundle: extracts values from a bundle. * Closure Zone: outputs a closure zone for use in the `Evaluate Closure` node. * Evaluate Closure: evaluates the passed in closure. Things that will be added soon after this lands: * Fields in bundles and closures. The way this is done changes with #134811, so I rather implement this once both are in `main`. * UI features for keeping sockets in sync (right now there are warnings only). One bigger issue is the limited support for lazyness. For example, all inputs of a Combine Bundle node will be evaluated, even if they are not all needed. The same is true for all captured values of a closure. This is a deeper limitation that needs to be resolved at some point. This will likely be done after an initial version of this patch is done. Pull Request: https://projects.blender.org/blender/blender/pulls/128340
2025-04-03 15:44:06 +02:00
case SOCK_BUNDLE:
return "NodeSocketBundle";
case SOCK_CLOSURE:
return "NodeSocketClosure";
case SOCK_CUSTOM:
break;
}
return std::nullopt;
}
std::optional<StringRefNull> node_static_socket_interface_type_new(const int type,
const int subtype)
{
switch (eNodeSocketDatatype(type)) {
case SOCK_FLOAT:
switch (PropertySubType(subtype)) {
case PROP_UNSIGNED:
Nodes: Panels integration with blend files and UI Part 3/3 of #109135, #110272 Switch to new node group interfaces and deprecate old DNA and API. This completes support for panels in node drawing and in node group interface declarations in particular. The new node group interface DNA and RNA code has been added in parts 1 and 2 (#110885, #110952) but has not be enabled yet. This commit completes the integration by * enabling the new RNA API * using the new API in UI * read/write new interfaces from blend files * add versioning for backward compatibility * add forward-compatible writing code to reconstruct old interfaces All places accessing node group interface declarations should now be using the new API. A runtime cache has been added that allows simple linear access to socket inputs and outputs even when a panel hierarchy is used. Old DNA has been deprecated and should only be accessed for versioning (inputs/outputs renamed to inputs_legacy/outputs_legacy to catch errors). Versioning code ensures both backward and forward compatibility of existing files. The API for old interfaces is removed. The new API is very similar but is defined on the `ntree.interface` instead of the `ntree` directly. Breaking change notifications and detailed instructions for migrating will be added. A python test has been added for the node group API functions. This includes new functionality such as creating panels and moving items between different levels. This patch does not yet contain panel representations in the modifier UI. This has been tested in a separate branch and will be added with a later PR (#108565). Pull Request: https://projects.blender.org/blender/blender/pulls/111348
2023-08-30 12:37:21 +02:00
return "NodeTreeInterfaceSocketFloatUnsigned";
case PROP_PERCENTAGE:
Nodes: Panels integration with blend files and UI Part 3/3 of #109135, #110272 Switch to new node group interfaces and deprecate old DNA and API. This completes support for panels in node drawing and in node group interface declarations in particular. The new node group interface DNA and RNA code has been added in parts 1 and 2 (#110885, #110952) but has not be enabled yet. This commit completes the integration by * enabling the new RNA API * using the new API in UI * read/write new interfaces from blend files * add versioning for backward compatibility * add forward-compatible writing code to reconstruct old interfaces All places accessing node group interface declarations should now be using the new API. A runtime cache has been added that allows simple linear access to socket inputs and outputs even when a panel hierarchy is used. Old DNA has been deprecated and should only be accessed for versioning (inputs/outputs renamed to inputs_legacy/outputs_legacy to catch errors). Versioning code ensures both backward and forward compatibility of existing files. The API for old interfaces is removed. The new API is very similar but is defined on the `ntree.interface` instead of the `ntree` directly. Breaking change notifications and detailed instructions for migrating will be added. A python test has been added for the node group API functions. This includes new functionality such as creating panels and moving items between different levels. This patch does not yet contain panel representations in the modifier UI. This has been tested in a separate branch and will be added with a later PR (#108565). Pull Request: https://projects.blender.org/blender/blender/pulls/111348
2023-08-30 12:37:21 +02:00
return "NodeTreeInterfaceSocketFloatPercentage";
case PROP_FACTOR:
Nodes: Panels integration with blend files and UI Part 3/3 of #109135, #110272 Switch to new node group interfaces and deprecate old DNA and API. This completes support for panels in node drawing and in node group interface declarations in particular. The new node group interface DNA and RNA code has been added in parts 1 and 2 (#110885, #110952) but has not be enabled yet. This commit completes the integration by * enabling the new RNA API * using the new API in UI * read/write new interfaces from blend files * add versioning for backward compatibility * add forward-compatible writing code to reconstruct old interfaces All places accessing node group interface declarations should now be using the new API. A runtime cache has been added that allows simple linear access to socket inputs and outputs even when a panel hierarchy is used. Old DNA has been deprecated and should only be accessed for versioning (inputs/outputs renamed to inputs_legacy/outputs_legacy to catch errors). Versioning code ensures both backward and forward compatibility of existing files. The API for old interfaces is removed. The new API is very similar but is defined on the `ntree.interface` instead of the `ntree` directly. Breaking change notifications and detailed instructions for migrating will be added. A python test has been added for the node group API functions. This includes new functionality such as creating panels and moving items between different levels. This patch does not yet contain panel representations in the modifier UI. This has been tested in a separate branch and will be added with a later PR (#108565). Pull Request: https://projects.blender.org/blender/blender/pulls/111348
2023-08-30 12:37:21 +02:00
return "NodeTreeInterfaceSocketFloatFactor";
case PROP_ANGLE:
Nodes: Panels integration with blend files and UI Part 3/3 of #109135, #110272 Switch to new node group interfaces and deprecate old DNA and API. This completes support for panels in node drawing and in node group interface declarations in particular. The new node group interface DNA and RNA code has been added in parts 1 and 2 (#110885, #110952) but has not be enabled yet. This commit completes the integration by * enabling the new RNA API * using the new API in UI * read/write new interfaces from blend files * add versioning for backward compatibility * add forward-compatible writing code to reconstruct old interfaces All places accessing node group interface declarations should now be using the new API. A runtime cache has been added that allows simple linear access to socket inputs and outputs even when a panel hierarchy is used. Old DNA has been deprecated and should only be accessed for versioning (inputs/outputs renamed to inputs_legacy/outputs_legacy to catch errors). Versioning code ensures both backward and forward compatibility of existing files. The API for old interfaces is removed. The new API is very similar but is defined on the `ntree.interface` instead of the `ntree` directly. Breaking change notifications and detailed instructions for migrating will be added. A python test has been added for the node group API functions. This includes new functionality such as creating panels and moving items between different levels. This patch does not yet contain panel representations in the modifier UI. This has been tested in a separate branch and will be added with a later PR (#108565). Pull Request: https://projects.blender.org/blender/blender/pulls/111348
2023-08-30 12:37:21 +02:00
return "NodeTreeInterfaceSocketFloatAngle";
case PROP_TIME:
Nodes: Panels integration with blend files and UI Part 3/3 of #109135, #110272 Switch to new node group interfaces and deprecate old DNA and API. This completes support for panels in node drawing and in node group interface declarations in particular. The new node group interface DNA and RNA code has been added in parts 1 and 2 (#110885, #110952) but has not be enabled yet. This commit completes the integration by * enabling the new RNA API * using the new API in UI * read/write new interfaces from blend files * add versioning for backward compatibility * add forward-compatible writing code to reconstruct old interfaces All places accessing node group interface declarations should now be using the new API. A runtime cache has been added that allows simple linear access to socket inputs and outputs even when a panel hierarchy is used. Old DNA has been deprecated and should only be accessed for versioning (inputs/outputs renamed to inputs_legacy/outputs_legacy to catch errors). Versioning code ensures both backward and forward compatibility of existing files. The API for old interfaces is removed. The new API is very similar but is defined on the `ntree.interface` instead of the `ntree` directly. Breaking change notifications and detailed instructions for migrating will be added. A python test has been added for the node group API functions. This includes new functionality such as creating panels and moving items between different levels. This patch does not yet contain panel representations in the modifier UI. This has been tested in a separate branch and will be added with a later PR (#108565). Pull Request: https://projects.blender.org/blender/blender/pulls/111348
2023-08-30 12:37:21 +02:00
return "NodeTreeInterfaceSocketFloatTime";
case PROP_TIME_ABSOLUTE:
Nodes: Panels integration with blend files and UI Part 3/3 of #109135, #110272 Switch to new node group interfaces and deprecate old DNA and API. This completes support for panels in node drawing and in node group interface declarations in particular. The new node group interface DNA and RNA code has been added in parts 1 and 2 (#110885, #110952) but has not be enabled yet. This commit completes the integration by * enabling the new RNA API * using the new API in UI * read/write new interfaces from blend files * add versioning for backward compatibility * add forward-compatible writing code to reconstruct old interfaces All places accessing node group interface declarations should now be using the new API. A runtime cache has been added that allows simple linear access to socket inputs and outputs even when a panel hierarchy is used. Old DNA has been deprecated and should only be accessed for versioning (inputs/outputs renamed to inputs_legacy/outputs_legacy to catch errors). Versioning code ensures both backward and forward compatibility of existing files. The API for old interfaces is removed. The new API is very similar but is defined on the `ntree.interface` instead of the `ntree` directly. Breaking change notifications and detailed instructions for migrating will be added. A python test has been added for the node group API functions. This includes new functionality such as creating panels and moving items between different levels. This patch does not yet contain panel representations in the modifier UI. This has been tested in a separate branch and will be added with a later PR (#108565). Pull Request: https://projects.blender.org/blender/blender/pulls/111348
2023-08-30 12:37:21 +02:00
return "NodeTreeInterfaceSocketFloatTimeAbsolute";
case PROP_DISTANCE:
Nodes: Panels integration with blend files and UI Part 3/3 of #109135, #110272 Switch to new node group interfaces and deprecate old DNA and API. This completes support for panels in node drawing and in node group interface declarations in particular. The new node group interface DNA and RNA code has been added in parts 1 and 2 (#110885, #110952) but has not be enabled yet. This commit completes the integration by * enabling the new RNA API * using the new API in UI * read/write new interfaces from blend files * add versioning for backward compatibility * add forward-compatible writing code to reconstruct old interfaces All places accessing node group interface declarations should now be using the new API. A runtime cache has been added that allows simple linear access to socket inputs and outputs even when a panel hierarchy is used. Old DNA has been deprecated and should only be accessed for versioning (inputs/outputs renamed to inputs_legacy/outputs_legacy to catch errors). Versioning code ensures both backward and forward compatibility of existing files. The API for old interfaces is removed. The new API is very similar but is defined on the `ntree.interface` instead of the `ntree` directly. Breaking change notifications and detailed instructions for migrating will be added. A python test has been added for the node group API functions. This includes new functionality such as creating panels and moving items between different levels. This patch does not yet contain panel representations in the modifier UI. This has been tested in a separate branch and will be added with a later PR (#108565). Pull Request: https://projects.blender.org/blender/blender/pulls/111348
2023-08-30 12:37:21 +02:00
return "NodeTreeInterfaceSocketFloatDistance";
case PROP_WAVELENGTH:
return "NodeTreeInterfaceSocketFloatWavelength";
case PROP_COLOR_TEMPERATURE:
return "NodeTreeInterfaceSocketFloatColorTemperature";
case PROP_FREQUENCY:
return "NodeTreeInterfaceSocketFloatFrequency";
case PROP_NONE:
default:
Nodes: Panels integration with blend files and UI Part 3/3 of #109135, #110272 Switch to new node group interfaces and deprecate old DNA and API. This completes support for panels in node drawing and in node group interface declarations in particular. The new node group interface DNA and RNA code has been added in parts 1 and 2 (#110885, #110952) but has not be enabled yet. This commit completes the integration by * enabling the new RNA API * using the new API in UI * read/write new interfaces from blend files * add versioning for backward compatibility * add forward-compatible writing code to reconstruct old interfaces All places accessing node group interface declarations should now be using the new API. A runtime cache has been added that allows simple linear access to socket inputs and outputs even when a panel hierarchy is used. Old DNA has been deprecated and should only be accessed for versioning (inputs/outputs renamed to inputs_legacy/outputs_legacy to catch errors). Versioning code ensures both backward and forward compatibility of existing files. The API for old interfaces is removed. The new API is very similar but is defined on the `ntree.interface` instead of the `ntree` directly. Breaking change notifications and detailed instructions for migrating will be added. A python test has been added for the node group API functions. This includes new functionality such as creating panels and moving items between different levels. This patch does not yet contain panel representations in the modifier UI. This has been tested in a separate branch and will be added with a later PR (#108565). Pull Request: https://projects.blender.org/blender/blender/pulls/111348
2023-08-30 12:37:21 +02:00
return "NodeTreeInterfaceSocketFloat";
}
case SOCK_INT:
switch (PropertySubType(subtype)) {
case PROP_UNSIGNED:
Nodes: Panels integration with blend files and UI Part 3/3 of #109135, #110272 Switch to new node group interfaces and deprecate old DNA and API. This completes support for panels in node drawing and in node group interface declarations in particular. The new node group interface DNA and RNA code has been added in parts 1 and 2 (#110885, #110952) but has not be enabled yet. This commit completes the integration by * enabling the new RNA API * using the new API in UI * read/write new interfaces from blend files * add versioning for backward compatibility * add forward-compatible writing code to reconstruct old interfaces All places accessing node group interface declarations should now be using the new API. A runtime cache has been added that allows simple linear access to socket inputs and outputs even when a panel hierarchy is used. Old DNA has been deprecated and should only be accessed for versioning (inputs/outputs renamed to inputs_legacy/outputs_legacy to catch errors). Versioning code ensures both backward and forward compatibility of existing files. The API for old interfaces is removed. The new API is very similar but is defined on the `ntree.interface` instead of the `ntree` directly. Breaking change notifications and detailed instructions for migrating will be added. A python test has been added for the node group API functions. This includes new functionality such as creating panels and moving items between different levels. This patch does not yet contain panel representations in the modifier UI. This has been tested in a separate branch and will be added with a later PR (#108565). Pull Request: https://projects.blender.org/blender/blender/pulls/111348
2023-08-30 12:37:21 +02:00
return "NodeTreeInterfaceSocketIntUnsigned";
case PROP_PERCENTAGE:
Nodes: Panels integration with blend files and UI Part 3/3 of #109135, #110272 Switch to new node group interfaces and deprecate old DNA and API. This completes support for panels in node drawing and in node group interface declarations in particular. The new node group interface DNA and RNA code has been added in parts 1 and 2 (#110885, #110952) but has not be enabled yet. This commit completes the integration by * enabling the new RNA API * using the new API in UI * read/write new interfaces from blend files * add versioning for backward compatibility * add forward-compatible writing code to reconstruct old interfaces All places accessing node group interface declarations should now be using the new API. A runtime cache has been added that allows simple linear access to socket inputs and outputs even when a panel hierarchy is used. Old DNA has been deprecated and should only be accessed for versioning (inputs/outputs renamed to inputs_legacy/outputs_legacy to catch errors). Versioning code ensures both backward and forward compatibility of existing files. The API for old interfaces is removed. The new API is very similar but is defined on the `ntree.interface` instead of the `ntree` directly. Breaking change notifications and detailed instructions for migrating will be added. A python test has been added for the node group API functions. This includes new functionality such as creating panels and moving items between different levels. This patch does not yet contain panel representations in the modifier UI. This has been tested in a separate branch and will be added with a later PR (#108565). Pull Request: https://projects.blender.org/blender/blender/pulls/111348
2023-08-30 12:37:21 +02:00
return "NodeTreeInterfaceSocketIntPercentage";
case PROP_FACTOR:
Nodes: Panels integration with blend files and UI Part 3/3 of #109135, #110272 Switch to new node group interfaces and deprecate old DNA and API. This completes support for panels in node drawing and in node group interface declarations in particular. The new node group interface DNA and RNA code has been added in parts 1 and 2 (#110885, #110952) but has not be enabled yet. This commit completes the integration by * enabling the new RNA API * using the new API in UI * read/write new interfaces from blend files * add versioning for backward compatibility * add forward-compatible writing code to reconstruct old interfaces All places accessing node group interface declarations should now be using the new API. A runtime cache has been added that allows simple linear access to socket inputs and outputs even when a panel hierarchy is used. Old DNA has been deprecated and should only be accessed for versioning (inputs/outputs renamed to inputs_legacy/outputs_legacy to catch errors). Versioning code ensures both backward and forward compatibility of existing files. The API for old interfaces is removed. The new API is very similar but is defined on the `ntree.interface` instead of the `ntree` directly. Breaking change notifications and detailed instructions for migrating will be added. A python test has been added for the node group API functions. This includes new functionality such as creating panels and moving items between different levels. This patch does not yet contain panel representations in the modifier UI. This has been tested in a separate branch and will be added with a later PR (#108565). Pull Request: https://projects.blender.org/blender/blender/pulls/111348
2023-08-30 12:37:21 +02:00
return "NodeTreeInterfaceSocketIntFactor";
case PROP_NONE:
default:
Nodes: Panels integration with blend files and UI Part 3/3 of #109135, #110272 Switch to new node group interfaces and deprecate old DNA and API. This completes support for panels in node drawing and in node group interface declarations in particular. The new node group interface DNA and RNA code has been added in parts 1 and 2 (#110885, #110952) but has not be enabled yet. This commit completes the integration by * enabling the new RNA API * using the new API in UI * read/write new interfaces from blend files * add versioning for backward compatibility * add forward-compatible writing code to reconstruct old interfaces All places accessing node group interface declarations should now be using the new API. A runtime cache has been added that allows simple linear access to socket inputs and outputs even when a panel hierarchy is used. Old DNA has been deprecated and should only be accessed for versioning (inputs/outputs renamed to inputs_legacy/outputs_legacy to catch errors). Versioning code ensures both backward and forward compatibility of existing files. The API for old interfaces is removed. The new API is very similar but is defined on the `ntree.interface` instead of the `ntree` directly. Breaking change notifications and detailed instructions for migrating will be added. A python test has been added for the node group API functions. This includes new functionality such as creating panels and moving items between different levels. This patch does not yet contain panel representations in the modifier UI. This has been tested in a separate branch and will be added with a later PR (#108565). Pull Request: https://projects.blender.org/blender/blender/pulls/111348
2023-08-30 12:37:21 +02:00
return "NodeTreeInterfaceSocketInt";
}
case SOCK_BOOLEAN:
Nodes: Panels integration with blend files and UI Part 3/3 of #109135, #110272 Switch to new node group interfaces and deprecate old DNA and API. This completes support for panels in node drawing and in node group interface declarations in particular. The new node group interface DNA and RNA code has been added in parts 1 and 2 (#110885, #110952) but has not be enabled yet. This commit completes the integration by * enabling the new RNA API * using the new API in UI * read/write new interfaces from blend files * add versioning for backward compatibility * add forward-compatible writing code to reconstruct old interfaces All places accessing node group interface declarations should now be using the new API. A runtime cache has been added that allows simple linear access to socket inputs and outputs even when a panel hierarchy is used. Old DNA has been deprecated and should only be accessed for versioning (inputs/outputs renamed to inputs_legacy/outputs_legacy to catch errors). Versioning code ensures both backward and forward compatibility of existing files. The API for old interfaces is removed. The new API is very similar but is defined on the `ntree.interface` instead of the `ntree` directly. Breaking change notifications and detailed instructions for migrating will be added. A python test has been added for the node group API functions. This includes new functionality such as creating panels and moving items between different levels. This patch does not yet contain panel representations in the modifier UI. This has been tested in a separate branch and will be added with a later PR (#108565). Pull Request: https://projects.blender.org/blender/blender/pulls/111348
2023-08-30 12:37:21 +02:00
return "NodeTreeInterfaceSocketBool";
case SOCK_ROTATION:
Nodes: Panels integration with blend files and UI Part 3/3 of #109135, #110272 Switch to new node group interfaces and deprecate old DNA and API. This completes support for panels in node drawing and in node group interface declarations in particular. The new node group interface DNA and RNA code has been added in parts 1 and 2 (#110885, #110952) but has not be enabled yet. This commit completes the integration by * enabling the new RNA API * using the new API in UI * read/write new interfaces from blend files * add versioning for backward compatibility * add forward-compatible writing code to reconstruct old interfaces All places accessing node group interface declarations should now be using the new API. A runtime cache has been added that allows simple linear access to socket inputs and outputs even when a panel hierarchy is used. Old DNA has been deprecated and should only be accessed for versioning (inputs/outputs renamed to inputs_legacy/outputs_legacy to catch errors). Versioning code ensures both backward and forward compatibility of existing files. The API for old interfaces is removed. The new API is very similar but is defined on the `ntree.interface` instead of the `ntree` directly. Breaking change notifications and detailed instructions for migrating will be added. A python test has been added for the node group API functions. This includes new functionality such as creating panels and moving items between different levels. This patch does not yet contain panel representations in the modifier UI. This has been tested in a separate branch and will be added with a later PR (#108565). Pull Request: https://projects.blender.org/blender/blender/pulls/111348
2023-08-30 12:37:21 +02:00
return "NodeTreeInterfaceSocketRotation";
case SOCK_MATRIX:
return "NodeTreeInterfaceSocketMatrix";
case SOCK_VECTOR:
switch (PropertySubType(subtype)) {
case PROP_FACTOR:
return "NodeTreeInterfaceSocketVectorFactor";
case PROP_PERCENTAGE:
return "NodeTreeInterfaceSocketVectorPercentage";
case PROP_TRANSLATION:
Nodes: Panels integration with blend files and UI Part 3/3 of #109135, #110272 Switch to new node group interfaces and deprecate old DNA and API. This completes support for panels in node drawing and in node group interface declarations in particular. The new node group interface DNA and RNA code has been added in parts 1 and 2 (#110885, #110952) but has not be enabled yet. This commit completes the integration by * enabling the new RNA API * using the new API in UI * read/write new interfaces from blend files * add versioning for backward compatibility * add forward-compatible writing code to reconstruct old interfaces All places accessing node group interface declarations should now be using the new API. A runtime cache has been added that allows simple linear access to socket inputs and outputs even when a panel hierarchy is used. Old DNA has been deprecated and should only be accessed for versioning (inputs/outputs renamed to inputs_legacy/outputs_legacy to catch errors). Versioning code ensures both backward and forward compatibility of existing files. The API for old interfaces is removed. The new API is very similar but is defined on the `ntree.interface` instead of the `ntree` directly. Breaking change notifications and detailed instructions for migrating will be added. A python test has been added for the node group API functions. This includes new functionality such as creating panels and moving items between different levels. This patch does not yet contain panel representations in the modifier UI. This has been tested in a separate branch and will be added with a later PR (#108565). Pull Request: https://projects.blender.org/blender/blender/pulls/111348
2023-08-30 12:37:21 +02:00
return "NodeTreeInterfaceSocketVectorTranslation";
case PROP_DIRECTION:
Nodes: Panels integration with blend files and UI Part 3/3 of #109135, #110272 Switch to new node group interfaces and deprecate old DNA and API. This completes support for panels in node drawing and in node group interface declarations in particular. The new node group interface DNA and RNA code has been added in parts 1 and 2 (#110885, #110952) but has not be enabled yet. This commit completes the integration by * enabling the new RNA API * using the new API in UI * read/write new interfaces from blend files * add versioning for backward compatibility * add forward-compatible writing code to reconstruct old interfaces All places accessing node group interface declarations should now be using the new API. A runtime cache has been added that allows simple linear access to socket inputs and outputs even when a panel hierarchy is used. Old DNA has been deprecated and should only be accessed for versioning (inputs/outputs renamed to inputs_legacy/outputs_legacy to catch errors). Versioning code ensures both backward and forward compatibility of existing files. The API for old interfaces is removed. The new API is very similar but is defined on the `ntree.interface` instead of the `ntree` directly. Breaking change notifications and detailed instructions for migrating will be added. A python test has been added for the node group API functions. This includes new functionality such as creating panels and moving items between different levels. This patch does not yet contain panel representations in the modifier UI. This has been tested in a separate branch and will be added with a later PR (#108565). Pull Request: https://projects.blender.org/blender/blender/pulls/111348
2023-08-30 12:37:21 +02:00
return "NodeTreeInterfaceSocketVectorDirection";
case PROP_VELOCITY:
Nodes: Panels integration with blend files and UI Part 3/3 of #109135, #110272 Switch to new node group interfaces and deprecate old DNA and API. This completes support for panels in node drawing and in node group interface declarations in particular. The new node group interface DNA and RNA code has been added in parts 1 and 2 (#110885, #110952) but has not be enabled yet. This commit completes the integration by * enabling the new RNA API * using the new API in UI * read/write new interfaces from blend files * add versioning for backward compatibility * add forward-compatible writing code to reconstruct old interfaces All places accessing node group interface declarations should now be using the new API. A runtime cache has been added that allows simple linear access to socket inputs and outputs even when a panel hierarchy is used. Old DNA has been deprecated and should only be accessed for versioning (inputs/outputs renamed to inputs_legacy/outputs_legacy to catch errors). Versioning code ensures both backward and forward compatibility of existing files. The API for old interfaces is removed. The new API is very similar but is defined on the `ntree.interface` instead of the `ntree` directly. Breaking change notifications and detailed instructions for migrating will be added. A python test has been added for the node group API functions. This includes new functionality such as creating panels and moving items between different levels. This patch does not yet contain panel representations in the modifier UI. This has been tested in a separate branch and will be added with a later PR (#108565). Pull Request: https://projects.blender.org/blender/blender/pulls/111348
2023-08-30 12:37:21 +02:00
return "NodeTreeInterfaceSocketVectorVelocity";
case PROP_ACCELERATION:
Nodes: Panels integration with blend files and UI Part 3/3 of #109135, #110272 Switch to new node group interfaces and deprecate old DNA and API. This completes support for panels in node drawing and in node group interface declarations in particular. The new node group interface DNA and RNA code has been added in parts 1 and 2 (#110885, #110952) but has not be enabled yet. This commit completes the integration by * enabling the new RNA API * using the new API in UI * read/write new interfaces from blend files * add versioning for backward compatibility * add forward-compatible writing code to reconstruct old interfaces All places accessing node group interface declarations should now be using the new API. A runtime cache has been added that allows simple linear access to socket inputs and outputs even when a panel hierarchy is used. Old DNA has been deprecated and should only be accessed for versioning (inputs/outputs renamed to inputs_legacy/outputs_legacy to catch errors). Versioning code ensures both backward and forward compatibility of existing files. The API for old interfaces is removed. The new API is very similar but is defined on the `ntree.interface` instead of the `ntree` directly. Breaking change notifications and detailed instructions for migrating will be added. A python test has been added for the node group API functions. This includes new functionality such as creating panels and moving items between different levels. This patch does not yet contain panel representations in the modifier UI. This has been tested in a separate branch and will be added with a later PR (#108565). Pull Request: https://projects.blender.org/blender/blender/pulls/111348
2023-08-30 12:37:21 +02:00
return "NodeTreeInterfaceSocketVectorAcceleration";
case PROP_EULER:
Nodes: Panels integration with blend files and UI Part 3/3 of #109135, #110272 Switch to new node group interfaces and deprecate old DNA and API. This completes support for panels in node drawing and in node group interface declarations in particular. The new node group interface DNA and RNA code has been added in parts 1 and 2 (#110885, #110952) but has not be enabled yet. This commit completes the integration by * enabling the new RNA API * using the new API in UI * read/write new interfaces from blend files * add versioning for backward compatibility * add forward-compatible writing code to reconstruct old interfaces All places accessing node group interface declarations should now be using the new API. A runtime cache has been added that allows simple linear access to socket inputs and outputs even when a panel hierarchy is used. Old DNA has been deprecated and should only be accessed for versioning (inputs/outputs renamed to inputs_legacy/outputs_legacy to catch errors). Versioning code ensures both backward and forward compatibility of existing files. The API for old interfaces is removed. The new API is very similar but is defined on the `ntree.interface` instead of the `ntree` directly. Breaking change notifications and detailed instructions for migrating will be added. A python test has been added for the node group API functions. This includes new functionality such as creating panels and moving items between different levels. This patch does not yet contain panel representations in the modifier UI. This has been tested in a separate branch and will be added with a later PR (#108565). Pull Request: https://projects.blender.org/blender/blender/pulls/111348
2023-08-30 12:37:21 +02:00
return "NodeTreeInterfaceSocketVectorEuler";
case PROP_XYZ:
Nodes: Panels integration with blend files and UI Part 3/3 of #109135, #110272 Switch to new node group interfaces and deprecate old DNA and API. This completes support for panels in node drawing and in node group interface declarations in particular. The new node group interface DNA and RNA code has been added in parts 1 and 2 (#110885, #110952) but has not be enabled yet. This commit completes the integration by * enabling the new RNA API * using the new API in UI * read/write new interfaces from blend files * add versioning for backward compatibility * add forward-compatible writing code to reconstruct old interfaces All places accessing node group interface declarations should now be using the new API. A runtime cache has been added that allows simple linear access to socket inputs and outputs even when a panel hierarchy is used. Old DNA has been deprecated and should only be accessed for versioning (inputs/outputs renamed to inputs_legacy/outputs_legacy to catch errors). Versioning code ensures both backward and forward compatibility of existing files. The API for old interfaces is removed. The new API is very similar but is defined on the `ntree.interface` instead of the `ntree` directly. Breaking change notifications and detailed instructions for migrating will be added. A python test has been added for the node group API functions. This includes new functionality such as creating panels and moving items between different levels. This patch does not yet contain panel representations in the modifier UI. This has been tested in a separate branch and will be added with a later PR (#108565). Pull Request: https://projects.blender.org/blender/blender/pulls/111348
2023-08-30 12:37:21 +02:00
return "NodeTreeInterfaceSocketVectorXYZ";
case PROP_NONE:
default:
Nodes: Panels integration with blend files and UI Part 3/3 of #109135, #110272 Switch to new node group interfaces and deprecate old DNA and API. This completes support for panels in node drawing and in node group interface declarations in particular. The new node group interface DNA and RNA code has been added in parts 1 and 2 (#110885, #110952) but has not be enabled yet. This commit completes the integration by * enabling the new RNA API * using the new API in UI * read/write new interfaces from blend files * add versioning for backward compatibility * add forward-compatible writing code to reconstruct old interfaces All places accessing node group interface declarations should now be using the new API. A runtime cache has been added that allows simple linear access to socket inputs and outputs even when a panel hierarchy is used. Old DNA has been deprecated and should only be accessed for versioning (inputs/outputs renamed to inputs_legacy/outputs_legacy to catch errors). Versioning code ensures both backward and forward compatibility of existing files. The API for old interfaces is removed. The new API is very similar but is defined on the `ntree.interface` instead of the `ntree` directly. Breaking change notifications and detailed instructions for migrating will be added. A python test has been added for the node group API functions. This includes new functionality such as creating panels and moving items between different levels. This patch does not yet contain panel representations in the modifier UI. This has been tested in a separate branch and will be added with a later PR (#108565). Pull Request: https://projects.blender.org/blender/blender/pulls/111348
2023-08-30 12:37:21 +02:00
return "NodeTreeInterfaceSocketVector";
}
case SOCK_RGBA:
Nodes: Panels integration with blend files and UI Part 3/3 of #109135, #110272 Switch to new node group interfaces and deprecate old DNA and API. This completes support for panels in node drawing and in node group interface declarations in particular. The new node group interface DNA and RNA code has been added in parts 1 and 2 (#110885, #110952) but has not be enabled yet. This commit completes the integration by * enabling the new RNA API * using the new API in UI * read/write new interfaces from blend files * add versioning for backward compatibility * add forward-compatible writing code to reconstruct old interfaces All places accessing node group interface declarations should now be using the new API. A runtime cache has been added that allows simple linear access to socket inputs and outputs even when a panel hierarchy is used. Old DNA has been deprecated and should only be accessed for versioning (inputs/outputs renamed to inputs_legacy/outputs_legacy to catch errors). Versioning code ensures both backward and forward compatibility of existing files. The API for old interfaces is removed. The new API is very similar but is defined on the `ntree.interface` instead of the `ntree` directly. Breaking change notifications and detailed instructions for migrating will be added. A python test has been added for the node group API functions. This includes new functionality such as creating panels and moving items between different levels. This patch does not yet contain panel representations in the modifier UI. This has been tested in a separate branch and will be added with a later PR (#108565). Pull Request: https://projects.blender.org/blender/blender/pulls/111348
2023-08-30 12:37:21 +02:00
return "NodeTreeInterfaceSocketColor";
case SOCK_STRING:
switch (PropertySubType(subtype)) {
case PROP_FILEPATH:
return "NodeTreeInterfaceSocketStringFilePath";
default:
return "NodeTreeInterfaceSocketString";
}
case SOCK_SHADER:
Nodes: Panels integration with blend files and UI Part 3/3 of #109135, #110272 Switch to new node group interfaces and deprecate old DNA and API. This completes support for panels in node drawing and in node group interface declarations in particular. The new node group interface DNA and RNA code has been added in parts 1 and 2 (#110885, #110952) but has not be enabled yet. This commit completes the integration by * enabling the new RNA API * using the new API in UI * read/write new interfaces from blend files * add versioning for backward compatibility * add forward-compatible writing code to reconstruct old interfaces All places accessing node group interface declarations should now be using the new API. A runtime cache has been added that allows simple linear access to socket inputs and outputs even when a panel hierarchy is used. Old DNA has been deprecated and should only be accessed for versioning (inputs/outputs renamed to inputs_legacy/outputs_legacy to catch errors). Versioning code ensures both backward and forward compatibility of existing files. The API for old interfaces is removed. The new API is very similar but is defined on the `ntree.interface` instead of the `ntree` directly. Breaking change notifications and detailed instructions for migrating will be added. A python test has been added for the node group API functions. This includes new functionality such as creating panels and moving items between different levels. This patch does not yet contain panel representations in the modifier UI. This has been tested in a separate branch and will be added with a later PR (#108565). Pull Request: https://projects.blender.org/blender/blender/pulls/111348
2023-08-30 12:37:21 +02:00
return "NodeTreeInterfaceSocketShader";
case SOCK_OBJECT:
Nodes: Panels integration with blend files and UI Part 3/3 of #109135, #110272 Switch to new node group interfaces and deprecate old DNA and API. This completes support for panels in node drawing and in node group interface declarations in particular. The new node group interface DNA and RNA code has been added in parts 1 and 2 (#110885, #110952) but has not be enabled yet. This commit completes the integration by * enabling the new RNA API * using the new API in UI * read/write new interfaces from blend files * add versioning for backward compatibility * add forward-compatible writing code to reconstruct old interfaces All places accessing node group interface declarations should now be using the new API. A runtime cache has been added that allows simple linear access to socket inputs and outputs even when a panel hierarchy is used. Old DNA has been deprecated and should only be accessed for versioning (inputs/outputs renamed to inputs_legacy/outputs_legacy to catch errors). Versioning code ensures both backward and forward compatibility of existing files. The API for old interfaces is removed. The new API is very similar but is defined on the `ntree.interface` instead of the `ntree` directly. Breaking change notifications and detailed instructions for migrating will be added. A python test has been added for the node group API functions. This includes new functionality such as creating panels and moving items between different levels. This patch does not yet contain panel representations in the modifier UI. This has been tested in a separate branch and will be added with a later PR (#108565). Pull Request: https://projects.blender.org/blender/blender/pulls/111348
2023-08-30 12:37:21 +02:00
return "NodeTreeInterfaceSocketObject";
case SOCK_IMAGE:
Nodes: Panels integration with blend files and UI Part 3/3 of #109135, #110272 Switch to new node group interfaces and deprecate old DNA and API. This completes support for panels in node drawing and in node group interface declarations in particular. The new node group interface DNA and RNA code has been added in parts 1 and 2 (#110885, #110952) but has not be enabled yet. This commit completes the integration by * enabling the new RNA API * using the new API in UI * read/write new interfaces from blend files * add versioning for backward compatibility * add forward-compatible writing code to reconstruct old interfaces All places accessing node group interface declarations should now be using the new API. A runtime cache has been added that allows simple linear access to socket inputs and outputs even when a panel hierarchy is used. Old DNA has been deprecated and should only be accessed for versioning (inputs/outputs renamed to inputs_legacy/outputs_legacy to catch errors). Versioning code ensures both backward and forward compatibility of existing files. The API for old interfaces is removed. The new API is very similar but is defined on the `ntree.interface` instead of the `ntree` directly. Breaking change notifications and detailed instructions for migrating will be added. A python test has been added for the node group API functions. This includes new functionality such as creating panels and moving items between different levels. This patch does not yet contain panel representations in the modifier UI. This has been tested in a separate branch and will be added with a later PR (#108565). Pull Request: https://projects.blender.org/blender/blender/pulls/111348
2023-08-30 12:37:21 +02:00
return "NodeTreeInterfaceSocketImage";
case SOCK_GEOMETRY:
Nodes: Panels integration with blend files and UI Part 3/3 of #109135, #110272 Switch to new node group interfaces and deprecate old DNA and API. This completes support for panels in node drawing and in node group interface declarations in particular. The new node group interface DNA and RNA code has been added in parts 1 and 2 (#110885, #110952) but has not be enabled yet. This commit completes the integration by * enabling the new RNA API * using the new API in UI * read/write new interfaces from blend files * add versioning for backward compatibility * add forward-compatible writing code to reconstruct old interfaces All places accessing node group interface declarations should now be using the new API. A runtime cache has been added that allows simple linear access to socket inputs and outputs even when a panel hierarchy is used. Old DNA has been deprecated and should only be accessed for versioning (inputs/outputs renamed to inputs_legacy/outputs_legacy to catch errors). Versioning code ensures both backward and forward compatibility of existing files. The API for old interfaces is removed. The new API is very similar but is defined on the `ntree.interface` instead of the `ntree` directly. Breaking change notifications and detailed instructions for migrating will be added. A python test has been added for the node group API functions. This includes new functionality such as creating panels and moving items between different levels. This patch does not yet contain panel representations in the modifier UI. This has been tested in a separate branch and will be added with a later PR (#108565). Pull Request: https://projects.blender.org/blender/blender/pulls/111348
2023-08-30 12:37:21 +02:00
return "NodeTreeInterfaceSocketGeometry";
case SOCK_COLLECTION:
Nodes: Panels integration with blend files and UI Part 3/3 of #109135, #110272 Switch to new node group interfaces and deprecate old DNA and API. This completes support for panels in node drawing and in node group interface declarations in particular. The new node group interface DNA and RNA code has been added in parts 1 and 2 (#110885, #110952) but has not be enabled yet. This commit completes the integration by * enabling the new RNA API * using the new API in UI * read/write new interfaces from blend files * add versioning for backward compatibility * add forward-compatible writing code to reconstruct old interfaces All places accessing node group interface declarations should now be using the new API. A runtime cache has been added that allows simple linear access to socket inputs and outputs even when a panel hierarchy is used. Old DNA has been deprecated and should only be accessed for versioning (inputs/outputs renamed to inputs_legacy/outputs_legacy to catch errors). Versioning code ensures both backward and forward compatibility of existing files. The API for old interfaces is removed. The new API is very similar but is defined on the `ntree.interface` instead of the `ntree` directly. Breaking change notifications and detailed instructions for migrating will be added. A python test has been added for the node group API functions. This includes new functionality such as creating panels and moving items between different levels. This patch does not yet contain panel representations in the modifier UI. This has been tested in a separate branch and will be added with a later PR (#108565). Pull Request: https://projects.blender.org/blender/blender/pulls/111348
2023-08-30 12:37:21 +02:00
return "NodeTreeInterfaceSocketCollection";
case SOCK_TEXTURE:
Nodes: Panels integration with blend files and UI Part 3/3 of #109135, #110272 Switch to new node group interfaces and deprecate old DNA and API. This completes support for panels in node drawing and in node group interface declarations in particular. The new node group interface DNA and RNA code has been added in parts 1 and 2 (#110885, #110952) but has not be enabled yet. This commit completes the integration by * enabling the new RNA API * using the new API in UI * read/write new interfaces from blend files * add versioning for backward compatibility * add forward-compatible writing code to reconstruct old interfaces All places accessing node group interface declarations should now be using the new API. A runtime cache has been added that allows simple linear access to socket inputs and outputs even when a panel hierarchy is used. Old DNA has been deprecated and should only be accessed for versioning (inputs/outputs renamed to inputs_legacy/outputs_legacy to catch errors). Versioning code ensures both backward and forward compatibility of existing files. The API for old interfaces is removed. The new API is very similar but is defined on the `ntree.interface` instead of the `ntree` directly. Breaking change notifications and detailed instructions for migrating will be added. A python test has been added for the node group API functions. This includes new functionality such as creating panels and moving items between different levels. This patch does not yet contain panel representations in the modifier UI. This has been tested in a separate branch and will be added with a later PR (#108565). Pull Request: https://projects.blender.org/blender/blender/pulls/111348
2023-08-30 12:37:21 +02:00
return "NodeTreeInterfaceSocketTexture";
case SOCK_MATERIAL:
Nodes: Panels integration with blend files and UI Part 3/3 of #109135, #110272 Switch to new node group interfaces and deprecate old DNA and API. This completes support for panels in node drawing and in node group interface declarations in particular. The new node group interface DNA and RNA code has been added in parts 1 and 2 (#110885, #110952) but has not be enabled yet. This commit completes the integration by * enabling the new RNA API * using the new API in UI * read/write new interfaces from blend files * add versioning for backward compatibility * add forward-compatible writing code to reconstruct old interfaces All places accessing node group interface declarations should now be using the new API. A runtime cache has been added that allows simple linear access to socket inputs and outputs even when a panel hierarchy is used. Old DNA has been deprecated and should only be accessed for versioning (inputs/outputs renamed to inputs_legacy/outputs_legacy to catch errors). Versioning code ensures both backward and forward compatibility of existing files. The API for old interfaces is removed. The new API is very similar but is defined on the `ntree.interface` instead of the `ntree` directly. Breaking change notifications and detailed instructions for migrating will be added. A python test has been added for the node group API functions. This includes new functionality such as creating panels and moving items between different levels. This patch does not yet contain panel representations in the modifier UI. This has been tested in a separate branch and will be added with a later PR (#108565). Pull Request: https://projects.blender.org/blender/blender/pulls/111348
2023-08-30 12:37:21 +02:00
return "NodeTreeInterfaceSocketMaterial";
Geometry Nodes: Menu Switch Node This patch adds support for _Menu Switch_ nodes and enum definitions in node trees more generally. The design is based on the outcome of the [2022 Nodes Workshop](https://code.blender.org/2022/11/geometry-nodes-workshop-2022/#menu-switch). The _Menu Switch_ node is an advanced version of the _Switch_ node which has a customizable **menu input socket** instead of a simple boolean. The _items_ of this menu are owned by the node itself. Each item has a name and description and unique identifier that is used internally. A menu _socket_ represents a concrete value out of the list of items. To enable selection of an enum value for unconnected sockets the menu is presented as a dropdown list like built-in enums. When the socket is connected a shared pointer to the enum definition is propagated along links and stored in socket default values. This allows node groups to expose a menu from an internal menu switch as a parameter. The enum definition is a runtime copy of the enum items in DNA that allows sharing. A menu socket can have multiple connections, which can lead to ambiguity. If two or more different menu source nodes are connected to a socket it gets marked as _undefined_. Any connection to an undefined menu socket is invalid as a hint to users that there is a problem. A warning/error is also shown on nodes with undefined menu sockets. At runtime the value of a menu socket is the simple integer identifier. This can also be a field in geometry nodes. The identifier is unique within each enum definition, and it is persistent even when items are added, removed, or changed. Changing the name of an item does not affect the internal identifier, so users can rename enum items without breaking existing input values. This also persists if, for example, a linked node group is temporarily unavailable. Pull Request: https://projects.blender.org/blender/blender/pulls/113445
2024-01-26 12:40:01 +01:00
case SOCK_MENU:
return "NodeTreeInterfaceSocketMenu";
Geometry Nodes: add Closures and Bundles behind experimental feature flag This implements bundles and closures which are described in more detail in this blog post: https://code.blender.org/2024/11/geometry-nodes-workshop-october-2024/ tl;dr: * Bundles are containers that allow storing multiple socket values in a single value. Each value in the bundle is identified by a name. Bundles can be nested. * Closures are functions that are created with the Closure Zone and can be evaluated with the Evaluate Closure node. To use the patch, the `Bundle and Closure Nodes` experimental feature has to be enabled. This is necessary, because these features are not fully done yet and still need iterations to improve the workflow before they can be officially released. These iterations are easier to do in `main` than in a separate branch though. That's because this patch is quite large and somewhat prone to merge conflicts. Also other work we want to do, depends on this. This adds the following new nodes: * Combine Bundle: can pack multiple values into one. * Separate Bundle: extracts values from a bundle. * Closure Zone: outputs a closure zone for use in the `Evaluate Closure` node. * Evaluate Closure: evaluates the passed in closure. Things that will be added soon after this lands: * Fields in bundles and closures. The way this is done changes with #134811, so I rather implement this once both are in `main`. * UI features for keeping sockets in sync (right now there are warnings only). One bigger issue is the limited support for lazyness. For example, all inputs of a Combine Bundle node will be evaluated, even if they are not all needed. The same is true for all captured values of a closure. This is a deeper limitation that needs to be resolved at some point. This will likely be done after an initial version of this patch is done. Pull Request: https://projects.blender.org/blender/blender/pulls/128340
2025-04-03 15:44:06 +02:00
case SOCK_BUNDLE:
return "NodeTreeInterfaceSocketBundle";
case SOCK_CLOSURE:
return "NodeTreeInterfaceSocketClosure";
case SOCK_CUSTOM:
break;
}
return std::nullopt;
}
std::optional<StringRefNull> node_static_socket_label(const int type, const int /*subtype*/)
{
switch (eNodeSocketDatatype(type)) {
case SOCK_FLOAT:
return "Float";
case SOCK_INT:
return "Integer";
case SOCK_BOOLEAN:
return "Boolean";
case SOCK_ROTATION:
return "Rotation";
case SOCK_MATRIX:
return "Matrix";
case SOCK_VECTOR:
return "Vector";
case SOCK_RGBA:
return "Color";
case SOCK_STRING:
return "String";
case SOCK_SHADER:
return "Shader";
case SOCK_OBJECT:
return "Object";
case SOCK_IMAGE:
return "Image";
case SOCK_GEOMETRY:
return "Geometry";
case SOCK_COLLECTION:
return "Collection";
case SOCK_TEXTURE:
return "Texture";
case SOCK_MATERIAL:
return "Material";
Geometry Nodes: Menu Switch Node This patch adds support for _Menu Switch_ nodes and enum definitions in node trees more generally. The design is based on the outcome of the [2022 Nodes Workshop](https://code.blender.org/2022/11/geometry-nodes-workshop-2022/#menu-switch). The _Menu Switch_ node is an advanced version of the _Switch_ node which has a customizable **menu input socket** instead of a simple boolean. The _items_ of this menu are owned by the node itself. Each item has a name and description and unique identifier that is used internally. A menu _socket_ represents a concrete value out of the list of items. To enable selection of an enum value for unconnected sockets the menu is presented as a dropdown list like built-in enums. When the socket is connected a shared pointer to the enum definition is propagated along links and stored in socket default values. This allows node groups to expose a menu from an internal menu switch as a parameter. The enum definition is a runtime copy of the enum items in DNA that allows sharing. A menu socket can have multiple connections, which can lead to ambiguity. If two or more different menu source nodes are connected to a socket it gets marked as _undefined_. Any connection to an undefined menu socket is invalid as a hint to users that there is a problem. A warning/error is also shown on nodes with undefined menu sockets. At runtime the value of a menu socket is the simple integer identifier. This can also be a field in geometry nodes. The identifier is unique within each enum definition, and it is persistent even when items are added, removed, or changed. Changing the name of an item does not affect the internal identifier, so users can rename enum items without breaking existing input values. This also persists if, for example, a linked node group is temporarily unavailable. Pull Request: https://projects.blender.org/blender/blender/pulls/113445
2024-01-26 12:40:01 +01:00
case SOCK_MENU:
return "Menu";
Geometry Nodes: add Closures and Bundles behind experimental feature flag This implements bundles and closures which are described in more detail in this blog post: https://code.blender.org/2024/11/geometry-nodes-workshop-october-2024/ tl;dr: * Bundles are containers that allow storing multiple socket values in a single value. Each value in the bundle is identified by a name. Bundles can be nested. * Closures are functions that are created with the Closure Zone and can be evaluated with the Evaluate Closure node. To use the patch, the `Bundle and Closure Nodes` experimental feature has to be enabled. This is necessary, because these features are not fully done yet and still need iterations to improve the workflow before they can be officially released. These iterations are easier to do in `main` than in a separate branch though. That's because this patch is quite large and somewhat prone to merge conflicts. Also other work we want to do, depends on this. This adds the following new nodes: * Combine Bundle: can pack multiple values into one. * Separate Bundle: extracts values from a bundle. * Closure Zone: outputs a closure zone for use in the `Evaluate Closure` node. * Evaluate Closure: evaluates the passed in closure. Things that will be added soon after this lands: * Fields in bundles and closures. The way this is done changes with #134811, so I rather implement this once both are in `main`. * UI features for keeping sockets in sync (right now there are warnings only). One bigger issue is the limited support for lazyness. For example, all inputs of a Combine Bundle node will be evaluated, even if they are not all needed. The same is true for all captured values of a closure. This is a deeper limitation that needs to be resolved at some point. This will likely be done after an initial version of this patch is done. Pull Request: https://projects.blender.org/blender/blender/pulls/128340
2025-04-03 15:44:06 +02:00
case SOCK_BUNDLE:
return "Bundle";
case SOCK_CLOSURE:
return "Closure";
case SOCK_CUSTOM:
break;
}
return std::nullopt;
}
bNodeSocket *node_add_static_socket(bNodeTree &ntree,
bNode &node,
eNodeSocketInOut in_out,
int type,
int subtype,
const StringRefNull identifier,
const StringRefNull name)
{
const std::optional<StringRefNull> idname = node_static_socket_type(type, subtype);
if (!idname.has_value()) {
CLOG_ERROR(&LOG, "static node socket type %d undefined", type);
return nullptr;
}
bNodeSocket *sock = node_add_socket(ntree, node, in_out, *idname, identifier, name);
sock->type = type;
return sock;
}
static void node_socket_free(bNodeSocket *sock, const bool do_id_user)
{
if (sock->prop) {
IDP_FreePropertyContent_ex(sock->prop, do_id_user);
MEM_freeN(sock->prop);
}
if (sock->default_value) {
if (do_id_user) {
socket_id_user_decrement(sock);
}
Geometry Nodes: Menu Switch Node This patch adds support for _Menu Switch_ nodes and enum definitions in node trees more generally. The design is based on the outcome of the [2022 Nodes Workshop](https://code.blender.org/2022/11/geometry-nodes-workshop-2022/#menu-switch). The _Menu Switch_ node is an advanced version of the _Switch_ node which has a customizable **menu input socket** instead of a simple boolean. The _items_ of this menu are owned by the node itself. Each item has a name and description and unique identifier that is used internally. A menu _socket_ represents a concrete value out of the list of items. To enable selection of an enum value for unconnected sockets the menu is presented as a dropdown list like built-in enums. When the socket is connected a shared pointer to the enum definition is propagated along links and stored in socket default values. This allows node groups to expose a menu from an internal menu switch as a parameter. The enum definition is a runtime copy of the enum items in DNA that allows sharing. A menu socket can have multiple connections, which can lead to ambiguity. If two or more different menu source nodes are connected to a socket it gets marked as _undefined_. Any connection to an undefined menu socket is invalid as a hint to users that there is a problem. A warning/error is also shown on nodes with undefined menu sockets. At runtime the value of a menu socket is the simple integer identifier. This can also be a field in geometry nodes. The identifier is unique within each enum definition, and it is persistent even when items are added, removed, or changed. Changing the name of an item does not affect the internal identifier, so users can rename enum items without breaking existing input values. This also persists if, for example, a linked node group is temporarily unavailable. Pull Request: https://projects.blender.org/blender/blender/pulls/113445
2024-01-26 12:40:01 +01:00
if (sock->type == SOCK_MENU) {
auto &default_value_menu = *sock->default_value_typed<bNodeSocketValueMenu>();
if (default_value_menu.enum_items) {
/* Release shared data pointer. */
default_value_menu.enum_items->remove_user_and_delete_if_last();
}
}
MEM_freeN(sock->default_value);
}
if (sock->default_attribute_name) {
MEM_freeN(sock->default_attribute_name);
}
MEM_delete(sock->runtime);
}
void node_remove_socket(bNodeTree &ntree, bNode &node, bNodeSocket &sock)
{
node_remove_socket_ex(ntree, node, sock, true);
}
void node_remove_socket_ex(bNodeTree &ntree, bNode &node, bNodeSocket &sock, const bool do_id_user)
{
LISTBASE_FOREACH_MUTABLE (bNodeLink *, link, &ntree.links) {
if (link->fromsock == &sock || link->tosock == &sock) {
node_remove_link(&ntree, *link);
}
}
for (const int64_t i : node.runtime->internal_links.index_range()) {
const bNodeLink &link = node.runtime->internal_links[i];
if (link.fromsock == &sock || link.tosock == &sock) {
node.runtime->internal_links.remove_and_reorder(i);
BKE_ntree_update_tag_node_internal_link(&ntree, &node);
break;
}
}
/* this is fast, this way we don't need an in_out argument */
BLI_remlink(&node.inputs, &sock);
BLI_remlink(&node.outputs, &sock);
node_socket_free(&sock, do_id_user);
MEM_freeN(&sock);
BKE_ntree_update_tag_socket_removed(&ntree);
}
bNode *node_find_node_by_name(bNodeTree &ntree, const StringRefNull name)
{
return reinterpret_cast<bNode *>(
BLI_findstring(&ntree.nodes, name.c_str(), offsetof(bNode, name)));
}
bNode &node_find_node(bNodeTree &ntree, bNodeSocket &socket)
{
ntree.ensure_topology_cache();
return socket.owner_node();
}
const bNode &node_find_node(const bNodeTree &ntree, const bNodeSocket &socket)
{
ntree.ensure_topology_cache();
return socket.owner_node();
}
bNode *node_find_node_try(bNodeTree &ntree, bNodeSocket &socket)
{
for (bNode *node : ntree.all_nodes()) {
const ListBase *sockets = (socket.in_out == SOCK_IN) ? &node->inputs : &node->outputs;
LISTBASE_FOREACH (const bNodeSocket *, socket_iter, sockets) {
if (socket_iter == &socket) {
return node;
}
}
}
return nullptr;
}
const bNodeTreeInterfaceSocket *node_find_interface_input_by_identifier(const bNodeTree &ntree,
const StringRef identifier)
{
ntree.ensure_interface_cache();
for (const bNodeTreeInterfaceSocket *input : ntree.interface_inputs()) {
if (input->identifier == identifier) {
return input;
}
}
return nullptr;
}
bNode *node_find_root_parent(bNode &node)
{
bNode *parent_iter = &node;
while (parent_iter->parent != nullptr) {
parent_iter = parent_iter->parent;
}
if (!parent_iter->is_frame()) {
return nullptr;
}
return parent_iter;
}
bool node_is_parent_and_child(const bNode &parent, const bNode &child)
{
for (const bNode *child_iter = &child; child_iter; child_iter = child_iter->parent) {
if (child_iter == &parent) {
return true;
}
}
return false;
}
void node_chain_iterator(const bNodeTree *ntree,
const bNode *node_start,
bool (*callback)(bNode *, bNode *, void *, const bool),
void *userdata,
const bool reversed)
{
LISTBASE_FOREACH (bNodeLink *, link, &ntree->links) {
if ((link->flag & NODE_LINK_VALID) == 0) {
/* Skip links marked as cyclic. */
continue;
}
/* Is the link part of the chain meaning node_start == fromnode
* (or tonode for reversed case)? */
if (!reversed) {
if (link->fromnode != node_start) {
continue;
}
}
else {
if (link->tonode != node_start) {
continue;
}
}
if (!callback(link->fromnode, link->tonode, userdata, reversed)) {
return;
}
node_chain_iterator(
ntree, reversed ? link->fromnode : link->tonode, callback, userdata, reversed);
}
}
static void iter_backwards_ex(const bNodeTree *ntree,
const bNode *node_start,
bool (*callback)(bNode *, bNode *, void *),
void *userdata,
const char recursion_mask)
{
LISTBASE_FOREACH (bNodeSocket *, sock, &node_start->inputs) {
bNodeLink *link = sock->link;
if (link == nullptr) {
continue;
}
if ((link->flag & NODE_LINK_VALID) == 0) {
/* Skip links marked as cyclic. */
continue;
}
if (link->fromnode->runtime->iter_flag & recursion_mask) {
continue;
}
link->fromnode->runtime->iter_flag |= recursion_mask;
if (!callback(link->fromnode, link->tonode, userdata)) {
return;
}
iter_backwards_ex(ntree, link->fromnode, callback, userdata, recursion_mask);
Merge of the PyNodes branch (aka "custom nodes") into trunk. PyNodes opens up the node system in Blender to scripters and adds a number of UI-level improvements. === Dynamic node type registration === Node types can now be added at runtime, using the RNA registration mechanism from python. This enables addons such as render engines to create a complete user interface with nodes. Examples of how such nodes can be defined can be found in my personal wiki docs atm [1] and as a script template in release/scripts/templates_py/custom_nodes.py [2]. === Node group improvements === Each node editor now has a tree history of edited node groups, which allows opening and editing nested node groups. The node editor also supports pinning now, so that different spaces can be used to edit different node groups simultaneously. For more ramblings and rationale see (really old) blog post on code.blender.org [3]. The interface of node groups has been overhauled. Sockets of a node group are no longer displayed in columns on either side, but instead special input/output nodes are used to mirror group sockets inside a node tree. This solves the problem of long node lines in groups and allows more adaptable node layout. Internal sockets can be exposed from a group by either connecting to the extension sockets in input/output nodes (shown as empty circle) or by adding sockets from the node property bar in the "Interface" panel. Further details such as the socket name can also be changed there. [1] http://wiki.blender.org/index.php/User:Phonybone/Python_Nodes [2] http://projects.blender.org/scm/viewvc.php/trunk/blender/release/scripts/templates_py/custom_nodes.py?view=markup&root=bf-blender [3] http://code.blender.org/index.php/2012/01/improving-node-group-interface-editing/
2013-03-18 16:34:57 +00:00
}
}
void node_chain_iterator_backwards(const bNodeTree *ntree,
const bNode *node_start,
bool (*callback)(bNode *, bNode *, void *),
void *userdata,
const int recursion_lvl)
Merge of the PyNodes branch (aka "custom nodes") into trunk. PyNodes opens up the node system in Blender to scripters and adds a number of UI-level improvements. === Dynamic node type registration === Node types can now be added at runtime, using the RNA registration mechanism from python. This enables addons such as render engines to create a complete user interface with nodes. Examples of how such nodes can be defined can be found in my personal wiki docs atm [1] and as a script template in release/scripts/templates_py/custom_nodes.py [2]. === Node group improvements === Each node editor now has a tree history of edited node groups, which allows opening and editing nested node groups. The node editor also supports pinning now, so that different spaces can be used to edit different node groups simultaneously. For more ramblings and rationale see (really old) blog post on code.blender.org [3]. The interface of node groups has been overhauled. Sockets of a node group are no longer displayed in columns on either side, but instead special input/output nodes are used to mirror group sockets inside a node tree. This solves the problem of long node lines in groups and allows more adaptable node layout. Internal sockets can be exposed from a group by either connecting to the extension sockets in input/output nodes (shown as empty circle) or by adding sockets from the node property bar in the "Interface" panel. Further details such as the socket name can also be changed there. [1] http://wiki.blender.org/index.php/User:Phonybone/Python_Nodes [2] http://projects.blender.org/scm/viewvc.php/trunk/blender/release/scripts/templates_py/custom_nodes.py?view=markup&root=bf-blender [3] http://code.blender.org/index.php/2012/01/improving-node-group-interface-editing/
2013-03-18 16:34:57 +00:00
{
if (!node_start) {
return;
}
/* Limited by iter_flag type. */
BLI_assert(recursion_lvl < 8);
const char recursion_mask = (1 << recursion_lvl);
/* Reset flag. */
LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
node->runtime->iter_flag &= ~recursion_mask;
}
iter_backwards_ex(ntree, node_start, callback, userdata, recursion_mask);
}
void node_parents_iterator(bNode *node, bool (*callback)(bNode *, void *), void *userdata)
{
if (node->parent) {
if (!callback(node->parent, userdata)) {
return;
}
node_parents_iterator(node->parent, callback, userdata);
}
}
void node_unique_name(bNodeTree &ntree, bNode &node)
{
BLI_uniquename(
&ntree.nodes, &node, DATA_("Node"), '.', offsetof(bNode, name), sizeof(node.name));
}
void node_unique_id(bNodeTree &ntree, bNode &node)
{
/* Use a pointer cast to avoid overflow warnings. */
const double time = BLI_time_now_seconds() * 1000000.0;
RandomNumberGenerator id_rng{*reinterpret_cast<const uint32_t *>(&time)};
/* In the unlikely case that the random ID doesn't match, choose a new one until it does. */
int32_t new_id = id_rng.get_int32();
while (ntree.runtime->nodes_by_id.contains_as(new_id) || new_id <= 0) {
new_id = id_rng.get_int32();
Nodes: Adds button to groups to change type of sockets. The menu lists all socket types that are valid for the node tree. Changing a socket type updates all instances of the group and keeps existing links to the socket. If changing the socket type leads to incorrect node connections the links are flagged as invalid (red) and ignored but not removed. This is so users don't lose information and can then fix resulting issues. For example: Changing a Color socket to a Shader socket can cause an invalid Shader-to-Color connection. Implementation details: The new `NODE_OT_tree_socket_change_type` operator uses the generic `rna_node_socket_type_itemf` function to list all eligible socket types. It uses the tree type's `valid_socket_type` callback to test for valid types. In addition it also checks the subtype, because multiple RNA types are registered for the same base type. The `valid_socket_type` callback has been modified slightly to accept full socket types instead of just the base type enum, so that custom (python) socket types can be used by this operator. The `nodeModifySocketType` function is now called when group nodes encounter a socket type mismatch, instead of replacing the socket entirely. This ensures that links are kept to/from group nodes as well as group input/output nodes. The `nodeModifySocketType` function now also takes a full `bNodeSocketType` instead of just the base and subtype enum (a shortcut `nodeModifySocketTypeStatic` exists for when only static types are used). Differential Revision: https://developer.blender.org/D10912
2021-07-06 18:36:11 +01:00
}
node.identifier = new_id;
ntree.runtime->nodes_by_id.add_new(&node);
node.runtime->index_in_tree = ntree.runtime->nodes_by_id.index_range().last();
BLI_assert(node.runtime->index_in_tree == ntree.runtime->nodes_by_id.index_of(&node));
Nodes: Adds button to groups to change type of sockets. The menu lists all socket types that are valid for the node tree. Changing a socket type updates all instances of the group and keeps existing links to the socket. If changing the socket type leads to incorrect node connections the links are flagged as invalid (red) and ignored but not removed. This is so users don't lose information and can then fix resulting issues. For example: Changing a Color socket to a Shader socket can cause an invalid Shader-to-Color connection. Implementation details: The new `NODE_OT_tree_socket_change_type` operator uses the generic `rna_node_socket_type_itemf` function to list all eligible socket types. It uses the tree type's `valid_socket_type` callback to test for valid types. In addition it also checks the subtype, because multiple RNA types are registered for the same base type. The `valid_socket_type` callback has been modified slightly to accept full socket types instead of just the base type enum, so that custom (python) socket types can be used by this operator. The `nodeModifySocketType` function is now called when group nodes encounter a socket type mismatch, instead of replacing the socket entirely. This ensures that links are kept to/from group nodes as well as group input/output nodes. The `nodeModifySocketType` function now also takes a full `bNodeSocketType` instead of just the base and subtype enum (a shortcut `nodeModifySocketTypeStatic` exists for when only static types are used). Differential Revision: https://developer.blender.org/D10912
2021-07-06 18:36:11 +01:00
}
bNode *node_add_node(const bContext *C, bNodeTree &ntree, const StringRef idname)
Merge of the PyNodes branch (aka "custom nodes") into trunk. PyNodes opens up the node system in Blender to scripters and adds a number of UI-level improvements. === Dynamic node type registration === Node types can now be added at runtime, using the RNA registration mechanism from python. This enables addons such as render engines to create a complete user interface with nodes. Examples of how such nodes can be defined can be found in my personal wiki docs atm [1] and as a script template in release/scripts/templates_py/custom_nodes.py [2]. === Node group improvements === Each node editor now has a tree history of edited node groups, which allows opening and editing nested node groups. The node editor also supports pinning now, so that different spaces can be used to edit different node groups simultaneously. For more ramblings and rationale see (really old) blog post on code.blender.org [3]. The interface of node groups has been overhauled. Sockets of a node group are no longer displayed in columns on either side, but instead special input/output nodes are used to mirror group sockets inside a node tree. This solves the problem of long node lines in groups and allows more adaptable node layout. Internal sockets can be exposed from a group by either connecting to the extension sockets in input/output nodes (shown as empty circle) or by adding sockets from the node property bar in the "Interface" panel. Further details such as the socket name can also be changed there. [1] http://wiki.blender.org/index.php/User:Phonybone/Python_Nodes [2] http://projects.blender.org/scm/viewvc.php/trunk/blender/release/scripts/templates_py/custom_nodes.py?view=markup&root=bf-blender [3] http://code.blender.org/index.php/2012/01/improving-node-group-interface-editing/
2013-03-18 16:34:57 +00:00
{
bNode *node = MEM_callocN<bNode>(__func__);
node->runtime = MEM_new<bNodeRuntime>(__func__);
BLI_addtail(&ntree.nodes, node);
node_unique_id(ntree, *node);
node->ui_order = ntree.all_nodes().size();
idname.copy_utf8_truncated(node->idname);
node_set_typeinfo(C, &ntree, node, node_type_find(idname));
BKE_ntree_update_tag_node_new(&ntree, node);
return node;
Merge of the PyNodes branch (aka "custom nodes") into trunk. PyNodes opens up the node system in Blender to scripters and adds a number of UI-level improvements. === Dynamic node type registration === Node types can now be added at runtime, using the RNA registration mechanism from python. This enables addons such as render engines to create a complete user interface with nodes. Examples of how such nodes can be defined can be found in my personal wiki docs atm [1] and as a script template in release/scripts/templates_py/custom_nodes.py [2]. === Node group improvements === Each node editor now has a tree history of edited node groups, which allows opening and editing nested node groups. The node editor also supports pinning now, so that different spaces can be used to edit different node groups simultaneously. For more ramblings and rationale see (really old) blog post on code.blender.org [3]. The interface of node groups has been overhauled. Sockets of a node group are no longer displayed in columns on either side, but instead special input/output nodes are used to mirror group sockets inside a node tree. This solves the problem of long node lines in groups and allows more adaptable node layout. Internal sockets can be exposed from a group by either connecting to the extension sockets in input/output nodes (shown as empty circle) or by adding sockets from the node property bar in the "Interface" panel. Further details such as the socket name can also be changed there. [1] http://wiki.blender.org/index.php/User:Phonybone/Python_Nodes [2] http://projects.blender.org/scm/viewvc.php/trunk/blender/release/scripts/templates_py/custom_nodes.py?view=markup&root=bf-blender [3] http://code.blender.org/index.php/2012/01/improving-node-group-interface-editing/
2013-03-18 16:34:57 +00:00
}
bNode *node_add_static_node(const bContext *C, bNodeTree &ntree, const int type)
Merge of the PyNodes branch (aka "custom nodes") into trunk. PyNodes opens up the node system in Blender to scripters and adds a number of UI-level improvements. === Dynamic node type registration === Node types can now be added at runtime, using the RNA registration mechanism from python. This enables addons such as render engines to create a complete user interface with nodes. Examples of how such nodes can be defined can be found in my personal wiki docs atm [1] and as a script template in release/scripts/templates_py/custom_nodes.py [2]. === Node group improvements === Each node editor now has a tree history of edited node groups, which allows opening and editing nested node groups. The node editor also supports pinning now, so that different spaces can be used to edit different node groups simultaneously. For more ramblings and rationale see (really old) blog post on code.blender.org [3]. The interface of node groups has been overhauled. Sockets of a node group are no longer displayed in columns on either side, but instead special input/output nodes are used to mirror group sockets inside a node tree. This solves the problem of long node lines in groups and allows more adaptable node layout. Internal sockets can be exposed from a group by either connecting to the extension sockets in input/output nodes (shown as empty circle) or by adding sockets from the node property bar in the "Interface" panel. Further details such as the socket name can also be changed there. [1] http://wiki.blender.org/index.php/User:Phonybone/Python_Nodes [2] http://projects.blender.org/scm/viewvc.php/trunk/blender/release/scripts/templates_py/custom_nodes.py?view=markup&root=bf-blender [3] http://code.blender.org/index.php/2012/01/improving-node-group-interface-editing/
2013-03-18 16:34:57 +00:00
{
std::optional<StringRefNull> idname;
for (bNodeType *ntype : node_types_get()) {
/* Do an extra poll here, because some int types are used
* for multiple node types, this helps find the desired type. */
if (ntype->type_legacy != type) {
continue;
}
const char *disabled_hint;
if (ntype->poll && ntype->poll(ntype, &ntree, &disabled_hint)) {
idname = ntype->idname;
break;
}
}
if (!idname) {
CLOG_ERROR(&LOG, "static node type %d undefined", type);
return nullptr;
Merge of the PyNodes branch (aka "custom nodes") into trunk. PyNodes opens up the node system in Blender to scripters and adds a number of UI-level improvements. === Dynamic node type registration === Node types can now be added at runtime, using the RNA registration mechanism from python. This enables addons such as render engines to create a complete user interface with nodes. Examples of how such nodes can be defined can be found in my personal wiki docs atm [1] and as a script template in release/scripts/templates_py/custom_nodes.py [2]. === Node group improvements === Each node editor now has a tree history of edited node groups, which allows opening and editing nested node groups. The node editor also supports pinning now, so that different spaces can be used to edit different node groups simultaneously. For more ramblings and rationale see (really old) blog post on code.blender.org [3]. The interface of node groups has been overhauled. Sockets of a node group are no longer displayed in columns on either side, but instead special input/output nodes are used to mirror group sockets inside a node tree. This solves the problem of long node lines in groups and allows more adaptable node layout. Internal sockets can be exposed from a group by either connecting to the extension sockets in input/output nodes (shown as empty circle) or by adding sockets from the node property bar in the "Interface" panel. Further details such as the socket name can also be changed there. [1] http://wiki.blender.org/index.php/User:Phonybone/Python_Nodes [2] http://projects.blender.org/scm/viewvc.php/trunk/blender/release/scripts/templates_py/custom_nodes.py?view=markup&root=bf-blender [3] http://code.blender.org/index.php/2012/01/improving-node-group-interface-editing/
2013-03-18 16:34:57 +00:00
}
return node_add_node(C, ntree, *idname);
}
static void node_socket_copy(bNodeSocket *sock_dst, const bNodeSocket *sock_src, const int flag)
{
sock_dst->runtime = MEM_new<bNodeSocketRuntime>(__func__);
if (sock_src->prop) {
sock_dst->prop = IDP_CopyProperty_ex(sock_src->prop, flag);
}
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);
}
Geometry Nodes: Menu Switch Node This patch adds support for _Menu Switch_ nodes and enum definitions in node trees more generally. The design is based on the outcome of the [2022 Nodes Workshop](https://code.blender.org/2022/11/geometry-nodes-workshop-2022/#menu-switch). The _Menu Switch_ node is an advanced version of the _Switch_ node which has a customizable **menu input socket** instead of a simple boolean. The _items_ of this menu are owned by the node itself. Each item has a name and description and unique identifier that is used internally. A menu _socket_ represents a concrete value out of the list of items. To enable selection of an enum value for unconnected sockets the menu is presented as a dropdown list like built-in enums. When the socket is connected a shared pointer to the enum definition is propagated along links and stored in socket default values. This allows node groups to expose a menu from an internal menu switch as a parameter. The enum definition is a runtime copy of the enum items in DNA that allows sharing. A menu socket can have multiple connections, which can lead to ambiguity. If two or more different menu source nodes are connected to a socket it gets marked as _undefined_. Any connection to an undefined menu socket is invalid as a hint to users that there is a problem. A warning/error is also shown on nodes with undefined menu sockets. At runtime the value of a menu socket is the simple integer identifier. This can also be a field in geometry nodes. The identifier is unique within each enum definition, and it is persistent even when items are added, removed, or changed. Changing the name of an item does not affect the internal identifier, so users can rename enum items without breaking existing input values. This also persists if, for example, a linked node group is temporarily unavailable. Pull Request: https://projects.blender.org/blender/blender/pulls/113445
2024-01-26 12:40:01 +01:00
if (sock_src->type == SOCK_MENU) {
auto &default_value_menu = *sock_dst->default_value_typed<bNodeSocketValueMenu>();
if (default_value_menu.enum_items) {
/* Copy of shared data pointer. */
default_value_menu.enum_items->add_user();
}
}
2022-09-09 13:35:21 +02:00
}
Merge of the PyNodes branch (aka "custom nodes") into trunk. PyNodes opens up the node system in Blender to scripters and adds a number of UI-level improvements. === Dynamic node type registration === Node types can now be added at runtime, using the RNA registration mechanism from python. This enables addons such as render engines to create a complete user interface with nodes. Examples of how such nodes can be defined can be found in my personal wiki docs atm [1] and as a script template in release/scripts/templates_py/custom_nodes.py [2]. === Node group improvements === Each node editor now has a tree history of edited node groups, which allows opening and editing nested node groups. The node editor also supports pinning now, so that different spaces can be used to edit different node groups simultaneously. For more ramblings and rationale see (really old) blog post on code.blender.org [3]. The interface of node groups has been overhauled. Sockets of a node group are no longer displayed in columns on either side, but instead special input/output nodes are used to mirror group sockets inside a node tree. This solves the problem of long node lines in groups and allows more adaptable node layout. Internal sockets can be exposed from a group by either connecting to the extension sockets in input/output nodes (shown as empty circle) or by adding sockets from the node property bar in the "Interface" panel. Further details such as the socket name can also be changed there. [1] http://wiki.blender.org/index.php/User:Phonybone/Python_Nodes [2] http://projects.blender.org/scm/viewvc.php/trunk/blender/release/scripts/templates_py/custom_nodes.py?view=markup&root=bf-blender [3] http://code.blender.org/index.php/2012/01/improving-node-group-interface-editing/
2013-03-18 16:34:57 +00:00
sock_dst->default_attribute_name = static_cast<char *>(
MEM_dupallocN(sock_src->default_attribute_name));
sock_dst->stack_index = 0;
}
bNode *node_copy_with_mapping(bNodeTree *dst_tree,
const bNode &node_src,
const int flag,
const bool use_unique,
Map<const bNodeSocket *, bNodeSocket *> &socket_map)
{
bNode *node_dst = MEM_mallocN<bNode>(__func__);
*node_dst = node_src;
node_dst->runtime = MEM_new<bNodeRuntime>(__func__);
/* Can be called for nodes outside a node tree (e.g. clipboard). */
if (dst_tree) {
if (use_unique) {
node_unique_name(*dst_tree, *node_dst);
node_unique_id(*dst_tree, *node_dst);
}
BLI_addtail(&dst_tree->nodes, node_dst);
}
BLI_listbase_clear(&node_dst->inputs);
LISTBASE_FOREACH (const bNodeSocket *, src_socket, &node_src.inputs) {
bNodeSocket *dst_socket = static_cast<bNodeSocket *>(MEM_dupallocN(src_socket));
node_socket_copy(dst_socket, src_socket, flag);
BLI_addtail(&node_dst->inputs, dst_socket);
socket_map.add_new(src_socket, dst_socket);
}
BLI_listbase_clear(&node_dst->outputs);
LISTBASE_FOREACH (const bNodeSocket *, src_socket, &node_src.outputs) {
bNodeSocket *dst_socket = static_cast<bNodeSocket *>(MEM_dupallocN(src_socket));
node_socket_copy(dst_socket, src_socket, flag);
BLI_addtail(&node_dst->outputs, dst_socket);
socket_map.add_new(src_socket, dst_socket);
}
if (node_src.prop) {
node_dst->prop = IDP_CopyProperty_ex(node_src.prop, flag);
}
Nodes: Panels integration with blend files and UI Part 3/3 of #109135, #110272 Switch to new node group interfaces and deprecate old DNA and API. This completes support for panels in node drawing and in node group interface declarations in particular. The new node group interface DNA and RNA code has been added in parts 1 and 2 (#110885, #110952) but has not be enabled yet. This commit completes the integration by * enabling the new RNA API * using the new API in UI * read/write new interfaces from blend files * add versioning for backward compatibility * add forward-compatible writing code to reconstruct old interfaces All places accessing node group interface declarations should now be using the new API. A runtime cache has been added that allows simple linear access to socket inputs and outputs even when a panel hierarchy is used. Old DNA has been deprecated and should only be accessed for versioning (inputs/outputs renamed to inputs_legacy/outputs_legacy to catch errors). Versioning code ensures both backward and forward compatibility of existing files. The API for old interfaces is removed. The new API is very similar but is defined on the `ntree.interface` instead of the `ntree` directly. Breaking change notifications and detailed instructions for migrating will be added. A python test has been added for the node group API functions. This includes new functionality such as creating panels and moving items between different levels. This patch does not yet contain panel representations in the modifier UI. This has been tested in a separate branch and will be added with a later PR (#108565). Pull Request: https://projects.blender.org/blender/blender/pulls/111348
2023-08-30 12:37:21 +02:00
node_dst->panel_states_array = static_cast<bNodePanelState *>(
MEM_dupallocN(node_src.panel_states_array));
node_dst->runtime->internal_links = node_src.runtime->internal_links;
for (bNodeLink &dst_link : node_dst->runtime->internal_links) {
dst_link.fromnode = node_dst;
dst_link.tonode = node_dst;
dst_link.fromsock = socket_map.lookup(dst_link.fromsock);
dst_link.tosock = socket_map.lookup(dst_link.tosock);
}
if ((flag & LIB_ID_CREATE_NO_USER_REFCOUNT) == 0) {
id_us_plus(node_dst->id);
}
if (node_src.typeinfo->copyfunc) {
node_src.typeinfo->copyfunc(dst_tree, node_dst, &node_src);
}
if (dst_tree) {
BKE_ntree_update_tag_node_new(dst_tree, node_dst);
}
/* Only call copy function when a copy is made for the main database, not
* for cases like the dependency graph and localization. */
if (node_dst->typeinfo->copyfunc_api && !(flag & LIB_ID_CREATE_NO_MAIN)) {
PointerRNA ptr = RNA_pointer_create_discrete(
reinterpret_cast<ID *>(dst_tree), &RNA_Node, node_dst);
node_dst->typeinfo->copyfunc_api(&ptr, &node_src);
Christmas coding work! ********* Node editor work: - To enable Nodes for Materials, you have to set the "Use Nodes" button, in the new Material buttons "Nodes" Panel or in header of the Node editor. Doing this will disable Material-Layers. - Nodes now execute materials ("shaders"), but still only using the previewrender code. - Nodes have (optional) previews for rendered images. - Node headers allow to hide buttons and/or preview image - Nodes can be dragged larger/smaller (right-bottom corner) - Nodes can be hidden (minimized) with hotkey H - CTRL+click on an Input Socket gives a popup with default values. - Changing Material/Texture or Mix node will adjust Node title. - Click-drag outside of a Node changes cursor to "Knife' and allows to draw a rect where to cut Links. - Added new node types RGBtoBW, Texture, In/Output, ColorRamp - Material Nodes have options to ouput diffuse or specular, or to use a negative normal. The input socket 'Normal' will force the material to use that normal, otherwise it uses the normal from the Material that has the node tree. - When drawing a link between two not-matching sockets, Blender inserts a converting node (now only for value/rgb combos) - When drawing a link to an input socket that's already in use, the old link will either disappear or flip to another unused socket. - A click on a Material Node will activate it, and show all its settings in the Material Buttons. Active Material Nodes draw the material icon in red. - A click on any node will show its options in the Node Panel in the Material buttons. - Multiple Output Nodes can be used, to sample contents of a tree, but only one Output is the real one, which is indicated in a different color and red material icon. - Added ThemeColors for node types - ALT+C will convert existing Material-Layers to Node... this currently only adds the material/mix nodes and connects them. Dunno if this is worth a lot of coding work to make perfect? - Press C to call another "Solve order", which will show all possible cyclic conflicts (if there are). - Technical: nodes now use "Type" structs which define the structure of nodes and in/output sockets. The Type structs store all fixed info, callbacks, and allow to reconstruct saved Nodes to match what is required by Blender. - Defining (new) nodes now is as simple as filling in a fixed Type struct, plus code some callbacks. A doc will be made! - Node preview images are by default float ********* Icon drawing: - Cleanup of how old icons were implemented in new system, making them 16x16 too, correctly centered *and* scaled. - Made drawing Icons use float coordinates - Moved BIF_calcpreview_image() into interface_icons.c, renamed it icon_from_image(). Removed a lot of unneeded Imbuf magic here! :) - Skipped scaling and imbuf copying when icons are OK size ********* Preview render: - Huge cleanup of code.... - renaming BIF_xxx calls that only were used internally - BIF_previewrender() now accepts an argument for rendering method, so it supports icons, buttonwindow previewrender and node editor - Only a single BIF_preview_changed() call now exists, supporting all signals as needed for buttos and node editor ********* More stuff: - glutil.c, glaDrawPixelsSafe() and glaDrawPixelsTex() now accept format argument for GL_FLOAT rects - Made the ColorBand become a built-in button for interface.c Was a load of cleanup work in buttons_shading.c... - removed a load of unneeded glBlendFunc() calls - Fixed bug in calculating text length for buttons (ancient!)
2005-12-28 15:42:51 +00:00
}
2018-06-17 17:05:51 +02:00
return node_dst;
}
/**
* Type of value storage related with socket is the same.
* \param socket: Node can have multiple sockets & storages pairs.
*/
static void *node_static_value_storage_for(bNode &node, const bNodeSocket &socket)
{
if (!socket.is_output()) {
return nullptr;
}
switch (node.type_legacy) {
case FN_NODE_INPUT_BOOL:
return &reinterpret_cast<NodeInputBool *>(node.storage)->boolean;
case SH_NODE_VALUE:
/* The value is stored in the default value of the first output socket. */
return &static_cast<bNodeSocket *>(node.outputs.first)
->default_value_typed<bNodeSocketValueFloat>()
->value;
case FN_NODE_INPUT_INT:
return &reinterpret_cast<NodeInputInt *>(node.storage)->integer;
case FN_NODE_INPUT_VECTOR:
return &reinterpret_cast<NodeInputVector *>(node.storage)->vector;
case FN_NODE_INPUT_COLOR:
return &reinterpret_cast<NodeInputColor *>(node.storage)->color;
case GEO_NODE_IMAGE:
return &node.id;
default:
break;
}
Orange: more noodle updates! **** NEW: Group Nodes Node trees usually become messy and confusing quickly, so we need not only a way to collapse Nodes into single 'groups', but also a way to re-use that data to create libraries of effects. This has been done by making a new Library data type, the NodeTree. Everything that has been grouped is stored here, and available for re-use, appending or linking. These NodeTrees are fully generic, i.e. can store shader trees, composit trees, and so on. The 'type' value as stored in the NodeTree will keep track of internal type definitions and execute/drawing callbacks. Needless to say, re-using shader trees in a composit tree is a bit useless, and will be prevented in the browsing code. :) So; any NodeTree can become a "Goup Node" inside in a NodeTree. This Group Node then works just like any Node. To prevent the current code to become too complex, I've disabled the possibility to insert Groups inside of Groups. That might be enabled later, but is a real nasty piece of code to get OK. Since Group Nodes are a dynamic Node type, a lot of work has been done to ensure Node definitions can be dynamic too, but still allow to be stored in files, and allow to be verified for type-definition changes on reloading. This system needs a little bit maturing still, so the Python gurus should better wait a little bit! (Also for me to write the definite API docs for it). What works now: - Press CTRL+G to create a new Group. The grouping code checks for impossible selections (like an unselected node between selected nodes). Everthing that's selected then gets removed from the current tree, and inserted in a new NodeTree library data block. A Group Node then is added which links to this new NodeTree. - Press ALT+G to ungroup. This will not delete the NodeTree library data, but just duplicate the Group into the current tree. - Press TAB, or click on the NodeTree icon to edit Groups. Note that NodeTrees are instances, so editing one Group will also change the other users. This also means that when removing nodes in a Group (or hiding sockets or changing internal links) this is immediately corrected for all users of this Group, also in other Materials. - While editing Groups, only the internal Nodes can be edited. A single click outside of the Group boundary will close this 'edit mode'. What needs to be done: - SHIFT+A menu in toolbox style, also including a list of Groups - Enable the single-user button in the Group Node - Displaying all (visible) internal group UI elements in the Node Panel - Enable Library linking and prevent editing of Groups then. **** NEW: Socket Visibility control Node types will be generated with a lot of possible inputs or outputs, and drawing all sockets all the time isn't very useful then. A new option in the Node header ('plus' icon) allows to either hide all unused sockets (first keypress) or to reveil them (when there are hidden sockets, the icon displays black, otherwise it's blended). Hidden sockets in Nodes also are not exported to a Group, so this way you can control what options (in/outputs) exactly are available. To be done: - a way to hide individual sockets, like with a RMB click on it. **** NEW: Nodes now render! This is still quite primitive, more on a level to replace the (now obsolete and disabled) Material Layers. What needs to be done: - make the "Geometry" node work properly, also for AA textures - make the Texture Node work (does very little at the moment) - give Material Nodes all inputs as needed (like Map-to Panel) - find a way to export more data from a Material Node, like the shadow value, or light intensity only, etc Very important also to separate from the Material Buttons the "global" options, like "Ztransp" or "Wire" or "Halo". These can not be set for each Material-Node individually. Also note that the Preview Render (Buttons window) now renders a bit differently. This was a horrid piece of antique code, using a totally incompatible way of rendering. Target is to fully re-use internal render code for previews. OK... that's it mostly. Now test!
2006-01-02 13:06:05 +00:00
return nullptr;
}
static void *socket_value_storage(bNodeSocket &socket)
{
switch (eNodeSocketDatatype(socket.type)) {
case SOCK_BOOLEAN:
return &socket.default_value_typed<bNodeSocketValueBoolean>()->value;
case SOCK_INT:
return &socket.default_value_typed<bNodeSocketValueInt>()->value;
case SOCK_FLOAT:
return &socket.default_value_typed<bNodeSocketValueFloat>()->value;
case SOCK_VECTOR:
return &socket.default_value_typed<bNodeSocketValueVector>()->value;
case SOCK_RGBA:
return &socket.default_value_typed<bNodeSocketValueRGBA>()->value;
case SOCK_IMAGE:
return &socket.default_value_typed<bNodeSocketValueImage>()->value;
case SOCK_TEXTURE:
return &socket.default_value_typed<bNodeSocketValueTexture>()->value;
case SOCK_COLLECTION:
return &socket.default_value_typed<bNodeSocketValueCollection>()->value;
case SOCK_OBJECT:
return &socket.default_value_typed<bNodeSocketValueObject>()->value;
case SOCK_MATERIAL:
return &socket.default_value_typed<bNodeSocketValueMaterial>()->value;
case SOCK_ROTATION:
return &socket.default_value_typed<bNodeSocketValueRotation>()->value_euler;
Geometry Nodes: Menu Switch Node This patch adds support for _Menu Switch_ nodes and enum definitions in node trees more generally. The design is based on the outcome of the [2022 Nodes Workshop](https://code.blender.org/2022/11/geometry-nodes-workshop-2022/#menu-switch). The _Menu Switch_ node is an advanced version of the _Switch_ node which has a customizable **menu input socket** instead of a simple boolean. The _items_ of this menu are owned by the node itself. Each item has a name and description and unique identifier that is used internally. A menu _socket_ represents a concrete value out of the list of items. To enable selection of an enum value for unconnected sockets the menu is presented as a dropdown list like built-in enums. When the socket is connected a shared pointer to the enum definition is propagated along links and stored in socket default values. This allows node groups to expose a menu from an internal menu switch as a parameter. The enum definition is a runtime copy of the enum items in DNA that allows sharing. A menu socket can have multiple connections, which can lead to ambiguity. If two or more different menu source nodes are connected to a socket it gets marked as _undefined_. Any connection to an undefined menu socket is invalid as a hint to users that there is a problem. A warning/error is also shown on nodes with undefined menu sockets. At runtime the value of a menu socket is the simple integer identifier. This can also be a field in geometry nodes. The identifier is unique within each enum definition, and it is persistent even when items are added, removed, or changed. Changing the name of an item does not affect the internal identifier, so users can rename enum items without breaking existing input values. This also persists if, for example, a linked node group is temporarily unavailable. Pull Request: https://projects.blender.org/blender/blender/pulls/113445
2024-01-26 12:40:01 +01:00
case SOCK_MENU:
return &socket.default_value_typed<bNodeSocketValueMenu>()->value;
case SOCK_MATRIX:
/* Matrix sockets currently have no default value. */
return nullptr;
case SOCK_STRING:
/* We don't want do this now! */
return nullptr;
case SOCK_CUSTOM:
case SOCK_SHADER:
case SOCK_GEOMETRY:
Geometry Nodes: add Closures and Bundles behind experimental feature flag This implements bundles and closures which are described in more detail in this blog post: https://code.blender.org/2024/11/geometry-nodes-workshop-october-2024/ tl;dr: * Bundles are containers that allow storing multiple socket values in a single value. Each value in the bundle is identified by a name. Bundles can be nested. * Closures are functions that are created with the Closure Zone and can be evaluated with the Evaluate Closure node. To use the patch, the `Bundle and Closure Nodes` experimental feature has to be enabled. This is necessary, because these features are not fully done yet and still need iterations to improve the workflow before they can be officially released. These iterations are easier to do in `main` than in a separate branch though. That's because this patch is quite large and somewhat prone to merge conflicts. Also other work we want to do, depends on this. This adds the following new nodes: * Combine Bundle: can pack multiple values into one. * Separate Bundle: extracts values from a bundle. * Closure Zone: outputs a closure zone for use in the `Evaluate Closure` node. * Evaluate Closure: evaluates the passed in closure. Things that will be added soon after this lands: * Fields in bundles and closures. The way this is done changes with #134811, so I rather implement this once both are in `main`. * UI features for keeping sockets in sync (right now there are warnings only). One bigger issue is the limited support for lazyness. For example, all inputs of a Combine Bundle node will be evaluated, even if they are not all needed. The same is true for all captured values of a closure. This is a deeper limitation that needs to be resolved at some point. This will likely be done after an initial version of this patch is done. Pull Request: https://projects.blender.org/blender/blender/pulls/128340
2025-04-03 15:44:06 +02:00
case SOCK_BUNDLE:
case SOCK_CLOSURE:
/* Unmovable types. */
break;
}
return nullptr;
}
void node_socket_move_default_value(Main & /*bmain*/,
bNodeTree &tree,
bNodeSocket &src,
bNodeSocket &dst)
{
tree.ensure_topology_cache();
bNode &dst_node = dst.owner_node();
bNode &src_node = src.owner_node();
const CPPType &src_type = *src.typeinfo->base_cpp_type;
const CPPType &dst_type = *dst.typeinfo->base_cpp_type;
const bke::DataTypeConversions &convert = bke::get_implicit_type_conversions();
2018-06-17 17:05:51 +02:00
if (src.is_multi_input()) {
/* Multi input sockets no have value. */
return;
}
if (dst_node.is_reroute() || src_node.is_reroute()) {
/* Reroute node can't have ownership of socket value directly. */
return;
}
if (&src_type != &dst_type) {
if (!convert.is_convertible(src_type, dst_type)) {
return;
}
Merge of the PyNodes branch (aka "custom nodes") into trunk. PyNodes opens up the node system in Blender to scripters and adds a number of UI-level improvements. === Dynamic node type registration === Node types can now be added at runtime, using the RNA registration mechanism from python. This enables addons such as render engines to create a complete user interface with nodes. Examples of how such nodes can be defined can be found in my personal wiki docs atm [1] and as a script template in release/scripts/templates_py/custom_nodes.py [2]. === Node group improvements === Each node editor now has a tree history of edited node groups, which allows opening and editing nested node groups. The node editor also supports pinning now, so that different spaces can be used to edit different node groups simultaneously. For more ramblings and rationale see (really old) blog post on code.blender.org [3]. The interface of node groups has been overhauled. Sockets of a node group are no longer displayed in columns on either side, but instead special input/output nodes are used to mirror group sockets inside a node tree. This solves the problem of long node lines in groups and allows more adaptable node layout. Internal sockets can be exposed from a group by either connecting to the extension sockets in input/output nodes (shown as empty circle) or by adding sockets from the node property bar in the "Interface" panel. Further details such as the socket name can also be changed there. [1] http://wiki.blender.org/index.php/User:Phonybone/Python_Nodes [2] http://projects.blender.org/scm/viewvc.php/trunk/blender/release/scripts/templates_py/custom_nodes.py?view=markup&root=bf-blender [3] http://code.blender.org/index.php/2012/01/improving-node-group-interface-editing/
2013-03-18 16:34:57 +00:00
}
void *src_value = socket_value_storage(src);
void *dst_value = node_static_value_storage_for(dst_node, dst);
if (!dst_value || !src_value) {
return;
Merge of the PyNodes branch (aka "custom nodes") into trunk. PyNodes opens up the node system in Blender to scripters and adds a number of UI-level improvements. === Dynamic node type registration === Node types can now be added at runtime, using the RNA registration mechanism from python. This enables addons such as render engines to create a complete user interface with nodes. Examples of how such nodes can be defined can be found in my personal wiki docs atm [1] and as a script template in release/scripts/templates_py/custom_nodes.py [2]. === Node group improvements === Each node editor now has a tree history of edited node groups, which allows opening and editing nested node groups. The node editor also supports pinning now, so that different spaces can be used to edit different node groups simultaneously. For more ramblings and rationale see (really old) blog post on code.blender.org [3]. The interface of node groups has been overhauled. Sockets of a node group are no longer displayed in columns on either side, but instead special input/output nodes are used to mirror group sockets inside a node tree. This solves the problem of long node lines in groups and allows more adaptable node layout. Internal sockets can be exposed from a group by either connecting to the extension sockets in input/output nodes (shown as empty circle) or by adding sockets from the node property bar in the "Interface" panel. Further details such as the socket name can also be changed there. [1] http://wiki.blender.org/index.php/User:Phonybone/Python_Nodes [2] http://projects.blender.org/scm/viewvc.php/trunk/blender/release/scripts/templates_py/custom_nodes.py?view=markup&root=bf-blender [3] http://code.blender.org/index.php/2012/01/improving-node-group-interface-editing/
2013-03-18 16:34:57 +00:00
}
2018-06-17 17:05:51 +02:00
convert.convert_to_uninitialized(src_type, dst_type, src_value, dst_value);
Christmas coding work! ********* Node editor work: - To enable Nodes for Materials, you have to set the "Use Nodes" button, in the new Material buttons "Nodes" Panel or in header of the Node editor. Doing this will disable Material-Layers. - Nodes now execute materials ("shaders"), but still only using the previewrender code. - Nodes have (optional) previews for rendered images. - Node headers allow to hide buttons and/or preview image - Nodes can be dragged larger/smaller (right-bottom corner) - Nodes can be hidden (minimized) with hotkey H - CTRL+click on an Input Socket gives a popup with default values. - Changing Material/Texture or Mix node will adjust Node title. - Click-drag outside of a Node changes cursor to "Knife' and allows to draw a rect where to cut Links. - Added new node types RGBtoBW, Texture, In/Output, ColorRamp - Material Nodes have options to ouput diffuse or specular, or to use a negative normal. The input socket 'Normal' will force the material to use that normal, otherwise it uses the normal from the Material that has the node tree. - When drawing a link between two not-matching sockets, Blender inserts a converting node (now only for value/rgb combos) - When drawing a link to an input socket that's already in use, the old link will either disappear or flip to another unused socket. - A click on a Material Node will activate it, and show all its settings in the Material Buttons. Active Material Nodes draw the material icon in red. - A click on any node will show its options in the Node Panel in the Material buttons. - Multiple Output Nodes can be used, to sample contents of a tree, but only one Output is the real one, which is indicated in a different color and red material icon. - Added ThemeColors for node types - ALT+C will convert existing Material-Layers to Node... this currently only adds the material/mix nodes and connects them. Dunno if this is worth a lot of coding work to make perfect? - Press C to call another "Solve order", which will show all possible cyclic conflicts (if there are). - Technical: nodes now use "Type" structs which define the structure of nodes and in/output sockets. The Type structs store all fixed info, callbacks, and allow to reconstruct saved Nodes to match what is required by Blender. - Defining (new) nodes now is as simple as filling in a fixed Type struct, plus code some callbacks. A doc will be made! - Node preview images are by default float ********* Icon drawing: - Cleanup of how old icons were implemented in new system, making them 16x16 too, correctly centered *and* scaled. - Made drawing Icons use float coordinates - Moved BIF_calcpreview_image() into interface_icons.c, renamed it icon_from_image(). Removed a lot of unneeded Imbuf magic here! :) - Skipped scaling and imbuf copying when icons are OK size ********* Preview render: - Huge cleanup of code.... - renaming BIF_xxx calls that only were used internally - BIF_previewrender() now accepts an argument for rendering method, so it supports icons, buttonwindow previewrender and node editor - Only a single BIF_preview_changed() call now exists, supporting all signals as needed for buttos and node editor ********* More stuff: - glutil.c, glaDrawPixelsSafe() and glaDrawPixelsTex() now accept format argument for GL_FLOAT rects - Made the ColorBand become a built-in button for interface.c Was a load of cleanup work in buttons_shading.c... - removed a load of unneeded glBlendFunc() calls - Fixed bug in calculating text length for buttons (ancient!)
2005-12-28 15:42:51 +00:00
src_type.destruct(src_value);
if (ELEM(eNodeSocketDatatype(src.type),
SOCK_COLLECTION,
SOCK_IMAGE,
SOCK_MATERIAL,
SOCK_TEXTURE,
SOCK_OBJECT))
{
src_type.value_initialize(src_value);
}
}
Orange: more noodle updates! **** NEW: Group Nodes Node trees usually become messy and confusing quickly, so we need not only a way to collapse Nodes into single 'groups', but also a way to re-use that data to create libraries of effects. This has been done by making a new Library data type, the NodeTree. Everything that has been grouped is stored here, and available for re-use, appending or linking. These NodeTrees are fully generic, i.e. can store shader trees, composit trees, and so on. The 'type' value as stored in the NodeTree will keep track of internal type definitions and execute/drawing callbacks. Needless to say, re-using shader trees in a composit tree is a bit useless, and will be prevented in the browsing code. :) So; any NodeTree can become a "Goup Node" inside in a NodeTree. This Group Node then works just like any Node. To prevent the current code to become too complex, I've disabled the possibility to insert Groups inside of Groups. That might be enabled later, but is a real nasty piece of code to get OK. Since Group Nodes are a dynamic Node type, a lot of work has been done to ensure Node definitions can be dynamic too, but still allow to be stored in files, and allow to be verified for type-definition changes on reloading. This system needs a little bit maturing still, so the Python gurus should better wait a little bit! (Also for me to write the definite API docs for it). What works now: - Press CTRL+G to create a new Group. The grouping code checks for impossible selections (like an unselected node between selected nodes). Everthing that's selected then gets removed from the current tree, and inserted in a new NodeTree library data block. A Group Node then is added which links to this new NodeTree. - Press ALT+G to ungroup. This will not delete the NodeTree library data, but just duplicate the Group into the current tree. - Press TAB, or click on the NodeTree icon to edit Groups. Note that NodeTrees are instances, so editing one Group will also change the other users. This also means that when removing nodes in a Group (or hiding sockets or changing internal links) this is immediately corrected for all users of this Group, also in other Materials. - While editing Groups, only the internal Nodes can be edited. A single click outside of the Group boundary will close this 'edit mode'. What needs to be done: - SHIFT+A menu in toolbox style, also including a list of Groups - Enable the single-user button in the Group Node - Displaying all (visible) internal group UI elements in the Node Panel - Enable Library linking and prevent editing of Groups then. **** NEW: Socket Visibility control Node types will be generated with a lot of possible inputs or outputs, and drawing all sockets all the time isn't very useful then. A new option in the Node header ('plus' icon) allows to either hide all unused sockets (first keypress) or to reveil them (when there are hidden sockets, the icon displays black, otherwise it's blended). Hidden sockets in Nodes also are not exported to a Group, so this way you can control what options (in/outputs) exactly are available. To be done: - a way to hide individual sockets, like with a RMB click on it. **** NEW: Nodes now render! This is still quite primitive, more on a level to replace the (now obsolete and disabled) Material Layers. What needs to be done: - make the "Geometry" node work properly, also for AA textures - make the Texture Node work (does very little at the moment) - give Material Nodes all inputs as needed (like Map-to Panel) - find a way to export more data from a Material Node, like the shadow value, or light intensity only, etc Very important also to separate from the Material Buttons the "global" options, like "Ztransp" or "Wire" or "Halo". These can not be set for each Material-Node individually. Also note that the Preview Render (Buttons window) now renders a bit differently. This was a horrid piece of antique code, using a totally incompatible way of rendering. Target is to fully re-use internal render code for previews. OK... that's it mostly. Now test!
2006-01-02 13:06:05 +00:00
bNode *node_copy(bNodeTree *dst_tree, const bNode &src_node, const int flag, const bool use_unique)
Orange: more noodle updates! **** NEW: Group Nodes Node trees usually become messy and confusing quickly, so we need not only a way to collapse Nodes into single 'groups', but also a way to re-use that data to create libraries of effects. This has been done by making a new Library data type, the NodeTree. Everything that has been grouped is stored here, and available for re-use, appending or linking. These NodeTrees are fully generic, i.e. can store shader trees, composit trees, and so on. The 'type' value as stored in the NodeTree will keep track of internal type definitions and execute/drawing callbacks. Needless to say, re-using shader trees in a composit tree is a bit useless, and will be prevented in the browsing code. :) So; any NodeTree can become a "Goup Node" inside in a NodeTree. This Group Node then works just like any Node. To prevent the current code to become too complex, I've disabled the possibility to insert Groups inside of Groups. That might be enabled later, but is a real nasty piece of code to get OK. Since Group Nodes are a dynamic Node type, a lot of work has been done to ensure Node definitions can be dynamic too, but still allow to be stored in files, and allow to be verified for type-definition changes on reloading. This system needs a little bit maturing still, so the Python gurus should better wait a little bit! (Also for me to write the definite API docs for it). What works now: - Press CTRL+G to create a new Group. The grouping code checks for impossible selections (like an unselected node between selected nodes). Everthing that's selected then gets removed from the current tree, and inserted in a new NodeTree library data block. A Group Node then is added which links to this new NodeTree. - Press ALT+G to ungroup. This will not delete the NodeTree library data, but just duplicate the Group into the current tree. - Press TAB, or click on the NodeTree icon to edit Groups. Note that NodeTrees are instances, so editing one Group will also change the other users. This also means that when removing nodes in a Group (or hiding sockets or changing internal links) this is immediately corrected for all users of this Group, also in other Materials. - While editing Groups, only the internal Nodes can be edited. A single click outside of the Group boundary will close this 'edit mode'. What needs to be done: - SHIFT+A menu in toolbox style, also including a list of Groups - Enable the single-user button in the Group Node - Displaying all (visible) internal group UI elements in the Node Panel - Enable Library linking and prevent editing of Groups then. **** NEW: Socket Visibility control Node types will be generated with a lot of possible inputs or outputs, and drawing all sockets all the time isn't very useful then. A new option in the Node header ('plus' icon) allows to either hide all unused sockets (first keypress) or to reveil them (when there are hidden sockets, the icon displays black, otherwise it's blended). Hidden sockets in Nodes also are not exported to a Group, so this way you can control what options (in/outputs) exactly are available. To be done: - a way to hide individual sockets, like with a RMB click on it. **** NEW: Nodes now render! This is still quite primitive, more on a level to replace the (now obsolete and disabled) Material Layers. What needs to be done: - make the "Geometry" node work properly, also for AA textures - make the Texture Node work (does very little at the moment) - give Material Nodes all inputs as needed (like Map-to Panel) - find a way to export more data from a Material Node, like the shadow value, or light intensity only, etc Very important also to separate from the Material Buttons the "global" options, like "Ztransp" or "Wire" or "Halo". These can not be set for each Material-Node individually. Also note that the Preview Render (Buttons window) now renders a bit differently. This was a horrid piece of antique code, using a totally incompatible way of rendering. Target is to fully re-use internal render code for previews. OK... that's it mostly. Now test!
2006-01-02 13:06:05 +00:00
{
Map<const bNodeSocket *, bNodeSocket *> socket_map;
return node_copy_with_mapping(dst_tree, src_node, flag, use_unique, socket_map);
}
static int node_count_links(const bNodeTree *ntree, const bNodeSocket *socket)
{
int count = 0;
LISTBASE_FOREACH (bNodeLink *, link, &ntree->links) {
if (ELEM(socket, link->fromsock, link->tosock)) {
count++;
}
}
return count;
}
2018-06-17 17:05:51 +02:00
bNodeLink &node_add_link(
bNodeTree &ntree, bNode &fromnode, bNodeSocket &fromsock, bNode &tonode, bNodeSocket &tosock)
{
BLI_assert(ntree.all_nodes().contains(&fromnode));
BLI_assert(ntree.all_nodes().contains(&tonode));
bNodeLink *link = nullptr;
if (eNodeSocketInOut(fromsock.in_out) == SOCK_OUT && eNodeSocketInOut(tosock.in_out) == SOCK_IN)
{
link = MEM_callocN<bNodeLink>(__func__);
BLI_addtail(&ntree.links, link);
link->fromnode = &fromnode;
link->fromsock = &fromsock;
link->tonode = &tonode;
link->tosock = &tosock;
}
else if (eNodeSocketInOut(fromsock.in_out) == SOCK_IN &&
eNodeSocketInOut(tosock.in_out) == SOCK_OUT)
{
/* OK but flip */
link = MEM_callocN<bNodeLink>(__func__);
BLI_addtail(&ntree.links, link);
link->fromnode = &tonode;
link->fromsock = &tosock;
link->tonode = &fromnode;
link->tosock = &fromsock;
Orange: more noodle updates! **** NEW: Group Nodes Node trees usually become messy and confusing quickly, so we need not only a way to collapse Nodes into single 'groups', but also a way to re-use that data to create libraries of effects. This has been done by making a new Library data type, the NodeTree. Everything that has been grouped is stored here, and available for re-use, appending or linking. These NodeTrees are fully generic, i.e. can store shader trees, composit trees, and so on. The 'type' value as stored in the NodeTree will keep track of internal type definitions and execute/drawing callbacks. Needless to say, re-using shader trees in a composit tree is a bit useless, and will be prevented in the browsing code. :) So; any NodeTree can become a "Goup Node" inside in a NodeTree. This Group Node then works just like any Node. To prevent the current code to become too complex, I've disabled the possibility to insert Groups inside of Groups. That might be enabled later, but is a real nasty piece of code to get OK. Since Group Nodes are a dynamic Node type, a lot of work has been done to ensure Node definitions can be dynamic too, but still allow to be stored in files, and allow to be verified for type-definition changes on reloading. This system needs a little bit maturing still, so the Python gurus should better wait a little bit! (Also for me to write the definite API docs for it). What works now: - Press CTRL+G to create a new Group. The grouping code checks for impossible selections (like an unselected node between selected nodes). Everthing that's selected then gets removed from the current tree, and inserted in a new NodeTree library data block. A Group Node then is added which links to this new NodeTree. - Press ALT+G to ungroup. This will not delete the NodeTree library data, but just duplicate the Group into the current tree. - Press TAB, or click on the NodeTree icon to edit Groups. Note that NodeTrees are instances, so editing one Group will also change the other users. This also means that when removing nodes in a Group (or hiding sockets or changing internal links) this is immediately corrected for all users of this Group, also in other Materials. - While editing Groups, only the internal Nodes can be edited. A single click outside of the Group boundary will close this 'edit mode'. What needs to be done: - SHIFT+A menu in toolbox style, also including a list of Groups - Enable the single-user button in the Group Node - Displaying all (visible) internal group UI elements in the Node Panel - Enable Library linking and prevent editing of Groups then. **** NEW: Socket Visibility control Node types will be generated with a lot of possible inputs or outputs, and drawing all sockets all the time isn't very useful then. A new option in the Node header ('plus' icon) allows to either hide all unused sockets (first keypress) or to reveil them (when there are hidden sockets, the icon displays black, otherwise it's blended). Hidden sockets in Nodes also are not exported to a Group, so this way you can control what options (in/outputs) exactly are available. To be done: - a way to hide individual sockets, like with a RMB click on it. **** NEW: Nodes now render! This is still quite primitive, more on a level to replace the (now obsolete and disabled) Material Layers. What needs to be done: - make the "Geometry" node work properly, also for AA textures - make the Texture Node work (does very little at the moment) - give Material Nodes all inputs as needed (like Map-to Panel) - find a way to export more data from a Material Node, like the shadow value, or light intensity only, etc Very important also to separate from the Material Buttons the "global" options, like "Ztransp" or "Wire" or "Halo". These can not be set for each Material-Node individually. Also note that the Preview Render (Buttons window) now renders a bit differently. This was a horrid piece of antique code, using a totally incompatible way of rendering. Target is to fully re-use internal render code for previews. OK... that's it mostly. Now test!
2006-01-02 13:06:05 +00:00
}
BKE_ntree_update_tag_link_added(&ntree, link);
if (link != nullptr && link->tosock->is_multi_input()) {
link->multi_input_sort_id = node_count_links(&ntree, link->tosock) - 1;
}
return *link;
}
void node_remove_link(bNodeTree *ntree, bNodeLink &link)
{
/* Can be called for links outside a node tree (e.g. clipboard). */
if (ntree) {
BLI_remlink(&ntree->links, &link);
}
if (link.tosock) {
link.tosock->link = nullptr;
}
MEM_freeN(&link);
if (ntree) {
BKE_ntree_update_tag_link_removed(ntree);
}
}
void node_link_set_mute(bNodeTree &ntree, bNodeLink &link, const bool muted)
{
const bool was_muted = link.is_muted();
SET_FLAG_FROM_TEST(link.flag, muted, NODE_LINK_MUTED);
if (muted != was_muted) {
BKE_ntree_update_tag_link_mute(&ntree, &link);
}
}
void node_remove_socket_links(bNodeTree &ntree, bNodeSocket &sock)
{
LISTBASE_FOREACH_MUTABLE (bNodeLink *, link, &ntree.links) {
if (link->fromsock == &sock || link->tosock == &sock) {
node_remove_link(&ntree, *link);
}
}
}
bool node_link_is_hidden(const bNodeLink &link)
{
return !(link.fromsock->is_visible() && link.tosock->is_visible());
}
bool node_link_is_selected(const bNodeLink &link)
{
return (link.fromnode->flag & NODE_SELECT) || (link.tonode->flag & NODE_SELECT);
}
/* Adjust the indices of links connected to the given multi input socket after deleting the link at
* `deleted_index`. This function also works if the link has not yet been deleted. */
static void adjust_multi_input_indices_after_removed_link(bNodeTree *ntree,
const bNodeSocket *sock,
const int deleted_index)
{
LISTBASE_FOREACH (bNodeLink *, link, &ntree->links) {
/* We only need to adjust those with a greater index, because the others will have the same
* index. */
if (link->tosock != sock || link->multi_input_sort_id <= deleted_index) {
continue;
}
link->multi_input_sort_id -= 1;
}
}
void node_internal_relink(bNodeTree &ntree, bNode &node)
{
/* store link pointers in output sockets, for efficient lookup */
for (bNodeLink &link : node.runtime->internal_links) {
link.tosock->link = &link;
}
Vector<bNodeLink *> duplicate_links_to_remove;
/* redirect downstream links */
LISTBASE_FOREACH_MUTABLE (bNodeLink *, link, &ntree.links) {
/* do we have internal link? */
if (link->fromnode != &node) {
continue;
}
bNodeLink *internal_link = link->fromsock->link;
bNodeLink *fromlink = internal_link ? internal_link->fromsock->link : nullptr;
if (fromlink == nullptr) {
if (link->tosock->is_multi_input()) {
adjust_multi_input_indices_after_removed_link(
&ntree, link->tosock, link->multi_input_sort_id);
}
node_remove_link(&ntree, *link);
continue;
}
if (link->tosock->is_multi_input()) {
/* remove the link that would be the same as the relinked one */
LISTBASE_FOREACH_MUTABLE (bNodeLink *, link_to_compare, &ntree.links) {
if (link_to_compare->fromsock == fromlink->fromsock &&
link_to_compare->tosock == link->tosock)
{
adjust_multi_input_indices_after_removed_link(
&ntree, link_to_compare->tosock, link_to_compare->multi_input_sort_id);
duplicate_links_to_remove.append_non_duplicates(link_to_compare);
}
}
}
link->fromnode = fromlink->fromnode;
link->fromsock = fromlink->fromsock;
/* if the up- or downstream link is invalid,
* the replacement link will be invalid too.
*/
if (!(fromlink->flag & NODE_LINK_VALID)) {
link->flag &= ~NODE_LINK_VALID;
}
if (fromlink->flag & NODE_LINK_MUTED) {
link->flag |= NODE_LINK_MUTED;
}
BKE_ntree_update_tag_link_changed(&ntree);
}
for (bNodeLink *link : duplicate_links_to_remove) {
node_remove_link(&ntree, *link);
}
/* remove remaining upstream links */
LISTBASE_FOREACH_MUTABLE (bNodeLink *, link, &ntree.links) {
if (link->tonode == &node) {
node_remove_link(&ntree, *link);
}
}
}
void node_attach_node(bNodeTree &ntree, bNode &node, bNode &parent)
{
BLI_assert(parent.is_frame());
BLI_assert(!node_is_parent_and_child(parent, node));
node.parent = &parent;
BKE_ntree_update_tag_parent_change(&ntree, &node);
}
void node_detach_node(bNodeTree &ntree, bNode &node)
{
if (node.parent) {
BLI_assert(node.parent->is_frame());
node.parent = nullptr;
BKE_ntree_update_tag_parent_change(&ntree, &node);
}
}
void node_position_relative(bNode &from_node,
const bNode &to_node,
const bNodeSocket &from_sock,
const bNodeSocket &to_sock)
{
float offset_x;
int tot_sock_idx;
2018-06-17 17:05:51 +02:00
/* Socket to plug into. */
if (eNodeSocketInOut(to_sock.in_out) == SOCK_IN) {
offset_x = -(from_node.typeinfo->width + 50);
tot_sock_idx = BLI_listbase_count(&to_node.outputs);
tot_sock_idx += BLI_findindex(&to_node.inputs, &to_sock);
}
else {
offset_x = to_node.typeinfo->width + 50;
tot_sock_idx = BLI_findindex(&to_node.outputs, &to_sock);
}
2018-06-17 17:05:51 +02:00
BLI_assert(tot_sock_idx != -1);
float offset_y = U.widget_unit * tot_sock_idx;
/* Output socket. */
if (eNodeSocketInOut(from_sock.in_out) == SOCK_IN) {
tot_sock_idx = BLI_listbase_count(&from_node.outputs);
tot_sock_idx += BLI_findindex(&from_node.inputs, &from_sock);
}
else {
tot_sock_idx = BLI_findindex(&from_node.outputs, &from_sock);
}
BLI_assert(tot_sock_idx != -1);
offset_y -= U.widget_unit * tot_sock_idx;
from_node.location[0] = to_node.location[0] + offset_x;
from_node.location[1] = to_node.location[1] - offset_y;
}
void node_position_propagate(bNode &node)
{
LISTBASE_FOREACH (bNodeSocket *, socket, &node.inputs) {
if (socket->link != nullptr) {
bNodeLink *link = socket->link;
node_position_relative(*link->fromnode, *link->tonode, *link->fromsock, *link->tosock);
node_position_propagate(*link->fromnode);
}
Merge of the PyNodes branch (aka "custom nodes") into trunk. PyNodes opens up the node system in Blender to scripters and adds a number of UI-level improvements. === Dynamic node type registration === Node types can now be added at runtime, using the RNA registration mechanism from python. This enables addons such as render engines to create a complete user interface with nodes. Examples of how such nodes can be defined can be found in my personal wiki docs atm [1] and as a script template in release/scripts/templates_py/custom_nodes.py [2]. === Node group improvements === Each node editor now has a tree history of edited node groups, which allows opening and editing nested node groups. The node editor also supports pinning now, so that different spaces can be used to edit different node groups simultaneously. For more ramblings and rationale see (really old) blog post on code.blender.org [3]. The interface of node groups has been overhauled. Sockets of a node group are no longer displayed in columns on either side, but instead special input/output nodes are used to mirror group sockets inside a node tree. This solves the problem of long node lines in groups and allows more adaptable node layout. Internal sockets can be exposed from a group by either connecting to the extension sockets in input/output nodes (shown as empty circle) or by adding sockets from the node property bar in the "Interface" panel. Further details such as the socket name can also be changed there. [1] http://wiki.blender.org/index.php/User:Phonybone/Python_Nodes [2] http://projects.blender.org/scm/viewvc.php/trunk/blender/release/scripts/templates_py/custom_nodes.py?view=markup&root=bf-blender [3] http://code.blender.org/index.php/2012/01/improving-node-group-interface-editing/
2013-03-18 16:34:57 +00:00
}
}
Merge of the PyNodes branch (aka "custom nodes") into trunk. PyNodes opens up the node system in Blender to scripters and adds a number of UI-level improvements. === Dynamic node type registration === Node types can now be added at runtime, using the RNA registration mechanism from python. This enables addons such as render engines to create a complete user interface with nodes. Examples of how such nodes can be defined can be found in my personal wiki docs atm [1] and as a script template in release/scripts/templates_py/custom_nodes.py [2]. === Node group improvements === Each node editor now has a tree history of edited node groups, which allows opening and editing nested node groups. The node editor also supports pinning now, so that different spaces can be used to edit different node groups simultaneously. For more ramblings and rationale see (really old) blog post on code.blender.org [3]. The interface of node groups has been overhauled. Sockets of a node group are no longer displayed in columns on either side, but instead special input/output nodes are used to mirror group sockets inside a node tree. This solves the problem of long node lines in groups and allows more adaptable node layout. Internal sockets can be exposed from a group by either connecting to the extension sockets in input/output nodes (shown as empty circle) or by adding sockets from the node property bar in the "Interface" panel. Further details such as the socket name can also be changed there. [1] http://wiki.blender.org/index.php/User:Phonybone/Python_Nodes [2] http://projects.blender.org/scm/viewvc.php/trunk/blender/release/scripts/templates_py/custom_nodes.py?view=markup&root=bf-blender [3] http://code.blender.org/index.php/2012/01/improving-node-group-interface-editing/
2013-03-18 16:34:57 +00:00
static bNodeTree *node_tree_add_tree_do(Main *bmain,
std::optional<Library *> owner_library,
ID *owner_id,
const bool is_embedded,
const StringRef name,
const StringRef idname)
{
/* trees are created as local trees for compositor, material or texture nodes,
* node groups and other tree types are created as library data.
*/
int flag = 0;
if (is_embedded || bmain == nullptr) {
flag |= LIB_ID_CREATE_NO_MAIN;
}
BLI_assert_msg(!owner_library || !owner_id,
"Embedded NTrees should never have a defined owner library here");
bNodeTree *ntree = reinterpret_cast<bNodeTree *>(
BKE_libblock_alloc_in_lib(bmain, owner_library, ID_NT, std::string(name).c_str(), flag));
BKE_libblock_init_empty(&ntree->id);
if (is_embedded) {
BLI_assert(owner_id != nullptr);
ntree->id.flag |= ID_FLAG_EMBEDDED_DATA;
ntree->owner_id = owner_id;
bNodeTree **ntree_owner_ptr = node_tree_ptr_from_id(owner_id);
BLI_assert(ntree_owner_ptr != nullptr);
*ntree_owner_ptr = ntree;
}
else {
BLI_assert(owner_id == nullptr);
}
idname.copy_utf8_truncated(ntree->idname);
ntree_set_typeinfo(ntree, node_tree_type_find(idname));
return ntree;
}
bNodeTree *node_tree_add_tree(Main *bmain, const StringRef name, const StringRef idname)
{
return node_tree_add_tree_do(bmain, std::nullopt, nullptr, false, name, idname);
}
bNodeTree *node_tree_add_in_lib(Main *bmain,
Library *owner_library,
const StringRefNull name,
const StringRefNull idname)
{
return node_tree_add_tree_do(bmain, owner_library, nullptr, false, name, idname);
}
bNodeTree *node_tree_add_tree_embedded(Main * /*bmain*/,
ID *owner_id,
const StringRefNull name,
const StringRefNull idname)
{
return node_tree_add_tree_do(nullptr, std::nullopt, owner_id, true, name, idname);
}
bNodeTree *node_tree_copy_tree_ex(const bNodeTree &ntree, Main *bmain, const bool do_id_user)
{
const int flag = do_id_user ? 0 : LIB_ID_CREATE_NO_USER_REFCOUNT | LIB_ID_CREATE_NO_MAIN;
Merge of the PyNodes branch (aka "custom nodes") into trunk. PyNodes opens up the node system in Blender to scripters and adds a number of UI-level improvements. === Dynamic node type registration === Node types can now be added at runtime, using the RNA registration mechanism from python. This enables addons such as render engines to create a complete user interface with nodes. Examples of how such nodes can be defined can be found in my personal wiki docs atm [1] and as a script template in release/scripts/templates_py/custom_nodes.py [2]. === Node group improvements === Each node editor now has a tree history of edited node groups, which allows opening and editing nested node groups. The node editor also supports pinning now, so that different spaces can be used to edit different node groups simultaneously. For more ramblings and rationale see (really old) blog post on code.blender.org [3]. The interface of node groups has been overhauled. Sockets of a node group are no longer displayed in columns on either side, but instead special input/output nodes are used to mirror group sockets inside a node tree. This solves the problem of long node lines in groups and allows more adaptable node layout. Internal sockets can be exposed from a group by either connecting to the extension sockets in input/output nodes (shown as empty circle) or by adding sockets from the node property bar in the "Interface" panel. Further details such as the socket name can also be changed there. [1] http://wiki.blender.org/index.php/User:Phonybone/Python_Nodes [2] http://projects.blender.org/scm/viewvc.php/trunk/blender/release/scripts/templates_py/custom_nodes.py?view=markup&root=bf-blender [3] http://code.blender.org/index.php/2012/01/improving-node-group-interface-editing/
2013-03-18 16:34:57 +00:00
bNodeTree *ntree_copy = reinterpret_cast<bNodeTree *>(
BKE_id_copy_ex(bmain, reinterpret_cast<const ID *>(&ntree), nullptr, flag));
return ntree_copy;
}
bNodeTree *node_tree_copy_tree(Main *bmain, const bNodeTree &ntree)
{
return node_tree_copy_tree_ex(ntree, bmain, true);
}
/* *************** Node Preview *********** */
/* XXX this should be removed eventually ...
* Currently BKE functions are modeled closely on previous code,
* using node_preview_init_tree to set up previews for a whole node tree in advance.
* This should be left more to the individual node tree implementations. */
bool node_preview_used(const bNode &node)
{
/* XXX check for closed nodes? */
return (node.typeinfo->flag & NODE_PREVIEW) != 0;
}
bNodePreview *node_preview_verify(Map<bNodeInstanceKey, bNodePreview> &previews,
bNodeInstanceKey key,
const int xsize,
const int ysize,
const bool create)
{
bNodePreview *preview = create ?
&previews.lookup_or_add_cb(key,
[&]() {
bNodePreview preview;
preview.ibuf = IMB_allocImBuf(
xsize, ysize, 32, IB_byte_data);
return preview;
}) :
previews.lookup_ptr(key);
if (!preview) {
return nullptr;
}
/* node previews can get added with variable size this way */
if (xsize == 0 || ysize == 0) {
return preview;
}
/* sanity checks & initialize */
const uint size[2] = {uint(xsize), uint(ysize)};
IMB_rect_size_set(preview->ibuf, size);
if (preview->ibuf->byte_buffer.data == nullptr) {
IMB_alloc_byte_pixels(preview->ibuf);
}
/* no clear, makes nicer previews */
return preview;
}
bNodePreview::bNodePreview(const bNodePreview &other)
{
this->ibuf = IMB_dupImBuf(other.ibuf);
}
bNodePreview::bNodePreview(bNodePreview &&other)
{
this->ibuf = other.ibuf;
other.ibuf = nullptr;
}
bNodePreview::~bNodePreview()
{
if (this->ibuf) {
IMB_freeImBuf(this->ibuf);
}
}
static void node_preview_init_tree_recursive(Map<bNodeInstanceKey, bNodePreview> &previews,
bNodeTree *ntree,
bNodeInstanceKey parent_key,
const int xsize,
const int ysize)
{
for (bNode *node : ntree->all_nodes()) {
bNodeInstanceKey key = node_instance_key(parent_key, ntree, node);
if (node_preview_used(*node)) {
node_preview_verify(previews, key, xsize, ysize, false);
}
bNodeTree *group = reinterpret_cast<bNodeTree *>(node->id);
if (node->is_group() && group != nullptr) {
node_preview_init_tree_recursive(previews, group, key, xsize, ysize);
}
}
}
void node_preview_init_tree(bNodeTree *ntree, int xsize, int ysize)
{
node_preview_init_tree_recursive(
ntree->runtime->previews, ntree, NODE_INSTANCE_KEY_BASE, xsize, ysize);
}
static void collect_used_previews(Map<bNodeInstanceKey, bNodePreview> &previews,
bNodeTree *ntree,
bNodeInstanceKey parent_key,
Set<bNodeInstanceKey> &used)
{
for (bNode *node : ntree->all_nodes()) {
bNodeInstanceKey key = node_instance_key(parent_key, ntree, node);
if (node_preview_used(*node)) {
used.add(key);
}
if (node->is_group()) {
if (bNodeTree *group = reinterpret_cast<bNodeTree *>(node->id)) {
collect_used_previews(previews, group, key, used);
}
}
}
}
void node_preview_remove_unused(bNodeTree *ntree)
{
Set<bNodeInstanceKey> used_previews;
collect_used_previews(ntree->runtime->previews, ntree, NODE_INSTANCE_KEY_BASE, used_previews);
ntree->runtime->previews.remove_if([&](const MapItem<bNodeInstanceKey, bNodePreview> &item) {
return !used_previews.contains(item.key);
});
}
void node_preview_merge_tree(bNodeTree *to_ntree, bNodeTree *from_ntree, bool remove_old)
{
if (remove_old || to_ntree->runtime->previews.is_empty()) {
to_ntree->runtime->previews.clear();
to_ntree->runtime->previews = std::move(from_ntree->runtime->previews);
node_preview_remove_unused(to_ntree);
}
else {
for (const auto &item : from_ntree->runtime->previews.items()) {
to_ntree->runtime->previews.add(item.key, std::move(item.value));
}
from_ntree->runtime->previews.clear();
}
}
void node_unlink_node(bNodeTree &ntree, bNode &node)
{
LISTBASE_FOREACH_MUTABLE (bNodeLink *, link, &ntree.links) {
ListBase *lb = nullptr;
if (link->fromnode == &node) {
lb = &node.outputs;
}
else if (link->tonode == &node) {
lb = &node.inputs;
}
if (lb) {
/* Only bother adjusting if the socket is not on the node we're deleting. */
if (link->tonode != &node && link->tosock->is_multi_input()) {
adjust_multi_input_indices_after_removed_link(
&ntree, link->tosock, link->multi_input_sort_id);
}
LISTBASE_FOREACH (const bNodeSocket *, sock, lb) {
if (link->fromsock == sock || link->tosock == sock) {
node_remove_link(&ntree, *link);
break;
}
}
}
}
}
static void node_unlink_attached(bNodeTree *ntree, const bNode *parent)
{
for (bNode *node : ntree->all_nodes()) {
if (node->parent == parent) {
node_detach_node(*ntree, *node);
}
}
}
void node_rebuild_id_vector(bNodeTree &node_tree)
{
/* Rebuild nodes #VectorSet which must have the same order as the list. */
node_tree.runtime->nodes_by_id.clear();
int i;
LISTBASE_FOREACH_INDEX (bNode *, node, &node_tree.nodes, i) {
node_tree.runtime->nodes_by_id.add_new(node);
node->runtime->index_in_tree = i;
}
}
void node_free_node(bNodeTree *ntree, bNode &node)
{
/* since it is called while free database, node->id is undefined */
/* can be called for nodes outside a node tree (e.g. clipboard) */
if (ntree) {
BLI_remlink(&ntree->nodes, &node);
/* Rebuild nodes #VectorSet which must have the same order as the list. */
node_rebuild_id_vector(*ntree);
/* texture node has bad habit of keeping exec data around */
if (ntree->type == NTREE_TEXTURE && ntree->runtime->execdata) {
ntreeTexEndExecTree(ntree->runtime->execdata);
ntree->runtime->execdata = nullptr;
}
}
if (node.typeinfo->freefunc) {
node.typeinfo->freefunc(&node);
}
LISTBASE_FOREACH_MUTABLE (bNodeSocket *, sock, &node.inputs) {
/* Remember, no ID user refcount management here! */
node_socket_free(sock, false);
MEM_freeN(sock);
Merge of the PyNodes branch (aka "custom nodes") into trunk. PyNodes opens up the node system in Blender to scripters and adds a number of UI-level improvements. === Dynamic node type registration === Node types can now be added at runtime, using the RNA registration mechanism from python. This enables addons such as render engines to create a complete user interface with nodes. Examples of how such nodes can be defined can be found in my personal wiki docs atm [1] and as a script template in release/scripts/templates_py/custom_nodes.py [2]. === Node group improvements === Each node editor now has a tree history of edited node groups, which allows opening and editing nested node groups. The node editor also supports pinning now, so that different spaces can be used to edit different node groups simultaneously. For more ramblings and rationale see (really old) blog post on code.blender.org [3]. The interface of node groups has been overhauled. Sockets of a node group are no longer displayed in columns on either side, but instead special input/output nodes are used to mirror group sockets inside a node tree. This solves the problem of long node lines in groups and allows more adaptable node layout. Internal sockets can be exposed from a group by either connecting to the extension sockets in input/output nodes (shown as empty circle) or by adding sockets from the node property bar in the "Interface" panel. Further details such as the socket name can also be changed there. [1] http://wiki.blender.org/index.php/User:Phonybone/Python_Nodes [2] http://projects.blender.org/scm/viewvc.php/trunk/blender/release/scripts/templates_py/custom_nodes.py?view=markup&root=bf-blender [3] http://code.blender.org/index.php/2012/01/improving-node-group-interface-editing/
2013-03-18 16:34:57 +00:00
}
LISTBASE_FOREACH_MUTABLE (bNodeSocket *, sock, &node.outputs) {
/* Remember, no ID user refcount management here! */
node_socket_free(sock, false);
MEM_freeN(sock);
}
MEM_SAFE_FREE(node.panel_states_array);
Nodes: Panels integration with blend files and UI Part 3/3 of #109135, #110272 Switch to new node group interfaces and deprecate old DNA and API. This completes support for panels in node drawing and in node group interface declarations in particular. The new node group interface DNA and RNA code has been added in parts 1 and 2 (#110885, #110952) but has not be enabled yet. This commit completes the integration by * enabling the new RNA API * using the new API in UI * read/write new interfaces from blend files * add versioning for backward compatibility * add forward-compatible writing code to reconstruct old interfaces All places accessing node group interface declarations should now be using the new API. A runtime cache has been added that allows simple linear access to socket inputs and outputs even when a panel hierarchy is used. Old DNA has been deprecated and should only be accessed for versioning (inputs/outputs renamed to inputs_legacy/outputs_legacy to catch errors). Versioning code ensures both backward and forward compatibility of existing files. The API for old interfaces is removed. The new API is very similar but is defined on the `ntree.interface` instead of the `ntree` directly. Breaking change notifications and detailed instructions for migrating will be added. A python test has been added for the node group API functions. This includes new functionality such as creating panels and moving items between different levels. This patch does not yet contain panel representations in the modifier UI. This has been tested in a separate branch and will be added with a later PR (#108565). Pull Request: https://projects.blender.org/blender/blender/pulls/111348
2023-08-30 12:37:21 +02:00
if (node.prop) {
/* Remember, no ID user refcount management here! */
IDP_FreePropertyContent_ex(node.prop, false);
MEM_freeN(node.prop);
}
2018-06-17 17:05:51 +02:00
if (node.runtime->declaration) {
Nodes: unify static and dynamic declarations This helps solving the problem encountered in #113553. The problem is that we currently can't support link-drag-search for nodes which have a dynamic declaration. With this patch, there is only a single `declare` function per node type, instead of the separate `declare` and `declare_dynamic` functions. The new `declare` function has access to the node and tree. However, both are allowed to be null. The final node declaration has a flag for whether it depends on the node context or not. Nodes that previously had a dynamic declaration should now create as much of the declaration as possible that does not depend on the node. This allows code like for link-drag-search to take those sockets into account even if the other sockets are dynamic. For node declarations that have dynamic types (e.g. Switch node), we can also add extra information to the static node declaration, like the identifier of the socket with the dynamic type. This is not part of this patch though. I can think of two main alternatives to the approach implemented here: * Define two separate functions for dynamic nodes. One that creates the "static declaration" without node context, and on that creates the actual declaration with node context. * Have a single declare function that generates "build instructions" for the actual node declaration. So instead of building the final declaration directly, one can for example add a socket whose type depends on a specific rna path in the node. The actual node declaration is then automatically generated based on the build instructions. This becomes quite a bit more tricky with dynamic amounts of sockets and introduces another indirection between declarations and what sockets the node actually has. I found the approach implemented in this patch to lead to the least amount of boilerplate (doesn't require a seperate "build instructions" data structure) and code duplication (socket properties are still only defined in one place). At the same time, it offers more flexibility to how nodes can be dynamic. Pull Request: https://projects.blender.org/blender/blender/pulls/113742
2023-10-15 20:28:23 +02:00
/* Only free if this declaration is not shared with the node type, which can happen if it does
* not depend on any context. */
if (node.runtime->declaration != node.typeinfo->static_declaration) {
delete node.runtime->declaration;
Nodes: unify static and dynamic declarations This helps solving the problem encountered in #113553. The problem is that we currently can't support link-drag-search for nodes which have a dynamic declaration. With this patch, there is only a single `declare` function per node type, instead of the separate `declare` and `declare_dynamic` functions. The new `declare` function has access to the node and tree. However, both are allowed to be null. The final node declaration has a flag for whether it depends on the node context or not. Nodes that previously had a dynamic declaration should now create as much of the declaration as possible that does not depend on the node. This allows code like for link-drag-search to take those sockets into account even if the other sockets are dynamic. For node declarations that have dynamic types (e.g. Switch node), we can also add extra information to the static node declaration, like the identifier of the socket with the dynamic type. This is not part of this patch though. I can think of two main alternatives to the approach implemented here: * Define two separate functions for dynamic nodes. One that creates the "static declaration" without node context, and on that creates the actual declaration with node context. * Have a single declare function that generates "build instructions" for the actual node declaration. So instead of building the final declaration directly, one can for example add a socket whose type depends on a specific rna path in the node. The actual node declaration is then automatically generated based on the build instructions. This becomes quite a bit more tricky with dynamic amounts of sockets and introduces another indirection between declarations and what sockets the node actually has. I found the approach implemented in this patch to lead to the least amount of boilerplate (doesn't require a seperate "build instructions" data structure) and code duplication (socket properties are still only defined in one place). At the same time, it offers more flexibility to how nodes can be dynamic. Pull Request: https://projects.blender.org/blender/blender/pulls/113742
2023-10-15 20:28:23 +02:00
}
}
MEM_delete(node.runtime);
MEM_freeN(&node);
if (ntree) {
BKE_ntree_update_tag_node_removed(ntree);
}
}
void node_tree_free_local_node(bNodeTree &ntree, bNode &node)
{
/* For removing nodes while editing localized node trees. */
BLI_assert((ntree.id.tag & ID_TAG_LOCALIZED) != 0);
Merge of the PyNodes branch (aka "custom nodes") into trunk. PyNodes opens up the node system in Blender to scripters and adds a number of UI-level improvements. === Dynamic node type registration === Node types can now be added at runtime, using the RNA registration mechanism from python. This enables addons such as render engines to create a complete user interface with nodes. Examples of how such nodes can be defined can be found in my personal wiki docs atm [1] and as a script template in release/scripts/templates_py/custom_nodes.py [2]. === Node group improvements === Each node editor now has a tree history of edited node groups, which allows opening and editing nested node groups. The node editor also supports pinning now, so that different spaces can be used to edit different node groups simultaneously. For more ramblings and rationale see (really old) blog post on code.blender.org [3]. The interface of node groups has been overhauled. Sockets of a node group are no longer displayed in columns on either side, but instead special input/output nodes are used to mirror group sockets inside a node tree. This solves the problem of long node lines in groups and allows more adaptable node layout. Internal sockets can be exposed from a group by either connecting to the extension sockets in input/output nodes (shown as empty circle) or by adding sockets from the node property bar in the "Interface" panel. Further details such as the socket name can also be changed there. [1] http://wiki.blender.org/index.php/User:Phonybone/Python_Nodes [2] http://projects.blender.org/scm/viewvc.php/trunk/blender/release/scripts/templates_py/custom_nodes.py?view=markup&root=bf-blender [3] http://code.blender.org/index.php/2012/01/improving-node-group-interface-editing/
2013-03-18 16:34:57 +00:00
/* These two lines assume the caller might want to free a single node and maintain
* a valid state in the node tree. */
node_unlink_node(ntree, node);
node_unlink_attached(&ntree, &node);
Merge of the PyNodes branch (aka "custom nodes") into trunk. PyNodes opens up the node system in Blender to scripters and adds a number of UI-level improvements. === Dynamic node type registration === Node types can now be added at runtime, using the RNA registration mechanism from python. This enables addons such as render engines to create a complete user interface with nodes. Examples of how such nodes can be defined can be found in my personal wiki docs atm [1] and as a script template in release/scripts/templates_py/custom_nodes.py [2]. === Node group improvements === Each node editor now has a tree history of edited node groups, which allows opening and editing nested node groups. The node editor also supports pinning now, so that different spaces can be used to edit different node groups simultaneously. For more ramblings and rationale see (really old) blog post on code.blender.org [3]. The interface of node groups has been overhauled. Sockets of a node group are no longer displayed in columns on either side, but instead special input/output nodes are used to mirror group sockets inside a node tree. This solves the problem of long node lines in groups and allows more adaptable node layout. Internal sockets can be exposed from a group by either connecting to the extension sockets in input/output nodes (shown as empty circle) or by adding sockets from the node property bar in the "Interface" panel. Further details such as the socket name can also be changed there. [1] http://wiki.blender.org/index.php/User:Phonybone/Python_Nodes [2] http://projects.blender.org/scm/viewvc.php/trunk/blender/release/scripts/templates_py/custom_nodes.py?view=markup&root=bf-blender [3] http://code.blender.org/index.php/2012/01/improving-node-group-interface-editing/
2013-03-18 16:34:57 +00:00
node_free_node(&ntree, node);
node_rebuild_id_vector(ntree);
Merge of the PyNodes branch (aka "custom nodes") into trunk. PyNodes opens up the node system in Blender to scripters and adds a number of UI-level improvements. === Dynamic node type registration === Node types can now be added at runtime, using the RNA registration mechanism from python. This enables addons such as render engines to create a complete user interface with nodes. Examples of how such nodes can be defined can be found in my personal wiki docs atm [1] and as a script template in release/scripts/templates_py/custom_nodes.py [2]. === Node group improvements === Each node editor now has a tree history of edited node groups, which allows opening and editing nested node groups. The node editor also supports pinning now, so that different spaces can be used to edit different node groups simultaneously. For more ramblings and rationale see (really old) blog post on code.blender.org [3]. The interface of node groups has been overhauled. Sockets of a node group are no longer displayed in columns on either side, but instead special input/output nodes are used to mirror group sockets inside a node tree. This solves the problem of long node lines in groups and allows more adaptable node layout. Internal sockets can be exposed from a group by either connecting to the extension sockets in input/output nodes (shown as empty circle) or by adding sockets from the node property bar in the "Interface" panel. Further details such as the socket name can also be changed there. [1] http://wiki.blender.org/index.php/User:Phonybone/Python_Nodes [2] http://projects.blender.org/scm/viewvc.php/trunk/blender/release/scripts/templates_py/custom_nodes.py?view=markup&root=bf-blender [3] http://code.blender.org/index.php/2012/01/improving-node-group-interface-editing/
2013-03-18 16:34:57 +00:00
}
void node_remove_node(Main *bmain, bNodeTree &ntree, bNode &node, const bool do_id_user)
Merge of the PyNodes branch (aka "custom nodes") into trunk. PyNodes opens up the node system in Blender to scripters and adds a number of UI-level improvements. === Dynamic node type registration === Node types can now be added at runtime, using the RNA registration mechanism from python. This enables addons such as render engines to create a complete user interface with nodes. Examples of how such nodes can be defined can be found in my personal wiki docs atm [1] and as a script template in release/scripts/templates_py/custom_nodes.py [2]. === Node group improvements === Each node editor now has a tree history of edited node groups, which allows opening and editing nested node groups. The node editor also supports pinning now, so that different spaces can be used to edit different node groups simultaneously. For more ramblings and rationale see (really old) blog post on code.blender.org [3]. The interface of node groups has been overhauled. Sockets of a node group are no longer displayed in columns on either side, but instead special input/output nodes are used to mirror group sockets inside a node tree. This solves the problem of long node lines in groups and allows more adaptable node layout. Internal sockets can be exposed from a group by either connecting to the extension sockets in input/output nodes (shown as empty circle) or by adding sockets from the node property bar in the "Interface" panel. Further details such as the socket name can also be changed there. [1] http://wiki.blender.org/index.php/User:Phonybone/Python_Nodes [2] http://projects.blender.org/scm/viewvc.php/trunk/blender/release/scripts/templates_py/custom_nodes.py?view=markup&root=bf-blender [3] http://code.blender.org/index.php/2012/01/improving-node-group-interface-editing/
2013-03-18 16:34:57 +00:00
{
/* This function is not for localized node trees, we do not want
2023-08-18 08:51:29 +10:00
* do to ID user reference-counting and removal of animation data then. */
BLI_assert((ntree.id.tag & ID_TAG_LOCALIZED) == 0);
Merge of the PyNodes branch (aka "custom nodes") into trunk. PyNodes opens up the node system in Blender to scripters and adds a number of UI-level improvements. === Dynamic node type registration === Node types can now be added at runtime, using the RNA registration mechanism from python. This enables addons such as render engines to create a complete user interface with nodes. Examples of how such nodes can be defined can be found in my personal wiki docs atm [1] and as a script template in release/scripts/templates_py/custom_nodes.py [2]. === Node group improvements === Each node editor now has a tree history of edited node groups, which allows opening and editing nested node groups. The node editor also supports pinning now, so that different spaces can be used to edit different node groups simultaneously. For more ramblings and rationale see (really old) blog post on code.blender.org [3]. The interface of node groups has been overhauled. Sockets of a node group are no longer displayed in columns on either side, but instead special input/output nodes are used to mirror group sockets inside a node tree. This solves the problem of long node lines in groups and allows more adaptable node layout. Internal sockets can be exposed from a group by either connecting to the extension sockets in input/output nodes (shown as empty circle) or by adding sockets from the node property bar in the "Interface" panel. Further details such as the socket name can also be changed there. [1] http://wiki.blender.org/index.php/User:Phonybone/Python_Nodes [2] http://projects.blender.org/scm/viewvc.php/trunk/blender/release/scripts/templates_py/custom_nodes.py?view=markup&root=bf-blender [3] http://code.blender.org/index.php/2012/01/improving-node-group-interface-editing/
2013-03-18 16:34:57 +00:00
if (do_id_user) {
/* Free callback for NodeCustomGroup. */
if (node.typeinfo->freefunc_api) {
PointerRNA ptr = RNA_pointer_create_discrete(&ntree.id, &RNA_Node, &node);
Merge of the PyNodes branch (aka "custom nodes") into trunk. PyNodes opens up the node system in Blender to scripters and adds a number of UI-level improvements. === Dynamic node type registration === Node types can now be added at runtime, using the RNA registration mechanism from python. This enables addons such as render engines to create a complete user interface with nodes. Examples of how such nodes can be defined can be found in my personal wiki docs atm [1] and as a script template in release/scripts/templates_py/custom_nodes.py [2]. === Node group improvements === Each node editor now has a tree history of edited node groups, which allows opening and editing nested node groups. The node editor also supports pinning now, so that different spaces can be used to edit different node groups simultaneously. For more ramblings and rationale see (really old) blog post on code.blender.org [3]. The interface of node groups has been overhauled. Sockets of a node group are no longer displayed in columns on either side, but instead special input/output nodes are used to mirror group sockets inside a node tree. This solves the problem of long node lines in groups and allows more adaptable node layout. Internal sockets can be exposed from a group by either connecting to the extension sockets in input/output nodes (shown as empty circle) or by adding sockets from the node property bar in the "Interface" panel. Further details such as the socket name can also be changed there. [1] http://wiki.blender.org/index.php/User:Phonybone/Python_Nodes [2] http://projects.blender.org/scm/viewvc.php/trunk/blender/release/scripts/templates_py/custom_nodes.py?view=markup&root=bf-blender [3] http://code.blender.org/index.php/2012/01/improving-node-group-interface-editing/
2013-03-18 16:34:57 +00:00
node.typeinfo->freefunc_api(&ptr);
}
Merge of the PyNodes branch (aka "custom nodes") into trunk. PyNodes opens up the node system in Blender to scripters and adds a number of UI-level improvements. === Dynamic node type registration === Node types can now be added at runtime, using the RNA registration mechanism from python. This enables addons such as render engines to create a complete user interface with nodes. Examples of how such nodes can be defined can be found in my personal wiki docs atm [1] and as a script template in release/scripts/templates_py/custom_nodes.py [2]. === Node group improvements === Each node editor now has a tree history of edited node groups, which allows opening and editing nested node groups. The node editor also supports pinning now, so that different spaces can be used to edit different node groups simultaneously. For more ramblings and rationale see (really old) blog post on code.blender.org [3]. The interface of node groups has been overhauled. Sockets of a node group are no longer displayed in columns on either side, but instead special input/output nodes are used to mirror group sockets inside a node tree. This solves the problem of long node lines in groups and allows more adaptable node layout. Internal sockets can be exposed from a group by either connecting to the extension sockets in input/output nodes (shown as empty circle) or by adding sockets from the node property bar in the "Interface" panel. Further details such as the socket name can also be changed there. [1] http://wiki.blender.org/index.php/User:Phonybone/Python_Nodes [2] http://projects.blender.org/scm/viewvc.php/trunk/blender/release/scripts/templates_py/custom_nodes.py?view=markup&root=bf-blender [3] http://code.blender.org/index.php/2012/01/improving-node-group-interface-editing/
2013-03-18 16:34:57 +00:00
/* Do user counting. */
if (node.id) {
id_us_min(node.id);
}
LISTBASE_FOREACH (bNodeSocket *, sock, &node.inputs) {
Geometry Nodes: improve detecting data-block dependencies Previously, the data-block dependencies were always detected in `update_depsgraph` in `MOD_nodes.cc`. This would only be called when something called `DEG_relations_tag_update` before. We don't want to trigger a depsgraph rebuild after each operation in the node editor, as that would be expensive. However, that also meant that we often had to add data-block dependencies that are not actually used, but might be used if the user changed e.g. a link. A typical example for that is a object socket that has a default value, but the socket is also linked. Now, the dependencies referenced by the node tree are collected by the node tree update code which runs after all changes. This way we can detect whether the dependencies have changed. Only if they have changed, a depsgraph rebuild is triggered. This now allows also taking into account the mute status of nodes and whether an input is linked. There are still more things that could be taken into account. Most obviously whether a node is connected to an output. This can be done later. The most tricky aspect here is probably that we also have to consider all viewer nodes as output, because at the time the node runs, it's not known which viewer will actually be used (which depends on other editors). This also cleans up some special cases we had for e.g. the scene time node where we always had to trigger a depsgraph rebuild when it was added/removed because of its time dependence. This is now part of a more general system. This fixes #109219. Pull Request: https://projects.blender.org/blender/blender/pulls/131446
2024-12-05 18:02:14 +01:00
socket_id_user_decrement(sock);
}
LISTBASE_FOREACH (bNodeSocket *, sock, &node.outputs) {
Geometry Nodes: improve detecting data-block dependencies Previously, the data-block dependencies were always detected in `update_depsgraph` in `MOD_nodes.cc`. This would only be called when something called `DEG_relations_tag_update` before. We don't want to trigger a depsgraph rebuild after each operation in the node editor, as that would be expensive. However, that also meant that we often had to add data-block dependencies that are not actually used, but might be used if the user changed e.g. a link. A typical example for that is a object socket that has a default value, but the socket is also linked. Now, the dependencies referenced by the node tree are collected by the node tree update code which runs after all changes. This way we can detect whether the dependencies have changed. Only if they have changed, a depsgraph rebuild is triggered. This now allows also taking into account the mute status of nodes and whether an input is linked. There are still more things that could be taken into account. Most obviously whether a node is connected to an output. This can be done later. The most tricky aspect here is probably that we also have to consider all viewer nodes as output, because at the time the node runs, it's not known which viewer will actually be used (which depends on other editors). This also cleans up some special cases we had for e.g. the scene time node where we always had to trigger a depsgraph rebuild when it was added/removed because of its time dependence. This is now part of a more general system. This fixes #109219. Pull Request: https://projects.blender.org/blender/blender/pulls/131446
2024-12-05 18:02:14 +01:00
socket_id_user_decrement(sock);
}
}
2018-06-17 17:05:51 +02:00
/* Remove animation data. */
char propname_esc[MAX_IDPROP_NAME * 2];
char prefix[MAX_IDPROP_NAME * 2];
2018-06-17 17:05:51 +02:00
BLI_str_escape(propname_esc, node.name, sizeof(propname_esc));
SNPRINTF(prefix, "nodes[\"%s\"]", propname_esc);
if (BKE_animdata_fix_paths_remove(&ntree.id, prefix)) {
if (bmain != nullptr) {
DEG_relations_tag_update(bmain);
}
}
node_unlink_node(ntree, node);
node_unlink_attached(&ntree, &node);
/* Free node itself. */
node_free_node(&ntree, node);
node_rebuild_id_vector(ntree);
}
static void free_localized_node_groups(bNodeTree *ntree)
{
/* Only localized node trees store a copy for each node group tree.
* Each node group tree in a localized node tree can be freed,
2023-12-07 12:15:45 +11:00
* since it is a localized copy itself (no risk of accessing freed
* data in main, see #37939). */
if (!(ntree->id.tag & ID_TAG_LOCALIZED)) {
return;
}
LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
bNodeTree *ngroup = reinterpret_cast<bNodeTree *>(node->id);
if (node->is_group() && ngroup != nullptr) {
node_tree_free_tree(*ngroup);
MEM_freeN(ngroup);
}
}
}
void node_tree_free_tree(bNodeTree &ntree)
{
ntree_free_data(&ntree.id);
BKE_animdata_free(&ntree.id, false);
}
void node_tree_free_embedded_tree(bNodeTree *ntree)
{
node_tree_free_tree(*ntree);
BKE_libblock_free_data(&ntree->id, true);
BKE_libblock_free_data_py(&ntree->id);
}
void node_tree_free_local_tree(bNodeTree *ntree)
{
if (ntree->id.tag & ID_TAG_LOCALIZED) {
node_tree_free_tree(*ntree);
}
else {
node_tree_free_tree(*ntree);
BKE_libblock_free_data(&ntree->id, true);
}
}
void node_tree_set_output(bNodeTree &ntree)
{
const bool is_compositor = ntree.type == NTREE_COMPOSIT;
const bool is_geometry = ntree.type == NTREE_GEOMETRY;
/* find the active outputs, might become tree type dependent handler */
LISTBASE_FOREACH (bNode *, node, &ntree.nodes) {
if (node->typeinfo->nclass == NODE_CLASS_OUTPUT) {
/* we need a check for which output node should be tagged like this, below an exception */
if (node->is_type("CompositorNodeOutputFile")) {
continue;
}
const bool node_is_output = node->is_type("CompositorNodeViewer") ||
node->is_type("GeometryNodeViewer");
int output = 0;
/* there is more types having output class, each one is checked */
LISTBASE_FOREACH (bNode *, tnode, &ntree.nodes) {
if (tnode->typeinfo->nclass != NODE_CLASS_OUTPUT) {
continue;
}
/* same type, exception for viewer */
const bool tnode_is_output = tnode->is_type("CompositorNodeViewer") ||
tnode->is_type("GeometryNodeViewer");
const bool viewer_case = (is_compositor || is_geometry) && tnode_is_output &&
node_is_output;
const bool has_same_shortcut = viewer_case && node != tnode &&
tnode->custom1 == node->custom1 &&
tnode->custom1 != NODE_VIEWER_SHORTCUT_NONE;
if (tnode->type_legacy == node->type_legacy || viewer_case) {
if (tnode->flag & NODE_DO_OUTPUT) {
output++;
if (output > 1) {
tnode->flag &= ~NODE_DO_OUTPUT;
}
}
}
if (has_same_shortcut) {
tnode->custom1 = NODE_VIEWER_SHORTCUT_NONE;
}
}
/* Only geometry nodes is allowed to have no active output in the node tree. */
if (output == 0 && !is_geometry) {
node->flag |= NODE_DO_OUTPUT;
}
}
/* group node outputs use this flag too */
if (node->is_group_output()) {
int output = 0;
LISTBASE_FOREACH (bNode *, tnode, &ntree.nodes) {
if (!tnode->is_group_output()) {
continue;
}
if (tnode->flag & NODE_DO_OUTPUT) {
output++;
if (output > 1) {
tnode->flag &= ~NODE_DO_OUTPUT;
}
}
}
if (output == 0) {
node->flag |= NODE_DO_OUTPUT;
}
}
}
/* here we could recursively set which nodes have to be done,
* might be different for editor or for "real" use... */
}
bNodeTree **node_tree_ptr_from_id(ID *id)
{
/* If this is ever extended such that a non-animatable ID type can embed a node
* tree, update blender::animrig::internal::rebuild_slot_user_cache(). That
* function assumes that node trees can only be embedded by animatable IDs. */
switch (GS(id->name)) {
case ID_MA:
return &reinterpret_cast<Material *>(id)->nodetree;
case ID_LA:
return &reinterpret_cast<Light *>(id)->nodetree;
case ID_WO:
return &reinterpret_cast<World *>(id)->nodetree;
case ID_TE:
return &reinterpret_cast<Tex *>(id)->nodetree;
case ID_SCE:
return &reinterpret_cast<Scene *>(id)->nodetree;
case ID_LS:
return &reinterpret_cast<FreestyleLineStyle *>(id)->nodetree;
default:
return nullptr;
}
}
bNodeTree *node_tree_from_id(ID *id)
Merge of the PyNodes branch (aka "custom nodes") into trunk. PyNodes opens up the node system in Blender to scripters and adds a number of UI-level improvements. === Dynamic node type registration === Node types can now be added at runtime, using the RNA registration mechanism from python. This enables addons such as render engines to create a complete user interface with nodes. Examples of how such nodes can be defined can be found in my personal wiki docs atm [1] and as a script template in release/scripts/templates_py/custom_nodes.py [2]. === Node group improvements === Each node editor now has a tree history of edited node groups, which allows opening and editing nested node groups. The node editor also supports pinning now, so that different spaces can be used to edit different node groups simultaneously. For more ramblings and rationale see (really old) blog post on code.blender.org [3]. The interface of node groups has been overhauled. Sockets of a node group are no longer displayed in columns on either side, but instead special input/output nodes are used to mirror group sockets inside a node tree. This solves the problem of long node lines in groups and allows more adaptable node layout. Internal sockets can be exposed from a group by either connecting to the extension sockets in input/output nodes (shown as empty circle) or by adding sockets from the node property bar in the "Interface" panel. Further details such as the socket name can also be changed there. [1] http://wiki.blender.org/index.php/User:Phonybone/Python_Nodes [2] http://projects.blender.org/scm/viewvc.php/trunk/blender/release/scripts/templates_py/custom_nodes.py?view=markup&root=bf-blender [3] http://code.blender.org/index.php/2012/01/improving-node-group-interface-editing/
2013-03-18 16:34:57 +00:00
{
bNodeTree **nodetree = node_tree_ptr_from_id(id);
return (nodetree != nullptr) ? *nodetree : nullptr;
Merge of the PyNodes branch (aka "custom nodes") into trunk. PyNodes opens up the node system in Blender to scripters and adds a number of UI-level improvements. === Dynamic node type registration === Node types can now be added at runtime, using the RNA registration mechanism from python. This enables addons such as render engines to create a complete user interface with nodes. Examples of how such nodes can be defined can be found in my personal wiki docs atm [1] and as a script template in release/scripts/templates_py/custom_nodes.py [2]. === Node group improvements === Each node editor now has a tree history of edited node groups, which allows opening and editing nested node groups. The node editor also supports pinning now, so that different spaces can be used to edit different node groups simultaneously. For more ramblings and rationale see (really old) blog post on code.blender.org [3]. The interface of node groups has been overhauled. Sockets of a node group are no longer displayed in columns on either side, but instead special input/output nodes are used to mirror group sockets inside a node tree. This solves the problem of long node lines in groups and allows more adaptable node layout. Internal sockets can be exposed from a group by either connecting to the extension sockets in input/output nodes (shown as empty circle) or by adding sockets from the node property bar in the "Interface" panel. Further details such as the socket name can also be changed there. [1] http://wiki.blender.org/index.php/User:Phonybone/Python_Nodes [2] http://projects.blender.org/scm/viewvc.php/trunk/blender/release/scripts/templates_py/custom_nodes.py?view=markup&root=bf-blender [3] http://code.blender.org/index.php/2012/01/improving-node-group-interface-editing/
2013-03-18 16:34:57 +00:00
}
void node_tree_node_flag_set(bNodeTree &ntree, const int flag, const bool enable)
{
for (bNode *node : ntree.all_nodes()) {
if (enable) {
node->flag |= flag;
}
else {
node->flag &= ~flag;
}
}
}
bNodeTree *node_tree_localize(bNodeTree *ntree, std::optional<ID *> new_owner_id)
{
if (ntree == nullptr) {
return nullptr;
}
/* Make full copy outside of Main database.
* NOTE: previews are not copied here. */
bNodeTree *ltree = reinterpret_cast<bNodeTree *>(
BKE_id_copy_in_lib(nullptr,
std::nullopt,
&ntree->id,
new_owner_id,
nullptr,
(LIB_ID_COPY_LOCALIZE | LIB_ID_COPY_NO_ANIMDATA)));
ltree->id.tag |= ID_TAG_LOCALIZED;
LISTBASE_FOREACH (bNode *, node, &ltree->nodes) {
bNodeTree *group = reinterpret_cast<bNodeTree *>(node->id);
if (node->is_group() && group != nullptr) {
node->id = reinterpret_cast<ID *>(node_tree_localize(group, nullptr));
Merge of the PyNodes branch (aka "custom nodes") into trunk. PyNodes opens up the node system in Blender to scripters and adds a number of UI-level improvements. === Dynamic node type registration === Node types can now be added at runtime, using the RNA registration mechanism from python. This enables addons such as render engines to create a complete user interface with nodes. Examples of how such nodes can be defined can be found in my personal wiki docs atm [1] and as a script template in release/scripts/templates_py/custom_nodes.py [2]. === Node group improvements === Each node editor now has a tree history of edited node groups, which allows opening and editing nested node groups. The node editor also supports pinning now, so that different spaces can be used to edit different node groups simultaneously. For more ramblings and rationale see (really old) blog post on code.blender.org [3]. The interface of node groups has been overhauled. Sockets of a node group are no longer displayed in columns on either side, but instead special input/output nodes are used to mirror group sockets inside a node tree. This solves the problem of long node lines in groups and allows more adaptable node layout. Internal sockets can be exposed from a group by either connecting to the extension sockets in input/output nodes (shown as empty circle) or by adding sockets from the node property bar in the "Interface" panel. Further details such as the socket name can also be changed there. [1] http://wiki.blender.org/index.php/User:Phonybone/Python_Nodes [2] http://projects.blender.org/scm/viewvc.php/trunk/blender/release/scripts/templates_py/custom_nodes.py?view=markup&root=bf-blender [3] http://code.blender.org/index.php/2012/01/improving-node-group-interface-editing/
2013-03-18 16:34:57 +00:00
}
}
/* Ensures only a single output node is enabled. */
node_tree_set_output(*ntree);
bNode *node_src = reinterpret_cast<bNode *>(ntree->nodes.first);
bNode *node_local = reinterpret_cast<bNode *>(ltree->nodes.first);
while (node_src != nullptr) {
node_local->runtime->original = node_src;
node_src = node_src->next;
node_local = node_local->next;
}
if (ntree->typeinfo->localize) {
ntree->typeinfo->localize(ltree, ntree);
}
return ltree;
}
void node_tree_local_merge(Main *bmain, bNodeTree *localtree, bNodeTree *ntree)
{
if (ntree && localtree) {
if (ntree->typeinfo->local_merge) {
ntree->typeinfo->local_merge(bmain, localtree, ntree);
}
}
}
static bool ntree_contains_tree_exec(const bNodeTree &tree_to_search_in,
const bNodeTree &tree_to_search_for,
Set<const bNodeTree *> &already_passed)
{
if (&tree_to_search_in == &tree_to_search_for) {
return true;
}
tree_to_search_in.ensure_topology_cache();
for (const bNode *node_group : tree_to_search_in.group_nodes()) {
const bNodeTree *sub_tree_search_in = reinterpret_cast<const bNodeTree *>(node_group->id);
if (!sub_tree_search_in) {
continue;
}
if (!already_passed.add(sub_tree_search_in)) {
continue;
}
if (ntree_contains_tree_exec(*sub_tree_search_in, tree_to_search_for, already_passed)) {
return true;
}
}
return false;
Merge of the PyNodes branch (aka "custom nodes") into trunk. PyNodes opens up the node system in Blender to scripters and adds a number of UI-level improvements. === Dynamic node type registration === Node types can now be added at runtime, using the RNA registration mechanism from python. This enables addons such as render engines to create a complete user interface with nodes. Examples of how such nodes can be defined can be found in my personal wiki docs atm [1] and as a script template in release/scripts/templates_py/custom_nodes.py [2]. === Node group improvements === Each node editor now has a tree history of edited node groups, which allows opening and editing nested node groups. The node editor also supports pinning now, so that different spaces can be used to edit different node groups simultaneously. For more ramblings and rationale see (really old) blog post on code.blender.org [3]. The interface of node groups has been overhauled. Sockets of a node group are no longer displayed in columns on either side, but instead special input/output nodes are used to mirror group sockets inside a node tree. This solves the problem of long node lines in groups and allows more adaptable node layout. Internal sockets can be exposed from a group by either connecting to the extension sockets in input/output nodes (shown as empty circle) or by adding sockets from the node property bar in the "Interface" panel. Further details such as the socket name can also be changed there. [1] http://wiki.blender.org/index.php/User:Phonybone/Python_Nodes [2] http://projects.blender.org/scm/viewvc.php/trunk/blender/release/scripts/templates_py/custom_nodes.py?view=markup&root=bf-blender [3] http://code.blender.org/index.php/2012/01/improving-node-group-interface-editing/
2013-03-18 16:34:57 +00:00
}
bool node_tree_contains_tree(const bNodeTree &tree_to_search_in,
const bNodeTree &tree_to_search_for)
Merge of the PyNodes branch (aka "custom nodes") into trunk. PyNodes opens up the node system in Blender to scripters and adds a number of UI-level improvements. === Dynamic node type registration === Node types can now be added at runtime, using the RNA registration mechanism from python. This enables addons such as render engines to create a complete user interface with nodes. Examples of how such nodes can be defined can be found in my personal wiki docs atm [1] and as a script template in release/scripts/templates_py/custom_nodes.py [2]. === Node group improvements === Each node editor now has a tree history of edited node groups, which allows opening and editing nested node groups. The node editor also supports pinning now, so that different spaces can be used to edit different node groups simultaneously. For more ramblings and rationale see (really old) blog post on code.blender.org [3]. The interface of node groups has been overhauled. Sockets of a node group are no longer displayed in columns on either side, but instead special input/output nodes are used to mirror group sockets inside a node tree. This solves the problem of long node lines in groups and allows more adaptable node layout. Internal sockets can be exposed from a group by either connecting to the extension sockets in input/output nodes (shown as empty circle) or by adding sockets from the node property bar in the "Interface" panel. Further details such as the socket name can also be changed there. [1] http://wiki.blender.org/index.php/User:Phonybone/Python_Nodes [2] http://projects.blender.org/scm/viewvc.php/trunk/blender/release/scripts/templates_py/custom_nodes.py?view=markup&root=bf-blender [3] http://code.blender.org/index.php/2012/01/improving-node-group-interface-editing/
2013-03-18 16:34:57 +00:00
{
if (&tree_to_search_in == &tree_to_search_for) {
return true;
}
Set<const bNodeTree *> already_passed;
return ntree_contains_tree_exec(tree_to_search_in, tree_to_search_for, already_passed);
}
int node_count_socket_links(const bNodeTree &ntree, const bNodeSocket &sock)
Merge of the PyNodes branch (aka "custom nodes") into trunk. PyNodes opens up the node system in Blender to scripters and adds a number of UI-level improvements. === Dynamic node type registration === Node types can now be added at runtime, using the RNA registration mechanism from python. This enables addons such as render engines to create a complete user interface with nodes. Examples of how such nodes can be defined can be found in my personal wiki docs atm [1] and as a script template in release/scripts/templates_py/custom_nodes.py [2]. === Node group improvements === Each node editor now has a tree history of edited node groups, which allows opening and editing nested node groups. The node editor also supports pinning now, so that different spaces can be used to edit different node groups simultaneously. For more ramblings and rationale see (really old) blog post on code.blender.org [3]. The interface of node groups has been overhauled. Sockets of a node group are no longer displayed in columns on either side, but instead special input/output nodes are used to mirror group sockets inside a node tree. This solves the problem of long node lines in groups and allows more adaptable node layout. Internal sockets can be exposed from a group by either connecting to the extension sockets in input/output nodes (shown as empty circle) or by adding sockets from the node property bar in the "Interface" panel. Further details such as the socket name can also be changed there. [1] http://wiki.blender.org/index.php/User:Phonybone/Python_Nodes [2] http://projects.blender.org/scm/viewvc.php/trunk/blender/release/scripts/templates_py/custom_nodes.py?view=markup&root=bf-blender [3] http://code.blender.org/index.php/2012/01/improving-node-group-interface-editing/
2013-03-18 16:34:57 +00:00
{
int tot = 0;
LISTBASE_FOREACH (const bNodeLink *, link, &ntree.links) {
if (link->fromsock == &sock || link->tosock == &sock) {
tot++;
}
}
return tot;
}
bNode *node_get_active(bNodeTree &ntree)
{
for (bNode *node : ntree.all_nodes()) {
if (node->flag & NODE_ACTIVE) {
return node;
}
}
return nullptr;
}
bool node_set_selected(bNode &node, const bool select)
{
bool changed = false;
if (select != ((node.flag & NODE_SELECT) != 0)) {
changed = true;
SET_FLAG_FROM_TEST(node.flag, select, NODE_SELECT);
}
if (select) {
return changed;
}
/* Deselect sockets too. */
LISTBASE_FOREACH (bNodeSocket *, sock, &node.inputs) {
changed |= (sock->flag & NODE_SELECT) != 0;
sock->flag &= ~NODE_SELECT;
}
LISTBASE_FOREACH (bNodeSocket *, sock, &node.outputs) {
changed |= (sock->flag & NODE_SELECT) != 0;
sock->flag &= ~NODE_SELECT;
}
return changed;
}
void node_clear_active(bNodeTree &ntree)
{
for (bNode *node : ntree.all_nodes()) {
node->flag &= ~NODE_ACTIVE;
}
}
void node_set_active(bNodeTree &ntree, bNode &node)
{
const bool is_paint_canvas = node_supports_active_flag(node, NODE_ACTIVE_PAINT_CANVAS);
const bool is_texture_class = node_supports_active_flag(node, NODE_ACTIVE_TEXTURE);
int flags_to_set = NODE_ACTIVE;
SET_FLAG_FROM_TEST(flags_to_set, is_paint_canvas, NODE_ACTIVE_PAINT_CANVAS);
SET_FLAG_FROM_TEST(flags_to_set, is_texture_class, NODE_ACTIVE_TEXTURE);
/* Make sure only one node is active per node tree. */
for (bNode *tnode : ntree.all_nodes()) {
tnode->flag &= ~flags_to_set;
}
node.flag |= flags_to_set;
}
void node_set_socket_availability(bNodeTree &ntree, bNodeSocket &sock, const bool is_available)
{
if (is_available == sock.is_available()) {
return;
}
if (is_available) {
sock.flag &= ~SOCK_UNAVAIL;
}
else {
sock.flag |= SOCK_UNAVAIL;
}
BKE_ntree_update_tag_socket_availability(&ntree, &sock);
}
int node_socket_link_limit(const bNodeSocket &sock)
{
if (sock.is_multi_input()) {
return 4095;
}
if (sock.typeinfo == nullptr) {
return sock.limit;
}
const bNodeSocketType &stype = *sock.typeinfo;
if (!stype.use_link_limits_of_type) {
return sock.limit;
Merge of the PyNodes branch (aka "custom nodes") into trunk. PyNodes opens up the node system in Blender to scripters and adds a number of UI-level improvements. === Dynamic node type registration === Node types can now be added at runtime, using the RNA registration mechanism from python. This enables addons such as render engines to create a complete user interface with nodes. Examples of how such nodes can be defined can be found in my personal wiki docs atm [1] and as a script template in release/scripts/templates_py/custom_nodes.py [2]. === Node group improvements === Each node editor now has a tree history of edited node groups, which allows opening and editing nested node groups. The node editor also supports pinning now, so that different spaces can be used to edit different node groups simultaneously. For more ramblings and rationale see (really old) blog post on code.blender.org [3]. The interface of node groups has been overhauled. Sockets of a node group are no longer displayed in columns on either side, but instead special input/output nodes are used to mirror group sockets inside a node tree. This solves the problem of long node lines in groups and allows more adaptable node layout. Internal sockets can be exposed from a group by either connecting to the extension sockets in input/output nodes (shown as empty circle) or by adding sockets from the node property bar in the "Interface" panel. Further details such as the socket name can also be changed there. [1] http://wiki.blender.org/index.php/User:Phonybone/Python_Nodes [2] http://projects.blender.org/scm/viewvc.php/trunk/blender/release/scripts/templates_py/custom_nodes.py?view=markup&root=bf-blender [3] http://code.blender.org/index.php/2012/01/improving-node-group-interface-editing/
2013-03-18 16:34:57 +00:00
}
return eNodeSocketInOut(sock.in_out) == SOCK_IN ? stype.input_link_limit :
stype.output_link_limit;
Merge of the PyNodes branch (aka "custom nodes") into trunk. PyNodes opens up the node system in Blender to scripters and adds a number of UI-level improvements. === Dynamic node type registration === Node types can now be added at runtime, using the RNA registration mechanism from python. This enables addons such as render engines to create a complete user interface with nodes. Examples of how such nodes can be defined can be found in my personal wiki docs atm [1] and as a script template in release/scripts/templates_py/custom_nodes.py [2]. === Node group improvements === Each node editor now has a tree history of edited node groups, which allows opening and editing nested node groups. The node editor also supports pinning now, so that different spaces can be used to edit different node groups simultaneously. For more ramblings and rationale see (really old) blog post on code.blender.org [3]. The interface of node groups has been overhauled. Sockets of a node group are no longer displayed in columns on either side, but instead special input/output nodes are used to mirror group sockets inside a node tree. This solves the problem of long node lines in groups and allows more adaptable node layout. Internal sockets can be exposed from a group by either connecting to the extension sockets in input/output nodes (shown as empty circle) or by adding sockets from the node property bar in the "Interface" panel. Further details such as the socket name can also be changed there. [1] http://wiki.blender.org/index.php/User:Phonybone/Python_Nodes [2] http://projects.blender.org/scm/viewvc.php/trunk/blender/release/scripts/templates_py/custom_nodes.py?view=markup&root=bf-blender [3] http://code.blender.org/index.php/2012/01/improving-node-group-interface-editing/
2013-03-18 16:34:57 +00:00
}
static void update_socket_declarations(ListBase *sockets,
Span<nodes::SocketDeclaration *> declarations)
Merge of the PyNodes branch (aka "custom nodes") into trunk. PyNodes opens up the node system in Blender to scripters and adds a number of UI-level improvements. === Dynamic node type registration === Node types can now be added at runtime, using the RNA registration mechanism from python. This enables addons such as render engines to create a complete user interface with nodes. Examples of how such nodes can be defined can be found in my personal wiki docs atm [1] and as a script template in release/scripts/templates_py/custom_nodes.py [2]. === Node group improvements === Each node editor now has a tree history of edited node groups, which allows opening and editing nested node groups. The node editor also supports pinning now, so that different spaces can be used to edit different node groups simultaneously. For more ramblings and rationale see (really old) blog post on code.blender.org [3]. The interface of node groups has been overhauled. Sockets of a node group are no longer displayed in columns on either side, but instead special input/output nodes are used to mirror group sockets inside a node tree. This solves the problem of long node lines in groups and allows more adaptable node layout. Internal sockets can be exposed from a group by either connecting to the extension sockets in input/output nodes (shown as empty circle) or by adding sockets from the node property bar in the "Interface" panel. Further details such as the socket name can also be changed there. [1] http://wiki.blender.org/index.php/User:Phonybone/Python_Nodes [2] http://projects.blender.org/scm/viewvc.php/trunk/blender/release/scripts/templates_py/custom_nodes.py?view=markup&root=bf-blender [3] http://code.blender.org/index.php/2012/01/improving-node-group-interface-editing/
2013-03-18 16:34:57 +00:00
{
int index;
LISTBASE_FOREACH_INDEX (bNodeSocket *, socket, sockets, index) {
const SocketDeclaration &socket_decl = *declarations[index];
socket->runtime->declaration = &socket_decl;
Merge of the PyNodes branch (aka "custom nodes") into trunk. PyNodes opens up the node system in Blender to scripters and adds a number of UI-level improvements. === Dynamic node type registration === Node types can now be added at runtime, using the RNA registration mechanism from python. This enables addons such as render engines to create a complete user interface with nodes. Examples of how such nodes can be defined can be found in my personal wiki docs atm [1] and as a script template in release/scripts/templates_py/custom_nodes.py [2]. === Node group improvements === Each node editor now has a tree history of edited node groups, which allows opening and editing nested node groups. The node editor also supports pinning now, so that different spaces can be used to edit different node groups simultaneously. For more ramblings and rationale see (really old) blog post on code.blender.org [3]. The interface of node groups has been overhauled. Sockets of a node group are no longer displayed in columns on either side, but instead special input/output nodes are used to mirror group sockets inside a node tree. This solves the problem of long node lines in groups and allows more adaptable node layout. Internal sockets can be exposed from a group by either connecting to the extension sockets in input/output nodes (shown as empty circle) or by adding sockets from the node property bar in the "Interface" panel. Further details such as the socket name can also be changed there. [1] http://wiki.blender.org/index.php/User:Phonybone/Python_Nodes [2] http://projects.blender.org/scm/viewvc.php/trunk/blender/release/scripts/templates_py/custom_nodes.py?view=markup&root=bf-blender [3] http://code.blender.org/index.php/2012/01/improving-node-group-interface-editing/
2013-03-18 16:34:57 +00:00
}
}
static void reset_socket_declarations(ListBase *sockets)
{
LISTBASE_FOREACH (bNodeSocket *, socket, sockets) {
socket->runtime->declaration = nullptr;
Merge of the PyNodes branch (aka "custom nodes") into trunk. PyNodes opens up the node system in Blender to scripters and adds a number of UI-level improvements. === Dynamic node type registration === Node types can now be added at runtime, using the RNA registration mechanism from python. This enables addons such as render engines to create a complete user interface with nodes. Examples of how such nodes can be defined can be found in my personal wiki docs atm [1] and as a script template in release/scripts/templates_py/custom_nodes.py [2]. === Node group improvements === Each node editor now has a tree history of edited node groups, which allows opening and editing nested node groups. The node editor also supports pinning now, so that different spaces can be used to edit different node groups simultaneously. For more ramblings and rationale see (really old) blog post on code.blender.org [3]. The interface of node groups has been overhauled. Sockets of a node group are no longer displayed in columns on either side, but instead special input/output nodes are used to mirror group sockets inside a node tree. This solves the problem of long node lines in groups and allows more adaptable node layout. Internal sockets can be exposed from a group by either connecting to the extension sockets in input/output nodes (shown as empty circle) or by adding sockets from the node property bar in the "Interface" panel. Further details such as the socket name can also be changed there. [1] http://wiki.blender.org/index.php/User:Phonybone/Python_Nodes [2] http://projects.blender.org/scm/viewvc.php/trunk/blender/release/scripts/templates_py/custom_nodes.py?view=markup&root=bf-blender [3] http://code.blender.org/index.php/2012/01/improving-node-group-interface-editing/
2013-03-18 16:34:57 +00:00
}
}
void node_socket_declarations_update(bNode *node)
Merge of the PyNodes branch (aka "custom nodes") into trunk. PyNodes opens up the node system in Blender to scripters and adds a number of UI-level improvements. === Dynamic node type registration === Node types can now be added at runtime, using the RNA registration mechanism from python. This enables addons such as render engines to create a complete user interface with nodes. Examples of how such nodes can be defined can be found in my personal wiki docs atm [1] and as a script template in release/scripts/templates_py/custom_nodes.py [2]. === Node group improvements === Each node editor now has a tree history of edited node groups, which allows opening and editing nested node groups. The node editor also supports pinning now, so that different spaces can be used to edit different node groups simultaneously. For more ramblings and rationale see (really old) blog post on code.blender.org [3]. The interface of node groups has been overhauled. Sockets of a node group are no longer displayed in columns on either side, but instead special input/output nodes are used to mirror group sockets inside a node tree. This solves the problem of long node lines in groups and allows more adaptable node layout. Internal sockets can be exposed from a group by either connecting to the extension sockets in input/output nodes (shown as empty circle) or by adding sockets from the node property bar in the "Interface" panel. Further details such as the socket name can also be changed there. [1] http://wiki.blender.org/index.php/User:Phonybone/Python_Nodes [2] http://projects.blender.org/scm/viewvc.php/trunk/blender/release/scripts/templates_py/custom_nodes.py?view=markup&root=bf-blender [3] http://code.blender.org/index.php/2012/01/improving-node-group-interface-editing/
2013-03-18 16:34:57 +00:00
{
BLI_assert(node->runtime->declaration != nullptr);
if (node->runtime->declaration->skip_updating_sockets) {
reset_socket_declarations(&node->inputs);
reset_socket_declarations(&node->outputs);
return;
}
update_socket_declarations(&node->inputs, node->runtime->declaration->inputs);
update_socket_declarations(&node->outputs, node->runtime->declaration->outputs);
}
bool node_declaration_ensure_on_outdated_node(bNodeTree &ntree, bNode &node)
{
if (node.runtime->declaration != nullptr) {
return false;
}
if (node.typeinfo->declare) {
if (node.typeinfo->static_declaration) {
if (!node.typeinfo->static_declaration->is_context_dependent) {
node.runtime->declaration = node.typeinfo->static_declaration;
Nodes: unify static and dynamic declarations This helps solving the problem encountered in #113553. The problem is that we currently can't support link-drag-search for nodes which have a dynamic declaration. With this patch, there is only a single `declare` function per node type, instead of the separate `declare` and `declare_dynamic` functions. The new `declare` function has access to the node and tree. However, both are allowed to be null. The final node declaration has a flag for whether it depends on the node context or not. Nodes that previously had a dynamic declaration should now create as much of the declaration as possible that does not depend on the node. This allows code like for link-drag-search to take those sockets into account even if the other sockets are dynamic. For node declarations that have dynamic types (e.g. Switch node), we can also add extra information to the static node declaration, like the identifier of the socket with the dynamic type. This is not part of this patch though. I can think of two main alternatives to the approach implemented here: * Define two separate functions for dynamic nodes. One that creates the "static declaration" without node context, and on that creates the actual declaration with node context. * Have a single declare function that generates "build instructions" for the actual node declaration. So instead of building the final declaration directly, one can for example add a socket whose type depends on a specific rna path in the node. The actual node declaration is then automatically generated based on the build instructions. This becomes quite a bit more tricky with dynamic amounts of sockets and introduces another indirection between declarations and what sockets the node actually has. I found the approach implemented in this patch to lead to the least amount of boilerplate (doesn't require a seperate "build instructions" data structure) and code duplication (socket properties are still only defined in one place). At the same time, it offers more flexibility to how nodes can be dynamic. Pull Request: https://projects.blender.org/blender/blender/pulls/113742
2023-10-15 20:28:23 +02:00
return true;
}
}
}
if (node.typeinfo->declare) {
nodes::update_node_declaration_and_sockets(ntree, node);
return true;
}
return false;
}
bool node_declaration_ensure(bNodeTree &ntree, bNode &node)
{
if (node_declaration_ensure_on_outdated_node(ntree, node)) {
node_socket_declarations_update(&node);
return true;
}
return false;
}
2018-06-17 17:05:51 +02:00
float2 node_dimensions_get(const bNode &node)
{
return float2(node.runtime->draw_bounds.xmax, node.runtime->draw_bounds.ymax) -
float2(node.runtime->draw_bounds.xmin, node.runtime->draw_bounds.ymin);
}
void node_tag_update_id(bNode &node)
{
node.runtime->update |= NODE_UPDATE_ID;
}
void node_internal_links(bNode &node, bNodeLink **r_links, int *r_len)
{
*r_links = node.runtime->internal_links.data();
*r_len = node.runtime->internal_links.size();
}
/* Node Instance Hash */
const bNodeInstanceKey NODE_INSTANCE_KEY_BASE = {5381};
const bNodeInstanceKey NODE_INSTANCE_KEY_NONE = {0};
/* Generate a hash key from ntree and node names
* Uses the djb2 algorithm with xor by Bernstein:
* http://www.cse.yorku.ca/~oz/hash.html
*/
static bNodeInstanceKey node_hash_int_str(bNodeInstanceKey hash, const char *str)
{
char c;
while ((c = *str++)) {
hash.value = ((hash.value << 5) + hash.value) ^ c; /* (hash * 33) ^ c */
}
/* separator '\0' character, to avoid ambiguity from concatenated strings */
hash.value = (hash.value << 5) + hash.value; /* hash * 33 */
return hash;
}
bNodeInstanceKey node_instance_key(bNodeInstanceKey parent_key,
const bNodeTree *ntree,
const bNode *node)
{
bNodeInstanceKey key = node_hash_int_str(parent_key, ntree->id.name + 2);
if (node) {
key = node_hash_int_str(key, node->name);
}
return key;
Christmas coding work! ********* Node editor work: - To enable Nodes for Materials, you have to set the "Use Nodes" button, in the new Material buttons "Nodes" Panel or in header of the Node editor. Doing this will disable Material-Layers. - Nodes now execute materials ("shaders"), but still only using the previewrender code. - Nodes have (optional) previews for rendered images. - Node headers allow to hide buttons and/or preview image - Nodes can be dragged larger/smaller (right-bottom corner) - Nodes can be hidden (minimized) with hotkey H - CTRL+click on an Input Socket gives a popup with default values. - Changing Material/Texture or Mix node will adjust Node title. - Click-drag outside of a Node changes cursor to "Knife' and allows to draw a rect where to cut Links. - Added new node types RGBtoBW, Texture, In/Output, ColorRamp - Material Nodes have options to ouput diffuse or specular, or to use a negative normal. The input socket 'Normal' will force the material to use that normal, otherwise it uses the normal from the Material that has the node tree. - When drawing a link between two not-matching sockets, Blender inserts a converting node (now only for value/rgb combos) - When drawing a link to an input socket that's already in use, the old link will either disappear or flip to another unused socket. - A click on a Material Node will activate it, and show all its settings in the Material Buttons. Active Material Nodes draw the material icon in red. - A click on any node will show its options in the Node Panel in the Material buttons. - Multiple Output Nodes can be used, to sample contents of a tree, but only one Output is the real one, which is indicated in a different color and red material icon. - Added ThemeColors for node types - ALT+C will convert existing Material-Layers to Node... this currently only adds the material/mix nodes and connects them. Dunno if this is worth a lot of coding work to make perfect? - Press C to call another "Solve order", which will show all possible cyclic conflicts (if there are). - Technical: nodes now use "Type" structs which define the structure of nodes and in/output sockets. The Type structs store all fixed info, callbacks, and allow to reconstruct saved Nodes to match what is required by Blender. - Defining (new) nodes now is as simple as filling in a fixed Type struct, plus code some callbacks. A doc will be made! - Node preview images are by default float ********* Icon drawing: - Cleanup of how old icons were implemented in new system, making them 16x16 too, correctly centered *and* scaled. - Made drawing Icons use float coordinates - Moved BIF_calcpreview_image() into interface_icons.c, renamed it icon_from_image(). Removed a lot of unneeded Imbuf magic here! :) - Skipped scaling and imbuf copying when icons are OK size ********* Preview render: - Huge cleanup of code.... - renaming BIF_xxx calls that only were used internally - BIF_previewrender() now accepts an argument for rendering method, so it supports icons, buttonwindow previewrender and node editor - Only a single BIF_preview_changed() call now exists, supporting all signals as needed for buttos and node editor ********* More stuff: - glutil.c, glaDrawPixelsSafe() and glaDrawPixelsTex() now accept format argument for GL_FLOAT rects - Made the ColorBand become a built-in button for interface.c Was a load of cleanup work in buttons_shading.c... - removed a load of unneeded glBlendFunc() calls - Fixed bug in calculating text length for buttons (ancient!)
2005-12-28 15:42:51 +00:00
}
/* Build a set of built-in node types to check for known types. */
static Set<int> get_known_node_types_set()
{
Set<int> result;
for (const bNodeType *ntype : node_types_get()) {
result.add(ntype->type_legacy);
}
return result;
}
static bool can_read_node_type(const bNode &node)
{
/* Can always read custom node types. */
if (ELEM(node.type_legacy, NODE_CUSTOM, NODE_CUSTOM_GROUP)) {
return true;
}
if (node.type_legacy < NODE_LEGACY_TYPE_GENERATION_START) {
/* Check known built-in types. */
static Set<int> known_types = get_known_node_types_set();
return known_types.contains(node.type_legacy);
}
/* Nodes with larger legacy_type are only identified by their idname. */
return node_type_find(node.idname) != nullptr;
}
static void node_replace_undefined_types(bNode *node)
{
/* If the node type is built-in but unknown, the node cannot be read. */
if (!can_read_node_type(*node)) {
node->type_legacy = NODE_CUSTOM;
/* This type name is arbitrary, it just has to be unique enough to not match a future node
* idname. Includes the old type identifier for debugging purposes. */
const std::string old_idname = node->idname;
SNPRINTF(node->idname, "Undefined[%s]", old_idname.c_str());
node->typeinfo = &NodeTypeUndefined;
}
}
void node_tree_update_all_new(Main &main)
Merge of the PyNodes branch (aka "custom nodes") into trunk. PyNodes opens up the node system in Blender to scripters and adds a number of UI-level improvements. === Dynamic node type registration === Node types can now be added at runtime, using the RNA registration mechanism from python. This enables addons such as render engines to create a complete user interface with nodes. Examples of how such nodes can be defined can be found in my personal wiki docs atm [1] and as a script template in release/scripts/templates_py/custom_nodes.py [2]. === Node group improvements === Each node editor now has a tree history of edited node groups, which allows opening and editing nested node groups. The node editor also supports pinning now, so that different spaces can be used to edit different node groups simultaneously. For more ramblings and rationale see (really old) blog post on code.blender.org [3]. The interface of node groups has been overhauled. Sockets of a node group are no longer displayed in columns on either side, but instead special input/output nodes are used to mirror group sockets inside a node tree. This solves the problem of long node lines in groups and allows more adaptable node layout. Internal sockets can be exposed from a group by either connecting to the extension sockets in input/output nodes (shown as empty circle) or by adding sockets from the node property bar in the "Interface" panel. Further details such as the socket name can also be changed there. [1] http://wiki.blender.org/index.php/User:Phonybone/Python_Nodes [2] http://projects.blender.org/scm/viewvc.php/trunk/blender/release/scripts/templates_py/custom_nodes.py?view=markup&root=bf-blender [3] http://code.blender.org/index.php/2012/01/improving-node-group-interface-editing/
2013-03-18 16:34:57 +00:00
{
/* Replace unknown node types with "Undefined".
* This happens when loading files from newer Blender versions. Such nodes cannot be read
* reliably so replace the idname with an undefined type. This keeps links and socket names but
* discards storage and other type-specific data.
*
* Replacement has to happen after after-liblink-versioning, since some node types still get
* replaced in those late versioning steps. */
FOREACH_NODETREE_BEGIN (&main, ntree, owner_id) {
for (bNode *node : ntree->all_nodes()) {
node_replace_undefined_types(node);
}
}
FOREACH_NODETREE_END;
/* Update all new node trees on file read or append, to add/remove sockets
* in groups nodes if the group changed, and handle any update flags that
* might have been set in file reading or versioning. */
FOREACH_NODETREE_BEGIN (&main, ntree, owner_id) {
if (owner_id->tag & ID_TAG_NEW) {
BKE_ntree_update_tag_all(ntree);
}
Merge of the PyNodes branch (aka "custom nodes") into trunk. PyNodes opens up the node system in Blender to scripters and adds a number of UI-level improvements. === Dynamic node type registration === Node types can now be added at runtime, using the RNA registration mechanism from python. This enables addons such as render engines to create a complete user interface with nodes. Examples of how such nodes can be defined can be found in my personal wiki docs atm [1] and as a script template in release/scripts/templates_py/custom_nodes.py [2]. === Node group improvements === Each node editor now has a tree history of edited node groups, which allows opening and editing nested node groups. The node editor also supports pinning now, so that different spaces can be used to edit different node groups simultaneously. For more ramblings and rationale see (really old) blog post on code.blender.org [3]. The interface of node groups has been overhauled. Sockets of a node group are no longer displayed in columns on either side, but instead special input/output nodes are used to mirror group sockets inside a node tree. This solves the problem of long node lines in groups and allows more adaptable node layout. Internal sockets can be exposed from a group by either connecting to the extension sockets in input/output nodes (shown as empty circle) or by adding sockets from the node property bar in the "Interface" panel. Further details such as the socket name can also be changed there. [1] http://wiki.blender.org/index.php/User:Phonybone/Python_Nodes [2] http://projects.blender.org/scm/viewvc.php/trunk/blender/release/scripts/templates_py/custom_nodes.py?view=markup&root=bf-blender [3] http://code.blender.org/index.php/2012/01/improving-node-group-interface-editing/
2013-03-18 16:34:57 +00:00
}
FOREACH_NODETREE_END;
BKE_ntree_update(main);
}
void node_tree_update_all_users(Main *main, ID *id)
{
if (id == nullptr) {
Geometry Nodes: initial scattering and geometry nodes This is the initial merge from the geometry-nodes branch. Nodes: * Attribute Math * Boolean * Edge Split * Float Compare * Object Info * Point Distribute * Point Instance * Random Attribute * Random Float * Subdivision Surface * Transform * Triangulate It includes the initial evaluation of geometry node groups in the Geometry Nodes modifier. Notes on the Generic attribute access API The API adds an indirection for attribute access. That has the following benefits: * Most code does not have to care about how an attribute is stored internally. This is mainly necessary, because we have to deal with "legacy" attributes such as vertex weights and attributes that are embedded into other structs such as vertex positions. * When reading from an attribute, we generally don't care what domain the attribute is stored on. So we want to abstract away the interpolation that that adapts attributes from one domain to another domain (this is not actually implemented yet). Other possible improvements for later iterations include: * Actually implement interpolation between domains. * Don't use inheritance for the different attribute types. A single class for read access and one for write access might be enough, because we know all the ways in which attributes are stored internally. We don't want more different internal structures in the future. On the contrary, ideally we can consolidate the different storage formats in the future to reduce the need for this indirection. * Remove the need for heap allocations when creating attribute accessors. It includes commits from: * Dalai Felinto * Hans Goudey * Jacques Lucke * Léo Depoix
2020-12-02 13:25:25 +01:00
return;
}
bool need_update = false;
/* Update all users of ngroup, to add/remove sockets as needed. */
FOREACH_NODETREE_BEGIN (main, ntree, owner_id) {
for (bNode *node : ntree->all_nodes()) {
if (node->id == id) {
BKE_ntree_update_tag_node_property(ntree, node);
need_update = true;
}
}
}
FOREACH_NODETREE_END;
if (need_update) {
BKE_ntree_update(*main);
}
}
Merge of the PyNodes branch (aka "custom nodes") into trunk. PyNodes opens up the node system in Blender to scripters and adds a number of UI-level improvements. === Dynamic node type registration === Node types can now be added at runtime, using the RNA registration mechanism from python. This enables addons such as render engines to create a complete user interface with nodes. Examples of how such nodes can be defined can be found in my personal wiki docs atm [1] and as a script template in release/scripts/templates_py/custom_nodes.py [2]. === Node group improvements === Each node editor now has a tree history of edited node groups, which allows opening and editing nested node groups. The node editor also supports pinning now, so that different spaces can be used to edit different node groups simultaneously. For more ramblings and rationale see (really old) blog post on code.blender.org [3]. The interface of node groups has been overhauled. Sockets of a node group are no longer displayed in columns on either side, but instead special input/output nodes are used to mirror group sockets inside a node tree. This solves the problem of long node lines in groups and allows more adaptable node layout. Internal sockets can be exposed from a group by either connecting to the extension sockets in input/output nodes (shown as empty circle) or by adding sockets from the node property bar in the "Interface" panel. Further details such as the socket name can also be changed there. [1] http://wiki.blender.org/index.php/User:Phonybone/Python_Nodes [2] http://projects.blender.org/scm/viewvc.php/trunk/blender/release/scripts/templates_py/custom_nodes.py?view=markup&root=bf-blender [3] http://code.blender.org/index.php/2012/01/improving-node-group-interface-editing/
2013-03-18 16:34:57 +00:00
/* ************* node type access ********** */
std::string node_label(const bNodeTree &ntree, const bNode &node)
{
if (node.label[0] != '\0') {
return node.label;
}
if (node.typeinfo->labelfunc) {
char label_buffer[MAX_NAME];
node.typeinfo->labelfunc(&ntree, &node, label_buffer, MAX_NAME);
return label_buffer;
}
return IFACE_(node.typeinfo->ui_name);
}
std::optional<StringRefNull> node_socket_short_label(const bNodeSocket &sock)
{
if (sock.runtime->declaration != nullptr) {
StringRefNull short_label = sock.runtime->declaration->short_label;
if (!short_label.is_empty()) {
return sock.runtime->declaration->short_label.data();
}
}
return std::nullopt;
}
StringRefNull node_socket_label(const bNodeSocket &sock)
{
return (sock.label[0] != '\0') ? sock.label : sock.name;
}
static void node_type_base_defaults(bNodeType &ntype)
{
/* default size values */
node_type_size_preset(ntype, eNodeSizePreset::Default);
ntype.height = 100;
ntype.minheight = 30;
ntype.maxheight = FLT_MAX;
}
/* allow this node for any tree type */
static bool node_poll_default(const bNodeType * /*ntype*/,
const bNodeTree * /*ntree*/,
const char ** /*r_disabled_hint*/)
{
return true;
}
static bool node_poll_instance_default(const bNode *node,
const bNodeTree *ntree,
const char **r_disabled_hint)
{
return node->typeinfo->poll(node->typeinfo, ntree, r_disabled_hint);
}
static int16_t get_next_auto_legacy_type()
{
static std::atomic<int> next_legacy_type = []() {
/* Randomize the value a bit to avoid accidentally depending on the generated legacy type to be
* stable across Blender sessions. */
RandomNumberGenerator rng = RandomNumberGenerator::from_random_seed();
return NODE_LEGACY_TYPE_GENERATION_START + rng.get_int32(100);
}();
const int new_type = next_legacy_type.fetch_add(1);
BLI_assert(new_type <= std::numeric_limits<int16_t>::max());
return new_type;
}
void node_type_base(bNodeType &ntype, std::string idname, std::optional<int16_t> legacy_type)
{
ntype.idname = std::move(idname);
if (!legacy_type.has_value()) {
/* Still auto-generate a legacy type for this node type if none was specified. This is
* necessary because some code checks if two nodes are the same type by comparing their legacy
* types. The exact value does not matter, but it must be unique. */
legacy_type = get_next_auto_legacy_type();
}
if (!ELEM(*legacy_type, NODE_CUSTOM, NODE_UNDEFINED)) {
StructRNA *srna = RNA_struct_find(ntype.idname.c_str());
BLI_assert(srna != nullptr);
ntype.rna_ext.srna = srna;
RNA_struct_blender_type_set(srna, &ntype);
}
2018-06-17 17:05:51 +02:00
Merge of the PyNodes branch (aka "custom nodes") into trunk. PyNodes opens up the node system in Blender to scripters and adds a number of UI-level improvements. === Dynamic node type registration === Node types can now be added at runtime, using the RNA registration mechanism from python. This enables addons such as render engines to create a complete user interface with nodes. Examples of how such nodes can be defined can be found in my personal wiki docs atm [1] and as a script template in release/scripts/templates_py/custom_nodes.py [2]. === Node group improvements === Each node editor now has a tree history of edited node groups, which allows opening and editing nested node groups. The node editor also supports pinning now, so that different spaces can be used to edit different node groups simultaneously. For more ramblings and rationale see (really old) blog post on code.blender.org [3]. The interface of node groups has been overhauled. Sockets of a node group are no longer displayed in columns on either side, but instead special input/output nodes are used to mirror group sockets inside a node tree. This solves the problem of long node lines in groups and allows more adaptable node layout. Internal sockets can be exposed from a group by either connecting to the extension sockets in input/output nodes (shown as empty circle) or by adding sockets from the node property bar in the "Interface" panel. Further details such as the socket name can also be changed there. [1] http://wiki.blender.org/index.php/User:Phonybone/Python_Nodes [2] http://projects.blender.org/scm/viewvc.php/trunk/blender/release/scripts/templates_py/custom_nodes.py?view=markup&root=bf-blender [3] http://code.blender.org/index.php/2012/01/improving-node-group-interface-editing/
2013-03-18 16:34:57 +00:00
/* make sure we have a valid type (everything registered) */
BLI_assert(ntype.idname[0] != '\0');
2018-06-17 17:05:51 +02:00
ntype.type_legacy = *legacy_type;
ntype.nclass = NODE_CLASS_CONVERTER;
Merge of the PyNodes branch (aka "custom nodes") into trunk. PyNodes opens up the node system in Blender to scripters and adds a number of UI-level improvements. === Dynamic node type registration === Node types can now be added at runtime, using the RNA registration mechanism from python. This enables addons such as render engines to create a complete user interface with nodes. Examples of how such nodes can be defined can be found in my personal wiki docs atm [1] and as a script template in release/scripts/templates_py/custom_nodes.py [2]. === Node group improvements === Each node editor now has a tree history of edited node groups, which allows opening and editing nested node groups. The node editor also supports pinning now, so that different spaces can be used to edit different node groups simultaneously. For more ramblings and rationale see (really old) blog post on code.blender.org [3]. The interface of node groups has been overhauled. Sockets of a node group are no longer displayed in columns on either side, but instead special input/output nodes are used to mirror group sockets inside a node tree. This solves the problem of long node lines in groups and allows more adaptable node layout. Internal sockets can be exposed from a group by either connecting to the extension sockets in input/output nodes (shown as empty circle) or by adding sockets from the node property bar in the "Interface" panel. Further details such as the socket name can also be changed there. [1] http://wiki.blender.org/index.php/User:Phonybone/Python_Nodes [2] http://projects.blender.org/scm/viewvc.php/trunk/blender/release/scripts/templates_py/custom_nodes.py?view=markup&root=bf-blender [3] http://code.blender.org/index.php/2012/01/improving-node-group-interface-editing/
2013-03-18 16:34:57 +00:00
node_type_base_defaults(ntype);
ntype.poll = node_poll_default;
ntype.poll_instance = node_poll_instance_default;
}
void node_type_base_custom(bNodeType &ntype,
const StringRefNull idname,
const StringRefNull name,
const StringRefNull enum_name,
const short nclass)
{
ntype.idname = idname;
ntype.type_legacy = NODE_CUSTOM;
ntype.ui_name = name;
ntype.nclass = nclass;
ntype.enum_name_legacy = enum_name.c_str();
node_type_base_defaults(ntype);
}
std::optional<eCustomDataType> socket_type_to_custom_data_type(eNodeSocketDatatype type)
{
switch (type) {
case SOCK_FLOAT:
return CD_PROP_FLOAT;
case SOCK_VECTOR:
return CD_PROP_FLOAT3;
case SOCK_RGBA:
return CD_PROP_COLOR;
case SOCK_BOOLEAN:
return CD_PROP_BOOL;
case SOCK_ROTATION:
return CD_PROP_QUATERNION;
case SOCK_MATRIX:
return CD_PROP_FLOAT4X4;
case SOCK_INT:
return CD_PROP_INT32;
case SOCK_STRING:
return CD_PROP_STRING;
default:
return std::nullopt;
}
}
std::optional<eNodeSocketDatatype> custom_data_type_to_socket_type(eCustomDataType type)
{
switch (type) {
case CD_PROP_FLOAT:
return SOCK_FLOAT;
case CD_PROP_INT8:
return SOCK_INT;
case CD_PROP_INT32:
return SOCK_INT;
case CD_PROP_FLOAT3:
return SOCK_VECTOR;
case CD_PROP_FLOAT2:
return SOCK_VECTOR;
case CD_PROP_BOOL:
return SOCK_BOOLEAN;
case CD_PROP_COLOR:
return SOCK_RGBA;
case CD_PROP_BYTE_COLOR:
return SOCK_RGBA;
case CD_PROP_QUATERNION:
return SOCK_ROTATION;
case CD_PROP_FLOAT4X4:
return SOCK_MATRIX;
default:
return std::nullopt;
}
}
static const CPPType *slow_socket_type_to_geo_nodes_base_cpp_type(const eNodeSocketDatatype type)
{
const bNodeSocketType *typeinfo = node_socket_type_find_static(type);
return typeinfo->base_cpp_type;
}
const CPPType *socket_type_to_geo_nodes_base_cpp_type(const eNodeSocketDatatype type)
{
const CPPType *cpp_type;
switch (type) {
case SOCK_FLOAT:
cpp_type = &CPPType::get<float>();
break;
case SOCK_INT:
cpp_type = &CPPType::get<int>();
break;
case SOCK_RGBA:
cpp_type = &CPPType::get<ColorGeometry4f>();
break;
case SOCK_BOOLEAN:
cpp_type = &CPPType::get<bool>();
break;
case SOCK_VECTOR:
cpp_type = &CPPType::get<float3>();
break;
case SOCK_ROTATION:
cpp_type = &CPPType::get<math::Quaternion>();
break;
case SOCK_MATRIX:
cpp_type = &CPPType::get<float4x4>();
break;
Geometry Nodes: add Closures and Bundles behind experimental feature flag This implements bundles and closures which are described in more detail in this blog post: https://code.blender.org/2024/11/geometry-nodes-workshop-october-2024/ tl;dr: * Bundles are containers that allow storing multiple socket values in a single value. Each value in the bundle is identified by a name. Bundles can be nested. * Closures are functions that are created with the Closure Zone and can be evaluated with the Evaluate Closure node. To use the patch, the `Bundle and Closure Nodes` experimental feature has to be enabled. This is necessary, because these features are not fully done yet and still need iterations to improve the workflow before they can be officially released. These iterations are easier to do in `main` than in a separate branch though. That's because this patch is quite large and somewhat prone to merge conflicts. Also other work we want to do, depends on this. This adds the following new nodes: * Combine Bundle: can pack multiple values into one. * Separate Bundle: extracts values from a bundle. * Closure Zone: outputs a closure zone for use in the `Evaluate Closure` node. * Evaluate Closure: evaluates the passed in closure. Things that will be added soon after this lands: * Fields in bundles and closures. The way this is done changes with #134811, so I rather implement this once both are in `main`. * UI features for keeping sockets in sync (right now there are warnings only). One bigger issue is the limited support for lazyness. For example, all inputs of a Combine Bundle node will be evaluated, even if they are not all needed. The same is true for all captured values of a closure. This is a deeper limitation that needs to be resolved at some point. This will likely be done after an initial version of this patch is done. Pull Request: https://projects.blender.org/blender/blender/pulls/128340
2025-04-03 15:44:06 +02:00
case SOCK_BUNDLE:
cpp_type = &CPPType::get<nodes::BundlePtr>();
break;
case SOCK_CLOSURE:
cpp_type = &CPPType::get<nodes::ClosurePtr>();
break;
default:
cpp_type = slow_socket_type_to_geo_nodes_base_cpp_type(type);
break;
}
BLI_assert(cpp_type == slow_socket_type_to_geo_nodes_base_cpp_type(type));
return cpp_type;
}
std::optional<eNodeSocketDatatype> geo_nodes_base_cpp_type_to_socket_type(const CPPType &type)
{
if (type.is<float>()) {
return SOCK_FLOAT;
}
if (type.is<int>()) {
return SOCK_INT;
}
if (type.is<float3>()) {
return SOCK_VECTOR;
}
if (type.is<ColorGeometry4f>()) {
return SOCK_RGBA;
}
if (type.is<bool>()) {
return SOCK_BOOLEAN;
}
if (type.is<math::Quaternion>()) {
return SOCK_ROTATION;
}
if (type.is<float4x4>()) {
return SOCK_MATRIX;
}
if (type.is<std::string>()) {
return SOCK_STRING;
}
Geometry Nodes: add Closures and Bundles behind experimental feature flag This implements bundles and closures which are described in more detail in this blog post: https://code.blender.org/2024/11/geometry-nodes-workshop-october-2024/ tl;dr: * Bundles are containers that allow storing multiple socket values in a single value. Each value in the bundle is identified by a name. Bundles can be nested. * Closures are functions that are created with the Closure Zone and can be evaluated with the Evaluate Closure node. To use the patch, the `Bundle and Closure Nodes` experimental feature has to be enabled. This is necessary, because these features are not fully done yet and still need iterations to improve the workflow before they can be officially released. These iterations are easier to do in `main` than in a separate branch though. That's because this patch is quite large and somewhat prone to merge conflicts. Also other work we want to do, depends on this. This adds the following new nodes: * Combine Bundle: can pack multiple values into one. * Separate Bundle: extracts values from a bundle. * Closure Zone: outputs a closure zone for use in the `Evaluate Closure` node. * Evaluate Closure: evaluates the passed in closure. Things that will be added soon after this lands: * Fields in bundles and closures. The way this is done changes with #134811, so I rather implement this once both are in `main`. * UI features for keeping sockets in sync (right now there are warnings only). One bigger issue is the limited support for lazyness. For example, all inputs of a Combine Bundle node will be evaluated, even if they are not all needed. The same is true for all captured values of a closure. This is a deeper limitation that needs to be resolved at some point. This will likely be done after an initial version of this patch is done. Pull Request: https://projects.blender.org/blender/blender/pulls/128340
2025-04-03 15:44:06 +02:00
if (type.is<nodes::BundlePtr>()) {
return SOCK_BUNDLE;
}
if (type.is<nodes::ClosurePtr>()) {
return SOCK_CLOSURE;
}
return std::nullopt;
}
std::optional<VolumeGridType> socket_type_to_grid_type(const eNodeSocketDatatype type)
{
switch (type) {
case SOCK_BOOLEAN:
return VOLUME_GRID_BOOLEAN;
case SOCK_FLOAT:
return VOLUME_GRID_FLOAT;
case SOCK_INT:
return VOLUME_GRID_INT;
case SOCK_VECTOR:
return VOLUME_GRID_VECTOR_FLOAT;
default:
return std::nullopt;
}
}
std::optional<eNodeSocketDatatype> grid_type_to_socket_type(const VolumeGridType type)
{
switch (type) {
case VOLUME_GRID_BOOLEAN:
return SOCK_BOOLEAN;
case VOLUME_GRID_FLOAT:
return SOCK_FLOAT;
case VOLUME_GRID_INT:
return SOCK_INT;
case VOLUME_GRID_VECTOR_FLOAT:
return SOCK_VECTOR;
default:
return std::nullopt;
}
}
static void unique_socket_template_identifier(bNodeSocketTemplate *list,
bNodeSocketTemplate *ntemp,
const char defname[],
const char delim)
{
BLI_uniquename_cb(
[&](const StringRef check_name) {
for (bNodeSocketTemplate *ntemp_iter = list; ntemp_iter->type >= 0; ntemp_iter++) {
if (ntemp_iter != ntemp) {
if (ntemp_iter->identifier == check_name) {
return true;
}
}
}
return false;
},
defname,
delim,
ntemp->identifier,
sizeof(ntemp->identifier));
}
void node_type_socket_templates(bNodeType *ntype,
bNodeSocketTemplate *inputs,
bNodeSocketTemplate *outputs)
{
ntype->inputs = inputs;
ntype->outputs = outputs;
2018-06-17 17:05:51 +02:00
Merge of the PyNodes branch (aka "custom nodes") into trunk. PyNodes opens up the node system in Blender to scripters and adds a number of UI-level improvements. === Dynamic node type registration === Node types can now be added at runtime, using the RNA registration mechanism from python. This enables addons such as render engines to create a complete user interface with nodes. Examples of how such nodes can be defined can be found in my personal wiki docs atm [1] and as a script template in release/scripts/templates_py/custom_nodes.py [2]. === Node group improvements === Each node editor now has a tree history of edited node groups, which allows opening and editing nested node groups. The node editor also supports pinning now, so that different spaces can be used to edit different node groups simultaneously. For more ramblings and rationale see (really old) blog post on code.blender.org [3]. The interface of node groups has been overhauled. Sockets of a node group are no longer displayed in columns on either side, but instead special input/output nodes are used to mirror group sockets inside a node tree. This solves the problem of long node lines in groups and allows more adaptable node layout. Internal sockets can be exposed from a group by either connecting to the extension sockets in input/output nodes (shown as empty circle) or by adding sockets from the node property bar in the "Interface" panel. Further details such as the socket name can also be changed there. [1] http://wiki.blender.org/index.php/User:Phonybone/Python_Nodes [2] http://projects.blender.org/scm/viewvc.php/trunk/blender/release/scripts/templates_py/custom_nodes.py?view=markup&root=bf-blender [3] http://code.blender.org/index.php/2012/01/improving-node-group-interface-editing/
2013-03-18 16:34:57 +00:00
/* automatically generate unique identifiers */
if (inputs) {
/* clear identifier strings (uninitialized memory) */
for (bNodeSocketTemplate *ntemp = inputs; ntemp->type >= 0; ntemp++) {
Merge of the PyNodes branch (aka "custom nodes") into trunk. PyNodes opens up the node system in Blender to scripters and adds a number of UI-level improvements. === Dynamic node type registration === Node types can now be added at runtime, using the RNA registration mechanism from python. This enables addons such as render engines to create a complete user interface with nodes. Examples of how such nodes can be defined can be found in my personal wiki docs atm [1] and as a script template in release/scripts/templates_py/custom_nodes.py [2]. === Node group improvements === Each node editor now has a tree history of edited node groups, which allows opening and editing nested node groups. The node editor also supports pinning now, so that different spaces can be used to edit different node groups simultaneously. For more ramblings and rationale see (really old) blog post on code.blender.org [3]. The interface of node groups has been overhauled. Sockets of a node group are no longer displayed in columns on either side, but instead special input/output nodes are used to mirror group sockets inside a node tree. This solves the problem of long node lines in groups and allows more adaptable node layout. Internal sockets can be exposed from a group by either connecting to the extension sockets in input/output nodes (shown as empty circle) or by adding sockets from the node property bar in the "Interface" panel. Further details such as the socket name can also be changed there. [1] http://wiki.blender.org/index.php/User:Phonybone/Python_Nodes [2] http://projects.blender.org/scm/viewvc.php/trunk/blender/release/scripts/templates_py/custom_nodes.py?view=markup&root=bf-blender [3] http://code.blender.org/index.php/2012/01/improving-node-group-interface-editing/
2013-03-18 16:34:57 +00:00
ntemp->identifier[0] = '\0';
}
2018-06-17 17:05:51 +02:00
for (bNodeSocketTemplate *ntemp = inputs; ntemp->type >= 0; ntemp++) {
2023-05-09 12:50:37 +10:00
STRNCPY(ntemp->identifier, ntemp->name);
Merge of the PyNodes branch (aka "custom nodes") into trunk. PyNodes opens up the node system in Blender to scripters and adds a number of UI-level improvements. === Dynamic node type registration === Node types can now be added at runtime, using the RNA registration mechanism from python. This enables addons such as render engines to create a complete user interface with nodes. Examples of how such nodes can be defined can be found in my personal wiki docs atm [1] and as a script template in release/scripts/templates_py/custom_nodes.py [2]. === Node group improvements === Each node editor now has a tree history of edited node groups, which allows opening and editing nested node groups. The node editor also supports pinning now, so that different spaces can be used to edit different node groups simultaneously. For more ramblings and rationale see (really old) blog post on code.blender.org [3]. The interface of node groups has been overhauled. Sockets of a node group are no longer displayed in columns on either side, but instead special input/output nodes are used to mirror group sockets inside a node tree. This solves the problem of long node lines in groups and allows more adaptable node layout. Internal sockets can be exposed from a group by either connecting to the extension sockets in input/output nodes (shown as empty circle) or by adding sockets from the node property bar in the "Interface" panel. Further details such as the socket name can also be changed there. [1] http://wiki.blender.org/index.php/User:Phonybone/Python_Nodes [2] http://projects.blender.org/scm/viewvc.php/trunk/blender/release/scripts/templates_py/custom_nodes.py?view=markup&root=bf-blender [3] http://code.blender.org/index.php/2012/01/improving-node-group-interface-editing/
2013-03-18 16:34:57 +00:00
unique_socket_template_identifier(inputs, ntemp, ntemp->identifier, '_');
}
}
if (outputs) {
/* clear identifier strings (uninitialized memory) */
for (bNodeSocketTemplate *ntemp = outputs; ntemp->type >= 0; ntemp++) {
Merge of the PyNodes branch (aka "custom nodes") into trunk. PyNodes opens up the node system in Blender to scripters and adds a number of UI-level improvements. === Dynamic node type registration === Node types can now be added at runtime, using the RNA registration mechanism from python. This enables addons such as render engines to create a complete user interface with nodes. Examples of how such nodes can be defined can be found in my personal wiki docs atm [1] and as a script template in release/scripts/templates_py/custom_nodes.py [2]. === Node group improvements === Each node editor now has a tree history of edited node groups, which allows opening and editing nested node groups. The node editor also supports pinning now, so that different spaces can be used to edit different node groups simultaneously. For more ramblings and rationale see (really old) blog post on code.blender.org [3]. The interface of node groups has been overhauled. Sockets of a node group are no longer displayed in columns on either side, but instead special input/output nodes are used to mirror group sockets inside a node tree. This solves the problem of long node lines in groups and allows more adaptable node layout. Internal sockets can be exposed from a group by either connecting to the extension sockets in input/output nodes (shown as empty circle) or by adding sockets from the node property bar in the "Interface" panel. Further details such as the socket name can also be changed there. [1] http://wiki.blender.org/index.php/User:Phonybone/Python_Nodes [2] http://projects.blender.org/scm/viewvc.php/trunk/blender/release/scripts/templates_py/custom_nodes.py?view=markup&root=bf-blender [3] http://code.blender.org/index.php/2012/01/improving-node-group-interface-editing/
2013-03-18 16:34:57 +00:00
ntemp->identifier[0] = '\0';
}
2018-06-17 17:05:51 +02:00
for (bNodeSocketTemplate *ntemp = outputs; ntemp->type >= 0; ntemp++) {
2023-05-09 12:50:37 +10:00
STRNCPY(ntemp->identifier, ntemp->name);
Merge of the PyNodes branch (aka "custom nodes") into trunk. PyNodes opens up the node system in Blender to scripters and adds a number of UI-level improvements. === Dynamic node type registration === Node types can now be added at runtime, using the RNA registration mechanism from python. This enables addons such as render engines to create a complete user interface with nodes. Examples of how such nodes can be defined can be found in my personal wiki docs atm [1] and as a script template in release/scripts/templates_py/custom_nodes.py [2]. === Node group improvements === Each node editor now has a tree history of edited node groups, which allows opening and editing nested node groups. The node editor also supports pinning now, so that different spaces can be used to edit different node groups simultaneously. For more ramblings and rationale see (really old) blog post on code.blender.org [3]. The interface of node groups has been overhauled. Sockets of a node group are no longer displayed in columns on either side, but instead special input/output nodes are used to mirror group sockets inside a node tree. This solves the problem of long node lines in groups and allows more adaptable node layout. Internal sockets can be exposed from a group by either connecting to the extension sockets in input/output nodes (shown as empty circle) or by adding sockets from the node property bar in the "Interface" panel. Further details such as the socket name can also be changed there. [1] http://wiki.blender.org/index.php/User:Phonybone/Python_Nodes [2] http://projects.blender.org/scm/viewvc.php/trunk/blender/release/scripts/templates_py/custom_nodes.py?view=markup&root=bf-blender [3] http://code.blender.org/index.php/2012/01/improving-node-group-interface-editing/
2013-03-18 16:34:57 +00:00
unique_socket_template_identifier(outputs, ntemp, ntemp->identifier, '_');
}
}
}
void node_type_size(bNodeType &ntype, const int width, const int minwidth, const int maxwidth)
{
ntype.width = width;
ntype.minwidth = minwidth;
if (maxwidth <= minwidth) {
ntype.maxwidth = FLT_MAX;
}
else {
ntype.maxwidth = maxwidth;
}
}
void node_type_size_preset(bNodeType &ntype, const eNodeSizePreset size)
{
switch (size) {
case eNodeSizePreset::Default:
node_type_size(ntype, 140, 100, NODE_DEFAULT_MAX_WIDTH);
break;
case eNodeSizePreset::Small:
node_type_size(ntype, 100, 80, NODE_DEFAULT_MAX_WIDTH);
break;
case eNodeSizePreset::Middle:
node_type_size(ntype, 150, 120, NODE_DEFAULT_MAX_WIDTH);
break;
case eNodeSizePreset::Large:
node_type_size(ntype, 240, 140, NODE_DEFAULT_MAX_WIDTH);
break;
}
}
void node_type_storage(bNodeType &ntype,
const std::optional<StringRefNull> storagename,
void (*freefunc)(bNode *node),
void (*copyfunc)(bNodeTree *dest_ntree,
bNode *dest_node,
const bNode *src_node))
{
ntype.storagename = storagename.value_or("");
ntype.copyfunc = copyfunc;
ntype.freefunc = freefunc;
}
void node_system_init()
{
register_nodes();
}
void node_system_exit()
{
get_node_type_alias_map().clear();
const Vector<bNodeType *> node_types = get_node_type_map().extract_vector();
for (bNodeType *nt : node_types) {
if (nt->rna_ext.free) {
nt->rna_ext.free(nt->rna_ext.data);
}
node_free_type(nt);
}
Render Layers and Collections (merge from render-layers) Design Documents ---------------- * https://wiki.blender.org/index.php/Dev:2.8/Source/Layers * https://wiki.blender.org/index.php/Dev:2.8/Source/DataDesignRevised User Commit Log --------------- * New Layer and Collection system to replace render layers and viewport layers. * A layer is a set of collections of objects (and their drawing options) required for specific tasks. * A collection is a set of objects, equivalent of the old layers in Blender. A collection can be shared across multiple layers. * All Scenes have a master collection that all other collections are children of. * New collection "context" tab (in Properties Editor) * New temporary viewport "collections" panel to control per-collection visibility Missing User Features --------------------- * Collection "Filter" Option to add objects based on their names * Collection Manager operators The existing buttons are placeholders * Collection Manager drawing The editor main region is empty * Collection Override * Per-Collection engine settings This will come as a separate commit, as part of the clay-engine branch Dev Commit Log -------------- * New DNA file (DNA_layer_types.h) with the new structs We are replacing Base by a new extended Base while keeping it backward compatible with some legacy settings (i.e., lay, flag_legacy). Renamed all Base to BaseLegacy to make it clear the areas of code that still need to be converted Note: manual changes were required on - deg_builder_nodes.h, rna_object.c, KX_Light.cpp * Unittesting for main syncronization requirements - read, write, add/copy/remove objects, copy scene, collection link/unlinking, context) * New Editor: Collection Manager Based on patch by Julian Eisel This is extracted from the layer-manager branch. With the following changes: - Renamed references of layer manager to collections manager - I doesn't include the editors/space_collections/ draw and util files - The drawing code itself will be implemented separately by Julian * Base / Object: A little note about them. Original Blender code would try to keep them in sync through the code, juggling flags back and forth. This will now be handled by Depsgraph, keeping Object and Bases more separated throughout the non-rendering code. Scene.base is being cleared in doversion, and the old viewport drawing code was poorly converted to use the new bases while the new viewport code doesn't get merged and replace the old one. Python API Changes ------------------ ``` - scene.layers + # no longer exists - scene.objects + scene.scene_layers.active.objects - scene.objects.active + scene.render_layers.active.objects.active - bpy.context.scene.objects.link() + bpy.context.scene_collection.objects.link() - bpy_extras.object_utils.object_data_add(context, obdata, operator=None, use_active_layer=True, name=None) + bpy_extras.object_utils.object_data_add(context, obdata, operator=None, name=None) - bpy.context.object.select + bpy.context.object.select = True + bpy.context.object.select = False + bpy.context.object.select_get() + bpy.context.object.select_set(action='SELECT') + bpy.context.object.select_set(action='DESELECT') -AddObjectHelper.layers + # no longer exists ```
2017-02-07 10:18:38 +01:00
const Vector<bNodeSocketType *> socket_types = get_socket_type_map().extract_vector();
for (bNodeSocketType *st : socket_types) {
if (st->ext_socket.free) {
st->ext_socket.free(st->ext_socket.data);
}
if (st->ext_interface.free) {
st->ext_interface.free(st->ext_interface.data);
}
node_free_socket_type(st);
}
const Vector<bNodeTreeType *> tree_types = get_node_tree_type_map().extract_vector();
for (bNodeTreeType *nt : tree_types) {
if (nt->rna_ext.free) {
nt->rna_ext.free(nt->rna_ext.data);
}
ntree_free_type(nt);
}
}
/* -------------------------------------------------------------------- */
/* NodeTree Iterator Helpers (FOREACH_NODETREE_BEGIN) */
void node_tree_iterator_init(NodeTreeIterStore *ntreeiter, Main *bmain)
{
ntreeiter->ngroup = (bNodeTree *)bmain->nodetrees.first;
ntreeiter->scene = (Scene *)bmain->scenes.first;
ntreeiter->mat = (Material *)bmain->materials.first;
ntreeiter->tex = (Tex *)bmain->textures.first;
ntreeiter->light = (Light *)bmain->lights.first;
ntreeiter->world = (World *)bmain->worlds.first;
ntreeiter->linestyle = (FreestyleLineStyle *)bmain->linestyles.first;
}
bool node_tree_iterator_step(NodeTreeIterStore *ntreeiter, bNodeTree **r_nodetree, ID **r_id)
{
if (ntreeiter->ngroup) {
bNodeTree &node_tree = *ntreeiter->ngroup;
*r_nodetree = &node_tree;
*r_id = &node_tree.id;
ntreeiter->ngroup = reinterpret_cast<bNodeTree *>(node_tree.id.next);
return true;
}
if (ntreeiter->scene) {
*r_nodetree = reinterpret_cast<bNodeTree *>(ntreeiter->scene->nodetree);
*r_id = &ntreeiter->scene->id;
ntreeiter->scene = reinterpret_cast<Scene *>(ntreeiter->scene->id.next);
return true;
}
if (ntreeiter->mat) {
*r_nodetree = reinterpret_cast<bNodeTree *>(ntreeiter->mat->nodetree);
*r_id = &ntreeiter->mat->id;
ntreeiter->mat = reinterpret_cast<Material *>(ntreeiter->mat->id.next);
return true;
}
if (ntreeiter->tex) {
*r_nodetree = reinterpret_cast<bNodeTree *>(ntreeiter->tex->nodetree);
*r_id = &ntreeiter->tex->id;
ntreeiter->tex = reinterpret_cast<Tex *>(ntreeiter->tex->id.next);
return true;
}
if (ntreeiter->light) {
*r_nodetree = reinterpret_cast<bNodeTree *>(ntreeiter->light->nodetree);
*r_id = &ntreeiter->light->id;
ntreeiter->light = reinterpret_cast<Light *>(ntreeiter->light->id.next);
return true;
}
if (ntreeiter->world) {
*r_nodetree = reinterpret_cast<bNodeTree *>(ntreeiter->world->nodetree);
*r_id = &ntreeiter->world->id;
ntreeiter->world = reinterpret_cast<World *>(ntreeiter->world->id.next);
return true;
}
if (ntreeiter->linestyle) {
*r_nodetree = reinterpret_cast<bNodeTree *>(ntreeiter->linestyle->nodetree);
*r_id = &ntreeiter->linestyle->id;
ntreeiter->linestyle = reinterpret_cast<FreestyleLineStyle *>(ntreeiter->linestyle->id.next);
return true;
}
return false;
}
void node_tree_remove_layer_n(bNodeTree *ntree, Scene *scene, const int layer_index)
{
BLI_assert(layer_index != -1);
BLI_assert(scene != nullptr);
for (bNode *node : ntree->all_nodes()) {
if (node->type_legacy == CMP_NODE_R_LAYERS && node->id == &scene->id) {
if (node->custom1 == layer_index) {
node->custom1 = 0;
}
else if (node->custom1 > layer_index) {
node->custom1--;
}
}
}
}
} // namespace blender::bke