2022-02-11 09:07:11 +11:00
|
|
|
/* SPDX-License-Identifier: GPL-2.0-or-later
|
|
|
|
|
* Copyright 2005 Blender Foundation. All rights reserved. */
|
2005-12-18 13:46:01 +00:00
|
|
|
|
2019-02-18 08:08:12 +11:00
|
|
|
/** \file
|
|
|
|
|
* \ingroup bke
|
2011-02-27 20:40:57 +00:00
|
|
|
*/
|
|
|
|
|
|
2019-02-01 12:44:19 +11:00
|
|
|
#include "CLG_log.h"
|
|
|
|
|
|
2011-02-21 13:47:49 +00:00
|
|
|
#include "MEM_guardedalloc.h"
|
|
|
|
|
|
2021-02-02 09:51:38 -06:00
|
|
|
#include <climits>
|
|
|
|
|
#include <cstddef>
|
|
|
|
|
#include <cstdlib>
|
|
|
|
|
#include <cstring>
|
2005-12-18 13:46:01 +00:00
|
|
|
|
2020-09-10 13:33:29 +02:00
|
|
|
/* Allow using deprecated functionality for .blend file I/O. */
|
|
|
|
|
#define DNA_DEPRECATED_ALLOW
|
|
|
|
|
|
2011-11-02 19:24:30 +00:00
|
|
|
#include "DNA_action_types.h"
|
2010-01-27 05:42:17 +00:00
|
|
|
#include "DNA_anim_types.h"
|
2020-12-15 10:47:58 +11:00
|
|
|
#include "DNA_collection_types.h"
|
2020-05-07 16:54:32 +02:00
|
|
|
#include "DNA_gpencil_types.h"
|
2019-02-27 12:34:56 +11:00
|
|
|
#include "DNA_light_types.h"
|
2020-03-19 09:33:03 +01:00
|
|
|
#include "DNA_linestyle_types.h"
|
2012-12-03 16:21:43 +00:00
|
|
|
#include "DNA_material_types.h"
|
2020-12-02 13:25:25 +01:00
|
|
|
#include "DNA_modifier_types.h"
|
2011-02-21 13:47:49 +00:00
|
|
|
#include "DNA_node_types.h"
|
2011-09-05 21:01:50 +00:00
|
|
|
#include "DNA_scene_types.h"
|
2020-04-20 12:56:16 +02:00
|
|
|
#include "DNA_simulation_types.h"
|
2012-12-03 16:21:43 +00:00
|
|
|
#include "DNA_texture_types.h"
|
|
|
|
|
#include "DNA_world_types.h"
|
2011-02-21 13:47:49 +00:00
|
|
|
|
2021-12-06 16:50:44 -05:00
|
|
|
#include "BLI_color.hh"
|
2019-06-03 17:08:25 +02:00
|
|
|
#include "BLI_ghash.h"
|
2020-03-19 09:33:03 +01:00
|
|
|
#include "BLI_listbase.h"
|
2021-02-16 17:15:08 -06:00
|
|
|
#include "BLI_map.hh"
|
2011-09-05 21:01:50 +00:00
|
|
|
#include "BLI_path_util.h"
|
2021-09-23 15:21:31 -05:00
|
|
|
#include "BLI_set.hh"
|
|
|
|
|
#include "BLI_stack.hh"
|
2017-01-16 17:33:34 +01:00
|
|
|
#include "BLI_string.h"
|
|
|
|
|
#include "BLI_string_utils.h"
|
2021-12-06 16:50:44 -05:00
|
|
|
#include "BLI_threads.h"
|
2011-09-05 21:01:50 +00:00
|
|
|
#include "BLI_utildefines.h"
|
2021-09-23 15:21:31 -05:00
|
|
|
#include "BLI_vector_set.hh"
|
2015-08-16 17:32:01 +10:00
|
|
|
#include "BLT_translation.h"
|
2012-03-17 14:42:44 +00:00
|
|
|
|
2020-04-03 13:07:36 +02:00
|
|
|
#include "BKE_anim_data.h"
|
2010-12-29 11:51:53 +00:00
|
|
|
#include "BKE_animsys.h"
|
Refactor BKE_bpath module.
The main goal of this refactor is to make BPath module use `IDTypeInfo`,
and move each ID-specific part of the `foreach_path` looper into their
own IDTypeInfo struct, using a new `foreach_path` callback.
Additionally, following improvements/cleanups are included:
* Attempt to get better, more consistent namings.
** In particular, move from `path_visitor` to more standard `foreach_path`.
* Update and extend documentation.
** API doc was moved to header, according to recent discussions on this
topic.
* Remove `BKE_bpath_relocate_visitor` from API, this is specific
callback that belongs in `lib_id.c` user code.
NOTE: This commit is expected to be 100% non-behavioral-change. This
implies that several potential further changes were only noted as
comments (like using a more generic solution for
`lib_id_library_local_paths`, addressing inconsistencies like path of
packed libraries always being skipped, regardless of the
`BKE_BPATH_FOREACH_PATH_SKIP_PACKED` `eBPathForeachFlag` flag value,
etc.).
NOTE: basic unittests were added to master already in
rBdcc500e5a265093bc9cc.
Reviewed By: brecht
Differential Revision: https://developer.blender.org/D13381
2021-11-29 14:20:58 +01:00
|
|
|
#include "BKE_bpath.h"
|
2020-09-10 13:33:29 +02:00
|
|
|
#include "BKE_colortools.h"
|
2021-12-29 19:40:00 +01:00
|
|
|
#include "BKE_context.h"
|
2020-12-15 12:17:31 +01:00
|
|
|
#include "BKE_cryptomatte.h"
|
2011-09-05 21:01:50 +00:00
|
|
|
#include "BKE_global.h"
|
2021-11-06 16:43:26 +01:00
|
|
|
#include "BKE_icons.h"
|
2013-03-18 16:34:57 +00:00
|
|
|
#include "BKE_idprop.h"
|
2020-03-06 14:57:26 +01:00
|
|
|
#include "BKE_idtype.h"
|
2022-03-11 17:50:57 +01:00
|
|
|
#include "BKE_image_format.h"
|
2020-02-10 12:58:59 +01:00
|
|
|
#include "BKE_lib_id.h"
|
2020-05-07 16:54:32 +02:00
|
|
|
#include "BKE_lib_query.h"
|
2011-09-05 21:01:50 +00:00
|
|
|
#include "BKE_main.h"
|
2011-02-07 09:33:36 +00:00
|
|
|
#include "BKE_node.h"
|
2022-05-30 12:54:07 +02:00
|
|
|
#include "BKE_node_runtime.hh"
|
2021-12-21 15:18:56 +01:00
|
|
|
#include "BKE_node_tree_update.h"
|
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
|
|
|
|
2011-09-05 21:01:50 +00:00
|
|
|
#include "RNA_access.h"
|
2013-03-18 16:34:57 +00:00
|
|
|
#include "RNA_define.h"
|
2022-03-14 16:54:46 +01:00
|
|
|
#include "RNA_prototypes.h"
|
2007-03-24 18:41:54 +00:00
|
|
|
|
2013-03-18 16:34:57 +00:00
|
|
|
#include "NOD_common.h"
|
2011-09-05 21:01:50 +00:00
|
|
|
#include "NOD_composite.h"
|
2020-04-20 15:27:12 +02:00
|
|
|
#include "NOD_function.h"
|
2020-12-02 13:25:25 +01:00
|
|
|
#include "NOD_geometry.h"
|
2021-08-30 17:13:46 +02:00
|
|
|
#include "NOD_node_declaration.hh"
|
2011-09-05 21:01:50 +00:00
|
|
|
#include "NOD_shader.h"
|
2020-03-19 09:33:03 +01:00
|
|
|
#include "NOD_socket.h"
|
2011-09-05 21:01:50 +00:00
|
|
|
#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
|
|
|
|
2018-03-16 11:17:45 +01:00
|
|
|
#include "DEG_depsgraph.h"
|
2018-11-23 17:02:55 +01:00
|
|
|
#include "DEG_depsgraph_build.h"
|
2018-03-16 11:17:45 +01:00
|
|
|
|
2020-09-10 13:33:29 +02:00
|
|
|
#include "BLO_read_write.h"
|
|
|
|
|
|
2020-12-02 13:25:25 +01:00
|
|
|
#include "MOD_nodes.h"
|
|
|
|
|
|
2016-03-12 19:10:36 +01:00
|
|
|
#define NODE_DEFAULT_MAX_WIDTH 700
|
|
|
|
|
|
2021-09-23 15:21:31 -05:00
|
|
|
using blender::Array;
|
2021-12-22 08:47:46 -06:00
|
|
|
using blender::Map;
|
2021-09-23 15:21:31 -05:00
|
|
|
using blender::MutableSpan;
|
|
|
|
|
using blender::Set;
|
|
|
|
|
using blender::Span;
|
|
|
|
|
using blender::Stack;
|
2021-12-15 09:51:57 -06:00
|
|
|
using blender::StringRef;
|
2021-09-23 15:21:31 -05:00
|
|
|
using blender::Vector;
|
|
|
|
|
using blender::VectorSet;
|
2022-05-30 15:31:13 +02:00
|
|
|
using blender::bke::bNodeRuntime;
|
|
|
|
|
using blender::bke::bNodeSocketRuntime;
|
2022-05-30 12:54:07 +02:00
|
|
|
using blender::bke::bNodeTreeRuntime;
|
2021-09-28 12:05:42 -05:00
|
|
|
using blender::nodes::FieldInferencingInterface;
|
2021-09-23 15:21:31 -05:00
|
|
|
using blender::nodes::InputSocketFieldType;
|
|
|
|
|
using blender::nodes::NodeDeclaration;
|
|
|
|
|
using blender::nodes::OutputFieldDependency;
|
|
|
|
|
using blender::nodes::OutputSocketFieldType;
|
|
|
|
|
using blender::nodes::SocketDeclaration;
|
|
|
|
|
|
2013-03-19 13:40:16 +00:00
|
|
|
/* Fallback types for undefined tree, nodes, sockets */
|
2019-02-23 19:17:30 +11:00
|
|
|
static bNodeTreeType NodeTreeTypeUndefined;
|
2013-03-19 13:40:16 +00:00
|
|
|
bNodeType NodeTypeUndefined;
|
|
|
|
|
bNodeSocketType NodeSocketTypeUndefined;
|
|
|
|
|
|
2019-02-01 12:44:19 +11:00
|
|
|
static CLG_LogRef LOG = {"bke.node"};
|
2007-03-26 15:07:38 +00:00
|
|
|
|
2020-03-06 14:57:26 +01:00
|
|
|
static void ntree_set_typeinfo(bNodeTree *ntree, bNodeTreeType *typeinfo);
|
|
|
|
|
static void node_socket_copy(bNodeSocket *sock_dst, const bNodeSocket *sock_src, const int flag);
|
|
|
|
|
static void free_localized_node_groups(bNodeTree *ntree);
|
|
|
|
|
static void node_free_node(bNodeTree *ntree, bNode *node);
|
2020-04-20 13:22:20 +02:00
|
|
|
static void node_socket_interface_free(bNodeTree *UNUSED(ntree),
|
|
|
|
|
bNodeSocket *sock,
|
|
|
|
|
const bool do_id_user);
|
2020-03-06 14:57:26 +01:00
|
|
|
|
|
|
|
|
static void ntree_init_data(ID *id)
|
|
|
|
|
{
|
|
|
|
|
bNodeTree *ntree = (bNodeTree *)id;
|
2022-05-30 12:54:07 +02:00
|
|
|
ntree->runtime = MEM_new<bNodeTreeRuntime>(__func__);
|
2021-02-02 09:51:38 -06:00
|
|
|
ntree_set_typeinfo(ntree, nullptr);
|
2020-03-06 14:57:26 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void ntree_copy_data(Main *UNUSED(bmain), ID *id_dst, const ID *id_src, const int flag)
|
|
|
|
|
{
|
|
|
|
|
bNodeTree *ntree_dst = (bNodeTree *)id_dst;
|
|
|
|
|
const bNodeTree *ntree_src = (const bNodeTree *)id_src;
|
|
|
|
|
|
|
|
|
|
/* We never handle usercount here for own data. */
|
|
|
|
|
const int flag_subdata = flag | LIB_ID_CREATE_NO_USER_REFCOUNT;
|
|
|
|
|
|
2022-05-30 12:54:07 +02:00
|
|
|
ntree_dst->runtime = MEM_new<bNodeTreeRuntime>(__func__);
|
|
|
|
|
|
2020-03-06 14:57:26 +01:00
|
|
|
/* in case a running nodetree is copied */
|
2021-02-02 09:51:38 -06:00
|
|
|
ntree_dst->execdata = nullptr;
|
2020-03-06 14:57:26 +01:00
|
|
|
|
|
|
|
|
BLI_listbase_clear(&ntree_dst->nodes);
|
|
|
|
|
BLI_listbase_clear(&ntree_dst->links);
|
|
|
|
|
|
2021-12-22 08:47:46 -06:00
|
|
|
Map<const bNode *, bNode *> node_map;
|
|
|
|
|
Map<const bNodeSocket *, bNodeSocket *> socket_map;
|
2020-03-06 14:57:26 +01:00
|
|
|
|
2021-12-22 08:47:46 -06:00
|
|
|
BLI_listbase_clear(&ntree_dst->nodes);
|
|
|
|
|
LISTBASE_FOREACH (const bNode *, src_node, &ntree_src->nodes) {
|
2021-12-22 08:52:46 -06:00
|
|
|
/* Don't find a unique name for every node, since they should have valid names already. */
|
2021-12-22 08:47:46 -06:00
|
|
|
bNode *new_node = blender::bke::node_copy_with_mapping(
|
2021-12-22 08:52:46 -06:00
|
|
|
ntree_dst, *src_node, flag_subdata, false, socket_map);
|
2021-12-22 08:47:46 -06:00
|
|
|
node_map.add(src_node, new_node);
|
2020-03-06 14:57:26 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* copy links */
|
2021-12-22 08:47:46 -06:00
|
|
|
BLI_listbase_clear(&ntree_dst->links);
|
|
|
|
|
LISTBASE_FOREACH (const bNodeLink *, src_link, &ntree_src->links) {
|
|
|
|
|
bNodeLink *dst_link = (bNodeLink *)MEM_dupallocN(src_link);
|
|
|
|
|
dst_link->fromnode = node_map.lookup(src_link->fromnode);
|
|
|
|
|
dst_link->fromsock = socket_map.lookup(src_link->fromsock);
|
|
|
|
|
dst_link->tonode = node_map.lookup(src_link->tonode);
|
|
|
|
|
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);
|
2020-03-06 14:57:26 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* copy interface sockets */
|
2021-12-22 08:47:46 -06:00
|
|
|
BLI_listbase_clear(&ntree_dst->inputs);
|
|
|
|
|
LISTBASE_FOREACH (const bNodeSocket *, src_socket, &ntree_src->inputs) {
|
|
|
|
|
bNodeSocket *dst_socket = (bNodeSocket *)MEM_dupallocN(src_socket);
|
|
|
|
|
node_socket_copy(dst_socket, src_socket, flag_subdata);
|
|
|
|
|
BLI_addtail(&ntree_dst->inputs, dst_socket);
|
2020-03-06 14:57:26 +01:00
|
|
|
}
|
2021-12-22 08:47:46 -06:00
|
|
|
BLI_listbase_clear(&ntree_dst->outputs);
|
|
|
|
|
LISTBASE_FOREACH (const bNodeSocket *, src_socket, &ntree_src->outputs) {
|
|
|
|
|
bNodeSocket *dst_socket = (bNodeSocket *)MEM_dupallocN(src_socket);
|
|
|
|
|
node_socket_copy(dst_socket, src_socket, flag_subdata);
|
|
|
|
|
BLI_addtail(&ntree_dst->outputs, dst_socket);
|
2020-03-06 14:57:26 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* copy preview hash */
|
|
|
|
|
if (ntree_src->previews && (flag & LIB_ID_COPY_NO_PREVIEW) == 0) {
|
|
|
|
|
bNodeInstanceHashIterator iter;
|
|
|
|
|
|
|
|
|
|
ntree_dst->previews = BKE_node_instance_hash_new("node previews");
|
|
|
|
|
|
|
|
|
|
NODE_INSTANCE_HASH_ITER (iter, ntree_src->previews) {
|
|
|
|
|
bNodeInstanceKey key = BKE_node_instance_hash_iterator_get_key(&iter);
|
2021-02-02 09:51:38 -06:00
|
|
|
bNodePreview *preview = (bNodePreview *)BKE_node_instance_hash_iterator_get_value(&iter);
|
2020-03-06 14:57:26 +01:00
|
|
|
BKE_node_instance_hash_insert(ntree_dst->previews, key, BKE_node_preview_copy(preview));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else {
|
2021-02-02 09:51:38 -06:00
|
|
|
ntree_dst->previews = nullptr;
|
2020-03-06 14:57:26 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* update node->parent pointers */
|
2021-12-22 08:47:46 -06:00
|
|
|
LISTBASE_FOREACH (bNode *, new_node, &ntree_dst->nodes) {
|
|
|
|
|
if (new_node->parent) {
|
|
|
|
|
new_node->parent = node_map.lookup(new_node->parent);
|
2020-03-06 14:57:26 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
/* node tree will generate its own interface type */
|
2021-02-02 09:51:38 -06:00
|
|
|
ntree_dst->interface_type = nullptr;
|
2021-09-23 15:21:31 -05:00
|
|
|
|
2022-05-30 12:54:07 +02:00
|
|
|
if (ntree_src->runtime->field_inferencing_interface) {
|
|
|
|
|
ntree_dst->runtime->field_inferencing_interface = std::make_unique<FieldInferencingInterface>(
|
|
|
|
|
*ntree_src->runtime->field_inferencing_interface);
|
2021-09-23 15:21:31 -05:00
|
|
|
}
|
2021-11-06 16:43:26 +01:00
|
|
|
|
|
|
|
|
if (flag & LIB_ID_COPY_NO_PREVIEW) {
|
2021-11-07 00:39:20 -05:00
|
|
|
ntree_dst->preview = nullptr;
|
2021-11-06 16:43:26 +01:00
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
BKE_previewimg_id_copy(&ntree_dst->id, &ntree_src->id);
|
|
|
|
|
}
|
2020-03-06 14:57:26 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void ntree_free_data(ID *id)
|
|
|
|
|
{
|
|
|
|
|
bNodeTree *ntree = (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
|
2021-12-20 10:48:01 -06:00
|
|
|
* after execution, until the node tree is updated or freed. */
|
2020-03-06 14:57:26 +01:00
|
|
|
if (ntree->execdata) {
|
|
|
|
|
switch (ntree->type) {
|
|
|
|
|
case NTREE_SHADER:
|
|
|
|
|
ntreeShaderEndExecTree(ntree->execdata);
|
|
|
|
|
break;
|
|
|
|
|
case NTREE_TEXTURE:
|
|
|
|
|
ntreeTexEndExecTree(ntree->execdata);
|
2021-02-02 09:51:38 -06:00
|
|
|
ntree->execdata = nullptr;
|
2020-03-06 14:57:26 +01:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* XXX not nice, but needed to free localized node groups properly */
|
|
|
|
|
free_localized_node_groups(ntree);
|
|
|
|
|
|
2021-12-20 10:48:01 -06:00
|
|
|
/* Unregister associated RNA types. */
|
2020-03-06 14:57:26 +01:00
|
|
|
ntreeInterfaceTypeFree(ntree);
|
|
|
|
|
|
2021-12-21 09:23:48 -06:00
|
|
|
BLI_freelistN(&ntree->links);
|
2020-03-06 14:57:26 +01:00
|
|
|
|
2020-08-31 13:59:33 +02:00
|
|
|
LISTBASE_FOREACH_MUTABLE (bNode *, node, &ntree->nodes) {
|
2020-03-06 14:57:26 +01:00
|
|
|
node_free_node(ntree, node);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* free interface sockets */
|
2020-08-31 13:59:33 +02:00
|
|
|
LISTBASE_FOREACH_MUTABLE (bNodeSocket *, sock, &ntree->inputs) {
|
2020-04-20 13:22:20 +02:00
|
|
|
node_socket_interface_free(ntree, sock, false);
|
2020-03-06 14:57:26 +01:00
|
|
|
MEM_freeN(sock);
|
|
|
|
|
}
|
2020-08-31 13:59:33 +02:00
|
|
|
LISTBASE_FOREACH_MUTABLE (bNodeSocket *, sock, &ntree->outputs) {
|
2020-04-20 13:22:20 +02:00
|
|
|
node_socket_interface_free(ntree, sock, false);
|
2020-03-06 14:57:26 +01:00
|
|
|
MEM_freeN(sock);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* free preview hash */
|
|
|
|
|
if (ntree->previews) {
|
|
|
|
|
BKE_node_instance_hash_free(ntree->previews, (bNodeInstanceValueFP)BKE_node_preview_free);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (ntree->id.tag & LIB_TAG_LOCALIZED) {
|
|
|
|
|
BKE_libblock_free_data(&ntree->id, true);
|
|
|
|
|
}
|
2021-11-06 16:43:26 +01:00
|
|
|
|
|
|
|
|
BKE_previewimg_free(&ntree->preview);
|
2022-05-30 12:54:07 +02:00
|
|
|
MEM_delete(ntree->runtime);
|
2020-03-06 14:57:26 +01:00
|
|
|
}
|
|
|
|
|
|
2020-05-07 16:54:32 +02:00
|
|
|
static void library_foreach_node_socket(LibraryForeachIDData *data, bNodeSocket *sock)
|
|
|
|
|
{
|
2021-10-27 11:30:43 +02:00
|
|
|
BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL(
|
|
|
|
|
data,
|
|
|
|
|
IDP_foreach_property(
|
|
|
|
|
sock->prop, IDP_TYPE_FILTER_ID, BKE_lib_query_idpropertiesForeachIDLink_callback, data));
|
2020-05-07 16:54:32 +02:00
|
|
|
|
|
|
|
|
switch ((eNodeSocketDatatype)sock->type) {
|
|
|
|
|
case SOCK_OBJECT: {
|
2021-02-02 09:51:38 -06:00
|
|
|
bNodeSocketValueObject *default_value = (bNodeSocketValueObject *)sock->default_value;
|
2021-10-26 10:40:36 +02:00
|
|
|
BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, default_value->value, IDWALK_CB_USER);
|
2020-05-07 16:54:32 +02:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case SOCK_IMAGE: {
|
2021-02-02 09:51:38 -06:00
|
|
|
bNodeSocketValueImage *default_value = (bNodeSocketValueImage *)sock->default_value;
|
2021-10-26 10:40:36 +02:00
|
|
|
BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, default_value->value, IDWALK_CB_USER);
|
2020-05-07 16:54:32 +02:00
|
|
|
break;
|
|
|
|
|
}
|
2020-12-11 17:32:08 +01:00
|
|
|
case SOCK_COLLECTION: {
|
2021-02-02 09:51:38 -06:00
|
|
|
bNodeSocketValueCollection *default_value = (bNodeSocketValueCollection *)
|
|
|
|
|
sock->default_value;
|
2021-10-26 10:40:36 +02:00
|
|
|
BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, default_value->value, IDWALK_CB_USER);
|
2020-12-11 17:32:08 +01:00
|
|
|
break;
|
|
|
|
|
}
|
2021-05-12 12:41:21 +02:00
|
|
|
case SOCK_TEXTURE: {
|
|
|
|
|
bNodeSocketValueTexture *default_value = (bNodeSocketValueTexture *)sock->default_value;
|
2021-10-26 10:40:36 +02:00
|
|
|
BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, default_value->value, IDWALK_CB_USER);
|
2021-05-12 12:41:21 +02:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case SOCK_MATERIAL: {
|
|
|
|
|
bNodeSocketValueMaterial *default_value = (bNodeSocketValueMaterial *)sock->default_value;
|
2021-10-26 10:40:36 +02:00
|
|
|
BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, default_value->value, IDWALK_CB_USER);
|
2021-05-12 12:41:21 +02:00
|
|
|
break;
|
|
|
|
|
}
|
2020-05-07 16:54:32 +02:00
|
|
|
case SOCK_FLOAT:
|
|
|
|
|
case SOCK_VECTOR:
|
|
|
|
|
case SOCK_RGBA:
|
|
|
|
|
case SOCK_BOOLEAN:
|
|
|
|
|
case SOCK_INT:
|
|
|
|
|
case SOCK_STRING:
|
|
|
|
|
case __SOCK_MESH:
|
|
|
|
|
case SOCK_CUSTOM:
|
|
|
|
|
case SOCK_SHADER:
|
2020-10-20 15:31:59 +02:00
|
|
|
case SOCK_GEOMETRY:
|
2020-05-07 16:54:32 +02:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void node_foreach_id(ID *id, LibraryForeachIDData *data)
|
|
|
|
|
{
|
|
|
|
|
bNodeTree *ntree = (bNodeTree *)id;
|
|
|
|
|
|
2022-09-05 15:46:00 +02:00
|
|
|
BKE_LIB_FOREACHID_PROCESS_ID(data, ntree->owner_id, IDWALK_CB_LOOPBACK);
|
|
|
|
|
|
2021-10-26 10:40:36 +02:00
|
|
|
BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, ntree->gpd, IDWALK_CB_USER);
|
2020-05-07 16:54:32 +02:00
|
|
|
|
|
|
|
|
LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
|
|
|
|
|
BKE_LIB_FOREACHID_PROCESS_ID(data, node->id, IDWALK_CB_USER);
|
|
|
|
|
|
2021-10-27 11:30:43 +02:00
|
|
|
BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL(
|
|
|
|
|
data,
|
|
|
|
|
IDP_foreach_property(node->prop,
|
|
|
|
|
IDP_TYPE_FILTER_ID,
|
|
|
|
|
BKE_lib_query_idpropertiesForeachIDLink_callback,
|
|
|
|
|
data));
|
2020-05-07 16:54:32 +02:00
|
|
|
LISTBASE_FOREACH (bNodeSocket *, sock, &node->inputs) {
|
2021-10-27 11:30:43 +02:00
|
|
|
BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL(data, library_foreach_node_socket(data, sock));
|
2020-05-07 16:54:32 +02:00
|
|
|
}
|
|
|
|
|
LISTBASE_FOREACH (bNodeSocket *, sock, &node->outputs) {
|
2021-10-27 11:30:43 +02:00
|
|
|
BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL(data, library_foreach_node_socket(data, sock));
|
2020-05-07 16:54:32 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
LISTBASE_FOREACH (bNodeSocket *, sock, &ntree->inputs) {
|
2021-10-27 11:30:43 +02:00
|
|
|
BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL(data, library_foreach_node_socket(data, sock));
|
2020-05-07 16:54:32 +02:00
|
|
|
}
|
|
|
|
|
LISTBASE_FOREACH (bNodeSocket *, sock, &ntree->outputs) {
|
2021-10-27 11:30:43 +02:00
|
|
|
BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL(data, library_foreach_node_socket(data, sock));
|
2020-05-07 16:54:32 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-07-06 16:21:41 +02:00
|
|
|
static void node_foreach_cache(ID *id,
|
|
|
|
|
IDTypeForeachCacheFunctionCallback function_callback,
|
|
|
|
|
void *user_data)
|
|
|
|
|
{
|
|
|
|
|
bNodeTree *nodetree = (bNodeTree *)id;
|
2021-02-02 11:26:17 -06:00
|
|
|
IDCacheKey key = {0};
|
|
|
|
|
key.id_session_uuid = id->session_uuid;
|
|
|
|
|
key.offset_in_ID = offsetof(bNodeTree, previews);
|
2020-07-06 16:21:41 +02:00
|
|
|
|
2021-07-03 23:08:40 +10:00
|
|
|
/* TODO: see also `direct_link_nodetree()` in readfile.c. */
|
2020-07-06 16:21:41 +02:00
|
|
|
#if 0
|
|
|
|
|
function_callback(id, &key, (void **)&nodetree->previews, 0, user_data);
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
if (nodetree->type == NTREE_COMPOSIT) {
|
2020-08-31 13:59:33 +02:00
|
|
|
LISTBASE_FOREACH (bNode *, node, &nodetree->nodes) {
|
2020-07-06 16:21:41 +02:00
|
|
|
if (node->type == CMP_NODE_MOVIEDISTORTION) {
|
|
|
|
|
key.offset_in_ID = (size_t)BLI_ghashutil_strhash_p(node->name);
|
|
|
|
|
function_callback(id, &key, (void **)&node->storage, 0, user_data);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
Refactor BKE_bpath module.
The main goal of this refactor is to make BPath module use `IDTypeInfo`,
and move each ID-specific part of the `foreach_path` looper into their
own IDTypeInfo struct, using a new `foreach_path` callback.
Additionally, following improvements/cleanups are included:
* Attempt to get better, more consistent namings.
** In particular, move from `path_visitor` to more standard `foreach_path`.
* Update and extend documentation.
** API doc was moved to header, according to recent discussions on this
topic.
* Remove `BKE_bpath_relocate_visitor` from API, this is specific
callback that belongs in `lib_id.c` user code.
NOTE: This commit is expected to be 100% non-behavioral-change. This
implies that several potential further changes were only noted as
comments (like using a more generic solution for
`lib_id_library_local_paths`, addressing inconsistencies like path of
packed libraries always being skipped, regardless of the
`BKE_BPATH_FOREACH_PATH_SKIP_PACKED` `eBPathForeachFlag` flag value,
etc.).
NOTE: basic unittests were added to master already in
rBdcc500e5a265093bc9cc.
Reviewed By: brecht
Differential Revision: https://developer.blender.org/D13381
2021-11-29 14:20:58 +01:00
|
|
|
static void node_foreach_path(ID *id, BPathForeachPathData *bpath_data)
|
|
|
|
|
{
|
|
|
|
|
bNodeTree *ntree = reinterpret_cast<bNodeTree *>(id);
|
|
|
|
|
|
|
|
|
|
switch (ntree->type) {
|
|
|
|
|
case NTREE_SHADER: {
|
|
|
|
|
LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
|
|
|
|
|
if (node->type == SH_NODE_SCRIPT) {
|
|
|
|
|
NodeShaderScript *nss = reinterpret_cast<NodeShaderScript *>(node->storage);
|
|
|
|
|
BKE_bpath_foreach_path_fixed_process(bpath_data, nss->filepath);
|
|
|
|
|
}
|
|
|
|
|
else if (node->type == SH_NODE_TEX_IES) {
|
|
|
|
|
NodeShaderTexIES *ies = reinterpret_cast<NodeShaderTexIES *>(node->storage);
|
|
|
|
|
BKE_bpath_foreach_path_fixed_process(bpath_data, ies->filepath);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-09-08 16:32:35 +02:00
|
|
|
static ID **node_owner_pointer_get(ID *id)
|
2021-02-25 10:17:31 +01:00
|
|
|
{
|
|
|
|
|
if ((id->flag & LIB_EMBEDDED_DATA) == 0) {
|
2022-09-08 16:32:35 +02:00
|
|
|
return NULL;
|
2021-02-25 10:17:31 +01:00
|
|
|
}
|
2021-03-01 10:59:07 +01:00
|
|
|
/* TODO: Sort this NO_MAIN or not for embedded node trees. See T86119. */
|
|
|
|
|
// BLI_assert((id->tag & LIB_TAG_NO_MAIN) == 0);
|
2021-02-25 10:17:31 +01:00
|
|
|
|
2022-08-12 10:39:03 +02:00
|
|
|
bNodeTree *ntree = reinterpret_cast<bNodeTree *>(id);
|
2022-09-05 15:46:00 +02:00
|
|
|
BLI_assert(ntree->owner_id != NULL);
|
|
|
|
|
BLI_assert(ntreeFromID(ntree->owner_id) == ntree);
|
2022-08-12 10:39:03 +02:00
|
|
|
|
2022-09-08 16:32:35 +02:00
|
|
|
return &ntree->owner_id;
|
2021-02-25 10:17:31 +01:00
|
|
|
}
|
|
|
|
|
|
2020-09-10 13:33:29 +02:00
|
|
|
static void write_node_socket_default_value(BlendWriter *writer, bNodeSocket *sock)
|
|
|
|
|
{
|
2021-02-02 09:51:38 -06:00
|
|
|
if (sock->default_value == nullptr) {
|
2020-09-10 13:33:29 +02:00
|
|
|
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;
|
2020-12-11 17:32:08 +01:00
|
|
|
case SOCK_COLLECTION:
|
|
|
|
|
BLO_write_struct(writer, bNodeSocketValueCollection, sock->default_value);
|
|
|
|
|
break;
|
2021-05-12 12:41:21 +02:00
|
|
|
case SOCK_TEXTURE:
|
|
|
|
|
BLO_write_struct(writer, bNodeSocketValueTexture, sock->default_value);
|
|
|
|
|
break;
|
|
|
|
|
case SOCK_MATERIAL:
|
|
|
|
|
BLO_write_struct(writer, bNodeSocketValueMaterial, sock->default_value);
|
|
|
|
|
break;
|
2020-09-10 13:33:29 +02:00
|
|
|
case SOCK_CUSTOM:
|
2021-11-15 08:07:11 +01:00
|
|
|
/* Custom node sockets where default_value is defined uses custom properties for storage. */
|
|
|
|
|
break;
|
|
|
|
|
case __SOCK_MESH:
|
2020-09-10 13:33:29 +02:00
|
|
|
case SOCK_SHADER:
|
2020-10-20 15:31:59 +02:00
|
|
|
case SOCK_GEOMETRY:
|
2021-03-23 16:49:47 +01:00
|
|
|
BLI_assert_unreachable();
|
2020-09-10 13:33:29 +02:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void write_node_socket(BlendWriter *writer, bNodeSocket *sock)
|
|
|
|
|
{
|
|
|
|
|
BLO_write_struct(writer, bNodeSocket, sock);
|
|
|
|
|
|
|
|
|
|
if (sock->prop) {
|
|
|
|
|
IDP_BlendWrite(writer, sock->prop);
|
|
|
|
|
}
|
|
|
|
|
|
2022-04-28 08:39:30 -05:00
|
|
|
/* This property should only be used for group node "interface" sockets. */
|
|
|
|
|
BLI_assert(sock->default_attribute_name == nullptr);
|
|
|
|
|
|
2020-09-10 13:33:29 +02:00
|
|
|
write_node_socket_default_value(writer, sock);
|
|
|
|
|
}
|
|
|
|
|
static void write_node_socket_interface(BlendWriter *writer, bNodeSocket *sock)
|
|
|
|
|
{
|
|
|
|
|
BLO_write_struct(writer, bNodeSocket, sock);
|
|
|
|
|
|
|
|
|
|
if (sock->prop) {
|
|
|
|
|
IDP_BlendWrite(writer, sock->prop);
|
|
|
|
|
}
|
|
|
|
|
|
2022-04-28 08:39:30 -05:00
|
|
|
BLO_write_string(writer, sock->default_attribute_name);
|
|
|
|
|
|
2020-09-10 13:33:29 +02:00
|
|
|
write_node_socket_default_value(writer, sock);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ntreeBlendWrite(BlendWriter *writer, bNodeTree *ntree)
|
|
|
|
|
{
|
2020-11-04 18:14:27 +01:00
|
|
|
BKE_id_blend_write(writer, &ntree->id);
|
|
|
|
|
|
2020-09-10 13:33:29 +02:00
|
|
|
if (ntree->adt) {
|
|
|
|
|
BKE_animdata_blend_write(writer, ntree->adt);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
|
|
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
LISTBASE_FOREACH (bNodeLink *, link, &node->internal_links) {
|
|
|
|
|
BLO_write_struct(writer, bNodeLink, link);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (node->storage) {
|
2021-07-16 11:45:52 +10:00
|
|
|
if (ELEM(ntree->type, NTREE_SHADER, NTREE_GEOMETRY) &&
|
2021-09-30 19:05:08 +01:00
|
|
|
ELEM(node->type, SH_NODE_CURVE_VEC, SH_NODE_CURVE_RGB, SH_NODE_CURVE_FLOAT)) {
|
2021-02-02 09:51:38 -06:00
|
|
|
BKE_curvemapping_blend_write(writer, (const CurveMapping *)node->storage);
|
2020-09-10 13:33:29 +02:00
|
|
|
}
|
|
|
|
|
else if (ntree->type == NTREE_SHADER && (node->type == SH_NODE_SCRIPT)) {
|
|
|
|
|
NodeShaderScript *nss = (NodeShaderScript *)node->storage;
|
|
|
|
|
if (nss->bytecode) {
|
|
|
|
|
BLO_write_string(writer, nss->bytecode);
|
|
|
|
|
}
|
|
|
|
|
BLO_write_struct_by_name(writer, node->typeinfo->storagename, node->storage);
|
|
|
|
|
}
|
|
|
|
|
else if ((ntree->type == NTREE_COMPOSIT) && ELEM(node->type,
|
|
|
|
|
CMP_NODE_TIME,
|
|
|
|
|
CMP_NODE_CURVE_VEC,
|
|
|
|
|
CMP_NODE_CURVE_RGB,
|
|
|
|
|
CMP_NODE_HUECORRECT)) {
|
2021-02-02 09:51:38 -06:00
|
|
|
BKE_curvemapping_blend_write(writer, (const CurveMapping *)node->storage);
|
2020-09-10 13:33:29 +02:00
|
|
|
}
|
|
|
|
|
else if ((ntree->type == NTREE_TEXTURE) &&
|
2022-03-09 09:35:37 +11:00
|
|
|
ELEM(node->type, TEX_NODE_CURVE_RGB, TEX_NODE_CURVE_TIME)) {
|
2021-02-02 09:51:38 -06:00
|
|
|
BKE_curvemapping_blend_write(writer, (const CurveMapping *)node->storage);
|
2020-09-10 13:33:29 +02:00
|
|
|
}
|
|
|
|
|
else if ((ntree->type == NTREE_COMPOSIT) && (node->type == CMP_NODE_MOVIEDISTORTION)) {
|
|
|
|
|
/* pass */
|
|
|
|
|
}
|
|
|
|
|
else if ((ntree->type == NTREE_COMPOSIT) && (node->type == CMP_NODE_GLARE)) {
|
|
|
|
|
/* Simple forward compatibility for fix for T50736.
|
|
|
|
|
* Not ideal (there is no ideal solution here), but should do for now. */
|
2021-02-02 09:51:38 -06:00
|
|
|
NodeGlare *ndg = (NodeGlare *)node->storage;
|
2020-09-10 13:33:29 +02:00
|
|
|
/* Not in undo case. */
|
|
|
|
|
if (!BLO_write_is_undo(writer)) {
|
|
|
|
|
switch (ndg->type) {
|
|
|
|
|
case 2: /* Grrrr! magic numbers :( */
|
|
|
|
|
ndg->angle = ndg->streaks;
|
|
|
|
|
break;
|
|
|
|
|
case 0:
|
|
|
|
|
ndg->angle = ndg->star_45;
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
BLO_write_struct_by_name(writer, node->typeinfo->storagename, node->storage);
|
|
|
|
|
}
|
Compositor: Redesign Cryptomatte node for better usability
In the current implementation, cryptomatte passes are connected to the node
and elements are picked by using the eyedropper tool on a special pick channel.
This design has two disadvantages - both connecting all passes individually
and always having to switch to the picker channel are tedious.
With the new design, the user selects the RenderLayer or Image from which the
Cryptomatte layers are directly loaded (the type of pass is determined by an
enum). This allows the node to automatically detect all relevant passes.
Then, when using the eyedropper tool, the operator looks up the selected
coordinates from the picked Image, Node backdrop or Clip and reads the picked
object directly from the Renderlayer/Image, therefore allowing to pick in any
context (e.g. by clicking on the Combined pass in the Image Viewer). The
sampled color is looked up in the metadata and the actual name is stored
in the cryptomatte node. This also allows to remove a hash by just removing
the name from the matte id.
Technically there is some loss of flexibility because the Cryptomatte pass
inputs can no longer be connected to other nodes, but since any compositing
done on them is likely to break the Cryptomatte system anyways, this isn't
really a concern in practise.
In the future, this would also allow to automatically translate values to names
by looking up the value in the associated metadata of the input, or to get a
better visualization of overlapping areas in the Pick output since we could
blend colors now that the output doesn't have to contain the exact value.
Idea + Original patch: Lucas Stockner
Reviewed By: Brecht van Lommel
Differential Revision: https://developer.blender.org/D3959
2021-03-16 07:37:30 +01:00
|
|
|
else if ((ntree->type == NTREE_COMPOSIT) &&
|
2022-03-09 09:35:37 +11:00
|
|
|
ELEM(node->type, CMP_NODE_CRYPTOMATTE, CMP_NODE_CRYPTOMATTE_LEGACY)) {
|
2020-09-10 13:33:29 +02:00
|
|
|
NodeCryptomatte *nc = (NodeCryptomatte *)node->storage;
|
2021-03-08 08:47:22 +01:00
|
|
|
BLO_write_string(writer, nc->matte_id);
|
2020-12-15 11:15:01 +01:00
|
|
|
LISTBASE_FOREACH (CryptomatteEntry *, entry, &nc->entries) {
|
|
|
|
|
BLO_write_struct(writer, CryptomatteEntry, entry);
|
|
|
|
|
}
|
2020-09-10 13:33:29 +02:00
|
|
|
BLO_write_struct_by_name(writer, node->typeinfo->storagename, node->storage);
|
|
|
|
|
}
|
2021-02-19 16:03:14 -06:00
|
|
|
else if (node->type == FN_NODE_INPUT_STRING) {
|
|
|
|
|
NodeInputString *storage = (NodeInputString *)node->storage;
|
|
|
|
|
if (storage->string) {
|
|
|
|
|
BLO_write_string(writer, storage->string);
|
|
|
|
|
}
|
|
|
|
|
BLO_write_struct_by_name(writer, node->typeinfo->storagename, storage);
|
|
|
|
|
}
|
2020-09-10 13:33:29 +02:00
|
|
|
else if (node->typeinfo != &NodeTypeUndefined) {
|
|
|
|
|
BLO_write_struct_by_name(writer, node->typeinfo->storagename, node->storage);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (node->type == CMP_NODE_OUTPUT_FILE) {
|
2021-12-20 10:48:01 -06:00
|
|
|
/* Inputs have their own storage data. */
|
2022-03-11 17:50:57 +01:00
|
|
|
NodeImageMultiFile *nimf = (NodeImageMultiFile *)node->storage;
|
|
|
|
|
BKE_image_format_blend_write(writer, &nimf->format);
|
|
|
|
|
|
2020-09-10 13:33:29 +02:00
|
|
|
LISTBASE_FOREACH (bNodeSocket *, sock, &node->inputs) {
|
2022-03-11 17:50:57 +01:00
|
|
|
NodeImageMultiFileSocket *sockdata = (NodeImageMultiFileSocket *)sock->storage;
|
|
|
|
|
BLO_write_struct(writer, NodeImageMultiFileSocket, sockdata);
|
|
|
|
|
BKE_image_format_blend_write(writer, &sockdata->format);
|
2020-09-10 13:33:29 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (ELEM(node->type, CMP_NODE_IMAGE, CMP_NODE_R_LAYERS)) {
|
2021-12-20 10:48:01 -06:00
|
|
|
/* Write extra socket info. */
|
2020-09-10 13:33:29 +02:00
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
LISTBASE_FOREACH (bNodeSocket *, sock, &ntree->inputs) {
|
|
|
|
|
write_node_socket_interface(writer, sock);
|
|
|
|
|
}
|
|
|
|
|
LISTBASE_FOREACH (bNodeSocket *, sock, &ntree->outputs) {
|
|
|
|
|
write_node_socket_interface(writer, sock);
|
|
|
|
|
}
|
2021-11-06 16:43:26 +01:00
|
|
|
|
|
|
|
|
BKE_previewimg_blend_write(writer, ntree->preview);
|
2020-09-10 13:33:29 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void ntree_blend_write(BlendWriter *writer, ID *id, const void *id_address)
|
|
|
|
|
{
|
|
|
|
|
bNodeTree *ntree = (bNodeTree *)id;
|
2021-08-19 11:13:55 +02:00
|
|
|
|
|
|
|
|
/* Clean up, important in undo case to reduce false detection of changed datablocks. */
|
|
|
|
|
ntree->is_updating = false;
|
|
|
|
|
ntree->typeinfo = nullptr;
|
|
|
|
|
ntree->interface_type = nullptr;
|
|
|
|
|
ntree->progress = nullptr;
|
|
|
|
|
ntree->execdata = nullptr;
|
|
|
|
|
|
|
|
|
|
BLO_write_id_struct(writer, bNodeTree, id_address, &ntree->id);
|
|
|
|
|
|
|
|
|
|
ntreeBlendWrite(writer, ntree);
|
2020-09-10 13:33:29 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void direct_link_node_socket(BlendDataReader *reader, bNodeSocket *sock)
|
|
|
|
|
{
|
|
|
|
|
BLO_read_data_address(reader, &sock->prop);
|
|
|
|
|
IDP_BlendDataRead(reader, &sock->prop);
|
|
|
|
|
|
|
|
|
|
BLO_read_data_address(reader, &sock->link);
|
2021-02-02 09:51:38 -06:00
|
|
|
sock->typeinfo = nullptr;
|
2020-09-10 13:33:29 +02:00
|
|
|
BLO_read_data_address(reader, &sock->storage);
|
|
|
|
|
BLO_read_data_address(reader, &sock->default_value);
|
2022-04-28 08:39:30 -05:00
|
|
|
BLO_read_data_address(reader, &sock->default_attribute_name);
|
2021-02-11 01:16:17 -06:00
|
|
|
sock->total_inputs = 0; /* Clear runtime data set before drawing. */
|
2021-02-02 09:51:38 -06:00
|
|
|
sock->cache = nullptr;
|
2022-05-30 15:31:13 +02:00
|
|
|
sock->runtime = MEM_new<bNodeSocketRuntime>(__func__);
|
2020-09-10 13:33:29 +02:00
|
|
|
}
|
|
|
|
|
|
2022-09-05 15:46:00 +02:00
|
|
|
void ntreeBlendReadData(BlendDataReader *reader, ID *owner_id, bNodeTree *ntree)
|
2020-09-10 13:33:29 +02:00
|
|
|
{
|
2022-09-05 15:46:00 +02:00
|
|
|
/* 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. */
|
|
|
|
|
BLI_assert((ntree->id.flag & LIB_EMBEDDED_DATA) != 0 || owner_id == nullptr);
|
2022-09-07 11:24:13 +02:00
|
|
|
BLI_assert(owner_id == NULL || owner_id->lib == ntree->id.lib);
|
2022-09-06 17:22:10 +02:00
|
|
|
if (owner_id != nullptr && (ntree->id.flag & LIB_EMBEDDED_DATA) == 0) {
|
|
|
|
|
/* This is unfortunate, but currently a lot of existing files (including startup ones) have
|
|
|
|
|
* missing `LIB_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
|
2022-09-07 12:52:05 +10:00
|
|
|
* bugs won't go easily unnoticed. */
|
2022-09-06 17:22:10 +02:00
|
|
|
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 |= LIB_EMBEDDED_DATA;
|
|
|
|
|
}
|
2022-09-05 15:46:00 +02:00
|
|
|
ntree->owner_id = owner_id;
|
|
|
|
|
|
2021-07-03 23:08:40 +10:00
|
|
|
/* NOTE: writing and reading goes in sync, for speed. */
|
2020-09-10 13:33:29 +02:00
|
|
|
ntree->is_updating = false;
|
2021-02-02 09:51:38 -06:00
|
|
|
ntree->typeinfo = nullptr;
|
|
|
|
|
ntree->interface_type = nullptr;
|
2020-09-10 13:33:29 +02:00
|
|
|
|
2021-02-02 09:51:38 -06:00
|
|
|
ntree->progress = nullptr;
|
|
|
|
|
ntree->execdata = nullptr;
|
2022-05-30 12:54:07 +02:00
|
|
|
ntree->runtime = MEM_new<bNodeTreeRuntime>(__func__);
|
2021-12-21 15:18:56 +01:00
|
|
|
BKE_ntree_update_tag_missing_runtime_data(ntree);
|
2021-09-23 15:21:31 -05:00
|
|
|
|
2020-09-10 13:33:29 +02:00
|
|
|
BLO_read_data_address(reader, &ntree->adt);
|
|
|
|
|
BKE_animdata_blend_read_data(reader, ntree->adt);
|
|
|
|
|
|
|
|
|
|
BLO_read_list(reader, &ntree->nodes);
|
|
|
|
|
LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
|
2022-05-30 15:31:13 +02:00
|
|
|
node->runtime = MEM_new<bNodeRuntime>(__func__);
|
2021-02-02 09:51:38 -06:00
|
|
|
node->typeinfo = nullptr;
|
2020-09-10 13:33:29 +02:00
|
|
|
|
|
|
|
|
BLO_read_list(reader, &node->inputs);
|
|
|
|
|
BLO_read_list(reader, &node->outputs);
|
|
|
|
|
|
|
|
|
|
BLO_read_data_address(reader, &node->prop);
|
|
|
|
|
IDP_BlendDataRead(reader, &node->prop);
|
|
|
|
|
|
|
|
|
|
BLO_read_list(reader, &node->internal_links);
|
|
|
|
|
LISTBASE_FOREACH (bNodeLink *, link, &node->internal_links) {
|
|
|
|
|
BLO_read_data_address(reader, &link->fromnode);
|
|
|
|
|
BLO_read_data_address(reader, &link->fromsock);
|
|
|
|
|
BLO_read_data_address(reader, &link->tonode);
|
|
|
|
|
BLO_read_data_address(reader, &link->tosock);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (node->type == CMP_NODE_MOVIEDISTORTION) {
|
|
|
|
|
/* Do nothing, this is runtime cache and hence handled by generic code using
|
|
|
|
|
* `IDTypeInfo.foreach_cache` callback. */
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
BLO_read_data_address(reader, &node->storage);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (node->storage) {
|
|
|
|
|
switch (node->type) {
|
|
|
|
|
case SH_NODE_CURVE_VEC:
|
|
|
|
|
case SH_NODE_CURVE_RGB:
|
2021-09-30 19:05:08 +01:00
|
|
|
case SH_NODE_CURVE_FLOAT:
|
2020-09-10 13:33:29 +02:00
|
|
|
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: {
|
2021-02-02 09:51:38 -06:00
|
|
|
BKE_curvemapping_blend_read(reader, (CurveMapping *)node->storage);
|
2020-09-10 13:33:29 +02:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case SH_NODE_SCRIPT: {
|
|
|
|
|
NodeShaderScript *nss = (NodeShaderScript *)node->storage;
|
|
|
|
|
BLO_read_data_address(reader, &nss->bytecode);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case SH_NODE_TEX_POINTDENSITY: {
|
|
|
|
|
NodeShaderTexPointDensity *npd = (NodeShaderTexPointDensity *)node->storage;
|
2022-04-12 10:56:51 +02:00
|
|
|
npd->pd = blender::dna::shallow_zero_initialize();
|
2020-09-10 13:33:29 +02:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case SH_NODE_TEX_IMAGE: {
|
|
|
|
|
NodeTexImage *tex = (NodeTexImage *)node->storage;
|
2021-02-02 09:51:38 -06:00
|
|
|
tex->iuser.scene = nullptr;
|
2020-09-10 13:33:29 +02:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case SH_NODE_TEX_ENVIRONMENT: {
|
|
|
|
|
NodeTexEnvironment *tex = (NodeTexEnvironment *)node->storage;
|
2021-02-02 09:51:38 -06:00
|
|
|
tex->iuser.scene = nullptr;
|
2020-09-10 13:33:29 +02:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case CMP_NODE_IMAGE:
|
|
|
|
|
case CMP_NODE_R_LAYERS:
|
|
|
|
|
case CMP_NODE_VIEWER:
|
|
|
|
|
case CMP_NODE_SPLITVIEWER: {
|
2021-02-02 09:51:38 -06:00
|
|
|
ImageUser *iuser = (ImageUser *)node->storage;
|
|
|
|
|
iuser->scene = nullptr;
|
2020-09-10 13:33:29 +02:00
|
|
|
break;
|
|
|
|
|
}
|
Compositor: Redesign Cryptomatte node for better usability
In the current implementation, cryptomatte passes are connected to the node
and elements are picked by using the eyedropper tool on a special pick channel.
This design has two disadvantages - both connecting all passes individually
and always having to switch to the picker channel are tedious.
With the new design, the user selects the RenderLayer or Image from which the
Cryptomatte layers are directly loaded (the type of pass is determined by an
enum). This allows the node to automatically detect all relevant passes.
Then, when using the eyedropper tool, the operator looks up the selected
coordinates from the picked Image, Node backdrop or Clip and reads the picked
object directly from the Renderlayer/Image, therefore allowing to pick in any
context (e.g. by clicking on the Combined pass in the Image Viewer). The
sampled color is looked up in the metadata and the actual name is stored
in the cryptomatte node. This also allows to remove a hash by just removing
the name from the matte id.
Technically there is some loss of flexibility because the Cryptomatte pass
inputs can no longer be connected to other nodes, but since any compositing
done on them is likely to break the Cryptomatte system anyways, this isn't
really a concern in practise.
In the future, this would also allow to automatically translate values to names
by looking up the value in the associated metadata of the input, or to get a
better visualization of overlapping areas in the Pick output since we could
blend colors now that the output doesn't have to contain the exact value.
Idea + Original patch: Lucas Stockner
Reviewed By: Brecht van Lommel
Differential Revision: https://developer.blender.org/D3959
2021-03-16 07:37:30 +01:00
|
|
|
case CMP_NODE_CRYPTOMATTE_LEGACY:
|
2020-09-10 13:33:29 +02:00
|
|
|
case CMP_NODE_CRYPTOMATTE: {
|
|
|
|
|
NodeCryptomatte *nc = (NodeCryptomatte *)node->storage;
|
|
|
|
|
BLO_read_data_address(reader, &nc->matte_id);
|
2020-12-15 11:15:01 +01:00
|
|
|
BLO_read_list(reader, &nc->entries);
|
Compositor: Redesign Cryptomatte node for better usability
In the current implementation, cryptomatte passes are connected to the node
and elements are picked by using the eyedropper tool on a special pick channel.
This design has two disadvantages - both connecting all passes individually
and always having to switch to the picker channel are tedious.
With the new design, the user selects the RenderLayer or Image from which the
Cryptomatte layers are directly loaded (the type of pass is determined by an
enum). This allows the node to automatically detect all relevant passes.
Then, when using the eyedropper tool, the operator looks up the selected
coordinates from the picked Image, Node backdrop or Clip and reads the picked
object directly from the Renderlayer/Image, therefore allowing to pick in any
context (e.g. by clicking on the Combined pass in the Image Viewer). The
sampled color is looked up in the metadata and the actual name is stored
in the cryptomatte node. This also allows to remove a hash by just removing
the name from the matte id.
Technically there is some loss of flexibility because the Cryptomatte pass
inputs can no longer be connected to other nodes, but since any compositing
done on them is likely to break the Cryptomatte system anyways, this isn't
really a concern in practise.
In the future, this would also allow to automatically translate values to names
by looking up the value in the associated metadata of the input, or to get a
better visualization of overlapping areas in the Pick output since we could
blend colors now that the output doesn't have to contain the exact value.
Idea + Original patch: Lucas Stockner
Reviewed By: Brecht van Lommel
Differential Revision: https://developer.blender.org/D3959
2021-03-16 07:37:30 +01:00
|
|
|
BLI_listbase_clear(&nc->runtime.layers);
|
2020-09-10 13:33:29 +02:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case TEX_NODE_IMAGE: {
|
2021-02-02 09:51:38 -06:00
|
|
|
ImageUser *iuser = (ImageUser *)node->storage;
|
|
|
|
|
iuser->scene = nullptr;
|
2020-09-10 13:33:29 +02:00
|
|
|
break;
|
|
|
|
|
}
|
2022-03-11 17:50:57 +01:00
|
|
|
case CMP_NODE_OUTPUT_FILE: {
|
|
|
|
|
NodeImageMultiFile *nimf = (NodeImageMultiFile *)node->storage;
|
|
|
|
|
BKE_image_format_blend_read_data(reader, &nimf->format);
|
|
|
|
|
break;
|
|
|
|
|
}
|
2021-02-19 16:03:14 -06:00
|
|
|
case FN_NODE_INPUT_STRING: {
|
|
|
|
|
NodeInputString *storage = (NodeInputString *)node->storage;
|
|
|
|
|
BLO_read_data_address(reader, &storage->string);
|
|
|
|
|
break;
|
|
|
|
|
}
|
2020-09-10 13:33:29 +02:00
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
BLO_read_list(reader, &ntree->links);
|
|
|
|
|
|
|
|
|
|
/* and we connect the rest */
|
|
|
|
|
LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
|
|
|
|
|
BLO_read_data_address(reader, &node->parent);
|
|
|
|
|
|
|
|
|
|
LISTBASE_FOREACH (bNodeSocket *, sock, &node->inputs) {
|
|
|
|
|
direct_link_node_socket(reader, sock);
|
|
|
|
|
}
|
|
|
|
|
LISTBASE_FOREACH (bNodeSocket *, sock, &node->outputs) {
|
|
|
|
|
direct_link_node_socket(reader, sock);
|
|
|
|
|
}
|
2022-03-11 17:50:57 +01:00
|
|
|
|
|
|
|
|
/* Socket storage. */
|
|
|
|
|
if (node->type == CMP_NODE_OUTPUT_FILE) {
|
|
|
|
|
LISTBASE_FOREACH (bNodeSocket *, sock, &node->inputs) {
|
|
|
|
|
NodeImageMultiFileSocket *sockdata = (NodeImageMultiFileSocket *)sock->storage;
|
|
|
|
|
BKE_image_format_blend_read_data(reader, &sockdata->format);
|
|
|
|
|
}
|
|
|
|
|
}
|
2020-09-10 13:33:29 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* interface socket lists */
|
|
|
|
|
BLO_read_list(reader, &ntree->inputs);
|
|
|
|
|
BLO_read_list(reader, &ntree->outputs);
|
|
|
|
|
LISTBASE_FOREACH (bNodeSocket *, sock, &ntree->inputs) {
|
|
|
|
|
direct_link_node_socket(reader, sock);
|
|
|
|
|
}
|
|
|
|
|
LISTBASE_FOREACH (bNodeSocket *, sock, &ntree->outputs) {
|
|
|
|
|
direct_link_node_socket(reader, sock);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
LISTBASE_FOREACH (bNodeLink *, link, &ntree->links) {
|
|
|
|
|
BLO_read_data_address(reader, &link->fromnode);
|
|
|
|
|
BLO_read_data_address(reader, &link->tonode);
|
|
|
|
|
BLO_read_data_address(reader, &link->fromsock);
|
|
|
|
|
BLO_read_data_address(reader, &link->tosock);
|
|
|
|
|
}
|
|
|
|
|
|
2021-07-03 23:08:40 +10:00
|
|
|
/* TODO: should be dealt by new generic cache handling of IDs... */
|
2021-02-02 09:51:38 -06:00
|
|
|
ntree->previews = nullptr;
|
2020-09-10 13:33:29 +02:00
|
|
|
|
2021-11-06 16:43:26 +01:00
|
|
|
BLO_read_data_address(reader, &ntree->preview);
|
|
|
|
|
BKE_previewimg_blend_read(reader, ntree->preview);
|
|
|
|
|
|
2020-09-10 13:33:29 +02:00
|
|
|
/* type verification is in lib-link */
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void ntree_blend_read_data(BlendDataReader *reader, ID *id)
|
|
|
|
|
{
|
|
|
|
|
bNodeTree *ntree = (bNodeTree *)id;
|
2022-09-05 15:46:00 +02:00
|
|
|
ntreeBlendReadData(reader, nullptr, ntree);
|
2020-09-10 13:33:29 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void lib_link_node_socket(BlendLibReader *reader, Library *lib, bNodeSocket *sock)
|
|
|
|
|
{
|
2022-07-29 12:23:39 +02:00
|
|
|
IDP_BlendReadLib(reader, lib, sock->prop);
|
2020-09-10 13:33:29 +02:00
|
|
|
|
2021-03-29 16:56:53 +02:00
|
|
|
/* This can happen for all socket types when a file is saved in an older version of Blender than
|
|
|
|
|
* it was originally created in (T86298). Some socket types still require a default value. The
|
|
|
|
|
* default value of those sockets will be created in `ntreeSetTypes`. */
|
|
|
|
|
if (sock->default_value == nullptr) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2020-09-10 13:33:29 +02:00
|
|
|
switch ((eNodeSocketDatatype)sock->type) {
|
|
|
|
|
case SOCK_OBJECT: {
|
2021-02-02 09:51:38 -06:00
|
|
|
bNodeSocketValueObject *default_value = (bNodeSocketValueObject *)sock->default_value;
|
2020-09-10 13:33:29 +02:00
|
|
|
BLO_read_id_address(reader, lib, &default_value->value);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case SOCK_IMAGE: {
|
2021-02-02 09:51:38 -06:00
|
|
|
bNodeSocketValueImage *default_value = (bNodeSocketValueImage *)sock->default_value;
|
2020-09-10 13:33:29 +02:00
|
|
|
BLO_read_id_address(reader, lib, &default_value->value);
|
|
|
|
|
break;
|
|
|
|
|
}
|
2020-12-11 17:32:08 +01:00
|
|
|
case SOCK_COLLECTION: {
|
2021-02-02 09:51:38 -06:00
|
|
|
bNodeSocketValueCollection *default_value = (bNodeSocketValueCollection *)
|
|
|
|
|
sock->default_value;
|
2020-12-11 17:32:08 +01:00
|
|
|
BLO_read_id_address(reader, lib, &default_value->value);
|
|
|
|
|
break;
|
|
|
|
|
}
|
2021-05-12 12:41:21 +02:00
|
|
|
case SOCK_TEXTURE: {
|
|
|
|
|
bNodeSocketValueTexture *default_value = (bNodeSocketValueTexture *)sock->default_value;
|
|
|
|
|
BLO_read_id_address(reader, lib, &default_value->value);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case SOCK_MATERIAL: {
|
|
|
|
|
bNodeSocketValueMaterial *default_value = (bNodeSocketValueMaterial *)sock->default_value;
|
|
|
|
|
BLO_read_id_address(reader, lib, &default_value->value);
|
|
|
|
|
break;
|
|
|
|
|
}
|
2020-09-10 13:33:29 +02:00
|
|
|
case SOCK_FLOAT:
|
|
|
|
|
case SOCK_VECTOR:
|
|
|
|
|
case SOCK_RGBA:
|
|
|
|
|
case SOCK_BOOLEAN:
|
|
|
|
|
case SOCK_INT:
|
|
|
|
|
case SOCK_STRING:
|
|
|
|
|
case __SOCK_MESH:
|
|
|
|
|
case SOCK_CUSTOM:
|
|
|
|
|
case SOCK_SHADER:
|
2020-10-20 15:31:59 +02:00
|
|
|
case SOCK_GEOMETRY:
|
2020-09-10 13:33:29 +02:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void lib_link_node_sockets(BlendLibReader *reader, Library *lib, ListBase *sockets)
|
|
|
|
|
{
|
|
|
|
|
LISTBASE_FOREACH (bNodeSocket *, sock, sockets) {
|
|
|
|
|
lib_link_node_socket(reader, lib, sock);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ntreeBlendReadLib(struct BlendLibReader *reader, struct bNodeTree *ntree)
|
|
|
|
|
{
|
|
|
|
|
Library *lib = ntree->id.lib;
|
|
|
|
|
|
|
|
|
|
BLO_read_id_address(reader, lib, &ntree->gpd);
|
|
|
|
|
|
|
|
|
|
LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
|
|
|
|
|
/* Link ID Properties -- and copy this comment EXACTLY for easy finding
|
2021-06-26 21:35:18 +10:00
|
|
|
* of library blocks that implement this. */
|
2022-07-29 12:23:39 +02:00
|
|
|
IDP_BlendReadLib(reader, lib, node->prop);
|
2020-09-10 13:33:29 +02:00
|
|
|
|
|
|
|
|
BLO_read_id_address(reader, lib, &node->id);
|
|
|
|
|
|
|
|
|
|
lib_link_node_sockets(reader, lib, &node->inputs);
|
|
|
|
|
lib_link_node_sockets(reader, lib, &node->outputs);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
lib_link_node_sockets(reader, lib, &ntree->inputs);
|
|
|
|
|
lib_link_node_sockets(reader, lib, &ntree->outputs);
|
|
|
|
|
|
2022-09-07 12:52:05 +10:00
|
|
|
/* Set `node->typeinfo` pointers. This is done in lib linking, after the
|
2020-09-10 13:33:29 +02:00
|
|
|
* first versioning that can change types still without functions that
|
2022-09-07 12:52:05 +10:00
|
|
|
* update the `typeinfo` pointers. Versioning after lib linking needs
|
2020-09-10 13:33:29 +02:00
|
|
|
* these top be valid. */
|
2021-02-02 09:51:38 -06:00
|
|
|
ntreeSetTypes(nullptr, ntree);
|
2020-09-10 13:33:29 +02:00
|
|
|
|
|
|
|
|
/* 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) {
|
2021-08-30 17:13:46 +02:00
|
|
|
node_verify_sockets(ntree, node, false);
|
2020-09-10 13:33:29 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void ntree_blend_read_lib(BlendLibReader *reader, ID *id)
|
|
|
|
|
{
|
|
|
|
|
bNodeTree *ntree = (bNodeTree *)id;
|
|
|
|
|
ntreeBlendReadLib(reader, ntree);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void expand_node_socket(BlendExpander *expander, bNodeSocket *sock)
|
|
|
|
|
{
|
|
|
|
|
IDP_BlendReadExpand(expander, sock->prop);
|
|
|
|
|
|
2021-02-02 09:51:38 -06:00
|
|
|
if (sock->default_value != nullptr) {
|
2020-09-10 13:33:29 +02:00
|
|
|
|
|
|
|
|
switch ((eNodeSocketDatatype)sock->type) {
|
|
|
|
|
case SOCK_OBJECT: {
|
2021-02-02 09:51:38 -06:00
|
|
|
bNodeSocketValueObject *default_value = (bNodeSocketValueObject *)sock->default_value;
|
2020-09-10 13:33:29 +02:00
|
|
|
BLO_expand(expander, default_value->value);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case SOCK_IMAGE: {
|
2021-02-02 09:51:38 -06:00
|
|
|
bNodeSocketValueImage *default_value = (bNodeSocketValueImage *)sock->default_value;
|
2020-09-10 13:33:29 +02:00
|
|
|
BLO_expand(expander, default_value->value);
|
|
|
|
|
break;
|
|
|
|
|
}
|
2020-12-11 17:32:08 +01:00
|
|
|
case SOCK_COLLECTION: {
|
2021-02-02 09:51:38 -06:00
|
|
|
bNodeSocketValueCollection *default_value = (bNodeSocketValueCollection *)
|
|
|
|
|
sock->default_value;
|
2020-12-11 17:32:08 +01:00
|
|
|
BLO_expand(expander, default_value->value);
|
|
|
|
|
break;
|
|
|
|
|
}
|
2021-05-12 12:41:21 +02:00
|
|
|
case SOCK_TEXTURE: {
|
|
|
|
|
bNodeSocketValueTexture *default_value = (bNodeSocketValueTexture *)sock->default_value;
|
|
|
|
|
BLO_expand(expander, default_value->value);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case SOCK_MATERIAL: {
|
|
|
|
|
bNodeSocketValueMaterial *default_value = (bNodeSocketValueMaterial *)sock->default_value;
|
|
|
|
|
BLO_expand(expander, default_value->value);
|
|
|
|
|
break;
|
|
|
|
|
}
|
2020-09-10 13:33:29 +02:00
|
|
|
case SOCK_FLOAT:
|
|
|
|
|
case SOCK_VECTOR:
|
|
|
|
|
case SOCK_RGBA:
|
|
|
|
|
case SOCK_BOOLEAN:
|
|
|
|
|
case SOCK_INT:
|
|
|
|
|
case SOCK_STRING:
|
|
|
|
|
case __SOCK_MESH:
|
|
|
|
|
case SOCK_CUSTOM:
|
|
|
|
|
case SOCK_SHADER:
|
2020-10-20 15:31:59 +02:00
|
|
|
case SOCK_GEOMETRY:
|
2020-09-10 13:33:29 +02:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void expand_node_sockets(BlendExpander *expander, ListBase *sockets)
|
|
|
|
|
{
|
|
|
|
|
LISTBASE_FOREACH (bNodeSocket *, sock, sockets) {
|
|
|
|
|
expand_node_socket(expander, sock);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ntreeBlendReadExpand(BlendExpander *expander, bNodeTree *ntree)
|
|
|
|
|
{
|
|
|
|
|
if (ntree->gpd) {
|
|
|
|
|
BLO_expand(expander, ntree->gpd);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
|
Compositor: Redesign Cryptomatte node for better usability
In the current implementation, cryptomatte passes are connected to the node
and elements are picked by using the eyedropper tool on a special pick channel.
This design has two disadvantages - both connecting all passes individually
and always having to switch to the picker channel are tedious.
With the new design, the user selects the RenderLayer or Image from which the
Cryptomatte layers are directly loaded (the type of pass is determined by an
enum). This allows the node to automatically detect all relevant passes.
Then, when using the eyedropper tool, the operator looks up the selected
coordinates from the picked Image, Node backdrop or Clip and reads the picked
object directly from the Renderlayer/Image, therefore allowing to pick in any
context (e.g. by clicking on the Combined pass in the Image Viewer). The
sampled color is looked up in the metadata and the actual name is stored
in the cryptomatte node. This also allows to remove a hash by just removing
the name from the matte id.
Technically there is some loss of flexibility because the Cryptomatte pass
inputs can no longer be connected to other nodes, but since any compositing
done on them is likely to break the Cryptomatte system anyways, this isn't
really a concern in practise.
In the future, this would also allow to automatically translate values to names
by looking up the value in the associated metadata of the input, or to get a
better visualization of overlapping areas in the Pick output since we could
blend colors now that the output doesn't have to contain the exact value.
Idea + Original patch: Lucas Stockner
Reviewed By: Brecht van Lommel
Differential Revision: https://developer.blender.org/D3959
2021-03-16 07:37:30 +01:00
|
|
|
if (node->id && !(node->type == CMP_NODE_R_LAYERS) &&
|
|
|
|
|
!(node->type == CMP_NODE_CRYPTOMATTE && node->custom1 == CMP_CRYPTOMATTE_SRC_RENDER)) {
|
2020-09-10 13:33:29 +02:00
|
|
|
BLO_expand(expander, node->id);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
IDP_BlendReadExpand(expander, node->prop);
|
|
|
|
|
|
|
|
|
|
expand_node_sockets(expander, &node->inputs);
|
|
|
|
|
expand_node_sockets(expander, &node->outputs);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
expand_node_sockets(expander, &ntree->inputs);
|
|
|
|
|
expand_node_sockets(expander, &ntree->outputs);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void ntree_blend_read_expand(BlendExpander *expander, ID *id)
|
|
|
|
|
{
|
|
|
|
|
bNodeTree *ntree = (bNodeTree *)id;
|
|
|
|
|
ntreeBlendReadExpand(expander, ntree);
|
|
|
|
|
}
|
|
|
|
|
|
2020-03-06 14:57:26 +01:00
|
|
|
IDTypeInfo IDType_ID_NT = {
|
2021-02-02 11:26:17 -06:00
|
|
|
/* id_code */ ID_NT,
|
|
|
|
|
/* id_filter */ FILTER_ID_NT,
|
|
|
|
|
/* main_listbase_index */ INDEX_ID_NT,
|
|
|
|
|
/* struct_size */ sizeof(bNodeTree),
|
|
|
|
|
/* name */ "NodeTree",
|
|
|
|
|
/* name_plural */ "node_groups",
|
|
|
|
|
/* translation_context */ BLT_I18NCONTEXT_ID_NODETREE,
|
2021-09-17 16:22:29 +02:00
|
|
|
/* flags */ IDTYPE_FLAGS_APPEND_IS_REUSABLE,
|
2021-11-24 10:32:28 +01:00
|
|
|
/* asset_type_info */ nullptr,
|
2021-02-02 11:26:17 -06:00
|
|
|
|
|
|
|
|
/* init_data */ ntree_init_data,
|
|
|
|
|
/* copy_data */ ntree_copy_data,
|
|
|
|
|
/* free_data */ ntree_free_data,
|
|
|
|
|
/* make_local */ nullptr,
|
|
|
|
|
/* foreach_id */ node_foreach_id,
|
|
|
|
|
/* foreach_cache */ node_foreach_cache,
|
Refactor BKE_bpath module.
The main goal of this refactor is to make BPath module use `IDTypeInfo`,
and move each ID-specific part of the `foreach_path` looper into their
own IDTypeInfo struct, using a new `foreach_path` callback.
Additionally, following improvements/cleanups are included:
* Attempt to get better, more consistent namings.
** In particular, move from `path_visitor` to more standard `foreach_path`.
* Update and extend documentation.
** API doc was moved to header, according to recent discussions on this
topic.
* Remove `BKE_bpath_relocate_visitor` from API, this is specific
callback that belongs in `lib_id.c` user code.
NOTE: This commit is expected to be 100% non-behavioral-change. This
implies that several potential further changes were only noted as
comments (like using a more generic solution for
`lib_id_library_local_paths`, addressing inconsistencies like path of
packed libraries always being skipped, regardless of the
`BKE_BPATH_FOREACH_PATH_SKIP_PACKED` `eBPathForeachFlag` flag value,
etc.).
NOTE: basic unittests were added to master already in
rBdcc500e5a265093bc9cc.
Reviewed By: brecht
Differential Revision: https://developer.blender.org/D13381
2021-11-29 14:20:58 +01:00
|
|
|
/* foreach_path */ node_foreach_path,
|
2022-09-08 16:32:35 +02:00
|
|
|
/* owner_pointer_get */ node_owner_pointer_get,
|
2021-02-02 11:26:17 -06:00
|
|
|
|
|
|
|
|
/* blend_write */ ntree_blend_write,
|
|
|
|
|
/* blend_read_data */ ntree_blend_read_data,
|
|
|
|
|
/* blend_read_lib */ ntree_blend_read_lib,
|
|
|
|
|
/* blend_read_expand */ ntree_blend_read_expand,
|
|
|
|
|
|
|
|
|
|
/* blend_read_undo_preserve */ nullptr,
|
|
|
|
|
|
|
|
|
|
/* lib_override_apply_post */ nullptr,
|
2020-03-06 14:57:26 +01:00
|
|
|
};
|
|
|
|
|
|
2013-03-18 16:34:57 +00:00
|
|
|
static void node_add_sockets_from_type(bNodeTree *ntree, bNode *node, bNodeType *ntype)
|
2011-09-05 21:01:50 +00:00
|
|
|
{
|
2021-08-30 17:13:46 +02:00
|
|
|
if (ntype->declare != nullptr) {
|
2021-11-08 12:23:50 +01:00
|
|
|
node_verify_sockets(ntree, node, true);
|
2021-08-30 17:13:46 +02:00
|
|
|
return;
|
|
|
|
|
}
|
2013-03-18 16:34:57 +00:00
|
|
|
bNodeSocketTemplate *sockdef;
|
|
|
|
|
|
|
|
|
|
if (ntype->inputs) {
|
|
|
|
|
sockdef = ntype->inputs;
|
|
|
|
|
while (sockdef->type != -1) {
|
2021-12-20 10:48:01 -06:00
|
|
|
node_add_socket_from_template(ntree, node, sockdef, SOCK_IN);
|
2013-03-18 16:34:57 +00:00
|
|
|
sockdef++;
|
|
|
|
|
}
|
2011-09-05 21:01:50 +00:00
|
|
|
}
|
2013-03-18 16:34:57 +00:00
|
|
|
if (ntype->outputs) {
|
|
|
|
|
sockdef = ntype->outputs;
|
|
|
|
|
while (sockdef->type != -1) {
|
2021-12-20 10:48:01 -06:00
|
|
|
node_add_socket_from_template(ntree, node, sockdef, SOCK_OUT);
|
2013-03-18 16:34:57 +00:00
|
|
|
sockdef++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-07-03 23:08:40 +10:00
|
|
|
/* NOTE: This function is called to initialize node data based on the type.
|
2022-09-07 12:52:05 +10:00
|
|
|
* The #bNodeType may not be registered at creation time of the node,
|
2013-03-18 16:34:57 +00:00
|
|
|
* so this can be delayed until the node type gets registered.
|
|
|
|
|
*/
|
|
|
|
|
static void node_init(const struct bContext *C, bNodeTree *ntree, bNode *node)
|
|
|
|
|
{
|
|
|
|
|
bNodeType *ntype = node->typeinfo;
|
2019-04-22 09:39:35 +10:00
|
|
|
if (ntype == &NodeTypeUndefined) {
|
2013-03-18 16:34:57 +00:00
|
|
|
return;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2013-03-18 16:34:57 +00:00
|
|
|
/* only do this once */
|
2019-04-22 09:39:35 +10:00
|
|
|
if (node->flag & NODE_INIT) {
|
2013-03-18 16:34:57 +00:00
|
|
|
return;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2013-05-29 15:14:09 +00:00
|
|
|
node->flag = NODE_SELECT | NODE_OPTIONS | ntype->flag;
|
2013-03-18 16:34:57 +00:00
|
|
|
node->width = ntype->width;
|
|
|
|
|
node->miniwidth = 42.0f;
|
|
|
|
|
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.
|
2021-07-03 23:08:40 +10:00
|
|
|
* NOTE: do this after the initfunc so nodes get their data set which may be used in naming
|
2013-03-18 16:34:57 +00:00
|
|
|
* (node groups for example) */
|
2019-04-27 12:07:07 +10:00
|
|
|
/* 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!
|
2013-03-18 16:34:57 +00:00
|
|
|
* This solution may be a bit rougher than nodeLabel()'s returned string, but it's simpler
|
2013-03-26 14:33:53 +00:00
|
|
|
* than adding "do_translate" flags to this func (and labelfunc() as well). */
|
|
|
|
|
BLI_strncpy(node->name, DATA_(ntype->ui_name), NODE_MAXSTR);
|
2013-03-18 16:34:57 +00:00
|
|
|
nodeUniqueName(ntree, node);
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2013-03-18 16:34:57 +00:00
|
|
|
node_add_sockets_from_type(ntree, node, ntype);
|
2013-12-01 21:56:52 +01:00
|
|
|
|
2021-02-02 09:51:38 -06:00
|
|
|
if (ntype->initfunc != nullptr) {
|
2013-03-18 16:34:57 +00:00
|
|
|
ntype->initfunc(ntree, node);
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2013-12-08 21:53:35 +01:00
|
|
|
|
2021-02-02 09:51:38 -06:00
|
|
|
if (ntree->typeinfo->node_add_init != nullptr) {
|
2013-12-08 21:53:35 +01:00
|
|
|
ntree->typeinfo->node_add_init(ntree, node);
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2013-12-08 21:53:35 +01:00
|
|
|
|
2019-04-22 09:39:35 +10:00
|
|
|
if (node->id) {
|
2019-03-16 18:54:00 +01:00
|
|
|
id_us_plus(node->id);
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2019-03-16 18:54:00 +01:00
|
|
|
|
2013-03-18 16:34:57 +00:00
|
|
|
/* extra init callback */
|
|
|
|
|
if (ntype->initfunc_api) {
|
|
|
|
|
PointerRNA ptr;
|
|
|
|
|
RNA_pointer_create((ID *)ntree, &RNA_Node, node, &ptr);
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2022-05-13 09:24:28 +10:00
|
|
|
/* XXX WARNING: context can be nullptr in case nodes are added in do_versions.
|
2021-12-20 10:48:01 -06:00
|
|
|
* Delayed init is not supported for nodes with context-based `initfunc_api` at the moment. */
|
2021-02-02 09:51:38 -06:00
|
|
|
BLI_assert(C != nullptr);
|
2013-03-18 16:34:57 +00:00
|
|
|
ntype->initfunc_api(C, &ptr);
|
|
|
|
|
}
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2013-03-18 16:34:57 +00:00
|
|
|
node->flag |= NODE_INIT;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void ntree_set_typeinfo(bNodeTree *ntree, bNodeTreeType *typeinfo)
|
|
|
|
|
{
|
|
|
|
|
if (typeinfo) {
|
2013-03-19 13:40:16 +00:00
|
|
|
ntree->typeinfo = typeinfo;
|
2011-09-05 21:01:50 +00:00
|
|
|
}
|
|
|
|
|
else {
|
2013-03-19 13:40:16 +00:00
|
|
|
ntree->typeinfo = &NodeTreeTypeUndefined;
|
2011-09-05 21:01:50 +00:00
|
|
|
}
|
2021-11-08 11:51:54 +01:00
|
|
|
|
|
|
|
|
/* Deprecated integer type. */
|
|
|
|
|
ntree->type = ntree->typeinfo->type;
|
2021-12-21 15:18:56 +01:00
|
|
|
BKE_ntree_update_tag_all(ntree);
|
2011-09-05 21:01:50 +00:00
|
|
|
}
|
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
|
|
|
|
2013-03-18 16:34:57 +00:00
|
|
|
static void node_set_typeinfo(const struct bContext *C,
|
|
|
|
|
bNodeTree *ntree,
|
|
|
|
|
bNode *node,
|
|
|
|
|
bNodeType *typeinfo)
|
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
|
|
|
{
|
2014-05-07 11:42:38 +02:00
|
|
|
/* for nodes saved in older versions storage can get lost, make undefined then */
|
|
|
|
|
if (node->flag & NODE_INIT) {
|
2019-04-22 09:39:35 +10:00
|
|
|
if (typeinfo && typeinfo->storagename[0] && !node->storage) {
|
2021-02-02 09:51:38 -06:00
|
|
|
typeinfo = nullptr;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2014-05-07 11:42:38 +02:00
|
|
|
}
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2013-03-18 16:34:57 +00:00
|
|
|
if (typeinfo) {
|
2013-03-19 13:40:16 +00:00
|
|
|
node->typeinfo = typeinfo;
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2013-03-18 16:34:57 +00:00
|
|
|
/* deprecated integer type */
|
|
|
|
|
node->type = typeinfo->type;
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2013-03-18 16:34:57 +00:00
|
|
|
/* initialize the node if necessary */
|
|
|
|
|
node_init(C, ntree, node);
|
|
|
|
|
}
|
|
|
|
|
else {
|
2013-03-19 13:40:16 +00:00
|
|
|
node->typeinfo = &NodeTypeUndefined;
|
2013-03-18 16:34:57 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-05-13 09:24:28 +10:00
|
|
|
/* WARNING: default_value must either be null or match the typeinfo at this point.
|
2022-05-01 09:27:22 +01:00
|
|
|
* This function is called both for initializing new sockets and after loading files.
|
|
|
|
|
*/
|
2013-03-18 16:34:57 +00:00
|
|
|
static void node_socket_set_typeinfo(bNodeTree *ntree,
|
|
|
|
|
bNodeSocket *sock,
|
|
|
|
|
bNodeSocketType *typeinfo)
|
|
|
|
|
{
|
|
|
|
|
if (typeinfo) {
|
2013-03-19 13:40:16 +00:00
|
|
|
sock->typeinfo = typeinfo;
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2013-04-02 11:59:27 +00:00
|
|
|
/* deprecated integer type */
|
|
|
|
|
sock->type = typeinfo->type;
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2021-02-02 09:51:38 -06:00
|
|
|
if (sock->default_value == nullptr) {
|
2013-03-18 16:34:57 +00:00
|
|
|
/* initialize the default_value pointer used by standard socket types */
|
|
|
|
|
node_socket_init_default_value(sock);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else {
|
2013-03-19 13:40:16 +00:00
|
|
|
sock->typeinfo = &NodeSocketTypeUndefined;
|
2013-03-18 16:34:57 +00:00
|
|
|
}
|
2021-12-21 15:18:56 +01:00
|
|
|
BKE_ntree_update_tag_socket_type(ntree, sock);
|
2013-03-18 16:34:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Set specific typeinfo pointers in all node trees on register/unregister */
|
|
|
|
|
static void update_typeinfo(Main *bmain,
|
|
|
|
|
const struct bContext *C,
|
|
|
|
|
bNodeTreeType *treetype,
|
|
|
|
|
bNodeType *nodetype,
|
|
|
|
|
bNodeSocketType *socktype,
|
|
|
|
|
bool unregister)
|
|
|
|
|
{
|
2019-04-22 09:39:35 +10:00
|
|
|
if (!bmain) {
|
2013-03-18 16:34:57 +00:00
|
|
|
return;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-11-30 15:22:01 +11:00
|
|
|
FOREACH_NODETREE_BEGIN (bmain, ntree, id) {
|
2019-04-22 09:39:35 +10:00
|
|
|
if (treetype && STREQ(ntree->idname, treetype->idname)) {
|
2021-02-02 09:51:38 -06:00
|
|
|
ntree_set_typeinfo(ntree, unregister ? nullptr : treetype);
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2013-03-18 16:34:57 +00:00
|
|
|
/* initialize nodes */
|
2020-08-31 13:59:33 +02:00
|
|
|
LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
|
2019-04-22 09:39:35 +10:00
|
|
|
if (nodetype && STREQ(node->idname, nodetype->idname)) {
|
2021-02-02 09:51:38 -06:00
|
|
|
node_set_typeinfo(C, ntree, node, unregister ? nullptr : nodetype);
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2013-03-18 16:34:57 +00:00
|
|
|
/* initialize node sockets */
|
2020-08-31 13:59:33 +02:00
|
|
|
LISTBASE_FOREACH (bNodeSocket *, sock, &node->inputs) {
|
2019-04-22 09:39:35 +10:00
|
|
|
if (socktype && STREQ(sock->idname, socktype->idname)) {
|
2021-02-02 09:51:38 -06:00
|
|
|
node_socket_set_typeinfo(ntree, sock, unregister ? nullptr : socktype);
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
|
|
|
|
}
|
2020-08-31 13:59:33 +02:00
|
|
|
LISTBASE_FOREACH (bNodeSocket *, sock, &node->outputs) {
|
2019-04-22 09:39:35 +10:00
|
|
|
if (socktype && STREQ(sock->idname, socktype->idname)) {
|
2021-02-02 09:51:38 -06:00
|
|
|
node_socket_set_typeinfo(ntree, sock, unregister ? nullptr : socktype);
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
|
|
|
|
}
|
2013-03-18 16:34:57 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2013-03-18 16:34:57 +00:00
|
|
|
/* initialize tree sockets */
|
2020-08-31 13:59:33 +02:00
|
|
|
LISTBASE_FOREACH (bNodeSocket *, sock, &ntree->inputs) {
|
2019-04-22 09:39:35 +10:00
|
|
|
if (socktype && STREQ(sock->idname, socktype->idname)) {
|
2021-02-02 09:51:38 -06:00
|
|
|
node_socket_set_typeinfo(ntree, sock, unregister ? nullptr : socktype);
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
|
|
|
|
}
|
2020-08-31 13:59:33 +02:00
|
|
|
LISTBASE_FOREACH (bNodeSocket *, sock, &ntree->outputs) {
|
2019-04-22 09:39:35 +10:00
|
|
|
if (socktype && STREQ(sock->idname, socktype->idname)) {
|
2021-02-02 09:51:38 -06:00
|
|
|
node_socket_set_typeinfo(ntree, sock, unregister ? nullptr : socktype);
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
|
|
|
|
}
|
2013-03-18 16:34:57 +00:00
|
|
|
}
|
2018-11-30 15:22:01 +11:00
|
|
|
FOREACH_NODETREE_END;
|
2013-03-18 16:34:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ntreeSetTypes(const struct bContext *C, bNodeTree *ntree)
|
|
|
|
|
{
|
|
|
|
|
ntree_set_typeinfo(ntree, ntreeTypeFind(ntree->idname));
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2020-08-31 13:59:33 +02:00
|
|
|
LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
|
2013-03-18 16:34:57 +00:00
|
|
|
node_set_typeinfo(C, ntree, node, nodeTypeFind(node->idname));
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2020-08-31 13:59:33 +02:00
|
|
|
LISTBASE_FOREACH (bNodeSocket *, sock, &node->inputs) {
|
2013-03-18 16:34:57 +00:00
|
|
|
node_socket_set_typeinfo(ntree, sock, nodeSocketTypeFind(sock->idname));
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2020-08-31 13:59:33 +02:00
|
|
|
LISTBASE_FOREACH (bNodeSocket *, sock, &node->outputs) {
|
2013-03-18 16:34:57 +00:00
|
|
|
node_socket_set_typeinfo(ntree, sock, nodeSocketTypeFind(sock->idname));
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2013-03-18 16:34:57 +00:00
|
|
|
}
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2020-08-31 13:59:33 +02:00
|
|
|
LISTBASE_FOREACH (bNodeSocket *, sock, &ntree->inputs) {
|
2013-03-18 16:34:57 +00:00
|
|
|
node_socket_set_typeinfo(ntree, sock, nodeSocketTypeFind(sock->idname));
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2020-08-31 13:59:33 +02:00
|
|
|
LISTBASE_FOREACH (bNodeSocket *, sock, &ntree->outputs) {
|
2013-03-18 16:34:57 +00:00
|
|
|
node_socket_set_typeinfo(ntree, sock, nodeSocketTypeFind(sock->idname));
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2013-03-18 16:34:57 +00:00
|
|
|
}
|
|
|
|
|
|
2021-02-02 09:51:38 -06:00
|
|
|
static GHash *nodetreetypes_hash = nullptr;
|
|
|
|
|
static GHash *nodetypes_hash = nullptr;
|
|
|
|
|
static GHash *nodesockettypes_hash = nullptr;
|
2013-03-18 16:34:57 +00:00
|
|
|
|
|
|
|
|
bNodeTreeType *ntreeTypeFind(const char *idname)
|
|
|
|
|
{
|
|
|
|
|
if (idname[0]) {
|
2021-02-02 09:51:38 -06:00
|
|
|
bNodeTreeType *nt = (bNodeTreeType *)BLI_ghash_lookup(nodetreetypes_hash, idname);
|
2019-04-22 09:39:35 +10:00
|
|
|
if (nt) {
|
2013-03-18 16:34:57 +00:00
|
|
|
return nt;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2013-03-18 16:34:57 +00:00
|
|
|
}
|
|
|
|
|
|
2021-02-02 09:51:38 -06:00
|
|
|
return nullptr;
|
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
|
|
|
}
|
|
|
|
|
|
2013-03-18 18:25:05 +00:00
|
|
|
void ntreeTypeAdd(bNodeTreeType *nt)
|
2013-03-18 16:34:57 +00:00
|
|
|
{
|
2015-05-11 12:39:39 +10:00
|
|
|
BLI_ghash_insert(nodetreetypes_hash, nt->idname, nt);
|
2013-03-18 16:34:57 +00:00
|
|
|
/* XXX pass Main to register function? */
|
2019-04-27 12:07:07 +10:00
|
|
|
/* 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. */
|
2021-02-02 09:51:38 -06:00
|
|
|
update_typeinfo(G_MAIN, nullptr, nt, nullptr, nullptr, false);
|
2013-03-18 16:34:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* callback for hash value free function */
|
|
|
|
|
static void ntree_free_type(void *treetype_v)
|
|
|
|
|
{
|
2021-02-02 09:51:38 -06:00
|
|
|
bNodeTreeType *treetype = (bNodeTreeType *)treetype_v;
|
2013-03-18 16:34:57 +00:00
|
|
|
/* XXX pass Main to unregister function? */
|
2019-04-27 12:07:07 +10:00
|
|
|
/* 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. */
|
2021-02-02 09:51:38 -06:00
|
|
|
update_typeinfo(G_MAIN, nullptr, treetype, nullptr, nullptr, true);
|
2013-03-18 16:34:57 +00:00
|
|
|
MEM_freeN(treetype);
|
|
|
|
|
}
|
|
|
|
|
|
2015-05-11 12:39:39 +10:00
|
|
|
void ntreeTypeFreeLink(const bNodeTreeType *nt)
|
2013-03-18 16:34:57 +00:00
|
|
|
{
|
2021-02-02 09:51:38 -06:00
|
|
|
BLI_ghash_remove(nodetreetypes_hash, nt->idname, nullptr, ntree_free_type);
|
2013-03-18 16:34:57 +00:00
|
|
|
}
|
|
|
|
|
|
2013-03-19 13:40:16 +00:00
|
|
|
bool ntreeIsRegistered(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
|
|
|
{
|
2013-03-19 13:40:16 +00:00
|
|
|
return (ntree->typeinfo != &NodeTreeTypeUndefined);
|
2011-09-05 21:01:50 +00:00
|
|
|
}
|
|
|
|
|
|
2021-12-08 00:31:20 -05:00
|
|
|
GHashIterator *ntreeTypeGetIterator()
|
2011-09-05 21:01:50 +00:00
|
|
|
{
|
2013-03-19 13:40:16 +00:00
|
|
|
return BLI_ghashIterator_new(nodetreetypes_hash);
|
2013-03-18 16:34:57 +00:00
|
|
|
}
|
2011-09-05 21:01:50 +00:00
|
|
|
|
2013-03-18 16:34:57 +00:00
|
|
|
bNodeType *nodeTypeFind(const char *idname)
|
|
|
|
|
{
|
|
|
|
|
if (idname[0]) {
|
2021-02-02 09:51:38 -06:00
|
|
|
bNodeType *nt = (bNodeType *)BLI_ghash_lookup(nodetypes_hash, idname);
|
2019-04-22 09:39:35 +10:00
|
|
|
if (nt) {
|
2013-03-18 16:34:57 +00:00
|
|
|
return nt;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2011-09-05 21:01:50 +00:00
|
|
|
}
|
|
|
|
|
|
2021-02-02 09:51:38 -06:00
|
|
|
return nullptr;
|
2013-03-18 16:34:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* callback for hash value free function */
|
|
|
|
|
static void node_free_type(void *nodetype_v)
|
|
|
|
|
{
|
2021-02-02 09:51:38 -06:00
|
|
|
bNodeType *nodetype = (bNodeType *)nodetype_v;
|
2013-03-18 16:34:57 +00:00
|
|
|
/* XXX pass Main to unregister function? */
|
2019-04-27 12:07:07 +10:00
|
|
|
/* 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. */
|
2021-02-02 09:51:38 -06:00
|
|
|
update_typeinfo(G_MAIN, nullptr, nullptr, nodetype, nullptr, true);
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2021-10-18 15:21:51 +02:00
|
|
|
delete nodetype->fixed_declaration;
|
2021-10-18 16:17:56 +02:00
|
|
|
nodetype->fixed_declaration = nullptr;
|
2021-10-18 15:21:51 +02:00
|
|
|
|
2021-02-02 09:51:38 -06:00
|
|
|
/* Can be null when the type is not dynamically allocated. */
|
2020-02-28 13:28:16 +01:00
|
|
|
if (nodetype->free_self) {
|
|
|
|
|
nodetype->free_self(nodetype);
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2013-03-18 16:34:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void nodeRegisterType(bNodeType *nt)
|
|
|
|
|
{
|
|
|
|
|
/* debug only: basic verification of registered types */
|
|
|
|
|
BLI_assert(nt->idname[0] != '\0');
|
2021-02-02 09:51:38 -06:00
|
|
|
BLI_assert(nt->poll != nullptr);
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2021-10-18 15:21:51 +02:00
|
|
|
if (nt->declare && !nt->declaration_is_dynamic) {
|
|
|
|
|
if (nt->fixed_declaration == nullptr) {
|
|
|
|
|
nt->fixed_declaration = new blender::nodes::NodeDeclaration();
|
|
|
|
|
blender::nodes::NodeDeclarationBuilder builder{*nt->fixed_declaration};
|
|
|
|
|
nt->declare(builder);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-05-11 12:39:39 +10:00
|
|
|
BLI_ghash_insert(nodetypes_hash, nt->idname, nt);
|
2013-03-18 16:34:57 +00:00
|
|
|
/* XXX pass Main to register function? */
|
2019-04-27 12:07:07 +10:00
|
|
|
/* 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. */
|
2021-02-02 09:51:38 -06:00
|
|
|
update_typeinfo(G_MAIN, nullptr, nullptr, nt, nullptr, false);
|
2013-03-18 16:34:57 +00:00
|
|
|
}
|
|
|
|
|
|
2013-03-18 18:25:05 +00:00
|
|
|
void nodeUnregisterType(bNodeType *nt)
|
2013-03-18 16:34:57 +00:00
|
|
|
{
|
2021-02-02 09:51:38 -06:00
|
|
|
BLI_ghash_remove(nodetypes_hash, nt->idname, nullptr, node_free_type);
|
2013-03-18 16:34:57 +00:00
|
|
|
}
|
|
|
|
|
|
2021-12-03 16:25:17 -05:00
|
|
|
bool nodeTypeUndefined(const bNode *node)
|
2013-03-19 13:40:16 +00:00
|
|
|
{
|
2020-11-19 14:23:48 +01:00
|
|
|
return (node->typeinfo == &NodeTypeUndefined) ||
|
2021-10-20 10:45:59 +11:00
|
|
|
((ELEM(node->type, NODE_GROUP, NODE_CUSTOM_GROUP)) && node->id &&
|
2021-04-08 16:25:09 -06:00
|
|
|
ID_IS_LINKED(node->id) && (node->id->tag & LIB_TAG_MISSING));
|
2013-03-19 13:40:16 +00:00
|
|
|
}
|
|
|
|
|
|
2021-12-08 00:31:20 -05:00
|
|
|
GHashIterator *nodeTypeGetIterator()
|
2013-03-18 16:34:57 +00:00
|
|
|
{
|
|
|
|
|
return BLI_ghashIterator_new(nodetypes_hash);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bNodeSocketType *nodeSocketTypeFind(const char *idname)
|
|
|
|
|
{
|
|
|
|
|
if (idname[0]) {
|
2021-02-02 09:51:38 -06:00
|
|
|
bNodeSocketType *st = (bNodeSocketType *)BLI_ghash_lookup(nodesockettypes_hash, idname);
|
2019-04-22 09:39:35 +10:00
|
|
|
if (st) {
|
2013-03-18 16:34:57 +00:00
|
|
|
return st;
|
2019-04-22 09:39:35 +10: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
|
|
|
}
|
2013-03-18 16:34:57 +00:00
|
|
|
|
2021-02-02 09:51:38 -06:00
|
|
|
return nullptr;
|
2011-09-05 21:01:50 +00:00
|
|
|
}
|
|
|
|
|
|
2013-03-18 16:34:57 +00:00
|
|
|
/* callback for hash value free function */
|
|
|
|
|
static void node_free_socket_type(void *socktype_v)
|
2011-09-05 21:01:50 +00:00
|
|
|
{
|
2021-02-02 09:51:38 -06:00
|
|
|
bNodeSocketType *socktype = (bNodeSocketType *)socktype_v;
|
2013-03-18 16:34:57 +00:00
|
|
|
/* XXX pass Main to unregister function? */
|
2019-04-27 12:07:07 +10:00
|
|
|
/* 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. */
|
2021-02-02 09:51:38 -06:00
|
|
|
update_typeinfo(G_MAIN, nullptr, nullptr, nullptr, socktype, true);
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2020-02-28 13:28:16 +01:00
|
|
|
socktype->free_self(socktype);
|
2013-03-18 16:34:57 +00:00
|
|
|
}
|
2008-02-09 23:17:15 +00:00
|
|
|
|
2013-03-18 18:25:05 +00:00
|
|
|
void nodeRegisterSocketType(bNodeSocketType *st)
|
2013-03-18 16:34:57 +00:00
|
|
|
{
|
|
|
|
|
BLI_ghash_insert(nodesockettypes_hash, (void *)st->idname, st);
|
|
|
|
|
/* XXX pass Main to register function? */
|
2019-04-27 12:07:07 +10:00
|
|
|
/* 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. */
|
2021-02-02 09:51:38 -06:00
|
|
|
update_typeinfo(G_MAIN, nullptr, nullptr, nullptr, st, false);
|
2013-03-18 16:34:57 +00:00
|
|
|
}
|
|
|
|
|
|
2013-03-18 18:25:05 +00:00
|
|
|
void nodeUnregisterSocketType(bNodeSocketType *st)
|
2013-03-18 16:34:57 +00:00
|
|
|
{
|
2021-02-02 09:51:38 -06:00
|
|
|
BLI_ghash_remove(nodesockettypes_hash, st->idname, nullptr, node_free_socket_type);
|
2013-03-18 16:34:57 +00:00
|
|
|
}
|
|
|
|
|
|
2013-03-19 13:40:16 +00:00
|
|
|
bool nodeSocketIsRegistered(bNodeSocket *sock)
|
|
|
|
|
{
|
|
|
|
|
return (sock->typeinfo != &NodeSocketTypeUndefined);
|
|
|
|
|
}
|
|
|
|
|
|
2021-12-08 00:31:20 -05:00
|
|
|
GHashIterator *nodeSocketTypeGetIterator()
|
2013-03-18 16:34:57 +00:00
|
|
|
{
|
|
|
|
|
return BLI_ghashIterator_new(nodesockettypes_hash);
|
|
|
|
|
}
|
|
|
|
|
|
2021-07-06 18:36:11 +01:00
|
|
|
const char *nodeSocketTypeLabel(const bNodeSocketType *stype)
|
|
|
|
|
{
|
|
|
|
|
/* Use socket type name as a fallback if label is undefined. */
|
|
|
|
|
return stype->label[0] != '\0' ? stype->label : RNA_struct_ui_name(stype->ext_socket.srna);
|
|
|
|
|
}
|
|
|
|
|
|
2021-03-26 14:25:52 -04:00
|
|
|
struct bNodeSocket *nodeFindSocket(const bNode *node,
|
|
|
|
|
eNodeSocketInOut in_out,
|
|
|
|
|
const char *identifier)
|
2013-03-18 16:34:57 +00:00
|
|
|
{
|
2020-09-02 18:28:04 +02:00
|
|
|
const ListBase *sockets = (in_out == SOCK_IN) ? &node->inputs : &node->outputs;
|
|
|
|
|
LISTBASE_FOREACH (bNodeSocket *, sock, sockets) {
|
2019-04-22 09:39:35 +10:00
|
|
|
if (STREQ(sock->identifier, identifier)) {
|
2013-03-18 16:34:57 +00:00
|
|
|
return sock;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2013-03-18 16:34:57 +00:00
|
|
|
}
|
2021-02-02 09:51:38 -06:00
|
|
|
return nullptr;
|
2013-03-18 16:34:57 +00:00
|
|
|
}
|
|
|
|
|
|
2021-12-15 09:51:57 -06:00
|
|
|
namespace blender::bke {
|
|
|
|
|
|
|
|
|
|
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->flag & SOCK_UNAVAIL) && socket->name == name) {
|
|
|
|
|
return socket;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bNodeSocket *node_find_enabled_input_socket(bNode &node, StringRef name)
|
|
|
|
|
{
|
|
|
|
|
return node_find_enabled_socket(node, SOCK_IN, name);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bNodeSocket *node_find_enabled_output_socket(bNode &node, StringRef name)
|
|
|
|
|
{
|
|
|
|
|
return node_find_enabled_socket(node, SOCK_OUT, name);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} // namespace blender::bke
|
|
|
|
|
|
2013-03-18 16:34:57 +00:00
|
|
|
/* find unique socket identifier */
|
|
|
|
|
static bool unique_identifier_check(void *arg, const char *identifier)
|
|
|
|
|
{
|
2021-02-02 09:51:38 -06:00
|
|
|
const ListBase *lb = (const ListBase *)arg;
|
2020-09-02 18:28:04 +02:00
|
|
|
LISTBASE_FOREACH (bNodeSocket *, sock, lb) {
|
2019-04-22 09:39:35 +10:00
|
|
|
if (STREQ(sock->identifier, identifier)) {
|
2013-03-18 16:34:57 +00:00
|
|
|
return true;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2013-03-18 16:34:57 +00:00
|
|
|
}
|
|
|
|
|
return false;
|
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
|
|
|
}
|
|
|
|
|
|
2013-03-18 16:34:57 +00:00
|
|
|
static bNodeSocket *make_socket(bNodeTree *ntree,
|
|
|
|
|
bNode *UNUSED(node),
|
|
|
|
|
int in_out,
|
|
|
|
|
ListBase *lb,
|
|
|
|
|
const char *idname,
|
|
|
|
|
const char *identifier,
|
|
|
|
|
const char *name)
|
2008-02-09 23:17:15 +00:00
|
|
|
{
|
2013-03-18 16:34:57 +00:00
|
|
|
char auto_identifier[MAX_NAME];
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2013-03-18 16:34:57 +00:00
|
|
|
if (identifier && identifier[0] != '\0') {
|
|
|
|
|
/* use explicit identifier */
|
|
|
|
|
BLI_strncpy(auto_identifier, identifier, sizeof(auto_identifier));
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
/* if no explicit identifier is given, assign a unique identifier based on the name */
|
|
|
|
|
BLI_strncpy(auto_identifier, name, sizeof(auto_identifier));
|
|
|
|
|
}
|
2021-12-20 10:48:01 -06:00
|
|
|
/* Make the identifier unique. */
|
2013-05-30 11:51:21 +00:00
|
|
|
BLI_uniquename_cb(
|
2021-11-12 12:22:43 -06:00
|
|
|
unique_identifier_check, lb, "socket", '_', auto_identifier, sizeof(auto_identifier));
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2021-12-24 22:17:49 -05:00
|
|
|
bNodeSocket *sock = MEM_cnew<bNodeSocket>("sock");
|
2022-05-30 15:31:13 +02:00
|
|
|
sock->runtime = MEM_new<bNodeSocketRuntime>(__func__);
|
2013-03-18 16:34:57 +00:00
|
|
|
sock->in_out = in_out;
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2013-03-18 16:34:57 +00:00
|
|
|
BLI_strncpy(sock->identifier, auto_identifier, NODE_MAXSTR);
|
2012-07-29 00:20:28 +00:00
|
|
|
sock->limit = (in_out == SOCK_IN ? 1 : 0xFFF);
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2013-03-18 16:34:57 +00:00
|
|
|
BLI_strncpy(sock->name, name, NODE_MAXSTR);
|
2021-02-02 09:51:38 -06:00
|
|
|
sock->storage = nullptr;
|
2012-10-24 21:57:16 +00:00
|
|
|
sock->flag |= SOCK_COLLAPSED;
|
2013-03-18 16:34:57 +00:00
|
|
|
sock->type = SOCK_CUSTOM; /* int type undefined by default */
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2013-03-18 16:34:57 +00:00
|
|
|
BLI_strncpy(sock->idname, idname, sizeof(sock->idname));
|
|
|
|
|
node_socket_set_typeinfo(ntree, sock, nodeSocketTypeFind(idname));
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2011-09-05 21:01:50 +00:00
|
|
|
return sock;
|
2008-02-09 23:17:15 +00:00
|
|
|
}
|
|
|
|
|
|
2020-04-20 13:22:20 +02:00
|
|
|
static void socket_id_user_increment(bNodeSocket *sock)
|
|
|
|
|
{
|
|
|
|
|
switch ((eNodeSocketDatatype)sock->type) {
|
|
|
|
|
case SOCK_OBJECT: {
|
2021-02-02 09:51:38 -06:00
|
|
|
bNodeSocketValueObject *default_value = (bNodeSocketValueObject *)sock->default_value;
|
2020-07-27 16:26:32 +02:00
|
|
|
id_us_plus((ID *)default_value->value);
|
2020-04-20 13:22:20 +02:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case SOCK_IMAGE: {
|
2021-02-02 09:51:38 -06:00
|
|
|
bNodeSocketValueImage *default_value = (bNodeSocketValueImage *)sock->default_value;
|
2020-07-27 16:26:32 +02:00
|
|
|
id_us_plus((ID *)default_value->value);
|
2020-04-20 13:22:20 +02:00
|
|
|
break;
|
|
|
|
|
}
|
2020-12-11 17:32:08 +01:00
|
|
|
case SOCK_COLLECTION: {
|
2021-02-02 09:51:38 -06:00
|
|
|
bNodeSocketValueCollection *default_value = (bNodeSocketValueCollection *)
|
|
|
|
|
sock->default_value;
|
2020-12-11 17:32:08 +01:00
|
|
|
id_us_plus((ID *)default_value->value);
|
|
|
|
|
break;
|
|
|
|
|
}
|
2021-05-12 12:41:21 +02:00
|
|
|
case SOCK_TEXTURE: {
|
|
|
|
|
bNodeSocketValueTexture *default_value = (bNodeSocketValueTexture *)sock->default_value;
|
|
|
|
|
id_us_plus((ID *)default_value->value);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case SOCK_MATERIAL: {
|
|
|
|
|
bNodeSocketValueMaterial *default_value = (bNodeSocketValueMaterial *)sock->default_value;
|
|
|
|
|
id_us_plus((ID *)default_value->value);
|
|
|
|
|
break;
|
|
|
|
|
}
|
2020-04-20 13:22:20 +02:00
|
|
|
case SOCK_FLOAT:
|
|
|
|
|
case SOCK_VECTOR:
|
|
|
|
|
case SOCK_RGBA:
|
|
|
|
|
case SOCK_BOOLEAN:
|
|
|
|
|
case SOCK_INT:
|
|
|
|
|
case SOCK_STRING:
|
|
|
|
|
case __SOCK_MESH:
|
|
|
|
|
case SOCK_CUSTOM:
|
|
|
|
|
case SOCK_SHADER:
|
2020-10-20 15:31:59 +02:00
|
|
|
case SOCK_GEOMETRY:
|
2020-04-20 13:22:20 +02:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-02-18 09:24:28 -06:00
|
|
|
/** \return True if the socket had an ID default value. */
|
|
|
|
|
static bool socket_id_user_decrement(bNodeSocket *sock)
|
2020-04-20 13:22:20 +02:00
|
|
|
{
|
|
|
|
|
switch ((eNodeSocketDatatype)sock->type) {
|
|
|
|
|
case SOCK_OBJECT: {
|
2021-02-02 09:51:38 -06:00
|
|
|
bNodeSocketValueObject *default_value = (bNodeSocketValueObject *)sock->default_value;
|
2021-02-19 12:05:59 +01:00
|
|
|
if (default_value->value != nullptr) {
|
|
|
|
|
id_us_min(&default_value->value->id);
|
2022-02-18 09:24:28 -06:00
|
|
|
return true;
|
2021-02-19 12:05:59 +01:00
|
|
|
}
|
2020-04-20 13:22:20 +02:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case SOCK_IMAGE: {
|
2021-02-02 09:51:38 -06:00
|
|
|
bNodeSocketValueImage *default_value = (bNodeSocketValueImage *)sock->default_value;
|
2021-02-19 12:05:59 +01:00
|
|
|
if (default_value->value != nullptr) {
|
|
|
|
|
id_us_min(&default_value->value->id);
|
2022-02-18 09:24:28 -06:00
|
|
|
return true;
|
2021-02-19 12:05:59 +01:00
|
|
|
}
|
2020-04-20 13:22:20 +02:00
|
|
|
break;
|
|
|
|
|
}
|
2020-12-11 17:32:08 +01:00
|
|
|
case SOCK_COLLECTION: {
|
2021-02-02 09:51:38 -06:00
|
|
|
bNodeSocketValueCollection *default_value = (bNodeSocketValueCollection *)
|
|
|
|
|
sock->default_value;
|
2021-02-19 12:05:59 +01:00
|
|
|
if (default_value->value != nullptr) {
|
|
|
|
|
id_us_min(&default_value->value->id);
|
2022-02-18 09:24:28 -06:00
|
|
|
return true;
|
2021-02-19 12:05:59 +01:00
|
|
|
}
|
2020-12-11 17:32:08 +01:00
|
|
|
break;
|
|
|
|
|
}
|
2021-05-12 12:41:21 +02:00
|
|
|
case SOCK_TEXTURE: {
|
|
|
|
|
bNodeSocketValueTexture *default_value = (bNodeSocketValueTexture *)sock->default_value;
|
|
|
|
|
if (default_value->value != nullptr) {
|
|
|
|
|
id_us_min(&default_value->value->id);
|
2022-02-18 09:24:28 -06:00
|
|
|
return true;
|
2021-05-12 12:41:21 +02:00
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case SOCK_MATERIAL: {
|
|
|
|
|
bNodeSocketValueMaterial *default_value = (bNodeSocketValueMaterial *)sock->default_value;
|
|
|
|
|
if (default_value->value != nullptr) {
|
|
|
|
|
id_us_min(&default_value->value->id);
|
2022-02-18 09:24:28 -06:00
|
|
|
return true;
|
2021-05-12 12:41:21 +02:00
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
2020-04-20 13:22:20 +02:00
|
|
|
case SOCK_FLOAT:
|
|
|
|
|
case SOCK_VECTOR:
|
|
|
|
|
case SOCK_RGBA:
|
|
|
|
|
case SOCK_BOOLEAN:
|
|
|
|
|
case SOCK_INT:
|
|
|
|
|
case SOCK_STRING:
|
|
|
|
|
case __SOCK_MESH:
|
|
|
|
|
case SOCK_CUSTOM:
|
|
|
|
|
case SOCK_SHADER:
|
2020-10-20 15:31:59 +02:00
|
|
|
case SOCK_GEOMETRY:
|
2020-04-20 13:22:20 +02:00
|
|
|
break;
|
|
|
|
|
}
|
2022-02-18 09:24:28 -06:00
|
|
|
return false;
|
2020-04-20 13:22:20 +02:00
|
|
|
}
|
|
|
|
|
|
2021-07-06 18:36:11 +01:00
|
|
|
void nodeModifySocketType(bNodeTree *ntree,
|
|
|
|
|
bNode *UNUSED(node),
|
|
|
|
|
bNodeSocket *sock,
|
|
|
|
|
const char *idname)
|
2018-01-20 01:04:07 +01:00
|
|
|
{
|
2021-07-06 18:36:11 +01:00
|
|
|
bNodeSocketType *socktype = nodeSocketTypeFind(idname);
|
2018-01-20 01:04:07 +01:00
|
|
|
|
2021-07-06 18:36:11 +01:00
|
|
|
if (!socktype) {
|
|
|
|
|
CLOG_ERROR(&LOG, "node socket type %s undefined", idname);
|
2018-01-20 01:04:07 +01:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (sock->default_value) {
|
2020-04-20 13:22:20 +02:00
|
|
|
socket_id_user_decrement(sock);
|
2018-01-20 01:04:07 +01:00
|
|
|
MEM_freeN(sock->default_value);
|
2021-02-02 09:51:38 -06:00
|
|
|
sock->default_value = nullptr;
|
2018-01-20 01:04:07 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BLI_strncpy(sock->idname, idname, sizeof(sock->idname));
|
2021-07-06 18:36:11 +01:00
|
|
|
node_socket_set_typeinfo(ntree, sock, socktype);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void nodeModifySocketTypeStatic(
|
|
|
|
|
bNodeTree *ntree, bNode *node, bNodeSocket *sock, int type, int subtype)
|
|
|
|
|
{
|
|
|
|
|
const char *idname = nodeStaticSocketType(type, subtype);
|
|
|
|
|
|
|
|
|
|
if (!idname) {
|
|
|
|
|
CLOG_ERROR(&LOG, "static node socket type %d undefined", type);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
nodeModifySocketType(ntree, node, sock, idname);
|
2018-01-20 01:04:07 +01:00
|
|
|
}
|
|
|
|
|
|
2013-03-18 16:34:57 +00:00
|
|
|
bNodeSocket *nodeAddSocket(bNodeTree *ntree,
|
|
|
|
|
bNode *node,
|
2021-03-26 14:25:52 -04:00
|
|
|
eNodeSocketInOut in_out,
|
2013-03-18 16:34:57 +00:00
|
|
|
const char *idname,
|
|
|
|
|
const char *identifier,
|
|
|
|
|
const char *name)
|
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
|
|
|
{
|
2020-05-08 17:34:17 +02:00
|
|
|
BLI_assert(node->type != NODE_FRAME);
|
|
|
|
|
BLI_assert(!(in_out == SOCK_IN && node->type == NODE_GROUP_INPUT));
|
|
|
|
|
BLI_assert(!(in_out == SOCK_OUT && node->type == NODE_GROUP_OUTPUT));
|
|
|
|
|
|
2013-03-18 16:34:57 +00:00
|
|
|
ListBase *lb = (in_out == SOCK_IN ? &node->inputs : &node->outputs);
|
|
|
|
|
bNodeSocket *sock = make_socket(ntree, node, in_out, lb, idname, identifier, name);
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2013-03-18 16:34:57 +00:00
|
|
|
BLI_remlink(lb, sock); /* does nothing for new socket */
|
|
|
|
|
BLI_addtail(lb, sock);
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2021-12-21 15:18:56 +01:00
|
|
|
BKE_ntree_update_tag_socket_new(ntree, sock);
|
2018-06-17 17:05:51 +02: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
|
|
|
return sock;
|
|
|
|
|
}
|
|
|
|
|
|
2021-07-06 18:36:11 +01:00
|
|
|
bool nodeIsStaticSocketType(const struct 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);
|
|
|
|
|
}
|
|
|
|
|
|
2013-03-18 16:34:57 +00:00
|
|
|
const char *nodeStaticSocketType(int type, int subtype)
|
|
|
|
|
{
|
|
|
|
|
switch (type) {
|
2013-07-19 15:23:42 +00:00
|
|
|
case SOCK_FLOAT:
|
|
|
|
|
switch (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";
|
2021-06-08 11:50:19 +02:00
|
|
|
case PROP_TIME_ABSOLUTE:
|
|
|
|
|
return "NodeSocketFloatTimeAbsolute";
|
2021-03-13 17:15:50 -05:00
|
|
|
case PROP_DISTANCE:
|
|
|
|
|
return "NodeSocketFloatDistance";
|
2013-07-19 15:23:42 +00:00
|
|
|
case PROP_NONE:
|
|
|
|
|
default:
|
|
|
|
|
return "NodeSocketFloat";
|
|
|
|
|
}
|
|
|
|
|
case SOCK_INT:
|
|
|
|
|
switch (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_VECTOR:
|
|
|
|
|
switch (subtype) {
|
|
|
|
|
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:
|
|
|
|
|
return "NodeSocketString";
|
|
|
|
|
case SOCK_SHADER:
|
|
|
|
|
return "NodeSocketShader";
|
2020-04-20 13:22:20 +02:00
|
|
|
case SOCK_OBJECT:
|
|
|
|
|
return "NodeSocketObject";
|
|
|
|
|
case SOCK_IMAGE:
|
|
|
|
|
return "NodeSocketImage";
|
2020-10-20 15:31:59 +02:00
|
|
|
case SOCK_GEOMETRY:
|
|
|
|
|
return "NodeSocketGeometry";
|
2020-12-11 17:32:08 +01:00
|
|
|
case SOCK_COLLECTION:
|
|
|
|
|
return "NodeSocketCollection";
|
2021-05-12 12:41:21 +02:00
|
|
|
case SOCK_TEXTURE:
|
|
|
|
|
return "NodeSocketTexture";
|
|
|
|
|
case SOCK_MATERIAL:
|
|
|
|
|
return "NodeSocketMaterial";
|
2013-03-18 16:34:57 +00:00
|
|
|
}
|
2021-02-02 09:51:38 -06:00
|
|
|
return nullptr;
|
2013-03-18 16:34:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const char *nodeStaticSocketInterfaceType(int type, int subtype)
|
|
|
|
|
{
|
|
|
|
|
switch (type) {
|
2013-07-19 15:23:42 +00:00
|
|
|
case SOCK_FLOAT:
|
|
|
|
|
switch (subtype) {
|
|
|
|
|
case PROP_UNSIGNED:
|
|
|
|
|
return "NodeSocketInterfaceFloatUnsigned";
|
|
|
|
|
case PROP_PERCENTAGE:
|
|
|
|
|
return "NodeSocketInterfaceFloatPercentage";
|
|
|
|
|
case PROP_FACTOR:
|
|
|
|
|
return "NodeSocketInterfaceFloatFactor";
|
|
|
|
|
case PROP_ANGLE:
|
|
|
|
|
return "NodeSocketInterfaceFloatAngle";
|
|
|
|
|
case PROP_TIME:
|
|
|
|
|
return "NodeSocketInterfaceFloatTime";
|
2021-06-08 11:50:19 +02:00
|
|
|
case PROP_TIME_ABSOLUTE:
|
|
|
|
|
return "NodeSocketInterfaceFloatTimeAbsolute";
|
2021-03-13 17:15:50 -05:00
|
|
|
case PROP_DISTANCE:
|
|
|
|
|
return "NodeSocketInterfaceFloatDistance";
|
2013-07-19 15:23:42 +00:00
|
|
|
case PROP_NONE:
|
|
|
|
|
default:
|
|
|
|
|
return "NodeSocketInterfaceFloat";
|
|
|
|
|
}
|
|
|
|
|
case SOCK_INT:
|
|
|
|
|
switch (subtype) {
|
|
|
|
|
case PROP_UNSIGNED:
|
|
|
|
|
return "NodeSocketInterfaceIntUnsigned";
|
|
|
|
|
case PROP_PERCENTAGE:
|
|
|
|
|
return "NodeSocketInterfaceIntPercentage";
|
|
|
|
|
case PROP_FACTOR:
|
|
|
|
|
return "NodeSocketInterfaceIntFactor";
|
|
|
|
|
case PROP_NONE:
|
|
|
|
|
default:
|
|
|
|
|
return "NodeSocketInterfaceInt";
|
|
|
|
|
}
|
|
|
|
|
case SOCK_BOOLEAN:
|
|
|
|
|
return "NodeSocketInterfaceBool";
|
|
|
|
|
case SOCK_VECTOR:
|
|
|
|
|
switch (subtype) {
|
|
|
|
|
case PROP_TRANSLATION:
|
|
|
|
|
return "NodeSocketInterfaceVectorTranslation";
|
|
|
|
|
case PROP_DIRECTION:
|
|
|
|
|
return "NodeSocketInterfaceVectorDirection";
|
|
|
|
|
case PROP_VELOCITY:
|
|
|
|
|
return "NodeSocketInterfaceVectorVelocity";
|
|
|
|
|
case PROP_ACCELERATION:
|
|
|
|
|
return "NodeSocketInterfaceVectorAcceleration";
|
|
|
|
|
case PROP_EULER:
|
|
|
|
|
return "NodeSocketInterfaceVectorEuler";
|
|
|
|
|
case PROP_XYZ:
|
|
|
|
|
return "NodeSocketInterfaceVectorXYZ";
|
|
|
|
|
case PROP_NONE:
|
|
|
|
|
default:
|
|
|
|
|
return "NodeSocketInterfaceVector";
|
|
|
|
|
}
|
|
|
|
|
case SOCK_RGBA:
|
|
|
|
|
return "NodeSocketInterfaceColor";
|
|
|
|
|
case SOCK_STRING:
|
|
|
|
|
return "NodeSocketInterfaceString";
|
|
|
|
|
case SOCK_SHADER:
|
|
|
|
|
return "NodeSocketInterfaceShader";
|
2020-04-20 13:22:20 +02:00
|
|
|
case SOCK_OBJECT:
|
|
|
|
|
return "NodeSocketInterfaceObject";
|
|
|
|
|
case SOCK_IMAGE:
|
|
|
|
|
return "NodeSocketInterfaceImage";
|
2020-10-20 15:31:59 +02:00
|
|
|
case SOCK_GEOMETRY:
|
|
|
|
|
return "NodeSocketInterfaceGeometry";
|
2020-12-11 17:32:08 +01:00
|
|
|
case SOCK_COLLECTION:
|
|
|
|
|
return "NodeSocketInterfaceCollection";
|
2021-05-12 12:41:21 +02:00
|
|
|
case SOCK_TEXTURE:
|
|
|
|
|
return "NodeSocketInterfaceTexture";
|
|
|
|
|
case SOCK_MATERIAL:
|
|
|
|
|
return "NodeSocketInterfaceMaterial";
|
2013-03-18 16:34:57 +00:00
|
|
|
}
|
2021-02-02 09:51:38 -06:00
|
|
|
return nullptr;
|
2013-03-18 16:34:57 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2021-07-06 18:36:11 +01:00
|
|
|
const char *nodeStaticSocketLabel(int type, int UNUSED(subtype))
|
|
|
|
|
{
|
|
|
|
|
switch (type) {
|
|
|
|
|
case SOCK_FLOAT:
|
|
|
|
|
return "Float";
|
|
|
|
|
case SOCK_INT:
|
|
|
|
|
return "Integer";
|
|
|
|
|
case SOCK_BOOLEAN:
|
|
|
|
|
return "Boolean";
|
|
|
|
|
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";
|
|
|
|
|
}
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
2013-03-18 16:34:57 +00:00
|
|
|
bNodeSocket *nodeAddStaticSocket(bNodeTree *ntree,
|
|
|
|
|
bNode *node,
|
2021-03-26 14:25:52 -04:00
|
|
|
eNodeSocketInOut in_out,
|
2013-03-18 16:34:57 +00:00
|
|
|
int type,
|
|
|
|
|
int subtype,
|
|
|
|
|
const char *identifier,
|
|
|
|
|
const char *name)
|
|
|
|
|
{
|
|
|
|
|
const char *idname = nodeStaticSocketType(type, subtype);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2013-03-18 16:34:57 +00:00
|
|
|
if (!idname) {
|
2019-02-01 12:44:19 +11:00
|
|
|
CLOG_ERROR(&LOG, "static node socket type %d undefined", type);
|
2021-02-02 09:51:38 -06:00
|
|
|
return nullptr;
|
2013-03-18 16:34:57 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-09-02 18:28:04 +02:00
|
|
|
bNodeSocket *sock = nodeAddSocket(ntree, node, in_out, idname, identifier, name);
|
2013-03-18 16:34:57 +00:00
|
|
|
sock->type = type;
|
|
|
|
|
return sock;
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2021-12-20 09:57:02 -06:00
|
|
|
static void node_socket_free(bNodeSocket *sock, const bool do_id_user)
|
2013-03-18 16:34:57 +00:00
|
|
|
{
|
|
|
|
|
if (sock->prop) {
|
2019-05-16 14:17:11 +02:00
|
|
|
IDP_FreePropertyContent_ex(sock->prop, do_id_user);
|
2013-03-18 16:34:57 +00:00
|
|
|
MEM_freeN(sock->prop);
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-04-22 09:39:35 +10:00
|
|
|
if (sock->default_value) {
|
2020-04-20 13:22:20 +02:00
|
|
|
if (do_id_user) {
|
|
|
|
|
socket_id_user_decrement(sock);
|
|
|
|
|
}
|
2013-03-18 16:34:57 +00:00
|
|
|
MEM_freeN(sock->default_value);
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2022-05-30 15:31:13 +02:00
|
|
|
MEM_delete(sock->runtime);
|
2013-03-18 16:34:57 +00:00
|
|
|
}
|
|
|
|
|
|
2011-09-05 21:01:50 +00:00
|
|
|
void nodeRemoveSocket(bNodeTree *ntree, bNode *node, bNodeSocket *sock)
|
2021-08-30 17:13:46 +02:00
|
|
|
{
|
|
|
|
|
nodeRemoveSocketEx(ntree, node, sock, true);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void nodeRemoveSocketEx(struct bNodeTree *ntree,
|
|
|
|
|
struct bNode *node,
|
|
|
|
|
struct bNodeSocket *sock,
|
|
|
|
|
bool do_id_user)
|
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
|
|
|
{
|
2020-09-02 18:28:04 +02:00
|
|
|
LISTBASE_FOREACH_MUTABLE (bNodeLink *, link, &ntree->links) {
|
2012-07-29 00:20:28 +00:00
|
|
|
if (link->fromsock == sock || link->tosock == sock) {
|
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
|
|
|
nodeRemLink(ntree, link);
|
|
|
|
|
}
|
|
|
|
|
}
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2022-01-08 17:36:43 +01:00
|
|
|
LISTBASE_FOREACH_MUTABLE (bNodeLink *, link, &node->internal_links) {
|
|
|
|
|
if (link->fromsock == sock || link->tosock == sock) {
|
|
|
|
|
BLI_remlink(&node->internal_links, link);
|
|
|
|
|
MEM_freeN(link);
|
|
|
|
|
BKE_ntree_update_tag_node_internal_link(ntree, node);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2011-09-05 21:01:50 +00:00
|
|
|
/* this is fast, this way we don't need an in_out argument */
|
|
|
|
|
BLI_remlink(&node->inputs, sock);
|
|
|
|
|
BLI_remlink(&node->outputs, sock);
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2021-12-20 09:57:02 -06:00
|
|
|
node_socket_free(sock, do_id_user);
|
2011-09-05 21:01:50 +00:00
|
|
|
MEM_freeN(sock);
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2021-12-21 15:18:56 +01:00
|
|
|
BKE_ntree_update_tag_socket_removed(ntree);
|
2011-02-08 09:14:18 +00:00
|
|
|
}
|
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
|
|
|
|
2011-09-05 21:01:50 +00:00
|
|
|
void nodeRemoveAllSockets(bNodeTree *ntree, bNode *node)
|
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
|
|
|
{
|
2020-09-02 18:28:04 +02:00
|
|
|
LISTBASE_FOREACH_MUTABLE (bNodeLink *, link, &ntree->links) {
|
2012-07-29 00:20:28 +00:00
|
|
|
if (link->fromnode == node || link->tonode == node) {
|
2011-09-05 21:01:50 +00:00
|
|
|
nodeRemLink(ntree, link);
|
2010-12-29 11:51:53 +00:00
|
|
|
}
|
|
|
|
|
}
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2022-03-01 11:34:22 +01:00
|
|
|
BLI_freelistN(&node->internal_links);
|
|
|
|
|
|
2020-09-02 18:28:04 +02:00
|
|
|
LISTBASE_FOREACH_MUTABLE (bNodeSocket *, sock, &node->inputs) {
|
2021-12-20 09:57:02 -06:00
|
|
|
node_socket_free(sock, true);
|
2013-03-18 16:34:57 +00:00
|
|
|
MEM_freeN(sock);
|
|
|
|
|
}
|
2016-11-19 12:16:14 +01:00
|
|
|
BLI_listbase_clear(&node->inputs);
|
|
|
|
|
|
2020-09-02 18:28:04 +02:00
|
|
|
LISTBASE_FOREACH_MUTABLE (bNodeSocket *, sock, &node->outputs) {
|
2021-12-20 09:57:02 -06:00
|
|
|
node_socket_free(sock, true);
|
2013-03-18 16:34:57 +00:00
|
|
|
MEM_freeN(sock);
|
|
|
|
|
}
|
2016-11-19 12:16:14 +01:00
|
|
|
BLI_listbase_clear(&node->outputs);
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2021-12-21 15:18:56 +01:00
|
|
|
BKE_ntree_update_tag_socket_removed(ntree);
|
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
|
|
|
}
|
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
|
|
|
|
2009-12-17 04:55:15 +00:00
|
|
|
bNode *nodeFindNodebyName(bNodeTree *ntree, const char *name)
|
|
|
|
|
{
|
2021-02-02 09:51:38 -06:00
|
|
|
return (bNode *)BLI_findstring(&ntree->nodes, name, offsetof(bNode, name));
|
2009-12-17 04:55:15 +00:00
|
|
|
}
|
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
|
|
|
|
2020-09-02 18:28:04 +02:00
|
|
|
bool nodeFindNode(bNodeTree *ntree, bNodeSocket *sock, bNode **r_node, int *r_sockindex)
|
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
|
|
|
{
|
2021-02-02 09:51:38 -06:00
|
|
|
*r_node = nullptr;
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2020-09-02 18:28:04 +02:00
|
|
|
LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
|
|
|
|
|
ListBase *sockets = (sock->in_out == SOCK_IN) ? &node->inputs : &node->outputs;
|
|
|
|
|
int index = 0;
|
|
|
|
|
LISTBASE_FOREACH (bNodeSocket *, tsock, sockets) {
|
|
|
|
|
if (sock == tsock) {
|
2021-02-02 09:51:38 -06:00
|
|
|
if (r_node != nullptr) {
|
2020-09-02 18:28:04 +02:00
|
|
|
*r_node = node;
|
|
|
|
|
}
|
2021-02-02 09:51:38 -06:00
|
|
|
if (r_sockindex != nullptr) {
|
2020-09-02 18:28:04 +02:00
|
|
|
*r_sockindex = index;
|
|
|
|
|
}
|
|
|
|
|
return true;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2020-09-02 18:28:04 +02:00
|
|
|
index++;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
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
|
|
|
}
|
2020-09-02 18:28:04 +02:00
|
|
|
return false;
|
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
|
|
|
}
|
Orange; daily noodler update commit.
- Adding execution code for Node trees. Was a bit a puzzle, since I want
it to be multithreading by design. This now is solved by defining a
stack per tree for all data that's being written into. This stack, which
resides now in the NodeTree itself, then can be allocated per thread.
- For testing pleasure, I've added a 'mix node' and a 'show node', so
you can already see it do something. :)
- reshuffled structure, to put things nice together, and have easier node
adding. Current state is still WIP though, structure might change.
For the record; new file node_shaders.c will contain all shader node
definitions, apart from the drawing callbacks.
Next: I'm going to check on Andrea's work on icons now, since this is very
much needed for true shader/composit work.
Now back to release work...
2005-12-21 14:24:51 +00:00
|
|
|
|
2015-08-01 16:16:16 +02:00
|
|
|
bNode *nodeFindRootParent(bNode *node)
|
|
|
|
|
{
|
|
|
|
|
if (node->parent) {
|
|
|
|
|
return nodeFindRootParent(node->parent);
|
|
|
|
|
}
|
2021-02-02 09:51:38 -06:00
|
|
|
return node->type == NODE_FRAME ? node : nullptr;
|
2015-08-01 16:16:16 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool nodeIsChildOf(const bNode *parent, const bNode *child)
|
|
|
|
|
{
|
|
|
|
|
if (parent == child) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
2020-08-07 12:30:43 +02:00
|
|
|
if (child->parent) {
|
2015-08-01 16:16:16 +02:00
|
|
|
return nodeIsChildOf(parent, child->parent);
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void nodeChainIter(const bNodeTree *ntree,
|
|
|
|
|
const bNode *node_start,
|
|
|
|
|
bool (*callback)(bNode *, bNode *, void *, const bool),
|
|
|
|
|
void *userdata,
|
|
|
|
|
const bool reversed)
|
|
|
|
|
{
|
2020-09-02 18:28:04 +02:00
|
|
|
LISTBASE_FOREACH (bNodeLink *, link, &ntree->links) {
|
2015-09-17 17:28:13 +05:00
|
|
|
if ((link->flag & NODE_LINK_VALID) == 0) {
|
2015-09-17 16:16:41 +05:00
|
|
|
/* Skip links marked as cyclic. */
|
|
|
|
|
continue;
|
|
|
|
|
}
|
2015-08-01 16:16:16 +02:00
|
|
|
if (link->tonode && link->fromnode) {
|
2019-04-27 12:07:07 +10:00
|
|
|
/* Is the link part of the chain meaning node_start == fromnode
|
|
|
|
|
* (or tonode for reversed case)? */
|
2015-08-01 16:16:16 +02:00
|
|
|
if ((reversed && (link->tonode == node_start)) ||
|
|
|
|
|
(!reversed && link->fromnode == node_start)) {
|
|
|
|
|
if (!callback(link->fromnode, link->tonode, userdata, reversed)) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
nodeChainIter(
|
|
|
|
|
ntree, reversed ? link->fromnode : link->tonode, callback, userdata, reversed);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-09-30 13:09:39 +02:00
|
|
|
static void iter_backwards_ex(const bNodeTree *ntree,
|
|
|
|
|
const bNode *node_start,
|
|
|
|
|
bool (*callback)(bNode *, bNode *, void *),
|
2019-10-10 00:31:47 +02:00
|
|
|
void *userdata,
|
|
|
|
|
char recursion_mask)
|
2019-09-30 13:09:39 +02:00
|
|
|
{
|
|
|
|
|
LISTBASE_FOREACH (bNodeSocket *, sock, &node_start->inputs) {
|
|
|
|
|
bNodeLink *link = sock->link;
|
2021-02-02 09:51:38 -06:00
|
|
|
if (link == nullptr) {
|
2019-09-30 13:09:39 +02:00
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
if ((link->flag & NODE_LINK_VALID) == 0) {
|
|
|
|
|
/* Skip links marked as cyclic. */
|
|
|
|
|
continue;
|
|
|
|
|
}
|
2019-10-10 00:31:47 +02:00
|
|
|
if (link->fromnode->iter_flag & recursion_mask) {
|
2019-09-30 13:09:39 +02:00
|
|
|
continue;
|
|
|
|
|
}
|
2020-08-07 12:30:43 +02:00
|
|
|
|
|
|
|
|
link->fromnode->iter_flag |= recursion_mask;
|
2019-09-30 13:09:39 +02:00
|
|
|
|
|
|
|
|
if (!callback(link->fromnode, link->tonode, userdata)) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
2019-10-10 00:31:47 +02:00
|
|
|
iter_backwards_ex(ntree, link->fromnode, callback, userdata, recursion_mask);
|
2019-09-30 13:09:39 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void nodeChainIterBackwards(const bNodeTree *ntree,
|
|
|
|
|
const bNode *node_start,
|
|
|
|
|
bool (*callback)(bNode *, bNode *, void *),
|
2019-10-10 00:31:47 +02:00
|
|
|
void *userdata,
|
|
|
|
|
int recursion_lvl)
|
2019-09-30 13:09:39 +02:00
|
|
|
{
|
2019-10-02 12:50:14 +02:00
|
|
|
if (!node_start) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2019-10-10 00:31:47 +02:00
|
|
|
/* Limited by iter_flag type. */
|
|
|
|
|
BLI_assert(recursion_lvl < 8);
|
|
|
|
|
char recursion_mask = (1 << recursion_lvl);
|
|
|
|
|
|
2019-09-30 13:09:39 +02:00
|
|
|
/* Reset flag. */
|
|
|
|
|
LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
|
2019-10-10 00:31:47 +02:00
|
|
|
node->iter_flag &= ~recursion_mask;
|
2019-09-30 13:09:39 +02:00
|
|
|
}
|
|
|
|
|
|
2019-10-10 00:31:47 +02:00
|
|
|
iter_backwards_ex(ntree, node_start, callback, userdata, recursion_mask);
|
2019-09-30 13:09:39 +02:00
|
|
|
}
|
|
|
|
|
|
2015-08-01 16:16:16 +02:00
|
|
|
void nodeParentsIter(bNode *node, bool (*callback)(bNode *, void *), void *userdata)
|
|
|
|
|
{
|
|
|
|
|
if (node->parent) {
|
|
|
|
|
if (!callback(node->parent, userdata)) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
nodeParentsIter(node->parent, callback, userdata);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2011-09-05 21:01:50 +00:00
|
|
|
/* ************** Add stuff ********** */
|
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
|
|
|
|
2011-09-05 21:01:50 +00:00
|
|
|
void nodeUniqueName(bNodeTree *ntree, bNode *node)
|
2009-11-11 09:11:21 +00:00
|
|
|
{
|
2013-03-25 08:29:06 +00:00
|
|
|
BLI_uniquename(
|
|
|
|
|
&ntree->nodes, node, DATA_("Node"), '.', offsetof(bNode, name), sizeof(node->name));
|
2009-11-11 09:11:21 +00:00
|
|
|
}
|
2008-02-09 23:17:15 +00:00
|
|
|
|
2013-03-18 16:34:57 +00:00
|
|
|
bNode *nodeAddNode(const struct bContext *C, bNodeTree *ntree, const char *idname)
|
2008-02-09 23:17:15 +00:00
|
|
|
{
|
2021-12-24 22:17:49 -05:00
|
|
|
bNode *node = MEM_cnew<bNode>("new node");
|
2022-05-30 15:31:13 +02:00
|
|
|
node->runtime = MEM_new<bNodeRuntime>(__func__);
|
2011-09-05 21:01:50 +00:00
|
|
|
BLI_addtail(&ntree->nodes, node);
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2013-03-18 16:34:57 +00:00
|
|
|
BLI_strncpy(node->idname, idname, sizeof(node->idname));
|
|
|
|
|
node_set_typeinfo(C, ntree, node, nodeTypeFind(idname));
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2021-12-21 15:18:56 +01:00
|
|
|
BKE_ntree_update_tag_node_new(ntree, node);
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2021-12-29 19:40:00 +01:00
|
|
|
if (node->type == GEO_NODE_INPUT_SCENE_TIME) {
|
|
|
|
|
DEG_relations_tag_update(CTX_data_main(C));
|
|
|
|
|
}
|
|
|
|
|
|
2008-02-09 23:17:15 +00:00
|
|
|
return node;
|
|
|
|
|
}
|
|
|
|
|
|
2013-03-18 16:34:57 +00:00
|
|
|
bNode *nodeAddStaticNode(const struct bContext *C, bNodeTree *ntree, int type)
|
|
|
|
|
{
|
2021-02-02 09:51:38 -06:00
|
|
|
const char *idname = nullptr;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-11-30 15:35:15 +11:00
|
|
|
NODE_TYPES_BEGIN (ntype) {
|
2021-12-20 10:48:01 -06:00
|
|
|
/* Do an extra poll here, because some int types are used
|
|
|
|
|
* for multiple node types, this helps find the desired type. */
|
2021-04-12 18:43:23 +02:00
|
|
|
const char *disabled_hint;
|
|
|
|
|
if (ntype->type == type && (!ntype->poll || ntype->poll(ntype, ntree, &disabled_hint))) {
|
2013-04-18 11:36:11 +00:00
|
|
|
idname = ntype->idname;
|
2013-03-18 16:34:57 +00:00
|
|
|
break;
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2013-03-18 16:34:57 +00:00
|
|
|
}
|
2018-11-30 15:35:15 +11:00
|
|
|
NODE_TYPES_END;
|
2013-03-18 16:34:57 +00:00
|
|
|
if (!idname) {
|
2019-02-01 12:44:19 +11:00
|
|
|
CLOG_ERROR(&LOG, "static node type %d undefined", type);
|
2021-02-02 09:51:38 -06:00
|
|
|
return nullptr;
|
2013-03-18 16:34:57 +00:00
|
|
|
}
|
|
|
|
|
return nodeAddNode(C, ntree, idname);
|
|
|
|
|
}
|
|
|
|
|
|
2019-06-03 17:08:25 +02:00
|
|
|
static void node_socket_copy(bNodeSocket *sock_dst, const bNodeSocket *sock_src, const int flag)
|
2013-03-18 16:34:57 +00:00
|
|
|
{
|
2022-05-30 15:31:13 +02:00
|
|
|
sock_dst->runtime = MEM_new<bNodeSocketRuntime>(__func__);
|
Refactor ID copying (and to some extent, ID freeing).
This will allow much finer controll over how we copy data-blocks, from
full copy in Main database, to "lighter" ones (out of Main, inside an
already allocated datablock, etc.).
This commit also transfers a llot of what was previously handled by
per-ID-type custom code to generic ID handling code in BKE_library.
Hopefully will avoid in future inconsistencies and missing bits we had
all over the codebase in the past.
It also adds missing copying handling for a few types, most notably
Scene (which where using a fully customized handling previously).
Note that the type of allocation used during copying (regular in Main,
allocated but outside of Main, or not allocated by ID handling code at
all) is stored in ID's, which allows to handle them correctly when
freeing. This needs to be taken care of with caution when doing 'weird'
unusual things with ID copying and/or allocation!
As a final note, while rather noisy, this commit will hopefully not
break too much existing branches, old 'API' has been kept for the main
part, as a wrapper around new code. Cleaning it up will happen later.
Design task : T51804
Phab Diff: D2714
2017-08-07 16:39:55 +02:00
|
|
|
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);
|
2020-04-20 13:22:20 +02:00
|
|
|
|
|
|
|
|
if ((flag & LIB_ID_CREATE_NO_USER_REFCOUNT) == 0) {
|
|
|
|
|
socket_id_user_increment(sock_dst);
|
|
|
|
|
}
|
Refactor ID copying (and to some extent, ID freeing).
This will allow much finer controll over how we copy data-blocks, from
full copy in Main database, to "lighter" ones (out of Main, inside an
already allocated datablock, etc.).
This commit also transfers a llot of what was previously handled by
per-ID-type custom code to generic ID handling code in BKE_library.
Hopefully will avoid in future inconsistencies and missing bits we had
all over the codebase in the past.
It also adds missing copying handling for a few types, most notably
Scene (which where using a fully customized handling previously).
Note that the type of allocation used during copying (regular in Main,
allocated but outside of Main, or not allocated by ID handling code at
all) is stored in ID's, which allows to handle them correctly when
freeing. This needs to be taken care of with caution when doing 'weird'
unusual things with ID copying and/or allocation!
As a final note, while rather noisy, this commit will hopefully not
break too much existing branches, old 'API' has been kept for the main
part, as a wrapper around new code. Cleaning it up will happen later.
Design task : T51804
Phab Diff: D2714
2017-08-07 16:39:55 +02:00
|
|
|
}
|
|
|
|
|
|
2022-04-28 08:39:30 -05:00
|
|
|
sock_dst->default_attribute_name = static_cast<char *>(
|
|
|
|
|
MEM_dupallocN(sock_src->default_attribute_name));
|
|
|
|
|
|
Refactor ID copying (and to some extent, ID freeing).
This will allow much finer controll over how we copy data-blocks, from
full copy in Main database, to "lighter" ones (out of Main, inside an
already allocated datablock, etc.).
This commit also transfers a llot of what was previously handled by
per-ID-type custom code to generic ID handling code in BKE_library.
Hopefully will avoid in future inconsistencies and missing bits we had
all over the codebase in the past.
It also adds missing copying handling for a few types, most notably
Scene (which where using a fully customized handling previously).
Note that the type of allocation used during copying (regular in Main,
allocated but outside of Main, or not allocated by ID handling code at
all) is stored in ID's, which allows to handle them correctly when
freeing. This needs to be taken care of with caution when doing 'weird'
unusual things with ID copying and/or allocation!
As a final note, while rather noisy, this commit will hopefully not
break too much existing branches, old 'API' has been kept for the main
part, as a wrapper around new code. Cleaning it up will happen later.
Design task : T51804
Phab Diff: D2714
2017-08-07 16:39:55 +02:00
|
|
|
sock_dst->stack_index = 0;
|
2021-12-20 10:48:01 -06:00
|
|
|
/* XXX some compositor nodes (e.g. image, render layers) still store
|
|
|
|
|
* some persistent buffer data here, need to clear this to avoid dangling pointers. */
|
2021-02-02 09:51:38 -06:00
|
|
|
sock_dst->cache = nullptr;
|
2013-03-18 16:34:57 +00:00
|
|
|
}
|
|
|
|
|
|
2021-12-22 08:47:46 -06:00
|
|
|
namespace blender::bke {
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2021-12-22 08:47:46 -06:00
|
|
|
bNode *node_copy_with_mapping(bNodeTree *dst_tree,
|
|
|
|
|
const bNode &node_src,
|
|
|
|
|
const int flag,
|
|
|
|
|
const bool unique_name,
|
|
|
|
|
Map<const bNodeSocket *, bNodeSocket *> &socket_map)
|
|
|
|
|
{
|
|
|
|
|
bNode *node_dst = (bNode *)MEM_mallocN(sizeof(bNode), __func__);
|
|
|
|
|
*node_dst = node_src;
|
2021-09-14 16:34:31 +02:00
|
|
|
|
2022-05-30 15:31:13 +02:00
|
|
|
node_dst->runtime = MEM_new<bNodeRuntime>(__func__);
|
|
|
|
|
|
2021-12-20 10:48:01 -06:00
|
|
|
/* Can be called for nodes outside a node tree (e.g. clipboard). */
|
2021-12-22 08:47:46 -06:00
|
|
|
if (dst_tree) {
|
2020-01-16 15:04:06 +01:00
|
|
|
if (unique_name) {
|
2021-12-22 08:47:46 -06:00
|
|
|
nodeUniqueName(dst_tree, node_dst);
|
2020-01-16 15:04:06 +01:00
|
|
|
}
|
2021-12-22 08:47:46 -06:00
|
|
|
BLI_addtail(&dst_tree->nodes, node_dst);
|
2012-08-02 09:52:37 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2021-12-22 08:47:46 -06:00
|
|
|
BLI_listbase_clear(&node_dst->inputs);
|
|
|
|
|
LISTBASE_FOREACH (const bNodeSocket *, src_socket, &node_src.inputs) {
|
|
|
|
|
bNodeSocket *dst_socket = (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);
|
2012-10-25 16:49:06 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2021-12-22 08:47:46 -06:00
|
|
|
BLI_listbase_clear(&node_dst->outputs);
|
|
|
|
|
LISTBASE_FOREACH (const bNodeSocket *, src_socket, &node_src.outputs) {
|
|
|
|
|
bNodeSocket *dst_socket = (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);
|
Refactor ID copying (and to some extent, ID freeing).
This will allow much finer controll over how we copy data-blocks, from
full copy in Main database, to "lighter" ones (out of Main, inside an
already allocated datablock, etc.).
This commit also transfers a llot of what was previously handled by
per-ID-type custom code to generic ID handling code in BKE_library.
Hopefully will avoid in future inconsistencies and missing bits we had
all over the codebase in the past.
It also adds missing copying handling for a few types, most notably
Scene (which where using a fully customized handling previously).
Note that the type of allocation used during copying (regular in Main,
allocated but outside of Main, or not allocated by ID handling code at
all) is stored in ID's, which allows to handle them correctly when
freeing. This needs to be taken care of with caution when doing 'weird'
unusual things with ID copying and/or allocation!
As a final note, while rather noisy, this commit will hopefully not
break too much existing branches, old 'API' has been kept for the main
part, as a wrapper around new code. Cleaning it up will happen later.
Design task : T51804
Phab Diff: D2714
2017-08-07 16:39:55 +02:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2021-12-22 08:47:46 -06:00
|
|
|
if (node_src.prop) {
|
|
|
|
|
node_dst->prop = IDP_CopyProperty_ex(node_src.prop, flag);
|
Refactor ID copying (and to some extent, ID freeing).
This will allow much finer controll over how we copy data-blocks, from
full copy in Main database, to "lighter" ones (out of Main, inside an
already allocated datablock, etc.).
This commit also transfers a llot of what was previously handled by
per-ID-type custom code to generic ID handling code in BKE_library.
Hopefully will avoid in future inconsistencies and missing bits we had
all over the codebase in the past.
It also adds missing copying handling for a few types, most notably
Scene (which where using a fully customized handling previously).
Note that the type of allocation used during copying (regular in Main,
allocated but outside of Main, or not allocated by ID handling code at
all) is stored in ID's, which allows to handle them correctly when
freeing. This needs to be taken care of with caution when doing 'weird'
unusual things with ID copying and/or allocation!
As a final note, while rather noisy, this commit will hopefully not
break too much existing branches, old 'API' has been kept for the main
part, as a wrapper around new code. Cleaning it up will happen later.
Design task : T51804
Phab Diff: D2714
2017-08-07 16:39:55 +02:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2021-12-22 08:47:46 -06:00
|
|
|
BLI_listbase_clear(&node_dst->internal_links);
|
|
|
|
|
LISTBASE_FOREACH (const bNodeLink *, src_link, &node_src.internal_links) {
|
|
|
|
|
bNodeLink *dst_link = (bNodeLink *)MEM_dupallocN(src_link);
|
|
|
|
|
dst_link->fromnode = node_dst;
|
|
|
|
|
dst_link->tonode = node_dst;
|
|
|
|
|
dst_link->fromsock = socket_map.lookup(src_link->fromsock);
|
|
|
|
|
dst_link->tosock = socket_map.lookup(src_link->tosock);
|
|
|
|
|
BLI_addtail(&node_dst->internal_links, dst_link);
|
Refactor ID copying (and to some extent, ID freeing).
This will allow much finer controll over how we copy data-blocks, from
full copy in Main database, to "lighter" ones (out of Main, inside an
already allocated datablock, etc.).
This commit also transfers a llot of what was previously handled by
per-ID-type custom code to generic ID handling code in BKE_library.
Hopefully will avoid in future inconsistencies and missing bits we had
all over the codebase in the past.
It also adds missing copying handling for a few types, most notably
Scene (which where using a fully customized handling previously).
Note that the type of allocation used during copying (regular in Main,
allocated but outside of Main, or not allocated by ID handling code at
all) is stored in ID's, which allows to handle them correctly when
freeing. This needs to be taken care of with caution when doing 'weird'
unusual things with ID copying and/or allocation!
As a final note, while rather noisy, this commit will hopefully not
break too much existing branches, old 'API' has been kept for the main
part, as a wrapper around new code. Cleaning it up will happen later.
Design task : T51804
Phab Diff: D2714
2017-08-07 16:39:55 +02:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
Refactor ID copying (and to some extent, ID freeing).
This will allow much finer controll over how we copy data-blocks, from
full copy in Main database, to "lighter" ones (out of Main, inside an
already allocated datablock, etc.).
This commit also transfers a llot of what was previously handled by
per-ID-type custom code to generic ID handling code in BKE_library.
Hopefully will avoid in future inconsistencies and missing bits we had
all over the codebase in the past.
It also adds missing copying handling for a few types, most notably
Scene (which where using a fully customized handling previously).
Note that the type of allocation used during copying (regular in Main,
allocated but outside of Main, or not allocated by ID handling code at
all) is stored in ID's, which allows to handle them correctly when
freeing. This needs to be taken care of with caution when doing 'weird'
unusual things with ID copying and/or allocation!
As a final note, while rather noisy, this commit will hopefully not
break too much existing branches, old 'API' has been kept for the main
part, as a wrapper around new code. Cleaning it up will happen later.
Design task : T51804
Phab Diff: D2714
2017-08-07 16:39:55 +02:00
|
|
|
if ((flag & LIB_ID_CREATE_NO_USER_REFCOUNT) == 0) {
|
|
|
|
|
id_us_plus(node_dst->id);
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2021-12-22 08:47:46 -06:00
|
|
|
if (node_src.typeinfo->copyfunc) {
|
|
|
|
|
node_src.typeinfo->copyfunc(dst_tree, node_dst, &node_src);
|
Refactor ID copying (and to some extent, ID freeing).
This will allow much finer controll over how we copy data-blocks, from
full copy in Main database, to "lighter" ones (out of Main, inside an
already allocated datablock, etc.).
This commit also transfers a llot of what was previously handled by
per-ID-type custom code to generic ID handling code in BKE_library.
Hopefully will avoid in future inconsistencies and missing bits we had
all over the codebase in the past.
It also adds missing copying handling for a few types, most notably
Scene (which where using a fully customized handling previously).
Note that the type of allocation used during copying (regular in Main,
allocated but outside of Main, or not allocated by ID handling code at
all) is stored in ID's, which allows to handle them correctly when
freeing. This needs to be taken care of with caution when doing 'weird'
unusual things with ID copying and/or allocation!
As a final note, while rather noisy, this commit will hopefully not
break too much existing branches, old 'API' has been kept for the main
part, as a wrapper around new code. Cleaning it up will happen later.
Design task : T51804
Phab Diff: D2714
2017-08-07 16:39:55 +02:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-12-07 19:35:52 +01:00
|
|
|
/* 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)) {
|
2013-03-18 16:34:57 +00:00
|
|
|
PointerRNA ptr;
|
2021-12-22 08:47:46 -06:00
|
|
|
RNA_pointer_create((ID *)dst_tree, &RNA_Node, node_dst, &ptr);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2021-12-22 08:47:46 -06:00
|
|
|
node_dst->typeinfo->copyfunc_api(&ptr, &node_src);
|
2012-10-26 11:29:30 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2021-12-22 08:47:46 -06:00
|
|
|
if (dst_tree) {
|
|
|
|
|
BKE_ntree_update_tag_node_new(dst_tree, node_dst);
|
Refactor ID copying (and to some extent, ID freeing).
This will allow much finer controll over how we copy data-blocks, from
full copy in Main database, to "lighter" ones (out of Main, inside an
already allocated datablock, etc.).
This commit also transfers a llot of what was previously handled by
per-ID-type custom code to generic ID handling code in BKE_library.
Hopefully will avoid in future inconsistencies and missing bits we had
all over the codebase in the past.
It also adds missing copying handling for a few types, most notably
Scene (which where using a fully customized handling previously).
Note that the type of allocation used during copying (regular in Main,
allocated but outside of Main, or not allocated by ID handling code at
all) is stored in ID's, which allows to handle them correctly when
freeing. This needs to be taken care of with caution when doing 'weird'
unusual things with ID copying and/or allocation!
As a final note, while rather noisy, this commit will hopefully not
break too much existing branches, old 'API' has been kept for the main
part, as a wrapper around new code. Cleaning it up will happen later.
Design task : T51804
Phab Diff: D2714
2017-08-07 16:39:55 +02:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2021-10-18 15:21:51 +02:00
|
|
|
/* Reset the declaration of the new node. */
|
2021-12-22 08:47:46 -06:00
|
|
|
nodeDeclarationEnsure(dst_tree, node_dst);
|
2021-10-18 15:21:51 +02:00
|
|
|
|
Refactor ID copying (and to some extent, ID freeing).
This will allow much finer controll over how we copy data-blocks, from
full copy in Main database, to "lighter" ones (out of Main, inside an
already allocated datablock, etc.).
This commit also transfers a llot of what was previously handled by
per-ID-type custom code to generic ID handling code in BKE_library.
Hopefully will avoid in future inconsistencies and missing bits we had
all over the codebase in the past.
It also adds missing copying handling for a few types, most notably
Scene (which where using a fully customized handling previously).
Note that the type of allocation used during copying (regular in Main,
allocated but outside of Main, or not allocated by ID handling code at
all) is stored in ID's, which allows to handle them correctly when
freeing. This needs to be taken care of with caution when doing 'weird'
unusual things with ID copying and/or allocation!
As a final note, while rather noisy, this commit will hopefully not
break too much existing branches, old 'API' has been kept for the main
part, as a wrapper around new code. Cleaning it up will happen later.
Design task : T51804
Phab Diff: D2714
2017-08-07 16:39:55 +02:00
|
|
|
return node_dst;
|
|
|
|
|
}
|
|
|
|
|
|
2021-12-22 08:47:46 -06:00
|
|
|
bNode *node_copy(bNodeTree *dst_tree,
|
|
|
|
|
const bNode &src_node,
|
|
|
|
|
const int flag,
|
|
|
|
|
const bool unique_name)
|
2019-06-03 17:08:25 +02:00
|
|
|
{
|
2021-12-22 08:47:46 -06:00
|
|
|
Map<const bNodeSocket *, bNodeSocket *> socket_map;
|
|
|
|
|
return node_copy_with_mapping(dst_tree, src_node, flag, unique_name, socket_map);
|
2019-06-07 17:45:31 +02:00
|
|
|
}
|
|
|
|
|
|
2021-12-22 08:47:46 -06:00
|
|
|
} // namespace blender::bke
|
2019-06-03 17:08:25 +02:00
|
|
|
|
2021-05-13 23:05:38 +02:00
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
2005-12-18 23:08:22 +00:00
|
|
|
bNodeLink *nodeAddLink(
|
|
|
|
|
bNodeTree *ntree, bNode *fromnode, bNodeSocket *fromsock, bNode *tonode, bNodeSocket *tosock)
|
|
|
|
|
{
|
2021-02-02 09:51:38 -06:00
|
|
|
bNodeLink *link = nullptr;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2021-12-20 10:48:01 -06:00
|
|
|
/* Test valid input. */
|
2013-03-18 16:34:57 +00:00
|
|
|
BLI_assert(fromnode);
|
|
|
|
|
BLI_assert(tonode);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2013-03-18 16:34:57 +00:00
|
|
|
if (fromsock->in_out == SOCK_OUT && tosock->in_out == SOCK_IN) {
|
2021-12-24 22:17:49 -05:00
|
|
|
link = MEM_cnew<bNodeLink>("link");
|
2019-04-22 09:39:35 +10:00
|
|
|
if (ntree) {
|
2012-08-02 09:52:37 +00:00
|
|
|
BLI_addtail(&ntree->links, link);
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2012-07-29 00:20:28 +00:00
|
|
|
link->fromnode = fromnode;
|
|
|
|
|
link->fromsock = fromsock;
|
|
|
|
|
link->tonode = tonode;
|
|
|
|
|
link->tosock = tosock;
|
2011-01-17 15:16:08 +00:00
|
|
|
}
|
2013-03-18 16:34:57 +00:00
|
|
|
else if (fromsock->in_out == SOCK_IN && tosock->in_out == SOCK_OUT) {
|
|
|
|
|
/* OK but flip */
|
2021-12-24 22:17:49 -05:00
|
|
|
link = MEM_cnew<bNodeLink>("link");
|
2019-04-22 09:39:35 +10:00
|
|
|
if (ntree) {
|
2012-08-02 09:52:37 +00:00
|
|
|
BLI_addtail(&ntree->links, link);
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2012-07-29 00:20:28 +00:00
|
|
|
link->fromnode = tonode;
|
|
|
|
|
link->fromsock = tosock;
|
|
|
|
|
link->tonode = fromnode;
|
|
|
|
|
link->tosock = fromsock;
|
2011-01-17 15:16:08 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-04-22 09:39:35 +10:00
|
|
|
if (ntree) {
|
2021-12-21 15:18:56 +01:00
|
|
|
BKE_ntree_update_tag_link_added(ntree, link);
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2021-08-10 10:27:57 +02:00
|
|
|
if (link != nullptr && link->tosock->flag & SOCK_MULTI_INPUT) {
|
2021-05-13 17:37:51 -05:00
|
|
|
link->multi_input_socket_index = node_count_links(ntree, link->tosock) - 1;
|
2021-05-13 23:05:38 +02:00
|
|
|
}
|
|
|
|
|
|
2005-12-18 23:08:22 +00:00
|
|
|
return link;
|
|
|
|
|
}
|
2005-12-18 13:46:01 +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
|
|
|
void nodeRemLink(bNodeTree *ntree, bNodeLink *link)
|
2005-12-20 15:43:55 +00:00
|
|
|
{
|
2021-12-20 10:48:01 -06:00
|
|
|
/* Can be called for links outside a node tree (e.g. clipboard). */
|
2019-04-22 09:39:35 +10:00
|
|
|
if (ntree) {
|
2012-08-02 09:52:37 +00:00
|
|
|
BLI_remlink(&ntree->links, link);
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2012-08-02 09:52:37 +00:00
|
|
|
|
2019-04-22 09:39:35 +10:00
|
|
|
if (link->tosock) {
|
2021-02-02 09:51:38 -06:00
|
|
|
link->tosock->link = nullptr;
|
2019-04-22 09:39:35 +10: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
|
|
|
MEM_freeN(link);
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2019-04-22 09:39:35 +10:00
|
|
|
if (ntree) {
|
2021-12-21 15:18:56 +01:00
|
|
|
BKE_ntree_update_tag_link_removed(ntree);
|
2019-04-22 09:39:35 +10: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
|
|
|
}
|
|
|
|
|
|
2022-09-03 17:57:53 -05:00
|
|
|
void nodeLinkSetMute(bNodeTree *ntree, bNodeLink *link, const bool muted)
|
2021-03-16 19:11:54 +00:00
|
|
|
{
|
2022-09-03 17:57:53 -05:00
|
|
|
const bool was_muted = link->flag & NODE_LINK_MUTED;
|
|
|
|
|
SET_FLAG_FROM_TEST(link->flag, muted, NODE_LINK_MUTED);
|
|
|
|
|
if (muted != was_muted) {
|
2021-12-21 15:18:56 +01:00
|
|
|
BKE_ntree_update_tag_link_mute(ntree, link);
|
2021-03-16 19:11:54 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2010-01-04 04:26:28 +00:00
|
|
|
void nodeRemSocketLinks(bNodeTree *ntree, bNodeSocket *sock)
|
|
|
|
|
{
|
2021-02-02 09:51:38 -06:00
|
|
|
LISTBASE_FOREACH_MUTABLE (bNodeLink *, link, &ntree->links) {
|
2012-07-29 00:20:28 +00:00
|
|
|
if (link->fromsock == sock || link->tosock == sock) {
|
2010-01-04 04:26:28 +00:00
|
|
|
nodeRemLink(ntree, link);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-01-15 10:48:22 -06:00
|
|
|
bool nodeLinkIsHidden(const bNodeLink *link)
|
2013-03-18 16:34:57 +00:00
|
|
|
{
|
|
|
|
|
return nodeSocketIsHidden(link->fromsock) || nodeSocketIsHidden(link->tosock);
|
|
|
|
|
}
|
|
|
|
|
|
2022-02-28 15:52:00 -05:00
|
|
|
bool nodeLinkIsSelected(const bNodeLink *link)
|
|
|
|
|
{
|
|
|
|
|
return (link->fromnode->flag & NODE_SELECT) || (link->tonode->flag & NODE_SELECT);
|
|
|
|
|
}
|
|
|
|
|
|
2021-07-28 15:43:24 +02:00
|
|
|
/* 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,
|
|
|
|
|
bNodeSocket *sock,
|
|
|
|
|
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_socket_index <= deleted_index) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
link->multi_input_socket_index -= 1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2012-02-27 17:38:16 +00:00
|
|
|
void nodeInternalRelink(bNodeTree *ntree, bNode *node)
|
|
|
|
|
{
|
|
|
|
|
/* store link pointers in output sockets, for efficient lookup */
|
2020-09-02 18:28:04 +02:00
|
|
|
LISTBASE_FOREACH (bNodeLink *, link, &node->internal_links) {
|
2012-02-27 17:38:16 +00:00
|
|
|
link->tosock->link = link;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-02-27 17:38:16 +00:00
|
|
|
/* redirect downstream links */
|
2020-09-02 18:28:04 +02:00
|
|
|
LISTBASE_FOREACH_MUTABLE (bNodeLink *, link, &ntree->links) {
|
2012-02-27 17:38:16 +00:00
|
|
|
/* do we have internal link? */
|
2012-07-29 00:20:28 +00:00
|
|
|
if (link->fromnode == node) {
|
2012-02-27 17:38:16 +00:00
|
|
|
if (link->fromsock->link) {
|
|
|
|
|
/* get the upstream input link */
|
|
|
|
|
bNodeLink *fromlink = link->fromsock->link->fromsock->link;
|
|
|
|
|
/* skip the node */
|
|
|
|
|
if (fromlink) {
|
2021-11-03 17:53:41 +01:00
|
|
|
if (link->tosock->flag & SOCK_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_socket_index);
|
|
|
|
|
nodeRemLink(ntree, link_to_compare);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2012-02-27 17:38:16 +00:00
|
|
|
link->fromnode = fromlink->fromnode;
|
|
|
|
|
link->fromsock = fromlink->fromsock;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2013-03-05 09:34:14 +00:00
|
|
|
/* if the up- or downstream link is invalid,
|
|
|
|
|
* the replacement link will be invalid too.
|
|
|
|
|
*/
|
2019-04-22 09:39:35 +10:00
|
|
|
if (!(fromlink->flag & NODE_LINK_VALID)) {
|
2013-03-05 09:34:14 +00:00
|
|
|
link->flag &= ~NODE_LINK_VALID;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2021-03-16 19:11:54 +00:00
|
|
|
if (fromlink->flag & NODE_LINK_MUTED) {
|
|
|
|
|
link->flag |= NODE_LINK_MUTED;
|
|
|
|
|
}
|
|
|
|
|
|
2021-12-21 15:18:56 +01:00
|
|
|
BKE_ntree_update_tag_link_changed(ntree);
|
2012-02-27 17:38:16 +00:00
|
|
|
}
|
2019-04-22 09:39:35 +10:00
|
|
|
else {
|
2021-07-28 15:43:24 +02:00
|
|
|
if (link->tosock->flag & SOCK_MULTI_INPUT) {
|
|
|
|
|
adjust_multi_input_indices_after_removed_link(
|
|
|
|
|
ntree, link->tosock, link->multi_input_socket_index);
|
|
|
|
|
}
|
2012-02-27 17:38:16 +00:00
|
|
|
nodeRemLink(ntree, link);
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2012-02-27 17:38:16 +00:00
|
|
|
}
|
2019-04-22 09:39:35 +10:00
|
|
|
else {
|
2021-07-28 15:43:24 +02:00
|
|
|
if (link->tosock->flag & SOCK_MULTI_INPUT) {
|
|
|
|
|
adjust_multi_input_indices_after_removed_link(
|
|
|
|
|
ntree, link->tosock, link->multi_input_socket_index);
|
|
|
|
|
};
|
2012-02-27 17:38:16 +00:00
|
|
|
nodeRemLink(ntree, link);
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2012-02-27 17:38:16 +00:00
|
|
|
}
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-02-27 17:38:16 +00:00
|
|
|
/* remove remaining upstream links */
|
2020-09-02 18:28:04 +02:00
|
|
|
LISTBASE_FOREACH_MUTABLE (bNodeLink *, link, &ntree->links) {
|
2019-04-22 09:39:35 +10:00
|
|
|
if (link->tonode == node) {
|
2012-02-27 17:38:16 +00:00
|
|
|
nodeRemLink(ntree, link);
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2012-02-27 17:38:16 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-01-15 10:48:22 -06:00
|
|
|
void nodeToView(const bNode *node, float x, float y, float *rx, float *ry)
|
2011-09-05 21:01:50 +00:00
|
|
|
{
|
|
|
|
|
if (node->parent) {
|
2012-05-22 14:13:33 +00:00
|
|
|
nodeToView(node->parent, x + node->locx, y + node->locy, rx, ry);
|
2011-09-05 21:01:50 +00:00
|
|
|
}
|
|
|
|
|
else {
|
2012-05-22 14:13:33 +00:00
|
|
|
*rx = x + node->locx;
|
|
|
|
|
*ry = y + node->locy;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-01-15 10:48:22 -06:00
|
|
|
void nodeFromView(const bNode *node, float x, float y, float *rx, float *ry)
|
2012-05-22 14:13:33 +00:00
|
|
|
{
|
|
|
|
|
if (node->parent) {
|
|
|
|
|
nodeFromView(node->parent, x, y, rx, ry);
|
|
|
|
|
*rx -= node->locx;
|
|
|
|
|
*ry -= node->locy;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
*rx = x - node->locx;
|
|
|
|
|
*ry = y - node->locy;
|
2011-09-05 21:01:50 +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
|
|
|
|
2021-01-15 10:48:22 -06:00
|
|
|
bool nodeAttachNodeCheck(const bNode *node, const bNode *parent)
|
2012-08-05 20:40:26 +00:00
|
|
|
{
|
2021-01-15 10:48:22 -06:00
|
|
|
for (const bNode *parent_iter = node; parent_iter; parent_iter = parent_iter->parent) {
|
|
|
|
|
if (parent_iter == parent) {
|
2014-04-01 11:34:00 +11:00
|
|
|
return true;
|
2012-08-05 20:40:26 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2014-04-01 11:34:00 +11:00
|
|
|
return false;
|
2012-08-05 20:40:26 +00:00
|
|
|
}
|
|
|
|
|
|
2011-09-05 21:01:50 +00:00
|
|
|
void nodeAttachNode(bNode *node, bNode *parent)
|
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
|
|
|
{
|
2012-08-05 20:40:26 +00:00
|
|
|
BLI_assert(parent->type == NODE_FRAME);
|
2014-04-01 11:34:00 +11:00
|
|
|
BLI_assert(nodeAttachNodeCheck(parent, node) == false);
|
2012-08-05 20:40:26 +00:00
|
|
|
|
2020-09-02 18:28:04 +02:00
|
|
|
float locx, locy;
|
2012-05-22 14:13:33 +00:00
|
|
|
nodeToView(node, 0.0f, 0.0f, &locx, &locy);
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2011-09-05 21:01:50 +00:00
|
|
|
node->parent = parent;
|
|
|
|
|
/* transform to parent space */
|
2012-05-22 14:13:33 +00:00
|
|
|
nodeFromView(parent, locx, locy, &node->locx, &node->locy);
|
2011-09-05 21:01:50 +00:00
|
|
|
}
|
2010-12-03 03:44:39 +00:00
|
|
|
|
2011-09-05 21:01:50 +00:00
|
|
|
void nodeDetachNode(struct bNode *node)
|
|
|
|
|
{
|
|
|
|
|
if (node->parent) {
|
2012-08-05 20:40:26 +00:00
|
|
|
BLI_assert(node->parent->type == NODE_FRAME);
|
|
|
|
|
|
2012-05-22 14:13:33 +00:00
|
|
|
/* transform to view space */
|
2020-09-02 18:28:04 +02:00
|
|
|
float locx, locy;
|
2012-05-22 14:13:33 +00:00
|
|
|
nodeToView(node, 0.0f, 0.0f, &locx, &locy);
|
|
|
|
|
node->locx = locx;
|
|
|
|
|
node->locy = locy;
|
2021-02-02 09:51:38 -06:00
|
|
|
node->parent = nullptr;
|
2011-09-05 21:01:50 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-09-20 19:53:16 +02:00
|
|
|
void nodePositionRelative(bNode *from_node,
|
|
|
|
|
bNode *to_node,
|
|
|
|
|
bNodeSocket *from_sock,
|
|
|
|
|
bNodeSocket *to_sock)
|
|
|
|
|
{
|
|
|
|
|
float offset_x;
|
|
|
|
|
int tot_sock_idx;
|
|
|
|
|
|
|
|
|
|
/* Socket to plug into. */
|
|
|
|
|
if (SOCK_IN == to_sock->in_out) {
|
|
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BLI_assert(tot_sock_idx != -1);
|
|
|
|
|
|
|
|
|
|
float offset_y = U.widget_unit * tot_sock_idx;
|
|
|
|
|
|
|
|
|
|
/* Output socket. */
|
2018-11-02 17:49:34 +01:00
|
|
|
if (from_sock) {
|
|
|
|
|
if (SOCK_IN == from_sock->in_out) {
|
|
|
|
|
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);
|
|
|
|
|
}
|
2018-09-20 19:53:16 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BLI_assert(tot_sock_idx != -1);
|
|
|
|
|
|
|
|
|
|
offset_y -= U.widget_unit * tot_sock_idx;
|
|
|
|
|
|
|
|
|
|
from_node->locx = to_node->locx + offset_x;
|
|
|
|
|
from_node->locy = to_node->locy - offset_y;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void nodePositionPropagate(bNode *node)
|
|
|
|
|
{
|
2022-09-02 17:48:46 -05:00
|
|
|
LISTBASE_FOREACH (bNodeSocket *, socket, &node->inputs) {
|
|
|
|
|
if (socket->link != nullptr) {
|
|
|
|
|
bNodeLink *link = socket->link;
|
2018-09-20 19:53:16 +02:00
|
|
|
nodePositionRelative(link->fromnode, link->tonode, link->fromsock, link->tosock);
|
|
|
|
|
nodePositionPropagate(link->fromnode);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-09-05 15:46:00 +02:00
|
|
|
static bNodeTree *ntreeAddTree_do(
|
|
|
|
|
Main *bmain, ID *owner_id, const bool is_embedded, const char *name, const char *idname)
|
2011-09-05 21:01:50 +00:00
|
|
|
{
|
2013-03-18 16:34:57 +00:00
|
|
|
/* trees are created as local trees for compositor, material or texture nodes,
|
2011-09-05 21:01:50 +00:00
|
|
|
* node groups and other tree types are created as library data.
|
|
|
|
|
*/
|
2021-01-11 16:09:11 +01:00
|
|
|
int flag = 0;
|
2022-09-06 14:55:39 +02:00
|
|
|
if (is_embedded || bmain == nullptr) {
|
2021-01-11 16:09:11 +01:00
|
|
|
flag |= LIB_ID_CREATE_NO_MAIN;
|
2013-03-18 16:34:57 +00:00
|
|
|
}
|
2021-02-02 09:51:38 -06:00
|
|
|
bNodeTree *ntree = (bNodeTree *)BKE_libblock_alloc(bmain, ID_NT, name, flag);
|
2022-05-30 12:43:26 +02:00
|
|
|
BKE_libblock_init_empty(&ntree->id);
|
2021-01-11 16:09:11 +01:00
|
|
|
if (is_embedded) {
|
2022-09-05 15:46:00 +02:00
|
|
|
BLI_assert(owner_id != NULL);
|
2020-03-11 12:47:25 +01:00
|
|
|
ntree->id.flag |= LIB_EMBEDDED_DATA;
|
2022-09-05 15:46:00 +02:00
|
|
|
ntree->owner_id = owner_id;
|
|
|
|
|
bNodeTree **ntree_owner_ptr = BKE_ntree_ptr_from_id(owner_id);
|
|
|
|
|
BLI_assert(ntree_owner_ptr != NULL);
|
|
|
|
|
*ntree_owner_ptr = ntree;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
BLI_assert(owner_id == NULL);
|
2010-12-03 03:44:39 +00:00
|
|
|
}
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2013-03-18 16:34:57 +00:00
|
|
|
BLI_strncpy(ntree->idname, idname, sizeof(ntree->idname));
|
|
|
|
|
ntree_set_typeinfo(ntree, ntreeTypeFind(idname));
|
2018-06-17 17:05:51 +02: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
|
|
|
return ntree;
|
2005-12-20 15:43:55 +00:00
|
|
|
}
|
2005-12-18 13:46:01 +00:00
|
|
|
|
2022-09-05 15:46:00 +02:00
|
|
|
bNodeTree *ntreeAddTree(Main *bmain, const char *name, const char *idname)
|
|
|
|
|
{
|
|
|
|
|
return ntreeAddTree_do(bmain, nullptr, false, name, idname);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bNodeTree *ntreeAddTreeEmbedded(Main *UNUSED(bmain),
|
|
|
|
|
ID *owner_id,
|
|
|
|
|
const char *name,
|
|
|
|
|
const char *idname)
|
|
|
|
|
{
|
|
|
|
|
return ntreeAddTree_do(nullptr, owner_id, true, name, idname);
|
|
|
|
|
}
|
|
|
|
|
|
2019-08-22 16:00:59 +02:00
|
|
|
bNodeTree *ntreeCopyTree_ex(const bNodeTree *ntree, Main *bmain, const bool do_id_user)
|
2012-08-22 08:54:18 +00:00
|
|
|
{
|
2020-01-05 16:46:11 +01:00
|
|
|
const int flag = do_id_user ? 0 : LIB_ID_CREATE_NO_USER_REFCOUNT | LIB_ID_CREATE_NO_MAIN;
|
2020-10-07 14:27:33 +02:00
|
|
|
|
2021-02-02 09:51:38 -06:00
|
|
|
bNodeTree *ntree_copy = (bNodeTree *)BKE_id_copy_ex(bmain, (ID *)ntree, nullptr, flag);
|
Refactor ID copying (and to some extent, ID freeing).
This will allow much finer controll over how we copy data-blocks, from
full copy in Main database, to "lighter" ones (out of Main, inside an
already allocated datablock, etc.).
This commit also transfers a llot of what was previously handled by
per-ID-type custom code to generic ID handling code in BKE_library.
Hopefully will avoid in future inconsistencies and missing bits we had
all over the codebase in the past.
It also adds missing copying handling for a few types, most notably
Scene (which where using a fully customized handling previously).
Note that the type of allocation used during copying (regular in Main,
allocated but outside of Main, or not allocated by ID handling code at
all) is stored in ID's, which allows to handle them correctly when
freeing. This needs to be taken care of with caution when doing 'weird'
unusual things with ID copying and/or allocation!
As a final note, while rather noisy, this commit will hopefully not
break too much existing branches, old 'API' has been kept for the main
part, as a wrapper around new code. Cleaning it up will happen later.
Design task : T51804
Phab Diff: D2714
2017-08-07 16:39:55 +02:00
|
|
|
return ntree_copy;
|
2012-08-22 08:54:18 +00:00
|
|
|
}
|
2019-08-22 16:00:59 +02:00
|
|
|
bNodeTree *ntreeCopyTree(Main *bmain, const bNodeTree *ntree)
|
2012-07-05 12:50:50 +00:00
|
|
|
{
|
2019-08-22 16:00:59 +02:00
|
|
|
return ntreeCopyTree_ex(ntree, bmain, true);
|
2012-07-05 12:50:50 +00:00
|
|
|
}
|
|
|
|
|
|
2013-03-18 16:34:57 +00:00
|
|
|
/* *************** Node Preview *********** */
|
2009-01-27 17:12:40 +00:00
|
|
|
|
2013-03-18 16:34:57 +00:00
|
|
|
/* XXX this should be removed eventually ...
|
2017-11-05 14:33:18 +11:00
|
|
|
* Currently BKE functions are modeled closely on previous code,
|
2013-03-18 16:34:57 +00:00
|
|
|
* using BKE_node_preview_init_tree to set up previews for a whole node tree in advance.
|
2021-12-07 17:19:15 +11:00
|
|
|
* This should be left more to the individual node tree implementations. */
|
|
|
|
|
|
2021-01-15 10:48:22 -06:00
|
|
|
bool BKE_node_preview_used(const bNode *node)
|
2009-01-27 17:12:40 +00:00
|
|
|
{
|
2013-03-18 16:34:57 +00:00
|
|
|
/* XXX check for closed nodes? */
|
|
|
|
|
return (node->typeinfo->flag & NODE_PREVIEW) != 0;
|
2009-01-27 17:12:40 +00:00
|
|
|
}
|
|
|
|
|
|
2021-12-19 17:57:51 -06:00
|
|
|
bNodePreview *BKE_node_preview_verify(bNodeInstanceHash *previews,
|
|
|
|
|
bNodeInstanceKey key,
|
|
|
|
|
const int xsize,
|
|
|
|
|
const int ysize,
|
|
|
|
|
const bool create)
|
2009-01-27 17:12:40 +00:00
|
|
|
{
|
2021-02-02 09:51:38 -06:00
|
|
|
bNodePreview *preview = (bNodePreview *)BKE_node_instance_hash_lookup(previews, key);
|
2013-03-18 16:34:57 +00:00
|
|
|
if (!preview) {
|
|
|
|
|
if (create) {
|
2021-12-24 22:17:49 -05:00
|
|
|
preview = MEM_cnew<bNodePreview>("node preview");
|
2013-03-18 16:34:57 +00:00
|
|
|
BKE_node_instance_hash_insert(previews, key, preview);
|
|
|
|
|
}
|
2019-04-22 09:39:35 +10:00
|
|
|
else {
|
2021-02-02 09:51:38 -06:00
|
|
|
return nullptr;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2009-01-27 17:12:40 +00:00
|
|
|
}
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2009-01-27 17:12:40 +00:00
|
|
|
/* node previews can get added with variable size this way */
|
2019-04-22 09:39:35 +10:00
|
|
|
if (xsize == 0 || ysize == 0) {
|
2013-03-18 16:34:57 +00:00
|
|
|
return preview;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2009-01-27 17:12:40 +00:00
|
|
|
/* sanity checks & initialize */
|
2013-03-18 16:34:57 +00:00
|
|
|
if (preview->rect) {
|
|
|
|
|
if (preview->xsize != xsize || preview->ysize != ysize) {
|
|
|
|
|
MEM_freeN(preview->rect);
|
2021-02-02 09:51:38 -06:00
|
|
|
preview->rect = nullptr;
|
2009-01-27 17:12:40 +00:00
|
|
|
}
|
|
|
|
|
}
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2021-02-02 09:51:38 -06:00
|
|
|
if (preview->rect == nullptr) {
|
|
|
|
|
preview->rect = (unsigned char *)MEM_callocN(4 * xsize + xsize * ysize * sizeof(char[4]),
|
|
|
|
|
"node preview rect");
|
2013-03-18 16:34:57 +00:00
|
|
|
preview->xsize = xsize;
|
|
|
|
|
preview->ysize = ysize;
|
2009-01-27 17:12:40 +00:00
|
|
|
}
|
2011-01-03 15:50:08 +00:00
|
|
|
/* no clear, makes nicer previews */
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2013-03-18 16:34:57 +00:00
|
|
|
return preview;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bNodePreview *BKE_node_preview_copy(bNodePreview *preview)
|
|
|
|
|
{
|
2021-02-02 09:51:38 -06:00
|
|
|
bNodePreview *new_preview = (bNodePreview *)MEM_dupallocN(preview);
|
2019-04-22 09:39:35 +10:00
|
|
|
if (preview->rect) {
|
2021-02-02 09:51:38 -06:00
|
|
|
new_preview->rect = (unsigned char *)MEM_dupallocN(preview->rect);
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2013-03-18 16:34:57 +00:00
|
|
|
return new_preview;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void BKE_node_preview_free(bNodePreview *preview)
|
|
|
|
|
{
|
2019-04-22 09:39:35 +10:00
|
|
|
if (preview->rect) {
|
2013-03-18 16:34:57 +00:00
|
|
|
MEM_freeN(preview->rect);
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2013-03-18 16:34:57 +00:00
|
|
|
MEM_freeN(preview);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void node_preview_init_tree_recursive(bNodeInstanceHash *previews,
|
|
|
|
|
bNodeTree *ntree,
|
|
|
|
|
bNodeInstanceKey parent_key,
|
2021-12-19 17:57:51 -06:00
|
|
|
const int xsize,
|
|
|
|
|
const int ysize)
|
2013-03-18 16:34:57 +00:00
|
|
|
{
|
2020-09-02 18:28:04 +02:00
|
|
|
LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
|
2013-03-18 16:34:57 +00:00
|
|
|
bNodeInstanceKey key = BKE_node_instance_key(parent_key, ntree, node);
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2013-03-18 16:34:57 +00:00
|
|
|
if (BKE_node_preview_used(node)) {
|
|
|
|
|
node->preview_xsize = xsize;
|
|
|
|
|
node->preview_ysize = ysize;
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2021-12-19 17:57:51 -06:00
|
|
|
BKE_node_preview_verify(previews, key, xsize, ysize, false);
|
2013-03-18 16:34:57 +00:00
|
|
|
}
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2019-04-22 09:39:35 +10:00
|
|
|
if (node->type == NODE_GROUP && node->id) {
|
2021-12-19 17:57:51 -06:00
|
|
|
node_preview_init_tree_recursive(previews, (bNodeTree *)node->id, key, xsize, ysize);
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2013-03-18 16:34:57 +00:00
|
|
|
}
|
2009-01-27 17:12:40 +00:00
|
|
|
}
|
|
|
|
|
|
2021-12-19 17:57:51 -06:00
|
|
|
void BKE_node_preview_init_tree(bNodeTree *ntree, int xsize, int ysize)
|
2013-03-18 16:34:57 +00:00
|
|
|
{
|
2019-04-22 09:39:35 +10:00
|
|
|
if (!ntree) {
|
2013-03-18 16:34:57 +00:00
|
|
|
return;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2019-04-22 09:39:35 +10:00
|
|
|
if (!ntree->previews) {
|
2013-03-18 16:34:57 +00:00
|
|
|
ntree->previews = BKE_node_instance_hash_new("node previews");
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2021-12-19 17:57:51 -06:00
|
|
|
node_preview_init_tree_recursive(ntree->previews, ntree, NODE_INSTANCE_KEY_BASE, xsize, ysize);
|
2013-03-18 16:34:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void node_preview_tag_used_recursive(bNodeInstanceHash *previews,
|
|
|
|
|
bNodeTree *ntree,
|
|
|
|
|
bNodeInstanceKey parent_key)
|
2009-01-27 17:12:40 +00:00
|
|
|
{
|
2020-09-02 18:28:04 +02:00
|
|
|
LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
|
2013-03-18 16:34:57 +00:00
|
|
|
bNodeInstanceKey key = BKE_node_instance_key(parent_key, ntree, node);
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2019-04-22 09:39:35 +10:00
|
|
|
if (BKE_node_preview_used(node)) {
|
2013-03-18 16:34:57 +00:00
|
|
|
BKE_node_instance_hash_tag_key(previews, key);
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2019-04-22 09:39:35 +10:00
|
|
|
if (node->type == NODE_GROUP && node->id) {
|
2013-03-18 16:34:57 +00:00
|
|
|
node_preview_tag_used_recursive(previews, (bNodeTree *)node->id, key);
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2013-03-18 16:34:57 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void BKE_node_preview_remove_unused(bNodeTree *ntree)
|
|
|
|
|
{
|
2019-04-22 09:39:35 +10:00
|
|
|
if (!ntree || !ntree->previews) {
|
2013-03-18 16:34:57 +00:00
|
|
|
return;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2013-03-18 16:34:57 +00:00
|
|
|
/* use the instance hash functions for tagging and removing unused previews */
|
|
|
|
|
BKE_node_instance_hash_clear_tags(ntree->previews);
|
|
|
|
|
node_preview_tag_used_recursive(ntree->previews, ntree, NODE_INSTANCE_KEY_BASE);
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2013-03-18 16:34:57 +00:00
|
|
|
BKE_node_instance_hash_remove_untagged(ntree->previews,
|
|
|
|
|
(bNodeInstanceValueFP)BKE_node_preview_free);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void BKE_node_preview_clear(bNodePreview *preview)
|
|
|
|
|
{
|
2019-04-22 09:39:35 +10:00
|
|
|
if (preview && preview->rect) {
|
2013-03-18 16:34:57 +00:00
|
|
|
memset(preview->rect, 0, MEM_allocN_len(preview->rect));
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2013-03-18 16:34:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void BKE_node_preview_clear_tree(bNodeTree *ntree)
|
|
|
|
|
{
|
2019-04-22 09:39:35 +10:00
|
|
|
if (!ntree || !ntree->previews) {
|
2013-03-18 16:34:57 +00:00
|
|
|
return;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2020-09-02 18:28:04 +02:00
|
|
|
bNodeInstanceHashIterator iter;
|
2019-04-21 04:40:16 +10:00
|
|
|
NODE_INSTANCE_HASH_ITER (iter, ntree->previews) {
|
2021-02-02 09:51:38 -06:00
|
|
|
bNodePreview *preview = (bNodePreview *)BKE_node_instance_hash_iterator_get_value(&iter);
|
2013-03-18 16:34:57 +00:00
|
|
|
BKE_node_preview_clear(preview);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2013-03-22 10:34:52 +00:00
|
|
|
void BKE_node_preview_merge_tree(bNodeTree *to_ntree, bNodeTree *from_ntree, bool remove_old)
|
2013-03-18 16:34:57 +00:00
|
|
|
{
|
2013-03-22 10:34:52 +00:00
|
|
|
if (remove_old || !to_ntree->previews) {
|
|
|
|
|
/* free old previews */
|
2019-04-22 09:39:35 +10:00
|
|
|
if (to_ntree->previews) {
|
2013-03-22 10:34:52 +00:00
|
|
|
BKE_node_instance_hash_free(to_ntree->previews, (bNodeInstanceValueFP)BKE_node_preview_free);
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2013-03-22 10:34:52 +00:00
|
|
|
/* transfer previews */
|
|
|
|
|
to_ntree->previews = from_ntree->previews;
|
2021-02-02 09:51:38 -06:00
|
|
|
from_ntree->previews = nullptr;
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2013-03-22 10:34:52 +00:00
|
|
|
/* clean up, in case any to_ntree nodes have been removed */
|
|
|
|
|
BKE_node_preview_remove_unused(to_ntree);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
if (from_ntree->previews) {
|
2020-09-02 18:28:04 +02:00
|
|
|
bNodeInstanceHashIterator iter;
|
2019-04-21 04:40:16 +10:00
|
|
|
NODE_INSTANCE_HASH_ITER (iter, from_ntree->previews) {
|
2013-03-22 10:34:52 +00:00
|
|
|
bNodeInstanceKey key = BKE_node_instance_hash_iterator_get_key(&iter);
|
2021-02-02 09:51:38 -06:00
|
|
|
bNodePreview *preview = (bNodePreview *)BKE_node_instance_hash_iterator_get_value(&iter);
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2013-03-22 10:34:52 +00:00
|
|
|
/* replace existing previews */
|
|
|
|
|
BKE_node_instance_hash_remove(
|
|
|
|
|
to_ntree->previews, key, (bNodeInstanceValueFP)BKE_node_preview_free);
|
|
|
|
|
BKE_node_instance_hash_insert(to_ntree->previews, key, preview);
|
|
|
|
|
}
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2021-07-03 23:08:40 +10:00
|
|
|
/* NOTE: null free function here,
|
2019-04-27 12:07:07 +10:00
|
|
|
* because pointers have already been moved over to to_ntree->previews! */
|
2021-02-02 09:51:38 -06:00
|
|
|
BKE_node_instance_hash_free(from_ntree->previews, nullptr);
|
|
|
|
|
from_ntree->previews = nullptr;
|
2013-03-22 10:34:52 +00:00
|
|
|
}
|
|
|
|
|
}
|
2013-03-18 16:34:57 +00:00
|
|
|
}
|
|
|
|
|
|
2006-12-30 16:35:46 +00:00
|
|
|
/* ************** Free stuff ********** */
|
2005-12-18 13:46:01 +00:00
|
|
|
|
2007-12-27 10:17:33 +00:00
|
|
|
void nodeUnlinkNode(bNodeTree *ntree, bNode *node)
|
2005-12-18 13:46:01 +00:00
|
|
|
{
|
2020-09-02 18:28:04 +02:00
|
|
|
LISTBASE_FOREACH_MUTABLE (bNodeLink *, link, &ntree->links) {
|
|
|
|
|
ListBase *lb;
|
2012-07-29 00:20:28 +00:00
|
|
|
if (link->fromnode == node) {
|
|
|
|
|
lb = &node->outputs;
|
2006-01-28 15:21:04 +00:00
|
|
|
}
|
2019-04-22 09:39:35 +10:00
|
|
|
else if (link->tonode == node) {
|
2012-07-29 00:20:28 +00:00
|
|
|
lb = &node->inputs;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
|
|
|
|
else {
|
2021-02-02 09:51:38 -06:00
|
|
|
lb = nullptr;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (lb) {
|
2021-07-28 15:43:24 +02:00
|
|
|
/* Only bother adjusting if the socket is not on the node we're deleting. */
|
|
|
|
|
if (link->tonode != node && link->tosock->flag & SOCK_MULTI_INPUT) {
|
|
|
|
|
adjust_multi_input_indices_after_removed_link(
|
|
|
|
|
ntree, link->tosock, link->multi_input_socket_index);
|
|
|
|
|
}
|
2020-09-02 18:28:04 +02:00
|
|
|
LISTBASE_FOREACH (bNodeSocket *, sock, lb) {
|
2019-04-22 09:39:35 +10:00
|
|
|
if (link->fromsock == sock || link->tosock == sock) {
|
2020-09-02 18:28:04 +02:00
|
|
|
nodeRemLink(ntree, link);
|
2005-12-20 15:43:55 +00:00
|
|
|
break;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2005-12-20 15:43:55 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2005-12-18 13:46:01 +00:00
|
|
|
}
|
|
|
|
|
|
2011-09-05 21:01:50 +00:00
|
|
|
static void node_unlink_attached(bNodeTree *ntree, bNode *parent)
|
2006-01-28 15:21:04 +00:00
|
|
|
{
|
2020-09-02 18:28:04 +02:00
|
|
|
LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
|
2019-04-22 09:39:35 +10:00
|
|
|
if (node->parent == parent) {
|
2011-09-05 21:01:50 +00:00
|
|
|
nodeDetachNode(node);
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2006-01-28 15:21:04 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-03-16 18:54:00 +01:00
|
|
|
/* Free the node itself. ID user refcounting is up the caller,
|
|
|
|
|
* that does not happen here. */
|
|
|
|
|
static void node_free_node(bNodeTree *ntree, bNode *node)
|
2005-12-18 13:46:01 +00:00
|
|
|
{
|
2013-03-18 16:34:57 +00:00
|
|
|
/* since it is called while free database, node->id is undefined */
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2012-08-02 09:52:37 +00:00
|
|
|
/* can be called for nodes outside a node tree (e.g. clipboard) */
|
|
|
|
|
if (ntree) {
|
|
|
|
|
BLI_remlink(&ntree->nodes, node);
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2019-04-22 09:39:35 +10:00
|
|
|
if (ntree->typeinfo->free_node_cache) {
|
2013-03-18 16:34:57 +00:00
|
|
|
ntree->typeinfo->free_node_cache(ntree, node);
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2013-02-27 14:25:39 +00:00
|
|
|
/* texture node has bad habit of keeping exec data around */
|
|
|
|
|
if (ntree->type == NTREE_TEXTURE && ntree->execdata) {
|
2013-03-18 16:34:57 +00:00
|
|
|
ntreeTexEndExecTree(ntree->execdata);
|
2021-02-02 09:51:38 -06:00
|
|
|
ntree->execdata = nullptr;
|
2013-02-27 14:25:39 +00:00
|
|
|
}
|
2012-08-02 09:52:37 +00:00
|
|
|
}
|
2017-07-11 11:06:36 +02:00
|
|
|
|
2018-06-11 17:39:05 +02:00
|
|
|
if (node->typeinfo->freefunc) {
|
2017-07-11 11:06:36 +02:00
|
|
|
node->typeinfo->freefunc(node);
|
|
|
|
|
}
|
|
|
|
|
|
2020-09-02 18:28:04 +02:00
|
|
|
LISTBASE_FOREACH_MUTABLE (bNodeSocket *, sock, &node->inputs) {
|
2019-03-04 16:44:33 +01:00
|
|
|
/* Remember, no ID user refcount management here! */
|
2021-12-20 09:57:02 -06:00
|
|
|
node_socket_free(sock, false);
|
2011-09-05 21:01:50 +00:00
|
|
|
MEM_freeN(sock);
|
|
|
|
|
}
|
2020-09-02 18:28:04 +02:00
|
|
|
LISTBASE_FOREACH_MUTABLE (bNodeSocket *, sock, &node->outputs) {
|
2019-03-04 16:44:33 +01:00
|
|
|
/* Remember, no ID user refcount management here! */
|
2021-12-20 09:57:02 -06:00
|
|
|
node_socket_free(sock, false);
|
2011-09-05 21:01:50 +00:00
|
|
|
MEM_freeN(sock);
|
|
|
|
|
}
|
|
|
|
|
|
2012-10-25 16:49:06 +00:00
|
|
|
BLI_freelistN(&node->internal_links);
|
|
|
|
|
|
2013-03-18 16:34:57 +00:00
|
|
|
if (node->prop) {
|
2019-02-13 16:10:46 +01:00
|
|
|
/* Remember, no ID user refcount management here! */
|
2019-05-16 14:17:11 +02:00
|
|
|
IDP_FreePropertyContent_ex(node->prop, false);
|
2013-03-18 16:34:57 +00:00
|
|
|
MEM_freeN(node->prop);
|
|
|
|
|
}
|
2009-01-27 17:12:40 +00:00
|
|
|
|
2021-10-18 15:21:51 +02:00
|
|
|
if (node->typeinfo->declaration_is_dynamic) {
|
2022-05-30 15:31:13 +02:00
|
|
|
delete node->runtime->declaration;
|
2021-10-18 15:21:51 +02:00
|
|
|
}
|
2021-09-14 16:34:31 +02:00
|
|
|
|
2022-05-30 15:31:13 +02:00
|
|
|
MEM_delete(node->runtime);
|
2005-12-18 13:46:01 +00:00
|
|
|
MEM_freeN(node);
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2019-04-22 09:39:35 +10:00
|
|
|
if (ntree) {
|
2021-12-21 15:18:56 +01:00
|
|
|
BKE_ntree_update_tag_node_removed(ntree);
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2005-12-18 13:46:01 +00:00
|
|
|
}
|
|
|
|
|
|
2019-03-16 18:54:00 +01:00
|
|
|
void ntreeFreeLocalNode(bNodeTree *ntree, bNode *node)
|
2013-12-05 15:02:17 +01:00
|
|
|
{
|
2019-03-16 18:54:00 +01:00
|
|
|
/* For removing nodes while editing localized node trees. */
|
|
|
|
|
BLI_assert((ntree->id.tag & LIB_TAG_LOCALIZED) != 0);
|
2021-12-21 09:23:48 -06:00
|
|
|
|
|
|
|
|
/* These two lines assume the caller might want to free a single node and maintain
|
|
|
|
|
* a valid state in the node tree. */
|
|
|
|
|
nodeUnlinkNode(ntree, node);
|
|
|
|
|
node_unlink_attached(ntree, node);
|
|
|
|
|
|
2019-03-16 18:54:00 +01:00
|
|
|
node_free_node(ntree, node);
|
2018-11-23 17:02:55 +01:00
|
|
|
}
|
|
|
|
|
|
2019-03-16 18:54:00 +01:00
|
|
|
void nodeRemoveNode(Main *bmain, bNodeTree *ntree, bNode *node, bool do_id_user)
|
2018-11-23 17:02:55 +01:00
|
|
|
{
|
2019-03-16 18:54:00 +01:00
|
|
|
/* This function is not for localized node trees, we do not want
|
|
|
|
|
* do to ID user refcounting and removal of animdation data then. */
|
|
|
|
|
BLI_assert((ntree->id.tag & LIB_TAG_LOCALIZED) == 0);
|
|
|
|
|
|
2022-02-18 09:24:28 -06:00
|
|
|
bool node_has_id = false;
|
|
|
|
|
|
2019-03-16 18:54:00 +01:00
|
|
|
if (do_id_user) {
|
|
|
|
|
/* Free callback for NodeCustomGroup. */
|
|
|
|
|
if (node->typeinfo->freefunc_api) {
|
|
|
|
|
PointerRNA ptr;
|
|
|
|
|
RNA_pointer_create((ID *)ntree, &RNA_Node, node, &ptr);
|
|
|
|
|
|
|
|
|
|
node->typeinfo->freefunc_api(&ptr);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Do user counting. */
|
|
|
|
|
if (node->id) {
|
|
|
|
|
id_us_min(node->id);
|
2022-02-18 09:24:28 -06:00
|
|
|
node_has_id = true;
|
2019-03-16 18:54:00 +01:00
|
|
|
}
|
2020-04-20 13:22:20 +02:00
|
|
|
|
|
|
|
|
LISTBASE_FOREACH (bNodeSocket *, sock, &node->inputs) {
|
2022-02-18 09:24:28 -06:00
|
|
|
node_has_id |= socket_id_user_decrement(sock);
|
2020-04-20 13:22:20 +02:00
|
|
|
}
|
|
|
|
|
LISTBASE_FOREACH (bNodeSocket *, sock, &node->outputs) {
|
2022-02-18 09:24:28 -06:00
|
|
|
node_has_id |= socket_id_user_decrement(sock);
|
2020-04-20 13:22:20 +02:00
|
|
|
}
|
2019-03-16 18:54:00 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Remove animation data. */
|
|
|
|
|
char propname_esc[MAX_IDPROP_NAME * 2];
|
|
|
|
|
char prefix[MAX_IDPROP_NAME * 2];
|
|
|
|
|
|
2020-12-10 13:25:49 +11:00
|
|
|
BLI_str_escape(propname_esc, node->name, sizeof(propname_esc));
|
2019-03-16 18:54:00 +01:00
|
|
|
BLI_snprintf(prefix, sizeof(prefix), "nodes[\"%s\"]", propname_esc);
|
|
|
|
|
|
|
|
|
|
if (BKE_animdata_fix_paths_remove((ID *)ntree, prefix)) {
|
2021-02-02 09:51:38 -06:00
|
|
|
if (bmain != nullptr) {
|
2019-03-16 18:54:00 +01:00
|
|
|
DEG_relations_tag_update(bmain);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-08-09 19:09:43 -05:00
|
|
|
/* Also update relations for the scene time node, which causes a dependency
|
|
|
|
|
* on time that users expect to be removed when the node is removed. */
|
|
|
|
|
if (node_has_id || node->type == GEO_NODE_INPUT_SCENE_TIME) {
|
2022-02-18 09:24:28 -06:00
|
|
|
if (bmain != nullptr) {
|
|
|
|
|
DEG_relations_tag_update(bmain);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-12-21 09:23:48 -06:00
|
|
|
nodeUnlinkNode(ntree, node);
|
|
|
|
|
node_unlink_attached(ntree, node);
|
|
|
|
|
|
2019-03-16 18:54:00 +01:00
|
|
|
/* Free node itself. */
|
|
|
|
|
node_free_node(ntree, node);
|
2013-12-05 15:02:17 +01:00
|
|
|
}
|
|
|
|
|
|
2020-04-20 13:22:20 +02:00
|
|
|
static void node_socket_interface_free(bNodeTree *UNUSED(ntree),
|
|
|
|
|
bNodeSocket *sock,
|
|
|
|
|
const bool do_id_user)
|
2013-03-18 16:34:57 +00:00
|
|
|
{
|
|
|
|
|
if (sock->prop) {
|
2020-04-20 13:22:20 +02:00
|
|
|
IDP_FreeProperty_ex(sock->prop, do_id_user);
|
2013-03-18 16:34:57 +00:00
|
|
|
}
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2019-04-22 09:39:35 +10:00
|
|
|
if (sock->default_value) {
|
2020-04-20 13:22:20 +02:00
|
|
|
if (do_id_user) {
|
|
|
|
|
socket_id_user_decrement(sock);
|
|
|
|
|
}
|
2013-03-18 16:34:57 +00:00
|
|
|
MEM_freeN(sock->default_value);
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2022-05-30 15:31:13 +02:00
|
|
|
MEM_delete(sock->runtime);
|
2013-03-18 16:34:57 +00:00
|
|
|
}
|
|
|
|
|
|
2013-10-01 09:29:56 +00:00
|
|
|
static void free_localized_node_groups(bNodeTree *ntree)
|
|
|
|
|
{
|
2013-12-28 14:51:53 +01:00
|
|
|
/* Only localized node trees store a copy for each node group tree.
|
|
|
|
|
* Each node group tree in a localized node tree can be freed,
|
|
|
|
|
* since it is a localized copy itself (no risk of accessing free'd
|
2021-12-20 10:48:01 -06:00
|
|
|
* data in main, see T37939). */
|
2019-04-22 09:39:35 +10:00
|
|
|
if (!(ntree->id.tag & LIB_TAG_LOCALIZED)) {
|
2013-12-28 14:51:53 +01:00
|
|
|
return;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2020-09-02 18:28:04 +02:00
|
|
|
LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
|
2021-07-16 11:45:52 +10:00
|
|
|
if (ELEM(node->type, NODE_GROUP, NODE_CUSTOM_GROUP) && node->id) {
|
2013-10-01 11:44:39 +00:00
|
|
|
bNodeTree *ngroup = (bNodeTree *)node->id;
|
ID-Remap - Step one: core work (cleanup and rework of generic ID datablock handling).
This commit changes a lot of how IDs are handled internally, especially the unlinking/freeing
processes. So far, this was very fuzy, to summarize cleanly deleting or replacing a datablock
was pretty much impossible, except for a few special cases.
Also, unlinking was handled by each datatype, in a rather messy and prone-to-errors way (quite
a few ID usages were missed or wrongly handled that way).
One of the main goal of id-remap branch was to cleanup this, and fatorize ID links handling
by using library_query utils to allow generic handling of those, which is now the case
(now, generic ID links handling is only "knwon" from readfile.c and library_query.c).
This commit also adds backends to allow live replacement and deletion of datablocks in Blender
(so-called 'remapping' process, where we replace all usages of a given ID pointer by a new one,
or NULL one in case of unlinking).
This will allow nice new features, like ability to easily reload or relocate libraries, real immediate
deletion of datablocks in blender, replacement of one datablock by another, etc.
Some of those are for next commits.
A word of warning: this commit is highly risky, because it affects potentially a lot in Blender core.
Though it was tested rather deeply, being totally impossible to check all possible ID usage cases,
it's likely there are some remaining issues and bugs in new code... Please report them! ;)
Review task: D2027 (https://developer.blender.org/D2027).
Reviewed by campbellbarton, thanks a bunch.
2016-06-22 17:29:38 +02:00
|
|
|
ntreeFreeTree(ngroup);
|
2013-12-28 14:51:53 +01:00
|
|
|
MEM_freeN(ngroup);
|
2013-10-01 09:29:56 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
ID-Remap - Step one: core work (cleanup and rework of generic ID datablock handling).
This commit changes a lot of how IDs are handled internally, especially the unlinking/freeing
processes. So far, this was very fuzy, to summarize cleanly deleting or replacing a datablock
was pretty much impossible, except for a few special cases.
Also, unlinking was handled by each datatype, in a rather messy and prone-to-errors way (quite
a few ID usages were missed or wrongly handled that way).
One of the main goal of id-remap branch was to cleanup this, and fatorize ID links handling
by using library_query utils to allow generic handling of those, which is now the case
(now, generic ID links handling is only "knwon" from readfile.c and library_query.c).
This commit also adds backends to allow live replacement and deletion of datablocks in Blender
(so-called 'remapping' process, where we replace all usages of a given ID pointer by a new one,
or NULL one in case of unlinking).
This will allow nice new features, like ability to easily reload or relocate libraries, real immediate
deletion of datablocks in blender, replacement of one datablock by another, etc.
Some of those are for next commits.
A word of warning: this commit is highly risky, because it affects potentially a lot in Blender core.
Though it was tested rather deeply, being totally impossible to check all possible ID usage cases,
it's likely there are some remaining issues and bugs in new code... Please report them! ;)
Review task: D2027 (https://developer.blender.org/D2027).
Reviewed by campbellbarton, thanks a bunch.
2016-06-22 17:29:38 +02:00
|
|
|
void ntreeFreeTree(bNodeTree *ntree)
|
2005-12-18 13:46:01 +00:00
|
|
|
{
|
2020-03-06 14:57:26 +01:00
|
|
|
ntree_free_data(&ntree->id);
|
2020-03-09 18:40:06 +01:00
|
|
|
BKE_animdata_free(&ntree->id, false);
|
2018-12-14 15:20:33 +01:00
|
|
|
}
|
|
|
|
|
|
2020-04-20 16:14:45 +02:00
|
|
|
void ntreeFreeEmbeddedTree(bNodeTree *ntree)
|
2018-12-14 15:20:33 +01:00
|
|
|
{
|
|
|
|
|
ntreeFreeTree(ntree);
|
|
|
|
|
BKE_libblock_free_data(&ntree->id, true);
|
2021-08-11 16:56:11 +10:00
|
|
|
BKE_libblock_free_data_py(&ntree->id);
|
2018-12-14 15:20:33 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ntreeFreeLocalTree(bNodeTree *ntree)
|
|
|
|
|
{
|
|
|
|
|
if (ntree->id.tag & LIB_TAG_LOCALIZED) {
|
|
|
|
|
ntreeFreeTree(ntree);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
ntreeFreeTree(ntree);
|
2017-06-14 11:16:34 +02:00
|
|
|
BKE_libblock_free_data(&ntree->id, true);
|
2012-10-28 17:09:50 +00:00
|
|
|
}
|
2005-12-18 13:46:01 +00:00
|
|
|
}
|
|
|
|
|
|
2006-02-08 17:30:28 +00:00
|
|
|
void ntreeFreeCache(bNodeTree *ntree)
|
|
|
|
|
{
|
2021-02-02 09:51:38 -06:00
|
|
|
if (ntree == nullptr) {
|
2012-07-29 00:20:28 +00:00
|
|
|
return;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2019-04-22 09:39:35 +10:00
|
|
|
if (ntree->typeinfo->free_cache) {
|
2013-03-18 16:34:57 +00:00
|
|
|
ntree->typeinfo->free_cache(ntree);
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2011-09-05 21:01:50 +00:00
|
|
|
}
|
2006-02-11 23:17:41 +00:00
|
|
|
|
2011-09-05 21:01:50 +00:00
|
|
|
void ntreeSetOutput(bNodeTree *ntree)
|
|
|
|
|
{
|
2012-03-01 12:20:18 +00:00
|
|
|
/* find the active outputs, might become tree type dependent handler */
|
2020-09-02 18:28:04 +02:00
|
|
|
LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
|
2012-07-29 00:20:28 +00:00
|
|
|
if (node->typeinfo->nclass == NODE_CLASS_OUTPUT) {
|
2011-09-05 21:01:50 +00:00
|
|
|
/* we need a check for which output node should be tagged like this, below an exception */
|
2019-04-22 09:39:35 +10:00
|
|
|
if (node->type == CMP_NODE_OUTPUT_FILE) {
|
2011-11-11 13:09:14 +00:00
|
|
|
continue;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-09-02 18:28:04 +02:00
|
|
|
int output = 0;
|
2011-09-05 21:01:50 +00:00
|
|
|
/* there is more types having output class, each one is checked */
|
2020-09-02 18:28:04 +02:00
|
|
|
LISTBASE_FOREACH (bNode *, tnode, &ntree->nodes) {
|
2012-07-29 00:20:28 +00:00
|
|
|
if (tnode->typeinfo->nclass == NODE_CLASS_OUTPUT) {
|
|
|
|
|
if (ntree->type == NTREE_COMPOSIT) {
|
2011-09-05 21:01:50 +00:00
|
|
|
/* same type, exception for viewer */
|
2012-07-29 00:20:28 +00:00
|
|
|
if (tnode->type == node->type ||
|
2021-07-05 10:46:00 +02:00
|
|
|
(ELEM(tnode->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER, GEO_NODE_VIEWER) &&
|
|
|
|
|
ELEM(node->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER, GEO_NODE_VIEWER))) {
|
2012-03-24 06:18:31 +00:00
|
|
|
if (tnode->flag & NODE_DO_OUTPUT) {
|
2011-09-05 21:01:50 +00:00
|
|
|
output++;
|
2019-04-22 09:39:35 +10:00
|
|
|
if (output > 1) {
|
2011-09-05 21:01:50 +00:00
|
|
|
tnode->flag &= ~NODE_DO_OUTPUT;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2011-09-05 21:01:50 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
/* same type */
|
2012-07-29 00:20:28 +00:00
|
|
|
if (tnode->type == node->type) {
|
2012-03-24 06:18:31 +00:00
|
|
|
if (tnode->flag & NODE_DO_OUTPUT) {
|
2011-09-05 21:01:50 +00:00
|
|
|
output++;
|
2019-04-22 09:39:35 +10:00
|
|
|
if (output > 1) {
|
2011-09-05 21:01:50 +00:00
|
|
|
tnode->flag &= ~NODE_DO_OUTPUT;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2011-09-05 21:01:50 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2019-04-22 09:39:35 +10:00
|
|
|
if (output == 0) {
|
2011-09-05 21:01:50 +00:00
|
|
|
node->flag |= NODE_DO_OUTPUT;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2011-09-05 21:01:50 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2013-03-18 16:34:57 +00:00
|
|
|
/* group node outputs use this flag too */
|
|
|
|
|
if (node->type == NODE_GROUP_OUTPUT) {
|
|
|
|
|
int output = 0;
|
2020-09-02 18:28:04 +02:00
|
|
|
LISTBASE_FOREACH (bNode *, tnode, &ntree->nodes) {
|
2013-03-18 16:34:57 +00:00
|
|
|
if (tnode->type == NODE_GROUP_OUTPUT) {
|
|
|
|
|
if (tnode->flag & NODE_DO_OUTPUT) {
|
|
|
|
|
output++;
|
2019-04-22 09:39:35 +10:00
|
|
|
if (output > 1) {
|
2013-03-18 16:34:57 +00:00
|
|
|
tnode->flag &= ~NODE_DO_OUTPUT;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2013-03-18 16:34:57 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2019-04-22 09:39:35 +10:00
|
|
|
if (output == 0) {
|
2013-03-18 16:34:57 +00:00
|
|
|
node->flag |= NODE_DO_OUTPUT;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2013-03-18 16:34:57 +00:00
|
|
|
}
|
2011-09-05 21:01:50 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2011-09-05 21:01:50 +00:00
|
|
|
/* here we could recursively set which nodes have to be done,
|
2012-03-03 20:19:11 +00:00
|
|
|
* might be different for editor or for "real" use... */
|
2011-09-05 21:01:50 +00:00
|
|
|
}
|
|
|
|
|
|
2020-02-06 16:24:19 +01:00
|
|
|
bNodeTree **BKE_ntree_ptr_from_id(ID *id)
|
2012-12-03 16:21:43 +00:00
|
|
|
{
|
|
|
|
|
switch (GS(id->name)) {
|
2018-05-29 15:57:14 +02:00
|
|
|
case ID_MA:
|
2020-02-06 16:24:19 +01:00
|
|
|
return &((Material *)id)->nodetree;
|
2019-02-27 10:46:48 +11:00
|
|
|
case ID_LA:
|
2020-02-06 16:24:19 +01:00
|
|
|
return &((Light *)id)->nodetree;
|
2018-05-29 15:57:14 +02:00
|
|
|
case ID_WO:
|
2020-02-06 16:24:19 +01:00
|
|
|
return &((World *)id)->nodetree;
|
2018-05-29 15:57:14 +02:00
|
|
|
case ID_TE:
|
2020-02-06 16:24:19 +01:00
|
|
|
return &((Tex *)id)->nodetree;
|
2018-05-29 15:57:14 +02:00
|
|
|
case ID_SCE:
|
2020-02-06 16:24:19 +01:00
|
|
|
return &((Scene *)id)->nodetree;
|
2018-05-29 15:57:14 +02:00
|
|
|
case ID_LS:
|
2020-02-06 16:24:19 +01:00
|
|
|
return &((FreestyleLineStyle *)id)->nodetree;
|
2020-04-20 12:56:16 +02:00
|
|
|
case ID_SIM:
|
|
|
|
|
return &((Simulation *)id)->nodetree;
|
2012-12-03 16:21:43 +00:00
|
|
|
default:
|
2021-02-02 09:51:38 -06:00
|
|
|
return nullptr;
|
2012-12-03 16:21:43 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-02-06 16:24:19 +01:00
|
|
|
bNodeTree *ntreeFromID(ID *id)
|
|
|
|
|
{
|
|
|
|
|
bNodeTree **nodetree = BKE_ntree_ptr_from_id(id);
|
2021-02-02 09:51:38 -06:00
|
|
|
return (nodetree != nullptr) ? *nodetree : nullptr;
|
2020-02-06 16:24:19 +01:00
|
|
|
}
|
|
|
|
|
|
2015-08-01 16:16:16 +02:00
|
|
|
void ntreeNodeFlagSet(const bNodeTree *ntree, const int flag, const bool enable)
|
|
|
|
|
{
|
2020-09-02 18:28:04 +02:00
|
|
|
LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
|
2015-08-01 16:16:16 +02:00
|
|
|
if (enable) {
|
|
|
|
|
node->flag |= flag;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
node->flag &= ~flag;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2011-09-05 21:01:50 +00:00
|
|
|
bNodeTree *ntreeLocalize(bNodeTree *ntree)
|
|
|
|
|
{
|
2021-12-10 16:42:16 -06:00
|
|
|
if (ntree == nullptr) {
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
2019-03-20 18:17:24 +01:00
|
|
|
|
2021-12-10 16:42:16 -06:00
|
|
|
/* Make full copy outside of Main database.
|
|
|
|
|
* NOTE: previews are not copied here. */
|
|
|
|
|
bNodeTree *ltree = (bNodeTree *)BKE_id_copy_ex(
|
|
|
|
|
nullptr, &ntree->id, nullptr, (LIB_ID_COPY_LOCALIZE | LIB_ID_COPY_NO_ANIMDATA));
|
2015-06-26 14:47:53 +02:00
|
|
|
|
2021-12-10 16:42:16 -06:00
|
|
|
ltree->id.tag |= LIB_TAG_LOCALIZED;
|
2015-06-26 14:47:53 +02:00
|
|
|
|
2021-12-10 16:42:16 -06:00
|
|
|
LISTBASE_FOREACH (bNode *, node, <ree->nodes) {
|
|
|
|
|
if (ELEM(node->type, NODE_GROUP, NODE_CUSTOM_GROUP) && node->id) {
|
|
|
|
|
node->id = (ID *)ntreeLocalize((bNodeTree *)node->id);
|
2013-03-18 16:34:57 +00:00
|
|
|
}
|
2021-12-10 16:42:16 -06:00
|
|
|
}
|
2015-06-26 14:47:53 +02:00
|
|
|
|
2021-12-20 10:48:01 -06:00
|
|
|
/* Ensures only a single output node is enabled. */
|
2021-12-10 16:42:16 -06:00
|
|
|
ntreeSetOutput(ntree);
|
|
|
|
|
|
|
|
|
|
bNode *node_src = (bNode *)ntree->nodes.first;
|
|
|
|
|
bNode *node_local = (bNode *)ltree->nodes.first;
|
|
|
|
|
while (node_src != nullptr) {
|
|
|
|
|
node_local->original = node_src;
|
|
|
|
|
node_src = node_src->next;
|
|
|
|
|
node_local = node_local->next;
|
|
|
|
|
}
|
2015-06-26 14:47:53 +02:00
|
|
|
|
2021-12-10 16:42:16 -06:00
|
|
|
if (ntree->typeinfo->localize) {
|
|
|
|
|
ntree->typeinfo->localize(ltree, ntree);
|
2013-03-18 16:34:57 +00:00
|
|
|
}
|
2020-08-07 12:30:43 +02:00
|
|
|
|
2021-12-10 16:42:16 -06:00
|
|
|
return ltree;
|
2013-03-18 16:34:57 +00:00
|
|
|
}
|
2011-09-05 21:01:50 +00:00
|
|
|
|
2018-06-11 15:40:37 +02:00
|
|
|
void ntreeLocalMerge(Main *bmain, bNodeTree *localtree, bNodeTree *ntree)
|
2013-03-18 16:34:57 +00:00
|
|
|
{
|
2013-10-01 09:29:56 +00:00
|
|
|
if (ntree && localtree) {
|
2019-04-22 09:39:35 +10:00
|
|
|
if (ntree->typeinfo->local_merge) {
|
2018-06-11 15:40:37 +02:00
|
|
|
ntree->typeinfo->local_merge(bmain, localtree, ntree);
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2018-06-17 17:05:51 +02:00
|
|
|
|
ID-Remap - Step one: core work (cleanup and rework of generic ID datablock handling).
This commit changes a lot of how IDs are handled internally, especially the unlinking/freeing
processes. So far, this was very fuzy, to summarize cleanly deleting or replacing a datablock
was pretty much impossible, except for a few special cases.
Also, unlinking was handled by each datatype, in a rather messy and prone-to-errors way (quite
a few ID usages were missed or wrongly handled that way).
One of the main goal of id-remap branch was to cleanup this, and fatorize ID links handling
by using library_query utils to allow generic handling of those, which is now the case
(now, generic ID links handling is only "knwon" from readfile.c and library_query.c).
This commit also adds backends to allow live replacement and deletion of datablocks in Blender
(so-called 'remapping' process, where we replace all usages of a given ID pointer by a new one,
or NULL one in case of unlinking).
This will allow nice new features, like ability to easily reload or relocate libraries, real immediate
deletion of datablocks in blender, replacement of one datablock by another, etc.
Some of those are for next commits.
A word of warning: this commit is highly risky, because it affects potentially a lot in Blender core.
Though it was tested rather deeply, being totally impossible to check all possible ID usage cases,
it's likely there are some remaining issues and bugs in new code... Please report them! ;)
Review task: D2027 (https://developer.blender.org/D2027).
Reviewed by campbellbarton, thanks a bunch.
2016-06-22 17:29:38 +02:00
|
|
|
ntreeFreeTree(localtree);
|
2013-03-18 16:34:57 +00:00
|
|
|
MEM_freeN(localtree);
|
2011-09-05 21:01:50 +00:00
|
|
|
}
|
2013-03-18 16:34:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* ************ NODE TREE INTERFACE *************** */
|
2011-09-05 21:01:50 +00:00
|
|
|
|
2013-03-28 10:32:04 +00:00
|
|
|
static bNodeSocket *make_socket_interface(bNodeTree *ntree,
|
2021-03-26 14:25:52 -04:00
|
|
|
eNodeSocketInOut in_out,
|
2013-03-18 16:34:57 +00:00
|
|
|
const char *idname,
|
|
|
|
|
const char *name)
|
|
|
|
|
{
|
|
|
|
|
bNodeSocketType *stype = nodeSocketTypeFind(idname);
|
2021-02-02 09:51:38 -06:00
|
|
|
if (stype == nullptr) {
|
|
|
|
|
return nullptr;
|
2013-06-13 11:49:22 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2021-12-24 22:17:49 -05:00
|
|
|
bNodeSocket *sock = MEM_cnew<bNodeSocket>("socket template");
|
2022-05-30 15:31:13 +02:00
|
|
|
sock->runtime = MEM_new<bNodeSocketRuntime>(__func__);
|
2013-03-18 16:34:57 +00:00
|
|
|
BLI_strncpy(sock->idname, stype->idname, sizeof(sock->idname));
|
|
|
|
|
sock->in_out = in_out;
|
|
|
|
|
sock->type = SOCK_CUSTOM; /* int type undefined by default */
|
2022-05-01 09:27:22 +01:00
|
|
|
node_socket_set_typeinfo(ntree, sock, stype);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2013-03-18 16:34:57 +00:00
|
|
|
/* assign new unique index */
|
2021-06-14 18:37:25 +10:00
|
|
|
const int own_index = ntree->cur_index++;
|
2013-03-18 16:34:57 +00:00
|
|
|
/* use the own_index as socket identifier */
|
2019-04-22 09:39:35 +10:00
|
|
|
if (in_out == SOCK_IN) {
|
2013-03-18 16:34:57 +00:00
|
|
|
BLI_snprintf(sock->identifier, MAX_NAME, "Input_%d", own_index);
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
|
|
|
|
else {
|
2013-03-18 16:34:57 +00:00
|
|
|
BLI_snprintf(sock->identifier, MAX_NAME, "Output_%d", own_index);
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2013-03-18 16:34:57 +00:00
|
|
|
sock->limit = (in_out == SOCK_IN ? 1 : 0xFFF);
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2013-03-18 16:34:57 +00:00
|
|
|
BLI_strncpy(sock->name, name, NODE_MAXSTR);
|
2021-02-02 09:51:38 -06:00
|
|
|
sock->storage = nullptr;
|
2013-03-18 16:34:57 +00:00
|
|
|
sock->flag |= SOCK_COLLAPSED;
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2013-03-18 16:34:57 +00:00
|
|
|
return sock;
|
|
|
|
|
}
|
2011-09-05 21:01:50 +00:00
|
|
|
|
2021-03-26 14:25:52 -04:00
|
|
|
bNodeSocket *ntreeFindSocketInterface(bNodeTree *ntree,
|
|
|
|
|
eNodeSocketInOut in_out,
|
|
|
|
|
const char *identifier)
|
2013-03-18 16:34:57 +00:00
|
|
|
{
|
2020-09-02 18:28:04 +02:00
|
|
|
ListBase *sockets = (in_out == SOCK_IN) ? &ntree->inputs : &ntree->outputs;
|
|
|
|
|
LISTBASE_FOREACH (bNodeSocket *, iosock, sockets) {
|
2019-04-22 09:39:35 +10:00
|
|
|
if (STREQ(iosock->identifier, identifier)) {
|
2013-03-18 16:34:57 +00:00
|
|
|
return iosock;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
|
|
|
|
}
|
2021-02-02 09:51:38 -06:00
|
|
|
return nullptr;
|
2013-03-18 16:34:57 +00:00
|
|
|
}
|
2011-09-05 21:01:50 +00:00
|
|
|
|
2013-03-18 16:34:57 +00:00
|
|
|
bNodeSocket *ntreeAddSocketInterface(bNodeTree *ntree,
|
2021-03-26 14:25:52 -04:00
|
|
|
eNodeSocketInOut in_out,
|
2013-03-18 16:34:57 +00:00
|
|
|
const char *idname,
|
|
|
|
|
const char *name)
|
|
|
|
|
{
|
2020-09-02 18:28:04 +02:00
|
|
|
bNodeSocket *iosock = make_socket_interface(ntree, in_out, idname, name);
|
2013-03-18 16:34:57 +00:00
|
|
|
if (in_out == SOCK_IN) {
|
|
|
|
|
BLI_addtail(&ntree->inputs, iosock);
|
2011-09-05 21:01:50 +00:00
|
|
|
}
|
2013-03-18 16:34:57 +00:00
|
|
|
else if (in_out == SOCK_OUT) {
|
|
|
|
|
BLI_addtail(&ntree->outputs, iosock);
|
|
|
|
|
}
|
2021-12-21 15:18:56 +01:00
|
|
|
BKE_ntree_update_tag_interface(ntree);
|
2013-03-18 16:34:57 +00:00
|
|
|
return iosock;
|
|
|
|
|
}
|
2011-09-05 21:01:50 +00:00
|
|
|
|
2021-03-26 14:25:52 -04:00
|
|
|
bNodeSocket *ntreeInsertSocketInterface(bNodeTree *ntree,
|
|
|
|
|
eNodeSocketInOut in_out,
|
|
|
|
|
const char *idname,
|
|
|
|
|
bNodeSocket *next_sock,
|
|
|
|
|
const char *name)
|
2013-03-18 16:34:57 +00:00
|
|
|
{
|
2020-09-02 18:28:04 +02:00
|
|
|
bNodeSocket *iosock = make_socket_interface(ntree, in_out, idname, name);
|
2013-03-18 16:34:57 +00:00
|
|
|
if (in_out == SOCK_IN) {
|
|
|
|
|
BLI_insertlinkbefore(&ntree->inputs, next_sock, iosock);
|
|
|
|
|
}
|
|
|
|
|
else if (in_out == SOCK_OUT) {
|
|
|
|
|
BLI_insertlinkbefore(&ntree->outputs, next_sock, iosock);
|
|
|
|
|
}
|
2021-12-21 15:18:56 +01:00
|
|
|
BKE_ntree_update_tag_interface(ntree);
|
2013-03-18 16:34:57 +00:00
|
|
|
return iosock;
|
|
|
|
|
}
|
2011-09-05 21:01:50 +00:00
|
|
|
|
2013-03-18 16:34:57 +00:00
|
|
|
struct bNodeSocket *ntreeAddSocketInterfaceFromSocket(bNodeTree *ntree,
|
|
|
|
|
bNode *from_node,
|
|
|
|
|
bNodeSocket *from_sock)
|
|
|
|
|
{
|
2022-08-30 16:15:45 +10:00
|
|
|
bNodeSocket *iosock = ntreeAddSocketInterface(ntree,
|
|
|
|
|
static_cast<eNodeSocketInOut>(from_sock->in_out),
|
|
|
|
|
from_sock->idname,
|
|
|
|
|
DATA_(from_sock->name));
|
2013-03-18 16:34:57 +00:00
|
|
|
if (iosock) {
|
2019-04-22 09:39:35 +10:00
|
|
|
if (iosock->typeinfo->interface_from_socket) {
|
2013-03-18 16:34:57 +00:00
|
|
|
iosock->typeinfo->interface_from_socket(ntree, iosock, from_node, from_sock);
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2011-09-05 21:01:50 +00:00
|
|
|
}
|
2013-03-18 16:34:57 +00:00
|
|
|
return iosock;
|
|
|
|
|
}
|
2011-09-05 21:01:50 +00:00
|
|
|
|
2013-03-18 16:34:57 +00:00
|
|
|
struct bNodeSocket *ntreeInsertSocketInterfaceFromSocket(bNodeTree *ntree,
|
|
|
|
|
bNodeSocket *next_sock,
|
|
|
|
|
bNode *from_node,
|
|
|
|
|
bNodeSocket *from_sock)
|
|
|
|
|
{
|
|
|
|
|
bNodeSocket *iosock = ntreeInsertSocketInterface(
|
2021-03-26 14:25:52 -04:00
|
|
|
ntree,
|
|
|
|
|
static_cast<eNodeSocketInOut>(from_sock->in_out),
|
|
|
|
|
from_sock->idname,
|
|
|
|
|
next_sock,
|
|
|
|
|
from_sock->name);
|
2013-03-18 16:34:57 +00:00
|
|
|
if (iosock) {
|
2019-04-22 09:39:35 +10:00
|
|
|
if (iosock->typeinfo->interface_from_socket) {
|
2013-03-18 16:34:57 +00:00
|
|
|
iosock->typeinfo->interface_from_socket(ntree, iosock, from_node, from_sock);
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2013-03-18 16:34:57 +00:00
|
|
|
}
|
|
|
|
|
return iosock;
|
|
|
|
|
}
|
2011-09-05 21:01:50 +00:00
|
|
|
|
2013-03-18 16:34:57 +00:00
|
|
|
void ntreeRemoveSocketInterface(bNodeTree *ntree, bNodeSocket *sock)
|
|
|
|
|
{
|
|
|
|
|
/* this is fast, this way we don't need an in_out argument */
|
|
|
|
|
BLI_remlink(&ntree->inputs, sock);
|
|
|
|
|
BLI_remlink(&ntree->outputs, sock);
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2020-04-20 13:22:20 +02:00
|
|
|
node_socket_interface_free(ntree, sock, true);
|
2013-03-18 16:34:57 +00:00
|
|
|
MEM_freeN(sock);
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2021-12-21 15:18:56 +01:00
|
|
|
BKE_ntree_update_tag_interface(ntree);
|
2011-09-05 21:01:50 +00:00
|
|
|
}
|
|
|
|
|
|
2013-03-18 16:34:57 +00:00
|
|
|
/* generates a valid RNA identifier from the node tree name */
|
|
|
|
|
static void ntree_interface_identifier_base(bNodeTree *ntree, char *base)
|
2011-09-05 21:01:50 +00:00
|
|
|
{
|
2013-03-18 16:34:57 +00:00
|
|
|
/* generate a valid RNA identifier */
|
2013-03-18 18:25:05 +00:00
|
|
|
sprintf(base, "NodeTreeInterface_%s", ntree->id.name + 2);
|
2014-04-01 11:34:00 +11:00
|
|
|
RNA_identifier_sanitize(base, false);
|
2013-03-18 16:34:57 +00:00
|
|
|
}
|
2011-09-05 21:01:50 +00:00
|
|
|
|
2013-03-18 16:34:57 +00:00
|
|
|
/* check if the identifier is already in use */
|
|
|
|
|
static bool ntree_interface_unique_identifier_check(void *UNUSED(data), const char *identifier)
|
|
|
|
|
{
|
2021-02-02 09:51:38 -06:00
|
|
|
return (RNA_struct_find(identifier) != nullptr);
|
2011-09-05 21:01:50 +00:00
|
|
|
}
|
|
|
|
|
|
2013-03-18 16:34:57 +00:00
|
|
|
/* generates the actual unique identifier and ui name and description */
|
|
|
|
|
static void ntree_interface_identifier(bNodeTree *ntree,
|
|
|
|
|
const char *base,
|
|
|
|
|
char *identifier,
|
|
|
|
|
int maxlen,
|
|
|
|
|
char *name,
|
|
|
|
|
char *description)
|
|
|
|
|
{
|
|
|
|
|
/* There is a possibility that different node tree names get mapped to the same identifier
|
2019-07-02 17:38:36 +10:00
|
|
|
* after sanitation (e.g. "SomeGroup_A", "SomeGroup.A" both get sanitized to "SomeGroup_A").
|
2013-03-18 16:34:57 +00:00
|
|
|
* On top of the sanitized id string add a number suffix if necessary to avoid duplicates.
|
|
|
|
|
*/
|
|
|
|
|
identifier[0] = '\0';
|
2021-02-02 09:51:38 -06:00
|
|
|
BLI_uniquename_cb(
|
|
|
|
|
ntree_interface_unique_identifier_check, nullptr, base, '_', identifier, maxlen);
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2013-03-18 18:25:05 +00:00
|
|
|
sprintf(name, "Node Tree %s Interface", ntree->id.name + 2);
|
|
|
|
|
sprintf(description, "Interface properties of node group %s", ntree->id.name + 2);
|
2013-03-18 16:34:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void ntree_interface_type_create(bNodeTree *ntree)
|
2011-09-05 21:01:50 +00:00
|
|
|
{
|
2013-03-18 16:34:57 +00:00
|
|
|
/* strings are generated from base string + ID name, sizes are sufficient */
|
2013-03-18 18:25:05 +00:00
|
|
|
char base[MAX_ID_NAME + 64], identifier[MAX_ID_NAME + 64], name[MAX_ID_NAME + 64],
|
|
|
|
|
description[MAX_ID_NAME + 64];
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2013-03-18 16:34:57 +00:00
|
|
|
/* generate a valid RNA identifier */
|
|
|
|
|
ntree_interface_identifier_base(ntree, base);
|
|
|
|
|
ntree_interface_identifier(ntree, base, identifier, sizeof(identifier), name, description);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2013-03-18 16:34:57 +00:00
|
|
|
/* register a subtype of PropertyGroup */
|
2020-09-02 18:28:04 +02:00
|
|
|
StructRNA *srna = RNA_def_struct_ptr(&BLENDER_RNA, identifier, &RNA_PropertyGroup);
|
2013-03-18 16:34:57 +00:00
|
|
|
RNA_def_struct_ui_text(srna, name, description);
|
2017-08-23 14:14:55 +10:00
|
|
|
RNA_def_struct_duplicate_pointers(&BLENDER_RNA, srna);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2013-03-18 16:34:57 +00:00
|
|
|
/* associate the RNA type with the node tree */
|
|
|
|
|
ntree->interface_type = srna;
|
|
|
|
|
RNA_struct_blender_type_set(srna, ntree);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2013-03-18 16:34:57 +00:00
|
|
|
/* add socket properties */
|
2020-09-02 18:28:04 +02:00
|
|
|
LISTBASE_FOREACH (bNodeSocket *, sock, &ntree->inputs) {
|
2013-03-18 16:34:57 +00:00
|
|
|
bNodeSocketType *stype = sock->typeinfo;
|
2019-04-22 09:39:35 +10:00
|
|
|
if (stype && stype->interface_register_properties) {
|
2013-03-18 16:34:57 +00:00
|
|
|
stype->interface_register_properties(ntree, sock, srna);
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2013-03-18 16:34:57 +00:00
|
|
|
}
|
2020-09-02 18:28:04 +02:00
|
|
|
LISTBASE_FOREACH (bNodeSocket *, sock, &ntree->outputs) {
|
2013-03-18 16:34:57 +00:00
|
|
|
bNodeSocketType *stype = sock->typeinfo;
|
2019-04-22 09:39:35 +10:00
|
|
|
if (stype && stype->interface_register_properties) {
|
2013-03-18 16:34:57 +00:00
|
|
|
stype->interface_register_properties(ntree, sock, srna);
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2013-03-18 16:34:57 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-01-15 10:48:22 -06:00
|
|
|
StructRNA *ntreeInterfaceTypeGet(bNodeTree *ntree, bool create)
|
2013-03-18 16:34:57 +00:00
|
|
|
{
|
|
|
|
|
if (ntree->interface_type) {
|
|
|
|
|
/* strings are generated from base string + ID name, sizes are sufficient */
|
2013-03-18 18:25:05 +00:00
|
|
|
char base[MAX_ID_NAME + 64], identifier[MAX_ID_NAME + 64], name[MAX_ID_NAME + 64],
|
|
|
|
|
description[MAX_ID_NAME + 64];
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2013-03-18 16:34:57 +00:00
|
|
|
/* A bit of a hack: when changing the ID name, update the RNA type identifier too,
|
|
|
|
|
* so that the names match. This is not strictly necessary to keep it working,
|
|
|
|
|
* but better for identifying associated NodeTree blocks and RNA types.
|
|
|
|
|
*/
|
|
|
|
|
StructRNA *srna = ntree->interface_type;
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2013-03-18 16:34:57 +00:00
|
|
|
ntree_interface_identifier_base(ntree, base);
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2013-03-18 16:34:57 +00:00
|
|
|
/* RNA identifier may have a number suffix, but should start with the idbase string */
|
2015-01-26 16:03:11 +01:00
|
|
|
if (!STREQLEN(RNA_struct_identifier(srna), base, sizeof(base))) {
|
2013-03-18 16:34:57 +00:00
|
|
|
/* generate new unique RNA identifier from the ID name */
|
|
|
|
|
ntree_interface_identifier(ntree, base, identifier, sizeof(identifier), name, description);
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2013-03-18 16:34:57 +00:00
|
|
|
/* rename the RNA type */
|
2017-08-23 14:14:55 +10:00
|
|
|
RNA_def_struct_free_pointers(&BLENDER_RNA, srna);
|
2017-08-11 20:09:22 +10:00
|
|
|
RNA_def_struct_identifier(&BLENDER_RNA, srna, identifier);
|
2013-03-18 16:34:57 +00:00
|
|
|
RNA_def_struct_ui_text(srna, name, description);
|
2017-08-23 14:14:55 +10:00
|
|
|
RNA_def_struct_duplicate_pointers(&BLENDER_RNA, srna);
|
2008-11-12 22:03:11 +00:00
|
|
|
}
|
2006-02-07 15:50:55 +00:00
|
|
|
}
|
2013-03-18 16:34:57 +00:00
|
|
|
else if (create) {
|
|
|
|
|
ntree_interface_type_create(ntree);
|
|
|
|
|
}
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2013-03-18 16:34:57 +00:00
|
|
|
return ntree->interface_type;
|
|
|
|
|
}
|
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
|
|
|
|
2013-03-18 16:34:57 +00:00
|
|
|
void ntreeInterfaceTypeFree(bNodeTree *ntree)
|
|
|
|
|
{
|
|
|
|
|
if (ntree->interface_type) {
|
|
|
|
|
RNA_struct_free(&BLENDER_RNA, ntree->interface_type);
|
2021-02-02 09:51:38 -06:00
|
|
|
ntree->interface_type = nullptr;
|
2013-03-18 16:34:57 +00:00
|
|
|
}
|
|
|
|
|
}
|
2011-09-05 21:01:50 +00:00
|
|
|
|
2013-03-18 16:34:57 +00:00
|
|
|
void ntreeInterfaceTypeUpdate(bNodeTree *ntree)
|
|
|
|
|
{
|
|
|
|
|
/* XXX it would be sufficient to just recreate all properties
|
|
|
|
|
* instead of re-registering the whole struct type,
|
|
|
|
|
* but there is currently no good way to do this in the RNA functions.
|
|
|
|
|
* Overhead should be negligible.
|
|
|
|
|
*/
|
|
|
|
|
ntreeInterfaceTypeFree(ntree);
|
|
|
|
|
ntree_interface_type_create(ntree);
|
2011-09-05 21:01:50 +00:00
|
|
|
}
|
2006-02-07 15:50:55 +00:00
|
|
|
|
2006-12-30 16:35:46 +00:00
|
|
|
/* ************ find stuff *************** */
|
2005-12-18 23:08:22 +00:00
|
|
|
|
2016-06-19 06:25:54 +10:00
|
|
|
bNode *ntreeFindType(const bNodeTree *ntree, int type)
|
|
|
|
|
{
|
2016-06-14 11:31:00 +02:00
|
|
|
if (ntree) {
|
2020-04-03 19:15:01 +02:00
|
|
|
LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
|
2016-06-14 11:31:00 +02:00
|
|
|
if (node->type == type) {
|
|
|
|
|
return node;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2021-02-02 09:51:38 -06:00
|
|
|
return nullptr;
|
2016-06-14 11:31:00 +02:00
|
|
|
}
|
|
|
|
|
|
2014-01-27 20:17:56 +11:00
|
|
|
bool ntreeHasTree(const bNodeTree *ntree, const bNodeTree *lookup)
|
|
|
|
|
{
|
2019-04-22 09:39:35 +10:00
|
|
|
if (ntree == lookup) {
|
2014-01-27 20:17:56 +11:00
|
|
|
return true;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2020-09-02 18:28:04 +02:00
|
|
|
LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
|
2019-04-22 09:39:35 +10:00
|
|
|
if (ELEM(node->type, NODE_GROUP, NODE_CUSTOM_GROUP) && node->id) {
|
|
|
|
|
if (ntreeHasTree((bNodeTree *)node->id, lookup)) {
|
2014-01-27 20:17:56 +11:00
|
|
|
return true;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2014-01-27 20:17:56 +11:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2021-01-15 10:48:22 -06:00
|
|
|
bNodeLink *nodeFindLink(bNodeTree *ntree, const bNodeSocket *from, const bNodeSocket *to)
|
2005-12-18 23:08:22 +00:00
|
|
|
{
|
2020-09-02 18:28:04 +02:00
|
|
|
LISTBASE_FOREACH (bNodeLink *, link, &ntree->links) {
|
2019-04-22 09:39:35 +10:00
|
|
|
if (link->fromsock == from && link->tosock == to) {
|
2005-12-18 23:08:22 +00:00
|
|
|
return link;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
|
|
|
|
if (link->fromsock == to && link->tosock == from) { /* hrms? */
|
2005-12-18 23:08:22 +00:00
|
|
|
return link;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2005-12-18 23:08:22 +00:00
|
|
|
}
|
2021-02-02 09:51:38 -06:00
|
|
|
return nullptr;
|
2005-12-18 23:08:22 +00:00
|
|
|
}
|
|
|
|
|
|
2021-01-15 10:48:22 -06:00
|
|
|
int nodeCountSocketLinks(const bNodeTree *ntree, const bNodeSocket *sock)
|
2005-12-20 15:43:55 +00:00
|
|
|
{
|
2012-07-29 00:20:28 +00:00
|
|
|
int tot = 0;
|
2021-01-15 10:48:22 -06:00
|
|
|
LISTBASE_FOREACH (const bNodeLink *, link, &ntree->links) {
|
2019-04-22 09:39:35 +10:00
|
|
|
if (link->fromsock == sock || link->tosock == sock) {
|
2005-12-20 15:43:55 +00:00
|
|
|
tot++;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2005-12-20 15:43:55 +00:00
|
|
|
}
|
|
|
|
|
return tot;
|
|
|
|
|
}
|
|
|
|
|
|
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
|
|
|
bNode *nodeGetActive(bNodeTree *ntree)
|
|
|
|
|
{
|
2021-02-02 09:51:38 -06:00
|
|
|
if (ntree == nullptr) {
|
|
|
|
|
return nullptr;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-09-02 18:28:04 +02:00
|
|
|
LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
|
2019-04-22 09:39:35 +10:00
|
|
|
if (node->flag & NODE_ACTIVE) {
|
2020-09-02 18:28:04 +02:00
|
|
|
return node;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
|
|
|
|
}
|
2021-02-02 09:51:38 -06:00
|
|
|
return nullptr;
|
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
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2014-03-31 23:39:08 +11:00
|
|
|
void nodeSetSelected(bNode *node, bool select)
|
2013-03-18 16:34:57 +00:00
|
|
|
{
|
|
|
|
|
if (select) {
|
|
|
|
|
node->flag |= NODE_SELECT;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
node->flag &= ~NODE_SELECT;
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2013-03-18 16:34:57 +00:00
|
|
|
/* deselect sockets too */
|
2020-09-02 18:28:04 +02:00
|
|
|
LISTBASE_FOREACH (bNodeSocket *, sock, &node->inputs) {
|
2013-03-18 16:34:57 +00:00
|
|
|
sock->flag &= ~NODE_SELECT;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2020-09-02 18:28:04 +02:00
|
|
|
LISTBASE_FOREACH (bNodeSocket *, sock, &node->outputs) {
|
2013-03-18 16:34:57 +00:00
|
|
|
sock->flag &= ~NODE_SELECT;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2013-03-18 16:34:57 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2012-06-11 18:43:48 +00:00
|
|
|
void nodeClearActive(bNodeTree *ntree)
|
|
|
|
|
{
|
2021-02-02 09:51:38 -06:00
|
|
|
if (ntree == nullptr) {
|
2012-07-29 00:20:28 +00:00
|
|
|
return;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2012-06-11 18:43:48 +00:00
|
|
|
|
2020-09-02 18:28:04 +02:00
|
|
|
LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
|
2022-01-10 16:42:50 -06:00
|
|
|
node->flag &= ~NODE_ACTIVE;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2012-06-11 18:43:48 +00:00
|
|
|
}
|
|
|
|
|
|
More node goodies!
First note; this is a WIP project, some commits might change things that
make formerly saved situations not to work identically... like now!
------ New Material integration ------
Until now, the Node system worked on top of the 'current' Material, just
like how the Material Layers worked. That's quite confusing in practice,
especially to see what Material is a Node, or what is the "base material"
Best solution is to completely separate the two. This has been implemented
as follows now;
- The confusing "Input" node has been removed.
- When choosing a Material in Blender, you can define this Material to be
either 'normal' (default) or be the root of a Node tree.
- If a Material is a Node tree, you have to add Nodes in the tree to see
something happen. An empty Node tree doesn't do anything (black).
- If a Material is a Node Tree, the 'data browse' menus show it with an
'N' mark before the name. The 'data block' buttons display it with the
suffix 'NT' (instead of 'MA').
- In a Node Tree, any Material can be inserted, including itself. Only in
that case the Material is being used itself for shading.
UI changes:
Added a new Panel "Links", which shows:
- where the Material is linked to (Object, Mesh, etc)
- if the Material is a NodeTree or not
- the actual active Material in the Tree
The "Node" Panel itself now only shows buttons from the other nodes, when
they are active.
Further the Material Nodes themselves allow browsing and renaming or adding
new Materials now too.
Second half of today's work was cleaning up selection when the Nodes
overlap... it was possible to drag links from invisible sockets, or click
headers for invisible nodes, etc. This because the mouse input code was
not checking for visibility yet.
Works now even for buttons. :)
2005-12-29 18:08:01 +00:00
|
|
|
void nodeSetActive(bNodeTree *ntree, bNode *node)
|
|
|
|
|
{
|
2022-04-08 16:37:35 +02:00
|
|
|
const bool is_paint_canvas = nodeSupportsActiveFlag(node, NODE_ACTIVE_PAINT_CANVAS);
|
|
|
|
|
const bool is_texture_class = nodeSupportsActiveFlag(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);
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2022-04-08 16:37:35 +02:00
|
|
|
/* Make sure only one node is active per node tree. */
|
|
|
|
|
LISTBASE_FOREACH (bNode *, tnode, &ntree->nodes) {
|
|
|
|
|
tnode->flag &= ~flags_to_set;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2022-04-08 16:37:35 +02:00
|
|
|
node->flag |= flags_to_set;
|
2009-01-27 17:12:40 +00:00
|
|
|
}
|
|
|
|
|
|
2021-01-15 10:48:22 -06:00
|
|
|
int nodeSocketIsHidden(const bNodeSocket *sock)
|
2012-01-08 10:23:19 +00:00
|
|
|
{
|
2013-03-18 16:34:57 +00:00
|
|
|
return ((sock->flag & (SOCK_HIDDEN | SOCK_UNAVAIL)) != 0);
|
2012-03-01 07:56:15 +00:00
|
|
|
}
|
|
|
|
|
|
2021-12-21 15:18:56 +01:00
|
|
|
void nodeSetSocketAvailability(bNodeTree *ntree, bNodeSocket *sock, bool is_available)
|
2019-08-18 11:16:04 +02:00
|
|
|
{
|
2021-12-21 15:18:56 +01:00
|
|
|
const bool was_available = (sock->flag & SOCK_UNAVAIL) == 0;
|
|
|
|
|
if (is_available != was_available) {
|
|
|
|
|
BKE_ntree_update_tag_socket_availability(ntree, sock);
|
|
|
|
|
}
|
|
|
|
|
|
2019-08-18 11:16:04 +02:00
|
|
|
if (is_available) {
|
|
|
|
|
sock->flag &= ~SOCK_UNAVAIL;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
sock->flag |= SOCK_UNAVAIL;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-01-15 10:48:22 -06:00
|
|
|
int nodeSocketLinkLimit(const bNodeSocket *sock)
|
Nodes: Support storing socket link limits in bNodeSocketType
Currently the link limit of sockets is stored in bNodeSocket->limit.
This allows for a lot of flexibility, but is also very redundant.
In every case I've had to deal with so far, it would have "more correct"
to set the link limit per socket type and not per socket. I did not enforce
this constraint yet, because the link limit is exposed in the Python API,
which I did not want to break here.
In the future it might even make sense to only support only three kinds of link limits:
a) no links, b) at most one link, c) an arbitrary number links links. The other link
limits usually don't work well with tools (e.g. which link should be removed when a new
one is connected?) and is not used in practice. However, that is for another day.
Eventually, I would like to get rid of bNodeSocket->limit completely and replace it
either with fixed link limits or a callback in bNodeSocketType.
This patch consists of three parts:
**1. Support defining link limit in socket type**
This introduces a new `nodeSocketLinkLimit` function that serves as an indirection to
hide where the link limit of a socket is defined.
**2. Define link limits for builtin sockets on socket type**
Data sockets: one input, many outputs
Virtual sockets: one input, one output
Undefined sockets: many inputs, many outputs (to avoid that links are removed when the type of the socket is not known)
**3. Remove `bNodeSocketTemplate->limit`**
This wasn't used anymore after the second commit. Removing it simplifies socket definitions
in hundreds of places and removes a lot of redundancy.
Differential Revision: https://developer.blender.org/D7038
Reviewers: brecht
2020-03-06 12:20:05 +01:00
|
|
|
{
|
|
|
|
|
bNodeSocketType *stype = sock->typeinfo;
|
2021-02-03 11:02:01 -06:00
|
|
|
if (sock->flag & SOCK_MULTI_INPUT) {
|
|
|
|
|
return 4095;
|
|
|
|
|
}
|
2021-02-02 09:51:38 -06:00
|
|
|
if (stype != nullptr && stype->use_link_limits_of_type) {
|
Nodes: Support storing socket link limits in bNodeSocketType
Currently the link limit of sockets is stored in bNodeSocket->limit.
This allows for a lot of flexibility, but is also very redundant.
In every case I've had to deal with so far, it would have "more correct"
to set the link limit per socket type and not per socket. I did not enforce
this constraint yet, because the link limit is exposed in the Python API,
which I did not want to break here.
In the future it might even make sense to only support only three kinds of link limits:
a) no links, b) at most one link, c) an arbitrary number links links. The other link
limits usually don't work well with tools (e.g. which link should be removed when a new
one is connected?) and is not used in practice. However, that is for another day.
Eventually, I would like to get rid of bNodeSocket->limit completely and replace it
either with fixed link limits or a callback in bNodeSocketType.
This patch consists of three parts:
**1. Support defining link limit in socket type**
This introduces a new `nodeSocketLinkLimit` function that serves as an indirection to
hide where the link limit of a socket is defined.
**2. Define link limits for builtin sockets on socket type**
Data sockets: one input, many outputs
Virtual sockets: one input, one output
Undefined sockets: many inputs, many outputs (to avoid that links are removed when the type of the socket is not known)
**3. Remove `bNodeSocketTemplate->limit`**
This wasn't used anymore after the second commit. Removing it simplifies socket definitions
in hundreds of places and removes a lot of redundancy.
Differential Revision: https://developer.blender.org/D7038
Reviewers: brecht
2020-03-06 12:20:05 +01:00
|
|
|
int limit = (sock->in_out == SOCK_IN) ? stype->input_link_limit : stype->output_link_limit;
|
|
|
|
|
return limit;
|
|
|
|
|
}
|
2020-08-07 12:30:43 +02:00
|
|
|
|
|
|
|
|
return sock->limit;
|
Nodes: Support storing socket link limits in bNodeSocketType
Currently the link limit of sockets is stored in bNodeSocket->limit.
This allows for a lot of flexibility, but is also very redundant.
In every case I've had to deal with so far, it would have "more correct"
to set the link limit per socket type and not per socket. I did not enforce
this constraint yet, because the link limit is exposed in the Python API,
which I did not want to break here.
In the future it might even make sense to only support only three kinds of link limits:
a) no links, b) at most one link, c) an arbitrary number links links. The other link
limits usually don't work well with tools (e.g. which link should be removed when a new
one is connected?) and is not used in practice. However, that is for another day.
Eventually, I would like to get rid of bNodeSocket->limit completely and replace it
either with fixed link limits or a callback in bNodeSocketType.
This patch consists of three parts:
**1. Support defining link limit in socket type**
This introduces a new `nodeSocketLinkLimit` function that serves as an indirection to
hide where the link limit of a socket is defined.
**2. Define link limits for builtin sockets on socket type**
Data sockets: one input, many outputs
Virtual sockets: one input, one output
Undefined sockets: many inputs, many outputs (to avoid that links are removed when the type of the socket is not known)
**3. Remove `bNodeSocketTemplate->limit`**
This wasn't used anymore after the second commit. Removing it simplifies socket definitions
in hundreds of places and removes a lot of redundancy.
Differential Revision: https://developer.blender.org/D7038
Reviewers: brecht
2020-03-06 12:20:05 +01:00
|
|
|
}
|
|
|
|
|
|
2021-11-08 12:23:50 +01:00
|
|
|
static void update_socket_declarations(ListBase *sockets,
|
|
|
|
|
Span<blender::nodes::SocketDeclarationPtr> declarations)
|
|
|
|
|
{
|
|
|
|
|
int index;
|
|
|
|
|
LISTBASE_FOREACH_INDEX (bNodeSocket *, socket, sockets, index) {
|
|
|
|
|
const SocketDeclaration &socket_decl = *declarations[index];
|
2022-05-30 15:31:13 +02:00
|
|
|
socket->runtime->declaration = &socket_decl;
|
2021-11-08 12:23:50 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void nodeSocketDeclarationsUpdate(bNode *node)
|
|
|
|
|
{
|
2022-05-30 15:31:13 +02:00
|
|
|
BLI_assert(node->runtime->declaration != nullptr);
|
|
|
|
|
update_socket_declarations(&node->inputs, node->runtime->declaration->inputs());
|
|
|
|
|
update_socket_declarations(&node->outputs, node->runtime->declaration->outputs());
|
2021-11-08 12:23:50 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool nodeDeclarationEnsureOnOutdatedNode(bNodeTree *UNUSED(ntree), bNode *node)
|
2021-09-14 16:34:31 +02:00
|
|
|
{
|
2022-05-30 15:31:13 +02:00
|
|
|
if (node->runtime->declaration != nullptr) {
|
2021-11-08 12:23:50 +01:00
|
|
|
return false;
|
2021-09-14 16:34:31 +02:00
|
|
|
}
|
2021-10-18 15:21:51 +02:00
|
|
|
if (node->typeinfo->declare == nullptr) {
|
2021-11-08 12:23:50 +01:00
|
|
|
return false;
|
2021-09-17 13:31:06 +02:00
|
|
|
}
|
2021-10-18 15:21:51 +02:00
|
|
|
if (node->typeinfo->declaration_is_dynamic) {
|
2022-05-30 15:31:13 +02:00
|
|
|
node->runtime->declaration = new blender::nodes::NodeDeclaration();
|
|
|
|
|
blender::nodes::NodeDeclarationBuilder builder{*node->runtime->declaration};
|
2021-10-18 15:21:51 +02:00
|
|
|
node->typeinfo->declare(builder);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
/* Declaration should have been created in #nodeRegisterType. */
|
|
|
|
|
BLI_assert(node->typeinfo->fixed_declaration != nullptr);
|
2022-05-30 15:31:13 +02:00
|
|
|
node->runtime->declaration = node->typeinfo->fixed_declaration;
|
2021-10-18 15:21:51 +02:00
|
|
|
}
|
2021-11-08 12:23:50 +01:00
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool nodeDeclarationEnsure(bNodeTree *ntree, bNode *node)
|
|
|
|
|
{
|
|
|
|
|
if (nodeDeclarationEnsureOnOutdatedNode(ntree, node)) {
|
|
|
|
|
nodeSocketDeclarationsUpdate(node);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
return false;
|
2021-09-14 16:34:31 +02:00
|
|
|
}
|
|
|
|
|
|
2012-08-02 09:52:37 +00:00
|
|
|
/* ************** Node Clipboard *********** */
|
|
|
|
|
|
2012-08-20 13:51:25 +00:00
|
|
|
#define USE_NODE_CB_VALIDATE
|
|
|
|
|
|
|
|
|
|
#ifdef USE_NODE_CB_VALIDATE
|
|
|
|
|
/**
|
|
|
|
|
* This data structure is to validate the node on creation,
|
|
|
|
|
* otherwise we may reference missing data.
|
|
|
|
|
*
|
|
|
|
|
* Currently its only used for ID's, but nodes may one day
|
2012-08-24 23:22:34 +00:00
|
|
|
* reference other pointers which need validation.
|
2012-08-20 13:51:25 +00:00
|
|
|
*/
|
2021-02-02 09:51:38 -06:00
|
|
|
struct bNodeClipboardExtraInfo {
|
2012-08-23 16:17:47 +00:00
|
|
|
struct bNodeClipboardExtraInfo *next, *prev;
|
2012-08-20 13:51:25 +00:00
|
|
|
ID *id;
|
2012-08-23 16:17:47 +00:00
|
|
|
char id_name[MAX_ID_NAME];
|
|
|
|
|
char library_name[FILE_MAX];
|
2021-02-02 09:51:38 -06:00
|
|
|
};
|
2012-08-20 13:51:25 +00:00
|
|
|
#endif /* USE_NODE_CB_VALIDATE */
|
|
|
|
|
|
2021-02-02 09:51:38 -06:00
|
|
|
struct bNodeClipboard {
|
2012-08-02 09:52:37 +00:00
|
|
|
ListBase nodes;
|
2012-08-20 13:51:25 +00:00
|
|
|
|
|
|
|
|
#ifdef USE_NODE_CB_VALIDATE
|
2012-08-23 16:17:47 +00:00
|
|
|
ListBase nodes_extra_info;
|
2012-08-20 13:51:25 +00:00
|
|
|
#endif
|
|
|
|
|
|
2012-08-02 09:52:37 +00:00
|
|
|
ListBase links;
|
2012-08-06 08:41:45 +00:00
|
|
|
int type;
|
2021-02-02 09:51:38 -06:00
|
|
|
};
|
2012-08-02 09:52:37 +00:00
|
|
|
|
2021-02-02 09:51:38 -06:00
|
|
|
static bNodeClipboard node_clipboard = {{nullptr}};
|
2012-08-02 09:52:37 +00:00
|
|
|
|
2021-01-25 21:11:57 -06:00
|
|
|
void BKE_node_clipboard_init(const struct bNodeTree *ntree)
|
2012-08-06 08:41:45 +00:00
|
|
|
{
|
|
|
|
|
node_clipboard.type = ntree->type;
|
|
|
|
|
}
|
|
|
|
|
|
2021-12-08 00:31:20 -05:00
|
|
|
void BKE_node_clipboard_clear()
|
2012-08-02 09:52:37 +00:00
|
|
|
{
|
2020-09-02 18:28:04 +02:00
|
|
|
LISTBASE_FOREACH_MUTABLE (bNodeLink *, link, &node_clipboard.links) {
|
2021-02-02 09:51:38 -06:00
|
|
|
nodeRemLink(nullptr, link);
|
2012-08-02 09:52:37 +00:00
|
|
|
}
|
2014-02-08 06:07:10 +11:00
|
|
|
BLI_listbase_clear(&node_clipboard.links);
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2020-09-02 18:28:04 +02:00
|
|
|
LISTBASE_FOREACH_MUTABLE (bNode *, node, &node_clipboard.nodes) {
|
2021-02-02 09:51:38 -06:00
|
|
|
node_free_node(nullptr, node);
|
2012-08-02 09:52:37 +00:00
|
|
|
}
|
2014-02-08 06:07:10 +11:00
|
|
|
BLI_listbase_clear(&node_clipboard.nodes);
|
2012-08-20 13:51:25 +00:00
|
|
|
|
|
|
|
|
#ifdef USE_NODE_CB_VALIDATE
|
2012-08-23 16:17:47 +00:00
|
|
|
BLI_freelistN(&node_clipboard.nodes_extra_info);
|
2012-08-20 13:51:25 +00:00
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
2021-12-08 00:31:20 -05:00
|
|
|
bool BKE_node_clipboard_validate()
|
2012-08-20 13:51:25 +00:00
|
|
|
{
|
2014-01-28 03:52:21 +11:00
|
|
|
bool ok = true;
|
2012-08-20 13:51:25 +00:00
|
|
|
|
|
|
|
|
#ifdef USE_NODE_CB_VALIDATE
|
|
|
|
|
bNodeClipboardExtraInfo *node_info;
|
|
|
|
|
bNode *node;
|
|
|
|
|
|
|
|
|
|
/* lists must be aligned */
|
2014-11-16 13:57:58 +01:00
|
|
|
BLI_assert(BLI_listbase_count(&node_clipboard.nodes) ==
|
|
|
|
|
BLI_listbase_count(&node_clipboard.nodes_extra_info));
|
2012-08-20 13:51:25 +00:00
|
|
|
|
2021-02-02 09:51:38 -06:00
|
|
|
for (node = (bNode *)node_clipboard.nodes.first,
|
|
|
|
|
node_info = (bNodeClipboardExtraInfo *)node_clipboard.nodes_extra_info.first;
|
|
|
|
|
node;
|
|
|
|
|
node = (bNode *)node->next, node_info = (bNodeClipboardExtraInfo *)node_info->next) {
|
2012-08-20 13:51:25 +00:00
|
|
|
/* validate the node against the stored node info */
|
|
|
|
|
|
|
|
|
|
/* re-assign each loop since we may clear,
|
|
|
|
|
* open a new file where the ID is valid, and paste again */
|
|
|
|
|
node->id = node_info->id;
|
|
|
|
|
|
|
|
|
|
/* currently only validate the ID */
|
|
|
|
|
if (node->id) {
|
2018-06-20 12:16:16 +02:00
|
|
|
/* We want to search into current blend file, so using G_MAIN is valid here too. */
|
|
|
|
|
ListBase *lb = which_libbase(G_MAIN, GS(node_info->id_name));
|
2021-02-02 09:51:38 -06:00
|
|
|
BLI_assert(lb != nullptr);
|
2012-08-20 13:51:25 +00:00
|
|
|
|
|
|
|
|
if (BLI_findindex(lb, node_info->id) == -1) {
|
2021-02-02 09:51:38 -06:00
|
|
|
/* May assign null. */
|
|
|
|
|
node->id = (ID *)BLI_findstring(lb, node_info->id_name + 2, offsetof(ID, name) + 2);
|
2012-08-20 13:59:19 +00:00
|
|
|
|
2021-02-02 09:51:38 -06:00
|
|
|
if (node->id == nullptr) {
|
2014-01-28 03:52:21 +11:00
|
|
|
ok = false;
|
2012-08-20 13:51:25 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#endif /* USE_NODE_CB_VALIDATE */
|
|
|
|
|
|
|
|
|
|
return ok;
|
2012-08-02 09:52:37 +00:00
|
|
|
}
|
|
|
|
|
|
2012-08-06 08:25:24 +00:00
|
|
|
void BKE_node_clipboard_add_node(bNode *node)
|
2012-08-02 09:52:37 +00:00
|
|
|
{
|
2012-08-20 13:51:25 +00:00
|
|
|
#ifdef USE_NODE_CB_VALIDATE
|
2012-08-23 16:17:47 +00:00
|
|
|
/* add extra info */
|
2021-02-02 09:51:38 -06:00
|
|
|
bNodeClipboardExtraInfo *node_info = (bNodeClipboardExtraInfo *)MEM_mallocN(
|
|
|
|
|
sizeof(bNodeClipboardExtraInfo), __func__);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-08-20 13:51:25 +00:00
|
|
|
node_info->id = node->id;
|
2012-08-23 16:17:47 +00:00
|
|
|
if (node->id) {
|
|
|
|
|
BLI_strncpy(node_info->id_name, node->id->name, sizeof(node_info->id_name));
|
2017-11-06 17:17:10 +01:00
|
|
|
if (ID_IS_LINKED(node->id)) {
|
2012-08-23 16:17:47 +00:00
|
|
|
BLI_strncpy(
|
2020-06-23 09:54:07 +10:00
|
|
|
node_info->library_name, node->id->lib->filepath_abs, sizeof(node_info->library_name));
|
2012-08-23 16:17:47 +00:00
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
node_info->library_name[0] = '\0';
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2012-08-23 16:17:47 +00:00
|
|
|
else {
|
|
|
|
|
node_info->id_name[0] = '\0';
|
|
|
|
|
node_info->library_name[0] = '\0';
|
|
|
|
|
}
|
|
|
|
|
BLI_addtail(&node_clipboard.nodes_extra_info, node_info);
|
2012-08-20 13:51:25 +00:00
|
|
|
/* end extra info */
|
|
|
|
|
#endif /* USE_NODE_CB_VALIDATE */
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-08-23 16:17:47 +00:00
|
|
|
/* add node */
|
2012-08-02 09:52:37 +00:00
|
|
|
BLI_addtail(&node_clipboard.nodes, node);
|
|
|
|
|
}
|
|
|
|
|
|
2012-08-06 08:25:24 +00:00
|
|
|
void BKE_node_clipboard_add_link(bNodeLink *link)
|
2012-08-02 09:52:37 +00:00
|
|
|
{
|
|
|
|
|
BLI_addtail(&node_clipboard.links, link);
|
|
|
|
|
}
|
|
|
|
|
|
2021-12-08 00:31:20 -05:00
|
|
|
const ListBase *BKE_node_clipboard_get_nodes()
|
2012-08-02 09:52:37 +00:00
|
|
|
{
|
|
|
|
|
return &node_clipboard.nodes;
|
|
|
|
|
}
|
|
|
|
|
|
2021-12-08 00:31:20 -05:00
|
|
|
const ListBase *BKE_node_clipboard_get_links()
|
2012-08-02 09:52:37 +00:00
|
|
|
{
|
|
|
|
|
return &node_clipboard.links;
|
|
|
|
|
}
|
|
|
|
|
|
2021-12-08 00:31:20 -05:00
|
|
|
int BKE_node_clipboard_get_type()
|
2012-08-06 08:41:45 +00:00
|
|
|
{
|
|
|
|
|
return node_clipboard.type;
|
|
|
|
|
}
|
|
|
|
|
|
2021-12-08 00:31:20 -05:00
|
|
|
void BKE_node_clipboard_free()
|
2019-03-16 18:54:00 +01:00
|
|
|
{
|
|
|
|
|
BKE_node_clipboard_validate();
|
|
|
|
|
BKE_node_clipboard_clear();
|
|
|
|
|
}
|
2013-03-18 16:34:57 +00:00
|
|
|
|
|
|
|
|
/* Node Instance Hash */
|
|
|
|
|
|
|
|
|
|
const bNodeInstanceKey NODE_INSTANCE_KEY_BASE = {5381};
|
2013-04-24 16:36:50 +00:00
|
|
|
const bNodeInstanceKey NODE_INSTANCE_KEY_NONE = {0};
|
2013-03-18 16:34:57 +00:00
|
|
|
|
|
|
|
|
/* 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;
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2019-04-22 09:39:35 +10:00
|
|
|
while ((c = *str++)) {
|
2013-03-18 16:34:57 +00:00
|
|
|
hash.value = ((hash.value << 5) + hash.value) ^ c; /* (hash * 33) ^ c */
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2013-03-18 16:34:57 +00:00
|
|
|
/* separator '\0' character, to avoid ambiguity from concatenated strings */
|
|
|
|
|
hash.value = (hash.value << 5) + hash.value; /* hash * 33 */
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2013-03-18 16:34:57 +00:00
|
|
|
return hash;
|
|
|
|
|
}
|
|
|
|
|
|
2021-01-25 21:11:57 -06:00
|
|
|
bNodeInstanceKey BKE_node_instance_key(bNodeInstanceKey parent_key,
|
|
|
|
|
const bNodeTree *ntree,
|
|
|
|
|
const bNode *node)
|
2013-03-18 16:34:57 +00:00
|
|
|
{
|
2021-01-25 21:11:57 -06:00
|
|
|
bNodeInstanceKey key = node_hash_int_str(parent_key, ntree->id.name + 2);
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2019-04-22 09:39:35 +10:00
|
|
|
if (node) {
|
2013-03-18 16:34:57 +00:00
|
|
|
key = node_hash_int_str(key, node->name);
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2013-03-18 16:34:57 +00:00
|
|
|
return key;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static unsigned int node_instance_hash_key(const void *key)
|
|
|
|
|
{
|
|
|
|
|
return ((const bNodeInstanceKey *)key)->value;
|
|
|
|
|
}
|
|
|
|
|
|
2014-09-25 06:15:52 +10:00
|
|
|
static bool node_instance_hash_key_cmp(const void *a, const void *b)
|
2013-03-18 16:34:57 +00:00
|
|
|
{
|
|
|
|
|
unsigned int value_a = ((const bNodeInstanceKey *)a)->value;
|
|
|
|
|
unsigned int value_b = ((const bNodeInstanceKey *)b)->value;
|
2014-09-25 06:15:52 +10:00
|
|
|
|
|
|
|
|
return (value_a != value_b);
|
2013-03-18 16:34:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bNodeInstanceHash *BKE_node_instance_hash_new(const char *info)
|
|
|
|
|
{
|
2021-02-02 09:51:38 -06:00
|
|
|
bNodeInstanceHash *hash = (bNodeInstanceHash *)MEM_mallocN(sizeof(bNodeInstanceHash), info);
|
2013-03-18 16:34:57 +00:00
|
|
|
hash->ghash = BLI_ghash_new(
|
|
|
|
|
node_instance_hash_key, node_instance_hash_key_cmp, "node instance hash ghash");
|
|
|
|
|
return hash;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void BKE_node_instance_hash_free(bNodeInstanceHash *hash, bNodeInstanceValueFP valfreefp)
|
|
|
|
|
{
|
2021-02-02 09:51:38 -06:00
|
|
|
BLI_ghash_free(hash->ghash, nullptr, (GHashValFreeFP)valfreefp);
|
2013-03-18 16:34:57 +00:00
|
|
|
MEM_freeN(hash);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void BKE_node_instance_hash_insert(bNodeInstanceHash *hash, bNodeInstanceKey key, void *value)
|
|
|
|
|
{
|
2021-02-02 09:51:38 -06:00
|
|
|
bNodeInstanceHashEntry *entry = (bNodeInstanceHashEntry *)value;
|
2013-03-18 16:34:57 +00:00
|
|
|
entry->key = key;
|
|
|
|
|
entry->tag = 0;
|
|
|
|
|
BLI_ghash_insert(hash->ghash, &entry->key, value);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void *BKE_node_instance_hash_lookup(bNodeInstanceHash *hash, bNodeInstanceKey key)
|
|
|
|
|
{
|
|
|
|
|
return BLI_ghash_lookup(hash->ghash, &key);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int BKE_node_instance_hash_remove(bNodeInstanceHash *hash,
|
|
|
|
|
bNodeInstanceKey key,
|
|
|
|
|
bNodeInstanceValueFP valfreefp)
|
|
|
|
|
{
|
2021-02-02 09:51:38 -06:00
|
|
|
return BLI_ghash_remove(hash->ghash, &key, nullptr, (GHashValFreeFP)valfreefp);
|
2013-03-18 16:34:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void BKE_node_instance_hash_clear(bNodeInstanceHash *hash, bNodeInstanceValueFP valfreefp)
|
|
|
|
|
{
|
2021-02-02 09:51:38 -06:00
|
|
|
BLI_ghash_clear(hash->ghash, nullptr, (GHashValFreeFP)valfreefp);
|
2013-03-18 16:34:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void *BKE_node_instance_hash_pop(bNodeInstanceHash *hash, bNodeInstanceKey key)
|
|
|
|
|
{
|
2021-02-02 09:51:38 -06:00
|
|
|
return BLI_ghash_popkey(hash->ghash, &key, nullptr);
|
2013-03-18 16:34:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int BKE_node_instance_hash_haskey(bNodeInstanceHash *hash, bNodeInstanceKey key)
|
|
|
|
|
{
|
|
|
|
|
return BLI_ghash_haskey(hash->ghash, &key);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int BKE_node_instance_hash_size(bNodeInstanceHash *hash)
|
|
|
|
|
{
|
2018-02-15 23:36:11 +11:00
|
|
|
return BLI_ghash_len(hash->ghash);
|
2013-03-18 16:34:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void BKE_node_instance_hash_clear_tags(bNodeInstanceHash *hash)
|
|
|
|
|
{
|
|
|
|
|
bNodeInstanceHashIterator iter;
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2019-04-21 04:40:16 +10:00
|
|
|
NODE_INSTANCE_HASH_ITER (iter, hash) {
|
2021-02-02 09:51:38 -06:00
|
|
|
bNodeInstanceHashEntry *value = (bNodeInstanceHashEntry *)
|
|
|
|
|
BKE_node_instance_hash_iterator_get_value(&iter);
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2013-03-18 16:34:57 +00:00
|
|
|
value->tag = 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void BKE_node_instance_hash_tag(bNodeInstanceHash *UNUSED(hash), void *value)
|
|
|
|
|
{
|
2021-02-02 09:51:38 -06:00
|
|
|
bNodeInstanceHashEntry *entry = (bNodeInstanceHashEntry *)value;
|
2013-03-18 16:34:57 +00:00
|
|
|
entry->tag = 1;
|
|
|
|
|
}
|
|
|
|
|
|
2014-03-31 23:39:08 +11:00
|
|
|
bool BKE_node_instance_hash_tag_key(bNodeInstanceHash *hash, bNodeInstanceKey key)
|
2013-03-18 16:34:57 +00:00
|
|
|
{
|
2021-02-02 09:51:38 -06:00
|
|
|
bNodeInstanceHashEntry *entry = (bNodeInstanceHashEntry *)BKE_node_instance_hash_lookup(hash,
|
|
|
|
|
key);
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2013-03-18 16:34:57 +00:00
|
|
|
if (entry) {
|
|
|
|
|
entry->tag = 1;
|
2014-04-01 11:34:00 +11:00
|
|
|
return true;
|
2013-03-18 16:34:57 +00:00
|
|
|
}
|
2020-08-07 12:30:43 +02:00
|
|
|
|
|
|
|
|
return false;
|
2013-03-18 16:34:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void BKE_node_instance_hash_remove_untagged(bNodeInstanceHash *hash,
|
|
|
|
|
bNodeInstanceValueFP valfreefp)
|
|
|
|
|
{
|
|
|
|
|
/* NOTE: Hash must not be mutated during iterating!
|
|
|
|
|
* Store tagged entries in a separate list and remove items afterward.
|
|
|
|
|
*/
|
2021-02-02 09:51:38 -06:00
|
|
|
bNodeInstanceKey *untagged = (bNodeInstanceKey *)MEM_mallocN(
|
|
|
|
|
sizeof(bNodeInstanceKey) * BKE_node_instance_hash_size(hash),
|
|
|
|
|
"temporary node instance key list");
|
2013-03-18 16:34:57 +00:00
|
|
|
bNodeInstanceHashIterator iter;
|
2020-09-02 18:28:04 +02:00
|
|
|
int num_untagged = 0;
|
2019-04-21 04:40:16 +10:00
|
|
|
NODE_INSTANCE_HASH_ITER (iter, hash) {
|
2021-02-02 09:51:38 -06:00
|
|
|
bNodeInstanceHashEntry *value = (bNodeInstanceHashEntry *)
|
|
|
|
|
BKE_node_instance_hash_iterator_get_value(&iter);
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2019-04-22 09:39:35 +10:00
|
|
|
if (!value->tag) {
|
2013-03-18 16:34:57 +00:00
|
|
|
untagged[num_untagged++] = BKE_node_instance_hash_iterator_get_key(&iter);
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2013-03-18 16:34:57 +00:00
|
|
|
}
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2020-09-02 18:28:04 +02:00
|
|
|
for (int i = 0; i < num_untagged; i++) {
|
2013-03-18 16:34:57 +00:00
|
|
|
BKE_node_instance_hash_remove(hash, untagged[i], valfreefp);
|
|
|
|
|
}
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2013-03-18 16:34:57 +00:00
|
|
|
MEM_freeN(untagged);
|
|
|
|
|
}
|
|
|
|
|
|
2011-09-05 21:01:50 +00:00
|
|
|
/* ************** dependency stuff *********** */
|
|
|
|
|
|
|
|
|
|
/* node is guaranteed to be not checked before */
|
2012-10-09 17:30:33 +00:00
|
|
|
static int node_get_deplist_recurs(bNodeTree *ntree, bNode *node, bNode ***nsort)
|
Merge of first part of changes from the apricot branch, especially
the features that are needed to run the game. Compile tested with
scons, make, but not cmake, that seems to have an issue not related
to these changes. The changes include:
* GLSL support in the viewport and game engine, enable in the game
menu in textured draw mode.
* Synced and merged part of the duplicated blender and gameengine/
gameplayer drawing code.
* Further refactoring of game engine drawing code, especially mesh
storage changed a lot.
* Optimizations in game engine armatures to avoid recomputations.
* A python function to get the framerate estimate in game.
* An option take object color into account in materials.
* An option to restrict shadow casters to a lamp's layers.
* Increase from 10 to 18 texture slots for materials, lamps, word.
An extra texture slot shows up once the last slot is used.
* Memory limit for undo, not enabled by default yet because it
needs the .B.blend to be changed.
* Multiple undo for image painting.
* An offset for dupligroups, so not all objects in a group have to
be at the origin.
2008-09-04 20:51:28 +00:00
|
|
|
{
|
2011-09-05 21:01:50 +00:00
|
|
|
int level = 0xFFF;
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2014-04-01 11:34:00 +11:00
|
|
|
node->done = true;
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2011-09-05 21:01:50 +00:00
|
|
|
/* check linked nodes */
|
2020-09-02 18:28:04 +02:00
|
|
|
LISTBASE_FOREACH (bNodeLink *, link, &ntree->links) {
|
2012-10-09 17:30:33 +00:00
|
|
|
if (link->tonode == node) {
|
2020-09-02 18:28:04 +02:00
|
|
|
bNode *fromnode = link->fromnode;
|
2019-04-22 09:39:35 +10:00
|
|
|
if (fromnode->done == 0) {
|
2013-03-18 16:34:57 +00:00
|
|
|
fromnode->level = node_get_deplist_recurs(ntree, fromnode, nsort);
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
|
|
|
|
if (fromnode->level <= level) {
|
2013-03-18 16:34:57 +00:00
|
|
|
level = fromnode->level - 1;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2011-09-05 21:01:50 +00:00
|
|
|
}
|
|
|
|
|
}
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2011-09-05 21:01:50 +00:00
|
|
|
/* check parent node */
|
|
|
|
|
if (node->parent) {
|
2019-04-22 09:39:35 +10:00
|
|
|
if (node->parent->done == 0) {
|
2012-10-09 17:30:33 +00:00
|
|
|
node->parent->level = node_get_deplist_recurs(ntree, node->parent, nsort);
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
|
|
|
|
if (node->parent->level <= level) {
|
2011-09-05 21:01:50 +00:00
|
|
|
level = node->parent->level - 1;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2011-09-05 21:01:50 +00:00
|
|
|
}
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2011-09-05 21:01:50 +00:00
|
|
|
if (nsort) {
|
2012-07-29 00:20:28 +00:00
|
|
|
**nsort = node;
|
2011-09-05 21:01:50 +00:00
|
|
|
(*nsort)++;
|
Merge of first part of changes from the apricot branch, especially
the features that are needed to run the game. Compile tested with
scons, make, but not cmake, that seems to have an issue not related
to these changes. The changes include:
* GLSL support in the viewport and game engine, enable in the game
menu in textured draw mode.
* Synced and merged part of the duplicated blender and gameengine/
gameplayer drawing code.
* Further refactoring of game engine drawing code, especially mesh
storage changed a lot.
* Optimizations in game engine armatures to avoid recomputations.
* A python function to get the framerate estimate in game.
* An option take object color into account in materials.
* An option to restrict shadow casters to a lamp's layers.
* Increase from 10 to 18 texture slots for materials, lamps, word.
An extra texture slot shows up once the last slot is used.
* Memory limit for undo, not enabled by default yet because it
needs the .B.blend to be changed.
* Multiple undo for image painting.
* An offset for dupligroups, so not all objects in a group have to
be at the origin.
2008-09-04 20:51:28 +00:00
|
|
|
}
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2011-09-05 21:01:50 +00:00
|
|
|
return level;
|
Merge of first part of changes from the apricot branch, especially
the features that are needed to run the game. Compile tested with
scons, make, but not cmake, that seems to have an issue not related
to these changes. The changes include:
* GLSL support in the viewport and game engine, enable in the game
menu in textured draw mode.
* Synced and merged part of the duplicated blender and gameengine/
gameplayer drawing code.
* Further refactoring of game engine drawing code, especially mesh
storage changed a lot.
* Optimizations in game engine armatures to avoid recomputations.
* A python function to get the framerate estimate in game.
* An option take object color into account in materials.
* An option to restrict shadow casters to a lamp's layers.
* Increase from 10 to 18 texture slots for materials, lamps, word.
An extra texture slot shows up once the last slot is used.
* Memory limit for undo, not enabled by default yet because it
needs the .B.blend to be changed.
* Multiple undo for image painting.
* An offset for dupligroups, so not all objects in a group have to
be at the origin.
2008-09-04 20:51:28 +00:00
|
|
|
}
|
|
|
|
|
|
2021-02-05 22:34:03 +11:00
|
|
|
void ntreeGetDependencyList(struct bNodeTree *ntree, struct bNode ***r_deplist, int *r_deplist_len)
|
Merge of first part of changes from the apricot branch, especially
the features that are needed to run the game. Compile tested with
scons, make, but not cmake, that seems to have an issue not related
to these changes. The changes include:
* GLSL support in the viewport and game engine, enable in the game
menu in textured draw mode.
* Synced and merged part of the duplicated blender and gameengine/
gameplayer drawing code.
* Further refactoring of game engine drawing code, especially mesh
storage changed a lot.
* Optimizations in game engine armatures to avoid recomputations.
* A python function to get the framerate estimate in game.
* An option take object color into account in materials.
* An option to restrict shadow casters to a lamp's layers.
* Increase from 10 to 18 texture slots for materials, lamps, word.
An extra texture slot shows up once the last slot is used.
* Memory limit for undo, not enabled by default yet because it
needs the .B.blend to be changed.
* Multiple undo for image painting.
* An offset for dupligroups, so not all objects in a group have to
be at the origin.
2008-09-04 20:51:28 +00:00
|
|
|
{
|
2021-02-05 22:34:03 +11:00
|
|
|
*r_deplist_len = 0;
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2011-09-05 21:01:50 +00:00
|
|
|
/* first clear data */
|
2020-09-02 18:28:04 +02:00
|
|
|
LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
|
2014-04-01 11:34:00 +11:00
|
|
|
node->done = false;
|
2021-02-05 22:34:03 +11:00
|
|
|
(*r_deplist_len)++;
|
2011-09-05 21:01:50 +00:00
|
|
|
}
|
2021-02-05 22:34:03 +11:00
|
|
|
if (*r_deplist_len == 0) {
|
|
|
|
|
*r_deplist = nullptr;
|
2011-09-05 21:01:50 +00:00
|
|
|
return;
|
|
|
|
|
}
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2020-09-02 18:28:04 +02:00
|
|
|
bNode **nsort;
|
2021-02-05 22:34:03 +11:00
|
|
|
nsort = *r_deplist = (bNode **)MEM_callocN((*r_deplist_len) * sizeof(bNode *),
|
|
|
|
|
"sorted node array");
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2011-09-05 21:01:50 +00:00
|
|
|
/* recursive check */
|
2020-09-02 18:28:04 +02:00
|
|
|
LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
|
2012-07-29 00:20:28 +00:00
|
|
|
if (node->done == 0) {
|
2012-10-09 17:30:33 +00:00
|
|
|
node->level = node_get_deplist_recurs(ntree, node, &nsort);
|
Merge of first part of changes from the apricot branch, especially
the features that are needed to run the game. Compile tested with
scons, make, but not cmake, that seems to have an issue not related
to these changes. The changes include:
* GLSL support in the viewport and game engine, enable in the game
menu in textured draw mode.
* Synced and merged part of the duplicated blender and gameengine/
gameplayer drawing code.
* Further refactoring of game engine drawing code, especially mesh
storage changed a lot.
* Optimizations in game engine armatures to avoid recomputations.
* A python function to get the framerate estimate in game.
* An option take object color into account in materials.
* An option to restrict shadow casters to a lamp's layers.
* Increase from 10 to 18 texture slots for materials, lamps, word.
An extra texture slot shows up once the last slot is used.
* Memory limit for undo, not enabled by default yet because it
needs the .B.blend to be changed.
* Multiple undo for image painting.
* An offset for dupligroups, so not all objects in a group have to
be at the origin.
2008-09-04 20:51:28 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2012-03-07 12:30:29 +00:00
|
|
|
/* only updates node->level for detecting cycles links */
|
2021-12-21 15:18:56 +01:00
|
|
|
void ntreeUpdateNodeLevels(bNodeTree *ntree)
|
2012-03-07 12:30:29 +00:00
|
|
|
{
|
|
|
|
|
/* first clear tag */
|
2020-09-02 18:28:04 +02:00
|
|
|
LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
|
2014-04-01 11:34:00 +11:00
|
|
|
node->done = false;
|
2012-03-07 12:30:29 +00:00
|
|
|
}
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2012-03-07 12:30:29 +00:00
|
|
|
/* recursive check */
|
2020-09-02 18:28:04 +02:00
|
|
|
LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
|
2012-07-29 00:20:28 +00:00
|
|
|
if (node->done == 0) {
|
2021-02-02 09:51:38 -06:00
|
|
|
node->level = node_get_deplist_recurs(ntree, node, nullptr);
|
2012-03-07 12:30:29 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-04-20 20:25:22 +02:00
|
|
|
void ntreeUpdateAllNew(Main *main)
|
2007-03-24 18:41:54 +00:00
|
|
|
{
|
2021-12-21 15:18:56 +01:00
|
|
|
Vector<bNodeTree *> new_ntrees;
|
|
|
|
|
|
2019-04-20 20:25:22 +02:00
|
|
|
/* 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. */
|
2018-11-30 15:22:01 +11:00
|
|
|
FOREACH_NODETREE_BEGIN (main, ntree, owner_id) {
|
2019-04-20 20:25:22 +02:00
|
|
|
if (owner_id->tag & LIB_TAG_NEW) {
|
2021-12-21 15:18:56 +01:00
|
|
|
BKE_ntree_update_tag_all(ntree);
|
2019-04-20 20:25:22 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
FOREACH_NODETREE_END;
|
2021-12-21 15:18:56 +01:00
|
|
|
BKE_ntree_update_main(main, nullptr);
|
2019-04-20 20:25:22 +02:00
|
|
|
}
|
|
|
|
|
|
2021-12-21 15:18:56 +01:00
|
|
|
void ntreeUpdateAllUsers(Main *main, ID *id)
|
2019-04-20 20:25:22 +02:00
|
|
|
{
|
2021-02-02 09:51:38 -06:00
|
|
|
if (id == nullptr) {
|
2020-12-02 13:25:25 +01:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2021-12-21 15:18:56 +01:00
|
|
|
bool need_update = false;
|
|
|
|
|
|
2019-04-20 20:25:22 +02:00
|
|
|
/* Update all users of ngroup, to add/remove sockets as needed. */
|
|
|
|
|
FOREACH_NODETREE_BEGIN (main, ntree, owner_id) {
|
2020-04-03 19:15:01 +02:00
|
|
|
LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
|
2020-12-10 16:12:11 +01:00
|
|
|
if (node->id == id) {
|
2021-12-21 15:18:56 +01:00
|
|
|
BKE_ntree_update_tag_node_property(ntree, node);
|
2019-04-20 20:25:22 +02:00
|
|
|
need_update = true;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
|
|
|
|
}
|
2018-11-30 15:22:01 +11:00
|
|
|
}
|
|
|
|
|
FOREACH_NODETREE_END;
|
2021-12-21 15:18:56 +01:00
|
|
|
if (need_update) {
|
|
|
|
|
BKE_ntree_update_main(main, nullptr);
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2012-10-25 16:49:06 +00:00
|
|
|
}
|
|
|
|
|
|
2013-03-18 16:34:57 +00:00
|
|
|
/* ************* node type access ********** */
|
|
|
|
|
|
2021-12-11 09:51:53 -06:00
|
|
|
void nodeLabel(const bNodeTree *ntree, const bNode *node, char *label, int maxlen)
|
2011-02-07 16:41:57 +00:00
|
|
|
{
|
2018-01-07 22:29:25 +01:00
|
|
|
label[0] = '\0';
|
|
|
|
|
|
2017-06-28 20:50:21 +02:00
|
|
|
if (node->label[0] != '\0') {
|
2013-11-12 18:17:58 +00:00
|
|
|
BLI_strncpy(label, node->label, maxlen);
|
2017-06-28 20:50:21 +02:00
|
|
|
}
|
|
|
|
|
else if (node->typeinfo->labelfunc) {
|
2013-11-12 18:18:04 +00:00
|
|
|
node->typeinfo->labelfunc(ntree, node, label, maxlen);
|
2017-06-28 20:50:21 +02:00
|
|
|
}
|
2018-01-07 22:29:25 +01:00
|
|
|
|
|
|
|
|
/* The previous methods (labelfunc) could not provide an adequate label for the node. */
|
|
|
|
|
if (label[0] == '\0') {
|
2017-06-28 20:50:21 +02:00
|
|
|
/* Kind of hacky and weak... Ideally would be better to use RNA here. :| */
|
|
|
|
|
const char *tmp = CTX_IFACE_(BLT_I18NCONTEXT_ID_NODETREE, node->typeinfo->ui_name);
|
|
|
|
|
if (tmp == node->typeinfo->ui_name) {
|
|
|
|
|
tmp = IFACE_(node->typeinfo->ui_name);
|
|
|
|
|
}
|
|
|
|
|
BLI_strncpy(label, tmp, maxlen);
|
|
|
|
|
}
|
2011-02-07 16:41:57 +00:00
|
|
|
}
|
|
|
|
|
|
2020-02-11 15:31:40 +00:00
|
|
|
const char *nodeSocketLabel(const bNodeSocket *sock)
|
|
|
|
|
{
|
|
|
|
|
return (sock->label[0] != '\0') ? sock->label : sock->name;
|
|
|
|
|
}
|
|
|
|
|
|
2013-03-18 16:34:57 +00:00
|
|
|
static void node_type_base_defaults(bNodeType *ntype)
|
2011-09-05 21:01:50 +00:00
|
|
|
{
|
2013-03-18 16:34:57 +00:00
|
|
|
/* default size values */
|
|
|
|
|
node_type_size_preset(ntype, NODE_SIZE_DEFAULT);
|
|
|
|
|
ntype->height = 100;
|
|
|
|
|
ntype->minheight = 30;
|
|
|
|
|
ntype->maxheight = FLT_MAX;
|
2011-09-05 21:01:50 +00:00
|
|
|
}
|
2011-02-07 16:41:57 +00:00
|
|
|
|
2013-03-18 16:34:57 +00:00
|
|
|
/* allow this node for any tree type */
|
2021-04-12 18:43:23 +02:00
|
|
|
static bool node_poll_default(bNodeType *UNUSED(ntype),
|
|
|
|
|
bNodeTree *UNUSED(ntree),
|
|
|
|
|
const char **UNUSED(disabled_hint))
|
2008-11-12 22:03:11 +00:00
|
|
|
{
|
2014-04-01 11:34:00 +11:00
|
|
|
return true;
|
2011-09-05 21:01:50 +00:00
|
|
|
}
|
|
|
|
|
|
2013-03-18 16:34:57 +00:00
|
|
|
/* use the basic poll function */
|
2021-04-12 18:43:23 +02:00
|
|
|
static bool node_poll_instance_default(bNode *node, bNodeTree *ntree, const char **disabled_hint)
|
2011-09-05 21:01:50 +00:00
|
|
|
{
|
2021-04-12 18:43:23 +02:00
|
|
|
return node->typeinfo->poll(node->typeinfo, ntree, disabled_hint);
|
2008-11-12 22:03:11 +00:00
|
|
|
}
|
|
|
|
|
|
2022-01-03 19:32:33 -05:00
|
|
|
void node_type_base(bNodeType *ntype, int type, const char *name, short nclass)
|
2011-09-05 21:01:50 +00:00
|
|
|
{
|
2013-03-18 16:34:57 +00:00
|
|
|
/* Use static type info header to map static int type to identifier string and RNA struct type.
|
|
|
|
|
* Associate the RNA struct type with the bNodeType.
|
|
|
|
|
* Dynamically registered nodes will create an RNA type at runtime
|
|
|
|
|
* and call RNA_struct_blender_type_set, so this only needs to be done for old RNA types
|
|
|
|
|
* created in makesrna, which can not be associated to a bNodeType immediately,
|
|
|
|
|
* since bNodeTypes are registered afterward ...
|
|
|
|
|
*/
|
2013-12-22 14:11:10 +11:00
|
|
|
#define DefNode(Category, ID, DefFunc, EnumName, StructName, UIName, UIDesc) \
|
2013-03-18 16:34:57 +00:00
|
|
|
case ID: \
|
|
|
|
|
BLI_strncpy(ntype->idname, #Category #StructName, sizeof(ntype->idname)); \
|
2020-04-03 18:24:08 +02:00
|
|
|
ntype->rna_ext.srna = RNA_struct_find(#Category #StructName); \
|
2021-02-02 09:51:38 -06:00
|
|
|
BLI_assert(ntype->rna_ext.srna != nullptr); \
|
2020-04-03 18:24:08 +02:00
|
|
|
RNA_struct_blender_type_set(ntype->rna_ext.srna, ntype); \
|
2013-03-18 16:34:57 +00:00
|
|
|
break;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2013-03-18 16:34:57 +00:00
|
|
|
switch (type) {
|
2013-12-22 14:11:10 +11:00
|
|
|
#include "NOD_static_types.h"
|
2011-09-05 21:01:50 +00:00
|
|
|
}
|
2018-06-17 17:05:51 +02:00
|
|
|
|
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
|
|
|
|
2013-03-18 16:34:57 +00:00
|
|
|
ntype->type = type;
|
|
|
|
|
BLI_strncpy(ntype->ui_name, name, sizeof(ntype->ui_name));
|
|
|
|
|
ntype->nclass = nclass;
|
|
|
|
|
|
|
|
|
|
node_type_base_defaults(ntype);
|
|
|
|
|
|
|
|
|
|
ntype->poll = node_poll_default;
|
|
|
|
|
ntype->poll_instance = node_poll_instance_default;
|
2011-09-05 21:01:50 +00:00
|
|
|
}
|
2007-03-26 15:07:38 +00:00
|
|
|
|
2022-01-03 19:32:33 -05:00
|
|
|
void node_type_base_custom(bNodeType *ntype, const char *idname, const char *name, short nclass)
|
2011-02-07 09:33:36 +00:00
|
|
|
{
|
2013-03-18 16:34:57 +00:00
|
|
|
BLI_strncpy(ntype->idname, idname, sizeof(ntype->idname));
|
|
|
|
|
ntype->type = NODE_CUSTOM;
|
|
|
|
|
BLI_strncpy(ntype->ui_name, name, sizeof(ntype->ui_name));
|
2011-02-07 09:33:36 +00:00
|
|
|
ntype->nclass = nclass;
|
2011-11-20 16:38:23 +00:00
|
|
|
|
2013-03-18 16:34:57 +00:00
|
|
|
node_type_base_defaults(ntype);
|
|
|
|
|
}
|
2011-11-20 16:38:23 +00:00
|
|
|
|
2021-02-02 09:51:38 -06:00
|
|
|
struct SocketTemplateIdentifierCallbackData {
|
|
|
|
|
bNodeSocketTemplate *list;
|
|
|
|
|
bNodeSocketTemplate *ntemp;
|
|
|
|
|
};
|
|
|
|
|
|
2013-03-18 16:34:57 +00:00
|
|
|
static bool unique_socket_template_identifier_check(void *arg, const char *name)
|
|
|
|
|
{
|
2021-02-02 09:51:38 -06:00
|
|
|
SocketTemplateIdentifierCallbackData *data = (SocketTemplateIdentifierCallbackData *)arg;
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2021-02-02 09:51:38 -06:00
|
|
|
for (bNodeSocketTemplate *ntemp = data->list; ntemp->type >= 0; ntemp++) {
|
2013-03-18 16:34:57 +00:00
|
|
|
if (ntemp != data->ntemp) {
|
2013-03-18 18:25:05 +00:00
|
|
|
if (STREQ(ntemp->identifier, name)) {
|
2013-03-18 16:34:57 +00:00
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2013-03-18 16:34:57 +00:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void unique_socket_template_identifier(bNodeSocketTemplate *list,
|
|
|
|
|
bNodeSocketTemplate *ntemp,
|
|
|
|
|
const char defname[],
|
|
|
|
|
char delim)
|
|
|
|
|
{
|
2021-02-02 09:51:38 -06:00
|
|
|
SocketTemplateIdentifierCallbackData data;
|
2013-03-18 18:25:05 +00:00
|
|
|
data.list = list;
|
2013-03-18 16:34:57 +00:00
|
|
|
data.ntemp = ntemp;
|
|
|
|
|
|
|
|
|
|
BLI_uniquename_cb(unique_socket_template_identifier_check,
|
|
|
|
|
&data,
|
|
|
|
|
defname,
|
|
|
|
|
delim,
|
|
|
|
|
ntemp->identifier,
|
|
|
|
|
sizeof(ntemp->identifier));
|
2011-09-05 21:01:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void node_type_socket_templates(struct bNodeType *ntype,
|
|
|
|
|
struct bNodeSocketTemplate *inputs,
|
|
|
|
|
struct bNodeSocketTemplate *outputs)
|
|
|
|
|
{
|
|
|
|
|
ntype->inputs = inputs;
|
|
|
|
|
ntype->outputs = outputs;
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2013-03-18 16:34:57 +00:00
|
|
|
/* automatically generate unique identifiers */
|
|
|
|
|
if (inputs) {
|
|
|
|
|
/* clear identifier strings (uninitialized memory) */
|
2020-09-02 18:28:04 +02:00
|
|
|
for (bNodeSocketTemplate *ntemp = inputs; ntemp->type >= 0; ntemp++) {
|
2013-03-18 16:34:57 +00:00
|
|
|
ntemp->identifier[0] = '\0';
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2020-09-02 18:28:04 +02:00
|
|
|
for (bNodeSocketTemplate *ntemp = inputs; ntemp->type >= 0; ntemp++) {
|
2013-03-18 16:34:57 +00:00
|
|
|
BLI_strncpy(ntemp->identifier, ntemp->name, sizeof(ntemp->identifier));
|
|
|
|
|
unique_socket_template_identifier(inputs, ntemp, ntemp->identifier, '_');
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (outputs) {
|
|
|
|
|
/* clear identifier strings (uninitialized memory) */
|
2020-09-02 18:28:04 +02:00
|
|
|
for (bNodeSocketTemplate *ntemp = outputs; ntemp->type >= 0; ntemp++) {
|
2013-03-18 16:34:57 +00:00
|
|
|
ntemp->identifier[0] = '\0';
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2020-09-02 18:28:04 +02:00
|
|
|
for (bNodeSocketTemplate *ntemp = outputs; ntemp->type >= 0; ntemp++) {
|
2013-03-18 16:34:57 +00:00
|
|
|
BLI_strncpy(ntemp->identifier, ntemp->name, sizeof(ntemp->identifier));
|
|
|
|
|
unique_socket_template_identifier(outputs, ntemp, ntemp->identifier, '_');
|
|
|
|
|
}
|
|
|
|
|
}
|
2011-02-07 09:33:36 +00:00
|
|
|
}
|
|
|
|
|
|
2013-03-18 16:34:57 +00:00
|
|
|
void node_type_init(struct bNodeType *ntype,
|
|
|
|
|
void (*initfunc)(struct bNodeTree *ntree, struct bNode *node))
|
2011-02-08 09:02:16 +00:00
|
|
|
{
|
|
|
|
|
ntype->initfunc = initfunc;
|
|
|
|
|
}
|
|
|
|
|
|
2011-02-07 09:33:36 +00:00
|
|
|
void node_type_size(struct bNodeType *ntype, int width, int minwidth, int maxwidth)
|
|
|
|
|
{
|
|
|
|
|
ntype->width = width;
|
|
|
|
|
ntype->minwidth = minwidth;
|
2019-04-22 09:39:35 +10:00
|
|
|
if (maxwidth <= minwidth) {
|
2011-09-05 21:01:50 +00:00
|
|
|
ntype->maxwidth = FLT_MAX;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
|
|
|
|
else {
|
2011-09-05 21:01:50 +00:00
|
|
|
ntype->maxwidth = maxwidth;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2011-02-07 09:33:36 +00:00
|
|
|
}
|
|
|
|
|
|
2013-02-22 10:46:27 +00:00
|
|
|
void node_type_size_preset(struct bNodeType *ntype, eNodeSizePreset size)
|
|
|
|
|
{
|
|
|
|
|
switch (size) {
|
|
|
|
|
case NODE_SIZE_DEFAULT:
|
2016-03-12 19:10:36 +01:00
|
|
|
node_type_size(ntype, 140, 100, NODE_DEFAULT_MAX_WIDTH);
|
2013-02-22 10:46:27 +00:00
|
|
|
break;
|
|
|
|
|
case NODE_SIZE_SMALL:
|
2016-03-12 19:10:36 +01:00
|
|
|
node_type_size(ntype, 100, 80, NODE_DEFAULT_MAX_WIDTH);
|
2013-02-22 10:46:27 +00:00
|
|
|
break;
|
2013-05-21 20:21:46 +00:00
|
|
|
case NODE_SIZE_MIDDLE:
|
2016-03-12 19:10:36 +01:00
|
|
|
node_type_size(ntype, 150, 120, NODE_DEFAULT_MAX_WIDTH);
|
2013-05-21 20:21:46 +00:00
|
|
|
break;
|
2013-02-22 10:46:27 +00:00
|
|
|
case NODE_SIZE_LARGE:
|
2016-03-12 19:10:36 +01:00
|
|
|
node_type_size(ntype, 240, 140, NODE_DEFAULT_MAX_WIDTH);
|
2013-02-22 10:46:27 +00:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2013-03-18 16:34:57 +00:00
|
|
|
void node_type_storage(bNodeType *ntype,
|
|
|
|
|
const char *storagename,
|
|
|
|
|
void (*freefunc)(struct bNode *node),
|
|
|
|
|
void (*copyfunc)(struct bNodeTree *dest_ntree,
|
|
|
|
|
struct bNode *dest_node,
|
2019-06-03 17:08:25 +02:00
|
|
|
const struct bNode *src_node))
|
2011-02-07 09:33:36 +00:00
|
|
|
{
|
2019-04-22 09:39:35 +10:00
|
|
|
if (storagename) {
|
2011-09-26 18:51:10 +00:00
|
|
|
BLI_strncpy(ntype->storagename, storagename, sizeof(ntype->storagename));
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
|
|
|
|
else {
|
2011-02-08 09:02:16 +00:00
|
|
|
ntype->storagename[0] = '\0';
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2013-03-18 16:34:57 +00:00
|
|
|
ntype->copyfunc = copyfunc;
|
|
|
|
|
ntype->freefunc = freefunc;
|
2011-02-07 09:33:36 +00:00
|
|
|
}
|
|
|
|
|
|
2011-09-05 21:01:50 +00:00
|
|
|
void node_type_update(struct bNodeType *ntype,
|
2019-04-20 20:25:22 +02:00
|
|
|
void (*updatefunc)(struct bNodeTree *ntree, struct bNode *node))
|
2011-09-05 21:01:50 +00:00
|
|
|
{
|
|
|
|
|
ntype->updatefunc = updatefunc;
|
2019-04-20 20:25:22 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void node_type_group_update(struct bNodeType *ntype,
|
|
|
|
|
void (*group_update_func)(struct bNodeTree *ntree, struct bNode *node))
|
|
|
|
|
{
|
|
|
|
|
ntype->group_update_func = group_update_func;
|
2011-09-05 21:01:50 +00:00
|
|
|
}
|
|
|
|
|
|
2013-03-18 16:34:57 +00:00
|
|
|
void node_type_exec(struct bNodeType *ntype,
|
2021-03-05 17:35:25 +01:00
|
|
|
NodeInitExecFunction init_exec_fn,
|
|
|
|
|
NodeFreeExecFunction free_exec_fn,
|
|
|
|
|
NodeExecFunction exec_fn)
|
2011-09-05 21:01:50 +00:00
|
|
|
{
|
2021-03-05 17:35:25 +01:00
|
|
|
ntype->init_exec_fn = init_exec_fn;
|
|
|
|
|
ntype->free_exec_fn = free_exec_fn;
|
|
|
|
|
ntype->exec_fn = exec_fn;
|
2011-11-20 16:38:23 +00:00
|
|
|
}
|
|
|
|
|
|
2021-03-05 17:35:25 +01:00
|
|
|
void node_type_gpu(struct bNodeType *ntype, NodeGPUExecFunction gpu_fn)
|
2011-02-07 09:33:36 +00:00
|
|
|
{
|
2021-03-05 17:35:25 +01:00
|
|
|
ntype->gpu_fn = gpu_fn;
|
2011-02-07 09:33:36 +00:00
|
|
|
}
|
|
|
|
|
|
2013-03-19 13:40:16 +00:00
|
|
|
/* callbacks for undefined types */
|
|
|
|
|
|
2021-04-12 18:43:23 +02:00
|
|
|
static bool node_undefined_poll(bNodeType *UNUSED(ntype),
|
|
|
|
|
bNodeTree *UNUSED(nodetree),
|
|
|
|
|
const char **UNUSED(r_disabled_hint))
|
2013-03-19 13:40:16 +00:00
|
|
|
{
|
|
|
|
|
/* this type can not be added deliberately, it's just a placeholder */
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* register fallback types used for undefined tree, nodes, sockets */
|
2021-02-02 09:51:38 -06:00
|
|
|
static void register_undefined_types()
|
2013-03-19 13:40:16 +00:00
|
|
|
{
|
2021-07-03 23:08:40 +10:00
|
|
|
/* NOTE: these types are not registered in the type hashes,
|
2013-03-19 13:40:16 +00:00
|
|
|
* they are just used as placeholders in case the actual types are not registered.
|
|
|
|
|
*/
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2021-11-08 11:51:54 +01:00
|
|
|
NodeTreeTypeUndefined.type = NTREE_UNDEFINED;
|
2013-03-19 13:40:16 +00:00
|
|
|
strcpy(NodeTreeTypeUndefined.idname, "NodeTreeUndefined");
|
2019-02-13 16:18:19 +01:00
|
|
|
strcpy(NodeTreeTypeUndefined.ui_name, N_("Undefined"));
|
|
|
|
|
strcpy(NodeTreeTypeUndefined.ui_description, N_("Undefined Node Tree Type"));
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2022-01-03 19:32:33 -05:00
|
|
|
node_type_base_custom(&NodeTypeUndefined, "NodeUndefined", "Undefined", 0);
|
2013-03-19 13:40:16 +00:00
|
|
|
NodeTypeUndefined.poll = node_undefined_poll;
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2013-03-19 13:40:16 +00:00
|
|
|
BLI_strncpy(NodeSocketTypeUndefined.idname,
|
|
|
|
|
"NodeSocketUndefined",
|
|
|
|
|
sizeof(NodeSocketTypeUndefined.idname));
|
|
|
|
|
/* extra type info for standard socket types */
|
|
|
|
|
NodeSocketTypeUndefined.type = SOCK_CUSTOM;
|
|
|
|
|
NodeSocketTypeUndefined.subtype = PROP_NONE;
|
Nodes: Support storing socket link limits in bNodeSocketType
Currently the link limit of sockets is stored in bNodeSocket->limit.
This allows for a lot of flexibility, but is also very redundant.
In every case I've had to deal with so far, it would have "more correct"
to set the link limit per socket type and not per socket. I did not enforce
this constraint yet, because the link limit is exposed in the Python API,
which I did not want to break here.
In the future it might even make sense to only support only three kinds of link limits:
a) no links, b) at most one link, c) an arbitrary number links links. The other link
limits usually don't work well with tools (e.g. which link should be removed when a new
one is connected?) and is not used in practice. However, that is for another day.
Eventually, I would like to get rid of bNodeSocket->limit completely and replace it
either with fixed link limits or a callback in bNodeSocketType.
This patch consists of three parts:
**1. Support defining link limit in socket type**
This introduces a new `nodeSocketLinkLimit` function that serves as an indirection to
hide where the link limit of a socket is defined.
**2. Define link limits for builtin sockets on socket type**
Data sockets: one input, many outputs
Virtual sockets: one input, one output
Undefined sockets: many inputs, many outputs (to avoid that links are removed when the type of the socket is not known)
**3. Remove `bNodeSocketTemplate->limit`**
This wasn't used anymore after the second commit. Removing it simplifies socket definitions
in hundreds of places and removes a lot of redundancy.
Differential Revision: https://developer.blender.org/D7038
Reviewers: brecht
2020-03-06 12:20:05 +01:00
|
|
|
|
|
|
|
|
NodeSocketTypeUndefined.use_link_limits_of_type = true;
|
|
|
|
|
NodeSocketTypeUndefined.input_link_limit = 0xFFF;
|
|
|
|
|
NodeSocketTypeUndefined.output_link_limit = 0xFFF;
|
2013-03-19 13:40:16 +00:00
|
|
|
}
|
|
|
|
|
|
2021-02-02 09:51:38 -06:00
|
|
|
static void registerCompositNodes()
|
2013-03-18 16:34:57 +00:00
|
|
|
{
|
|
|
|
|
register_node_type_cmp_group();
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2013-03-18 16:34:57 +00:00
|
|
|
register_node_type_cmp_rlayers();
|
|
|
|
|
register_node_type_cmp_image();
|
|
|
|
|
register_node_type_cmp_texture();
|
|
|
|
|
register_node_type_cmp_value();
|
|
|
|
|
register_node_type_cmp_rgb();
|
|
|
|
|
register_node_type_cmp_curve_time();
|
2022-01-12 12:16:41 +01:00
|
|
|
register_node_type_cmp_scene_time();
|
2013-03-18 16:34:57 +00:00
|
|
|
register_node_type_cmp_movieclip();
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2013-03-18 16:34:57 +00:00
|
|
|
register_node_type_cmp_composite();
|
|
|
|
|
register_node_type_cmp_viewer();
|
|
|
|
|
register_node_type_cmp_splitviewer();
|
|
|
|
|
register_node_type_cmp_output_file();
|
|
|
|
|
register_node_type_cmp_view_levels();
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2013-03-18 16:34:57 +00:00
|
|
|
register_node_type_cmp_curve_rgb();
|
|
|
|
|
register_node_type_cmp_mix_rgb();
|
|
|
|
|
register_node_type_cmp_hue_sat();
|
|
|
|
|
register_node_type_cmp_brightcontrast();
|
|
|
|
|
register_node_type_cmp_gamma();
|
2020-12-19 14:40:31 -05:00
|
|
|
register_node_type_cmp_exposure();
|
2013-03-18 16:34:57 +00:00
|
|
|
register_node_type_cmp_invert();
|
|
|
|
|
register_node_type_cmp_alphaover();
|
|
|
|
|
register_node_type_cmp_zcombine();
|
|
|
|
|
register_node_type_cmp_colorbalance();
|
|
|
|
|
register_node_type_cmp_huecorrect();
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2013-03-18 16:34:57 +00:00
|
|
|
register_node_type_cmp_normal();
|
|
|
|
|
register_node_type_cmp_curve_vec();
|
|
|
|
|
register_node_type_cmp_map_value();
|
|
|
|
|
register_node_type_cmp_map_range();
|
|
|
|
|
register_node_type_cmp_normalize();
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2013-03-18 16:34:57 +00:00
|
|
|
register_node_type_cmp_filter();
|
|
|
|
|
register_node_type_cmp_blur();
|
|
|
|
|
register_node_type_cmp_dblur();
|
|
|
|
|
register_node_type_cmp_bilateralblur();
|
|
|
|
|
register_node_type_cmp_vecblur();
|
|
|
|
|
register_node_type_cmp_dilateerode();
|
|
|
|
|
register_node_type_cmp_inpaint();
|
|
|
|
|
register_node_type_cmp_despeckle();
|
|
|
|
|
register_node_type_cmp_defocus();
|
2021-09-05 15:22:30 -04:00
|
|
|
register_node_type_cmp_posterize();
|
2014-07-26 12:59:29 +02:00
|
|
|
register_node_type_cmp_sunbeams();
|
Compositor: Added denoising node
This node is built on Intel's OpenImageDenoise library.
Other denoisers could be integrated, for example Lukas' Cycles denoiser.
Compositor: Made OpenImageDenoise optional, added CMake and build_env files to find OIDN
Compositor: Fixed some warnings in the denoising operator
build_environment: Updated OpenImageDenoise to 0.8.1
build_environment: Updated OpenImageDenoise in `make deps` for macOS
Reviewers: sergey, jbakker, brecht
Reviewed By: brecht
Subscribers: YAFU, LazyDodo, Zen_YS, slumber, samgreen, tjvoll, yeus, ponomarovmax, getrad, coder.kalyan, vitos1k, Yegor, DeepBlender, kumaran7, Darkfie9825, aliasguru, aafra, ace_dragon, juang3d, pandrodor, cdog, lordodin, jtheninja, mavek, marcog, 5k1n2, Atair, rawalanche, 0o00o0oo, filibis, poor, lukasstockner97
Tags: #compositing
Differential Revision: https://developer.blender.org/D4304
2019-08-14 15:30:26 +02:00
|
|
|
register_node_type_cmp_denoise();
|
2021-03-29 07:44:27 +02:00
|
|
|
register_node_type_cmp_antialiasing();
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2022-01-10 08:57:53 +01:00
|
|
|
register_node_type_cmp_convert_color_space();
|
2013-03-18 16:34:57 +00:00
|
|
|
register_node_type_cmp_valtorgb();
|
|
|
|
|
register_node_type_cmp_rgbtobw();
|
|
|
|
|
register_node_type_cmp_setalpha();
|
|
|
|
|
register_node_type_cmp_idmask();
|
|
|
|
|
register_node_type_cmp_math();
|
|
|
|
|
register_node_type_cmp_seprgba();
|
|
|
|
|
register_node_type_cmp_combrgba();
|
|
|
|
|
register_node_type_cmp_sephsva();
|
|
|
|
|
register_node_type_cmp_combhsva();
|
|
|
|
|
register_node_type_cmp_sepyuva();
|
|
|
|
|
register_node_type_cmp_combyuva();
|
|
|
|
|
register_node_type_cmp_sepycca();
|
|
|
|
|
register_node_type_cmp_combycca();
|
|
|
|
|
register_node_type_cmp_premulkey();
|
2022-02-01 18:17:51 -05:00
|
|
|
register_node_type_cmp_separate_xyz();
|
|
|
|
|
register_node_type_cmp_combine_xyz();
|
Nodes: Add general Combine/Separate Color nodes
Inspired by D12936 and D12929, this patch adds general purpose
"Combine Color" and "Separate Color" nodes to Geometry, Compositor,
Shader and Texture nodes.
- Within Geometry Nodes, it replaces the existing "Combine RGB" and
"Separate RGB" nodes.
- Within Compositor Nodes, it replaces the existing
"Combine RGBA/HSVA/YCbCrA/YUVA" and "Separate RGBA/HSVA/YCbCrA/YUVA"
nodes.
- Within Texture Nodes, it replaces the existing "Combine RGBA" and
"Separate RGBA" nodes.
- Within Shader Nodes, it replaces the existing "Combine RGB/HSV" and
"Separate RGB/HSV" nodes.
Python addons have not been updated to the new nodes yet.
**New shader code**
In node_color.h, color.h and gpu_shader_material_color_util.glsl,
missing methods hsl_to_rgb and rgb_to_hsl are added by directly
converting existing C code. They always produce the same result.
**Old code**
As requested by T96219, old nodes still exist but are not displayed in
the add menu. This means Python scripts can still create them as usual.
Otherwise, versioning replaces the old nodes with the new nodes when
opening .blend files.
Differential Revision: https://developer.blender.org/D14034
2022-05-04 18:44:03 +02:00
|
|
|
register_node_type_cmp_separate_color();
|
|
|
|
|
register_node_type_cmp_combine_color();
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2013-03-18 16:34:57 +00:00
|
|
|
register_node_type_cmp_diff_matte();
|
|
|
|
|
register_node_type_cmp_distance_matte();
|
|
|
|
|
register_node_type_cmp_chroma_matte();
|
|
|
|
|
register_node_type_cmp_color_matte();
|
|
|
|
|
register_node_type_cmp_channel_matte();
|
|
|
|
|
register_node_type_cmp_color_spill();
|
|
|
|
|
register_node_type_cmp_luma_matte();
|
|
|
|
|
register_node_type_cmp_doubleedgemask();
|
|
|
|
|
register_node_type_cmp_keyingscreen();
|
|
|
|
|
register_node_type_cmp_keying();
|
2018-07-18 13:03:09 +02:00
|
|
|
register_node_type_cmp_cryptomatte();
|
Compositor: Redesign Cryptomatte node for better usability
In the current implementation, cryptomatte passes are connected to the node
and elements are picked by using the eyedropper tool on a special pick channel.
This design has two disadvantages - both connecting all passes individually
and always having to switch to the picker channel are tedious.
With the new design, the user selects the RenderLayer or Image from which the
Cryptomatte layers are directly loaded (the type of pass is determined by an
enum). This allows the node to automatically detect all relevant passes.
Then, when using the eyedropper tool, the operator looks up the selected
coordinates from the picked Image, Node backdrop or Clip and reads the picked
object directly from the Renderlayer/Image, therefore allowing to pick in any
context (e.g. by clicking on the Combined pass in the Image Viewer). The
sampled color is looked up in the metadata and the actual name is stored
in the cryptomatte node. This also allows to remove a hash by just removing
the name from the matte id.
Technically there is some loss of flexibility because the Cryptomatte pass
inputs can no longer be connected to other nodes, but since any compositing
done on them is likely to break the Cryptomatte system anyways, this isn't
really a concern in practise.
In the future, this would also allow to automatically translate values to names
by looking up the value in the associated metadata of the input, or to get a
better visualization of overlapping areas in the Pick output since we could
blend colors now that the output doesn't have to contain the exact value.
Idea + Original patch: Lucas Stockner
Reviewed By: Brecht van Lommel
Differential Revision: https://developer.blender.org/D3959
2021-03-16 07:37:30 +01:00
|
|
|
register_node_type_cmp_cryptomatte_legacy();
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2013-03-18 16:34:57 +00:00
|
|
|
register_node_type_cmp_translate();
|
|
|
|
|
register_node_type_cmp_rotate();
|
|
|
|
|
register_node_type_cmp_scale();
|
|
|
|
|
register_node_type_cmp_flip();
|
|
|
|
|
register_node_type_cmp_crop();
|
|
|
|
|
register_node_type_cmp_displace();
|
|
|
|
|
register_node_type_cmp_mapuv();
|
|
|
|
|
register_node_type_cmp_glare();
|
|
|
|
|
register_node_type_cmp_tonemap();
|
|
|
|
|
register_node_type_cmp_lensdist();
|
|
|
|
|
register_node_type_cmp_transform();
|
|
|
|
|
register_node_type_cmp_stabilize2d();
|
|
|
|
|
register_node_type_cmp_moviedistortion();
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2013-03-18 16:34:57 +00:00
|
|
|
register_node_type_cmp_colorcorrection();
|
|
|
|
|
register_node_type_cmp_boxmask();
|
|
|
|
|
register_node_type_cmp_ellipsemask();
|
|
|
|
|
register_node_type_cmp_bokehimage();
|
|
|
|
|
register_node_type_cmp_bokehblur();
|
|
|
|
|
register_node_type_cmp_switch();
|
2015-04-06 10:40:12 -03:00
|
|
|
register_node_type_cmp_switch_view();
|
2013-03-18 16:34:57 +00:00
|
|
|
register_node_type_cmp_pixelate();
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2013-03-18 16:34:57 +00:00
|
|
|
register_node_type_cmp_mask();
|
|
|
|
|
register_node_type_cmp_trackpos();
|
Merge plane track feature from tomato branch
This commit includes all the changes made for plane tracker
in tomato branch.
Movie clip editor changes:
- Artist might create a plane track out of multiple point
tracks which belongs to the same track (minimum amount of
point tracks is 4, maximum is not actually limited).
When new plane track is added, it's getting "tracked"
across all point tracks, which makes it stick to the same
plane point tracks belong to.
- After plane track was added, it need to be manually adjusted
in a way it covers feature one might to mask/replace.
General transform tools (G, R, S) or sliding corners with
a mouse could be sued for this. Plane corner which
corresponds to left bottom image corner has got X/Y axis
on it (red is for X axis, green for Y).
- Re-adjusting plane corners makes plane to be "re-tracked"
for the frames sequence between current frame and next
and previous keyframes.
- Kayframes might be removed from the plane, using Shit-X
(Marker Delete) operator. However, currently manual
re-adjustment or "re-track" trigger is needed.
Compositor changes:
- Added new node called Plane Track Deform.
- User selects which plane track to use (for this he need
to select movie clip datablock, object and track names).
- Node gets an image input, which need to be warped into
the plane.
- Node outputs:
* Input image warped into the plane.
* Plane, rasterized to a mask.
Masking changes:
- Mask points might be parented to a plane track, which
makes this point deforming in a way as if it belongs
to the tracked plane.
Some video tutorials are available:
- Coder video: http://www.youtube.com/watch?v=vISEwqNHqe4
- Artist video: https://vimeo.com/71727578
This is mine and Keir's holiday code project :)
2013-08-16 09:46:30 +00:00
|
|
|
register_node_type_cmp_planetrackdeform();
|
2014-03-11 14:07:49 +01:00
|
|
|
register_node_type_cmp_cornerpin();
|
2013-03-18 16:34:57 +00:00
|
|
|
}
|
|
|
|
|
|
2021-02-02 09:51:38 -06:00
|
|
|
static void registerShaderNodes()
|
2013-03-18 16:34:57 +00:00
|
|
|
{
|
|
|
|
|
register_node_type_sh_group();
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2013-03-18 16:34:57 +00:00
|
|
|
register_node_type_sh_camera();
|
|
|
|
|
register_node_type_sh_gamma();
|
|
|
|
|
register_node_type_sh_brightcontrast();
|
|
|
|
|
register_node_type_sh_value();
|
|
|
|
|
register_node_type_sh_rgb();
|
2013-05-20 15:58:37 +00:00
|
|
|
register_node_type_sh_wireframe();
|
2013-06-09 20:46:22 +00:00
|
|
|
register_node_type_sh_wavelength();
|
2013-07-31 20:56:32 +00:00
|
|
|
register_node_type_sh_blackbody();
|
2013-03-18 16:34:57 +00:00
|
|
|
register_node_type_sh_mix_rgb();
|
2022-08-30 11:05:46 +01:00
|
|
|
register_node_type_sh_mix();
|
2021-12-07 13:26:39 +01:00
|
|
|
register_node_type_sh_valtorgb();
|
2013-03-18 16:34:57 +00:00
|
|
|
register_node_type_sh_rgbtobw();
|
2018-05-14 13:34:54 +02:00
|
|
|
register_node_type_sh_shadertorgb();
|
2013-03-18 16:34:57 +00:00
|
|
|
register_node_type_sh_normal();
|
|
|
|
|
register_node_type_sh_mapping();
|
2021-09-30 19:05:08 +01:00
|
|
|
register_node_type_sh_curve_float();
|
2013-03-18 16:34:57 +00:00
|
|
|
register_node_type_sh_curve_vec();
|
|
|
|
|
register_node_type_sh_curve_rgb();
|
2019-08-13 16:29:32 +02:00
|
|
|
register_node_type_sh_map_range();
|
2019-08-13 22:22:15 +02:00
|
|
|
register_node_type_sh_clamp();
|
2013-03-18 16:34:57 +00:00
|
|
|
register_node_type_sh_math();
|
|
|
|
|
register_node_type_sh_vect_math();
|
2020-02-17 15:15:46 +00:00
|
|
|
register_node_type_sh_vector_rotate();
|
2013-07-31 21:18:23 +00:00
|
|
|
register_node_type_sh_vect_transform();
|
2013-03-18 16:34:57 +00:00
|
|
|
register_node_type_sh_squeeze();
|
|
|
|
|
register_node_type_sh_invert();
|
Nodes: Add general Combine/Separate Color nodes
Inspired by D12936 and D12929, this patch adds general purpose
"Combine Color" and "Separate Color" nodes to Geometry, Compositor,
Shader and Texture nodes.
- Within Geometry Nodes, it replaces the existing "Combine RGB" and
"Separate RGB" nodes.
- Within Compositor Nodes, it replaces the existing
"Combine RGBA/HSVA/YCbCrA/YUVA" and "Separate RGBA/HSVA/YCbCrA/YUVA"
nodes.
- Within Texture Nodes, it replaces the existing "Combine RGBA" and
"Separate RGBA" nodes.
- Within Shader Nodes, it replaces the existing "Combine RGB/HSV" and
"Separate RGB/HSV" nodes.
Python addons have not been updated to the new nodes yet.
**New shader code**
In node_color.h, color.h and gpu_shader_material_color_util.glsl,
missing methods hsl_to_rgb and rgb_to_hsl are added by directly
converting existing C code. They always produce the same result.
**Old code**
As requested by T96219, old nodes still exist but are not displayed in
the add menu. This means Python scripts can still create them as usual.
Otherwise, versioning replaces the old nodes with the new nodes when
opening .blend files.
Differential Revision: https://developer.blender.org/D14034
2022-05-04 18:44:03 +02:00
|
|
|
register_node_type_sh_sepcolor();
|
|
|
|
|
register_node_type_sh_combcolor();
|
2013-03-18 16:34:57 +00:00
|
|
|
register_node_type_sh_seprgb();
|
|
|
|
|
register_node_type_sh_combrgb();
|
2013-07-03 23:46:56 +00:00
|
|
|
register_node_type_sh_sephsv();
|
|
|
|
|
register_node_type_sh_combhsv();
|
2014-06-13 21:44:48 +02:00
|
|
|
register_node_type_sh_sepxyz();
|
|
|
|
|
register_node_type_sh_combxyz();
|
2013-03-18 16:34:57 +00:00
|
|
|
register_node_type_sh_hue_sat();
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2013-03-18 16:34:57 +00:00
|
|
|
register_node_type_sh_attribute();
|
2017-08-18 18:37:05 +02:00
|
|
|
register_node_type_sh_bevel();
|
2018-01-13 13:11:03 +01:00
|
|
|
register_node_type_sh_displacement();
|
2018-01-21 00:40:42 +01:00
|
|
|
register_node_type_sh_vector_displacement();
|
2013-03-18 16:34:57 +00:00
|
|
|
register_node_type_sh_geometry();
|
|
|
|
|
register_node_type_sh_light_path();
|
|
|
|
|
register_node_type_sh_light_falloff();
|
|
|
|
|
register_node_type_sh_object_info();
|
|
|
|
|
register_node_type_sh_fresnel();
|
|
|
|
|
register_node_type_sh_layer_weight();
|
|
|
|
|
register_node_type_sh_tex_coord();
|
|
|
|
|
register_node_type_sh_particle_info();
|
|
|
|
|
register_node_type_sh_bump();
|
2019-09-12 17:42:13 +02:00
|
|
|
register_node_type_sh_vertex_color();
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2013-03-18 16:34:57 +00:00
|
|
|
register_node_type_sh_background();
|
|
|
|
|
register_node_type_sh_bsdf_anisotropic();
|
|
|
|
|
register_node_type_sh_bsdf_diffuse();
|
2017-04-18 11:43:09 +02:00
|
|
|
register_node_type_sh_bsdf_principled();
|
2013-03-18 16:34:57 +00:00
|
|
|
register_node_type_sh_bsdf_glossy();
|
|
|
|
|
register_node_type_sh_bsdf_glass();
|
|
|
|
|
register_node_type_sh_bsdf_translucent();
|
|
|
|
|
register_node_type_sh_bsdf_transparent();
|
|
|
|
|
register_node_type_sh_bsdf_velvet();
|
2013-05-23 17:45:20 +00:00
|
|
|
register_node_type_sh_bsdf_toon();
|
2013-09-15 23:58:00 +00:00
|
|
|
register_node_type_sh_bsdf_hair();
|
2018-07-18 11:14:43 +02:00
|
|
|
register_node_type_sh_bsdf_hair_principled();
|
2013-03-18 16:34:57 +00:00
|
|
|
register_node_type_sh_emission();
|
|
|
|
|
register_node_type_sh_holdout();
|
2013-12-28 16:56:19 +01:00
|
|
|
register_node_type_sh_volume_absorption();
|
2013-12-29 15:40:43 +01:00
|
|
|
register_node_type_sh_volume_scatter();
|
2018-01-30 15:05:19 +01:00
|
|
|
register_node_type_sh_volume_principled();
|
2013-04-01 20:26:52 +00:00
|
|
|
register_node_type_sh_subsurface_scattering();
|
2013-03-18 16:34:57 +00:00
|
|
|
register_node_type_sh_mix_shader();
|
|
|
|
|
register_node_type_sh_add_shader();
|
2014-04-02 11:40:29 +02:00
|
|
|
register_node_type_sh_uvmap();
|
2014-07-20 12:14:31 +09:00
|
|
|
register_node_type_sh_uvalongstroke();
|
2017-06-20 14:33:13 +02:00
|
|
|
register_node_type_sh_eevee_specular();
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-02-27 12:02:02 +11:00
|
|
|
register_node_type_sh_output_light();
|
2013-03-18 16:34:57 +00:00
|
|
|
register_node_type_sh_output_material();
|
|
|
|
|
register_node_type_sh_output_world();
|
2014-07-14 16:20:40 +09:00
|
|
|
register_node_type_sh_output_linestyle();
|
2019-12-04 19:57:28 +01:00
|
|
|
register_node_type_sh_output_aov();
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2013-03-18 16:34:57 +00:00
|
|
|
register_node_type_sh_tex_image();
|
|
|
|
|
register_node_type_sh_tex_environment();
|
|
|
|
|
register_node_type_sh_tex_sky();
|
|
|
|
|
register_node_type_sh_tex_noise();
|
|
|
|
|
register_node_type_sh_tex_wave();
|
|
|
|
|
register_node_type_sh_tex_voronoi();
|
|
|
|
|
register_node_type_sh_tex_musgrave();
|
|
|
|
|
register_node_type_sh_tex_gradient();
|
|
|
|
|
register_node_type_sh_tex_magic();
|
|
|
|
|
register_node_type_sh_tex_checker();
|
|
|
|
|
register_node_type_sh_tex_brick();
|
2015-07-18 22:36:09 +02:00
|
|
|
register_node_type_sh_tex_pointdensity();
|
Cycles: Add Support for IES files as textures for light strength
This patch adds support for IES files, a file format that is commonly used to store the directional intensity distribution of light sources.
The new IES node is supposed to be plugged into the Strength input of the Emission node of the lamp.
Since people generating IES files do not really seem to care about the standard, the parser is flexible enough to accept all test files I have tried.
Some common weirdnesses are distributing values over multiple lines that should go into one line, using commas instead of spaces as delimiters and adding various useless stuff at the end of the file.
The user interface of the node is similar to the script node, the user can either select an internal Text or load a file.
Internally, IES files are handled similar to Image textures: They are stored in slots by the LightManager and each unique IES is assigned to one slot.
The local coordinate system of the lamp is used, so that the direction of the light can be changed. For UI reasons, it's usually best to add an area light,
rotate it and then change its type, since especially the point light does not immediately show its local coordinate system in the viewport.
Reviewers: #cycles, dingto, sergey, brecht
Reviewed By: #cycles, dingto, brecht
Subscribers: OgDEV, crazyrobinhood, secundar, cardboard, pisuke, intrah, swerner, micah_denn, harvester, gottfried, disnel, campbellbarton, duarteframos, Lapineige, brecht, juicyfruit, dingto, marek, rickyblender, bliblubli, lockal, sergey
Differential Revision: https://developer.blender.org/D1543
2018-05-27 00:46:37 +02:00
|
|
|
register_node_type_sh_tex_ies();
|
2019-08-21 20:04:09 +02:00
|
|
|
register_node_type_sh_tex_white_noise();
|
2013-03-18 16:34:57 +00:00
|
|
|
}
|
|
|
|
|
|
2021-02-02 09:51:38 -06:00
|
|
|
static void registerTextureNodes()
|
2013-03-18 16:34:57 +00:00
|
|
|
{
|
|
|
|
|
register_node_type_tex_group();
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2013-03-18 16:34:57 +00:00
|
|
|
register_node_type_tex_math();
|
|
|
|
|
register_node_type_tex_mix_rgb();
|
|
|
|
|
register_node_type_tex_valtorgb();
|
|
|
|
|
register_node_type_tex_rgbtobw();
|
|
|
|
|
register_node_type_tex_valtonor();
|
|
|
|
|
register_node_type_tex_curve_rgb();
|
|
|
|
|
register_node_type_tex_curve_time();
|
|
|
|
|
register_node_type_tex_invert();
|
|
|
|
|
register_node_type_tex_hue_sat();
|
|
|
|
|
register_node_type_tex_coord();
|
|
|
|
|
register_node_type_tex_distance();
|
|
|
|
|
register_node_type_tex_compose();
|
|
|
|
|
register_node_type_tex_decompose();
|
Nodes: Add general Combine/Separate Color nodes
Inspired by D12936 and D12929, this patch adds general purpose
"Combine Color" and "Separate Color" nodes to Geometry, Compositor,
Shader and Texture nodes.
- Within Geometry Nodes, it replaces the existing "Combine RGB" and
"Separate RGB" nodes.
- Within Compositor Nodes, it replaces the existing
"Combine RGBA/HSVA/YCbCrA/YUVA" and "Separate RGBA/HSVA/YCbCrA/YUVA"
nodes.
- Within Texture Nodes, it replaces the existing "Combine RGBA" and
"Separate RGBA" nodes.
- Within Shader Nodes, it replaces the existing "Combine RGB/HSV" and
"Separate RGB/HSV" nodes.
Python addons have not been updated to the new nodes yet.
**New shader code**
In node_color.h, color.h and gpu_shader_material_color_util.glsl,
missing methods hsl_to_rgb and rgb_to_hsl are added by directly
converting existing C code. They always produce the same result.
**Old code**
As requested by T96219, old nodes still exist but are not displayed in
the add menu. This means Python scripts can still create them as usual.
Otherwise, versioning replaces the old nodes with the new nodes when
opening .blend files.
Differential Revision: https://developer.blender.org/D14034
2022-05-04 18:44:03 +02:00
|
|
|
register_node_type_tex_combine_color();
|
|
|
|
|
register_node_type_tex_separate_color();
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2013-03-18 16:34:57 +00:00
|
|
|
register_node_type_tex_output();
|
|
|
|
|
register_node_type_tex_viewer();
|
|
|
|
|
register_node_type_sh_script();
|
|
|
|
|
register_node_type_sh_tangent();
|
|
|
|
|
register_node_type_sh_normal_map();
|
|
|
|
|
register_node_type_sh_hair_info();
|
2022-01-25 13:25:33 +01:00
|
|
|
register_node_type_sh_point_info();
|
2019-08-21 20:22:24 +02:00
|
|
|
register_node_type_sh_volume_info();
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2013-03-18 16:34:57 +00:00
|
|
|
register_node_type_tex_checker();
|
|
|
|
|
register_node_type_tex_texture();
|
|
|
|
|
register_node_type_tex_bricks();
|
|
|
|
|
register_node_type_tex_image();
|
|
|
|
|
register_node_type_sh_bsdf_refraction();
|
|
|
|
|
register_node_type_sh_ambient_occlusion();
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2013-03-18 16:34:57 +00:00
|
|
|
register_node_type_tex_rotate();
|
|
|
|
|
register_node_type_tex_translate();
|
|
|
|
|
register_node_type_tex_scale();
|
|
|
|
|
register_node_type_tex_at();
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2013-03-18 16:34:57 +00:00
|
|
|
register_node_type_tex_proc_voronoi();
|
|
|
|
|
register_node_type_tex_proc_blend();
|
|
|
|
|
register_node_type_tex_proc_magic();
|
|
|
|
|
register_node_type_tex_proc_marble();
|
|
|
|
|
register_node_type_tex_proc_clouds();
|
|
|
|
|
register_node_type_tex_proc_wood();
|
|
|
|
|
register_node_type_tex_proc_musgrave();
|
|
|
|
|
register_node_type_tex_proc_noise();
|
|
|
|
|
register_node_type_tex_proc_stucci();
|
|
|
|
|
register_node_type_tex_proc_distnoise();
|
2008-02-09 23:17:15 +00:00
|
|
|
}
|
|
|
|
|
|
2021-02-02 09:51:38 -06:00
|
|
|
static void registerGeometryNodes()
|
2020-04-20 10:58:43 +02:00
|
|
|
{
|
2020-12-02 13:25:25 +01:00
|
|
|
register_node_type_geo_group();
|
|
|
|
|
|
2021-12-29 10:24:29 -06:00
|
|
|
register_node_type_geo_accumulate_field();
|
2021-09-28 14:20:29 -05:00
|
|
|
register_node_type_geo_attribute_capture();
|
2021-11-29 13:04:25 -06:00
|
|
|
register_node_type_geo_attribute_domain_size();
|
2021-09-20 18:39:39 -05:00
|
|
|
register_node_type_geo_attribute_statistic();
|
2020-12-02 13:25:25 +01:00
|
|
|
register_node_type_geo_boolean();
|
2021-04-06 16:02:55 -05:00
|
|
|
register_node_type_geo_bounding_box();
|
2021-02-07 17:21:21 -06:00
|
|
|
register_node_type_geo_collection_info();
|
2021-06-09 11:58:08 -05:00
|
|
|
register_node_type_geo_convex_hull();
|
2021-10-18 06:45:16 -05:00
|
|
|
register_node_type_geo_curve_endpoint_selection();
|
2021-08-29 23:27:35 -05:00
|
|
|
register_node_type_geo_curve_fill();
|
2021-09-28 14:20:29 -05:00
|
|
|
register_node_type_geo_curve_fillet();
|
2021-10-03 15:00:28 -05:00
|
|
|
register_node_type_geo_curve_handle_type_selection();
|
2021-06-03 19:12:38 -04:00
|
|
|
register_node_type_geo_curve_length();
|
2022-01-20 18:06:25 +00:00
|
|
|
register_node_type_geo_curve_primitive_arc();
|
2021-06-30 00:03:55 -05:00
|
|
|
register_node_type_geo_curve_primitive_bezier_segment();
|
2021-06-30 19:17:28 -05:00
|
|
|
register_node_type_geo_curve_primitive_circle();
|
2021-07-05 12:27:12 -05:00
|
|
|
register_node_type_geo_curve_primitive_line();
|
2021-06-29 22:39:08 -05:00
|
|
|
register_node_type_geo_curve_primitive_quadratic_bezier();
|
2021-07-12 13:10:56 -04:00
|
|
|
register_node_type_geo_curve_primitive_quadrilateral();
|
2021-06-29 22:20:54 -05:00
|
|
|
register_node_type_geo_curve_primitive_spiral();
|
2021-06-29 22:00:29 -05:00
|
|
|
register_node_type_geo_curve_primitive_star();
|
2021-05-07 15:37:06 -05:00
|
|
|
register_node_type_geo_curve_resample();
|
2021-06-14 13:28:38 -05:00
|
|
|
register_node_type_geo_curve_reverse();
|
2021-09-28 14:20:29 -05:00
|
|
|
register_node_type_geo_curve_sample();
|
2022-03-02 17:58:17 -05:00
|
|
|
register_node_type_geo_curve_set_handle_type();
|
2021-11-30 07:21:14 -06:00
|
|
|
register_node_type_geo_curve_spline_parameter();
|
2021-08-03 23:14:03 -04:00
|
|
|
register_node_type_geo_curve_spline_type();
|
2021-06-17 11:39:23 -05:00
|
|
|
register_node_type_geo_curve_subdivide();
|
2021-07-06 23:33:02 -05:00
|
|
|
register_node_type_geo_curve_to_mesh();
|
|
|
|
|
register_node_type_geo_curve_to_points();
|
2021-07-18 14:05:57 -04:00
|
|
|
register_node_type_geo_curve_trim();
|
2022-07-08 14:45:48 +02:00
|
|
|
register_node_type_geo_deform_curves_on_surface();
|
2021-06-01 17:32:03 -04:00
|
|
|
register_node_type_geo_delete_geometry();
|
2021-09-24 11:50:02 +02:00
|
|
|
register_node_type_geo_distribute_points_on_faces();
|
2021-12-01 11:11:50 -05:00
|
|
|
register_node_type_geo_dual_mesh();
|
2022-07-27 08:56:17 -05:00
|
|
|
register_node_type_geo_duplicate_elements();
|
2022-07-27 15:38:30 +02:00
|
|
|
register_node_type_geo_edge_paths_to_curves();
|
|
|
|
|
register_node_type_geo_edge_paths_to_selection();
|
2021-02-07 17:21:21 -06:00
|
|
|
register_node_type_geo_edge_split();
|
Geometry Nodes: Extrude Mesh Node
This patch introduces an extrude node with three modes. The vertex mode
is quite simple, and just attaches new edges to the selected vertices.
The edge mode attaches new faces to the selected edges. The faces mode
extrudes patches of selected faces, or each selected face individually,
depending on the "Individual" boolean input.
The default value of the "Offset" input is the mesh's normals, which
can be scaled with the "Offset Scale" input.
**Attribute Propagation**
Attributes are transferred to the new elements with specific rules.
Attributes will never change domains for interpolations. Generally
boolean attributes are propagated with "or", meaning any connected
"true" value that is mixed in for other types will cause the new value
to be "true" as well. The `"id"` attribute does not have any special
handling currently.
Vertex Mode
- Vertex: Copied values of selected vertices.
- Edge: Averaged values of selected edges. For booleans, edges are
selected if any connected edges are selected.
Edge Mode
- Vertex: Copied values of extruded vertices.
- Connecting edges (vertical): Average values of connected extruded
edges. For booleans, the edges are selected if any connected
extruded edges are selected.
- Duplicate edges: Copied values of selected edges.
- Face: Averaged values of all faces connected to the selected edge.
For booleans, faces are selected if any connected original faces
are selected.
- Corner: Averaged values of corresponding corners in all faces
connected to selected edges. For booleans, corners are selected
if one of those corners are selected.
Face Mode
- Vertex: Copied values of extruded vertices.
- Connecting edges (vertical): Average values of connected selected
edges, not including the edges "on top" of extruded regions.
For booleans, edges are selected when any connected extruded edges
were selected.
- Duplicate edges: Copied values of extruded edges.
- Face: Copied values of the corresponding selected faces.
- Corner: Copied values of corresponding corners in selected faces.
Individual Face Mode
- Vertex: Copied values of extruded vertices.
- Connecting edges (vertical): Average values of the two neighboring
edges on each extruded face. For booleans, edges are selected
when at least one neighbor on the extruded face was selected.
- Duplicate edges: Copied values of extruded edges.
- Face: Copied values of the corresponding selected faces.
- Corner: Copied values of corresponding corners in selected faces.
**Differences from edit mode**
In face mode (non-individual), the behavior can be different than the
extrude tools in edit mode-- this node doesn't handle keeping the back-
faces around in the cases that the edit mode tools do. The planned
"Solidify" node will handle that use case instead. Keeping this node
simpler and faster is preferable at this point, especially because that
sort of "smart" behavior is not that predictable and makes less sense
in a procedural context.
In the future, an "Even Offset" option could be added to this node
hopefully fairly simply. For now it is left out in order to keep
the patch simpler.
**Implementation**
For the implementation, the `Mesh` data structure is used directly
rather than converting to `BMesh` and back like D12224. This optimizes
for large extrusion operations rather than many sequential extrusions.
While this is potentially more verbose, it has some important benefits:
First, there is no conversion to and from `BMesh`. The code only has
to fill arrays and it can do that all at once, making each component of
the algorithm much easier to optimize. It also makes the attribute
interpolation more explicit, and likely faster. Only limited topology
maps must be created in most cases.
While there are some necessary loops and allocations with the size of
the entire mesh, I tried to keep everything I could on the order of the
size of the selection rather than the size of the mesh. In that respect,
the individual faces mode is the best, since there is no topology
information necessary, and the amount of work just depends on the size
of the selection.
Modifying an existing mesh instead of generating a new one was a bit
of a toss-up, but has a few potential benefits:
- Avoids manually copying over attribute data for original elements.
- Avoids some overhead of creating a new mesh.
- Can potentially take advantage of future ammortized mesh growth.
This could be changed easily if it turns out to be the wrong choice.
Differential Revision: https://developer.blender.org/D13709
2022-01-23 22:42:49 -06:00
|
|
|
register_node_type_geo_extrude_mesh();
|
2022-01-18 16:25:37 +01:00
|
|
|
register_node_type_geo_field_at_index();
|
2022-01-21 09:26:40 -06:00
|
|
|
register_node_type_geo_flip_faces();
|
2021-12-07 15:37:12 +01:00
|
|
|
register_node_type_geo_geometry_to_instance();
|
2021-10-25 13:02:43 +02:00
|
|
|
register_node_type_geo_image_texture();
|
2021-10-11 11:03:57 -05:00
|
|
|
register_node_type_geo_input_curve_handles();
|
|
|
|
|
register_node_type_geo_input_curve_tilt();
|
2021-10-26 15:40:57 -05:00
|
|
|
register_node_type_geo_input_id();
|
2021-09-09 12:54:20 +02:00
|
|
|
register_node_type_geo_input_index();
|
2022-06-06 11:50:13 -05:00
|
|
|
register_node_type_geo_input_instance_rotation();
|
2022-06-06 12:02:59 -05:00
|
|
|
register_node_type_geo_input_instance_scale();
|
2021-10-13 08:39:54 -05:00
|
|
|
register_node_type_geo_input_material_index();
|
2021-10-19 16:27:37 -05:00
|
|
|
register_node_type_geo_input_material();
|
2022-01-03 11:16:50 -06:00
|
|
|
register_node_type_geo_input_mesh_edge_angle();
|
2021-12-07 10:07:24 -06:00
|
|
|
register_node_type_geo_input_mesh_edge_neighbors();
|
2021-12-06 11:58:08 -06:00
|
|
|
register_node_type_geo_input_mesh_edge_vertices();
|
|
|
|
|
register_node_type_geo_input_mesh_face_area();
|
2022-02-23 14:19:08 -06:00
|
|
|
register_node_type_geo_input_mesh_face_is_planar();
|
2021-12-06 11:58:08 -06:00
|
|
|
register_node_type_geo_input_mesh_face_neighbors();
|
2021-12-08 10:14:03 -06:00
|
|
|
register_node_type_geo_input_mesh_island();
|
2021-12-06 11:58:08 -06:00
|
|
|
register_node_type_geo_input_mesh_vertex_neighbors();
|
2022-07-27 08:56:17 -05:00
|
|
|
register_node_type_geo_input_named_attribute();
|
2021-09-09 12:54:20 +02:00
|
|
|
register_node_type_geo_input_normal();
|
|
|
|
|
register_node_type_geo_input_position();
|
2021-10-11 11:03:57 -05:00
|
|
|
register_node_type_geo_input_radius();
|
2021-12-09 11:50:25 -06:00
|
|
|
register_node_type_geo_input_scene_time();
|
2021-10-11 11:03:57 -05:00
|
|
|
register_node_type_geo_input_shade_smooth();
|
2022-07-27 15:38:30 +02:00
|
|
|
register_node_type_geo_input_shortest_edge_paths();
|
2021-10-11 11:03:57 -05:00
|
|
|
register_node_type_geo_input_spline_cyclic();
|
2021-10-01 09:58:49 -05:00
|
|
|
register_node_type_geo_input_spline_length();
|
2021-10-11 11:03:57 -05:00
|
|
|
register_node_type_geo_input_spline_resolution();
|
|
|
|
|
register_node_type_geo_input_tangent();
|
2021-09-28 14:20:29 -05:00
|
|
|
register_node_type_geo_instance_on_points();
|
2021-10-23 00:01:59 -05:00
|
|
|
register_node_type_geo_instances_to_points();
|
2022-07-27 08:56:17 -05:00
|
|
|
register_node_type_geo_interpolate_domain();
|
2021-02-07 17:21:21 -06:00
|
|
|
register_node_type_geo_is_viewport();
|
|
|
|
|
register_node_type_geo_join_geometry();
|
2021-10-19 16:27:37 -05:00
|
|
|
register_node_type_geo_material_replace();
|
2021-09-28 14:20:29 -05:00
|
|
|
register_node_type_geo_material_selection();
|
2022-01-25 10:51:52 -06:00
|
|
|
register_node_type_geo_merge_by_distance();
|
2021-03-16 17:35:12 -04:00
|
|
|
register_node_type_geo_mesh_primitive_circle();
|
|
|
|
|
register_node_type_geo_mesh_primitive_cone();
|
|
|
|
|
register_node_type_geo_mesh_primitive_cube();
|
|
|
|
|
register_node_type_geo_mesh_primitive_cylinder();
|
2021-03-26 13:09:35 -04:00
|
|
|
register_node_type_geo_mesh_primitive_grid();
|
2021-03-16 17:35:12 -04:00
|
|
|
register_node_type_geo_mesh_primitive_ico_sphere();
|
|
|
|
|
register_node_type_geo_mesh_primitive_line();
|
|
|
|
|
register_node_type_geo_mesh_primitive_uv_sphere();
|
2021-07-06 23:33:02 -05:00
|
|
|
register_node_type_geo_mesh_subdivide();
|
2021-05-28 10:42:22 -04:00
|
|
|
register_node_type_geo_mesh_to_curve();
|
Geometry Nodes: Mesh Point Cloud Conversion Nodes
This commit adds nodes to do direct conversion between meshes and point
clouds in geometry nodes. The conversion from mesh to points is helpful
to instance once per face, or once per edge, which was previously only
possibly with ugly work-arounds. Fields can be evaluated on the mesh
to pass them to the points with the attribute capture node.
The other conversion, point cloud to mesh vertices, is a bit less
obvious, though it is still a common request from users. It's helpful
for flexibility when passing data around, better visualization in the
viewport (and in the future, cycles), and the simplicity of points.
This is a step towards T91754, where point clouds are currently
combined with meshes when outputing to the next modifier after geometry
nodes. Since we're removing the implicit behavior for realizing
instances, it feels natural to use an explicit node to convert points
to vertices too.
Differential Revision: https://developer.blender.org/D12657
2021-09-28 12:14:13 -05:00
|
|
|
register_node_type_geo_mesh_to_points();
|
2022-06-29 10:56:17 -05:00
|
|
|
register_node_type_geo_mesh_to_volume();
|
2021-02-07 17:21:21 -06:00
|
|
|
register_node_type_geo_object_info();
|
Geometry Nodes: Mesh Point Cloud Conversion Nodes
This commit adds nodes to do direct conversion between meshes and point
clouds in geometry nodes. The conversion from mesh to points is helpful
to instance once per face, or once per edge, which was previously only
possibly with ugly work-arounds. Fields can be evaluated on the mesh
to pass them to the points with the attribute capture node.
The other conversion, point cloud to mesh vertices, is a bit less
obvious, though it is still a common request from users. It's helpful
for flexibility when passing data around, better visualization in the
viewport (and in the future, cycles), and the simplicity of points.
This is a step towards T91754, where point clouds are currently
combined with meshes when outputing to the next modifier after geometry
nodes. Since we're removing the implicit behavior for realizing
instances, it feels natural to use an explicit node to convert points
to vertices too.
Differential Revision: https://developer.blender.org/D12657
2021-09-28 12:14:13 -05:00
|
|
|
register_node_type_geo_points_to_vertices();
|
2021-01-26 17:37:58 +01:00
|
|
|
register_node_type_geo_points_to_volume();
|
2022-07-27 08:56:17 -05:00
|
|
|
register_node_type_geo_points();
|
2021-09-28 15:21:36 -05:00
|
|
|
register_node_type_geo_proximity();
|
2021-06-17 09:31:53 +01:00
|
|
|
register_node_type_geo_raycast();
|
2021-09-20 12:37:52 +02:00
|
|
|
register_node_type_geo_realize_instances();
|
2022-03-14 11:48:11 -05:00
|
|
|
register_node_type_geo_remove_attribute();
|
2021-10-13 09:42:10 -05:00
|
|
|
register_node_type_geo_rotate_instances();
|
2022-01-21 17:34:47 +01:00
|
|
|
register_node_type_geo_scale_elements();
|
2021-10-13 09:08:02 -05:00
|
|
|
register_node_type_geo_scale_instances();
|
2021-06-15 22:31:57 -05:00
|
|
|
register_node_type_geo_separate_components();
|
2021-10-11 08:38:02 -05:00
|
|
|
register_node_type_geo_separate_geometry();
|
2021-10-11 11:03:57 -05:00
|
|
|
register_node_type_geo_set_curve_handles();
|
|
|
|
|
register_node_type_geo_set_curve_radius();
|
|
|
|
|
register_node_type_geo_set_curve_tilt();
|
2021-10-26 15:40:57 -05:00
|
|
|
register_node_type_geo_set_id();
|
2021-10-13 08:39:54 -05:00
|
|
|
register_node_type_geo_set_material_index();
|
2021-10-19 16:27:37 -05:00
|
|
|
register_node_type_geo_set_material();
|
2021-10-11 11:03:57 -05:00
|
|
|
register_node_type_geo_set_point_radius();
|
2021-09-09 12:54:20 +02:00
|
|
|
register_node_type_geo_set_position();
|
2021-10-11 11:03:57 -05:00
|
|
|
register_node_type_geo_set_shade_smooth();
|
|
|
|
|
register_node_type_geo_set_spline_cyclic();
|
|
|
|
|
register_node_type_geo_set_spline_resolution();
|
2022-03-14 11:48:11 -05:00
|
|
|
register_node_type_geo_store_named_attribute();
|
2021-09-28 14:20:29 -05:00
|
|
|
register_node_type_geo_string_join();
|
2021-09-24 12:41:49 -05:00
|
|
|
register_node_type_geo_string_to_curves();
|
2021-03-17 14:40:38 -04:00
|
|
|
register_node_type_geo_subdivision_surface();
|
2021-04-19 10:38:50 +02:00
|
|
|
register_node_type_geo_switch();
|
2021-10-15 14:08:52 -05:00
|
|
|
register_node_type_geo_transfer_attribute();
|
2021-02-07 17:21:21 -06:00
|
|
|
register_node_type_geo_transform();
|
2021-10-13 09:02:05 -05:00
|
|
|
register_node_type_geo_translate_instances();
|
2021-02-07 17:21:21 -06:00
|
|
|
register_node_type_geo_triangulate();
|
2022-07-27 08:56:17 -05:00
|
|
|
register_node_type_geo_uv_pack_islands();
|
|
|
|
|
register_node_type_geo_uv_unwrap();
|
2021-07-05 10:46:00 +02:00
|
|
|
register_node_type_geo_viewer();
|
2022-06-17 13:26:22 +02:00
|
|
|
register_node_type_geo_volume_cube();
|
2021-02-05 16:20:14 +01:00
|
|
|
register_node_type_geo_volume_to_mesh();
|
2020-04-20 10:58:43 +02:00
|
|
|
}
|
|
|
|
|
|
2021-02-02 09:51:38 -06:00
|
|
|
static void registerFunctionNodes()
|
2020-04-20 15:27:12 +02:00
|
|
|
{
|
2021-10-09 14:40:37 -05:00
|
|
|
register_node_type_fn_align_euler_to_vector();
|
2020-04-20 15:27:12 +02:00
|
|
|
register_node_type_fn_boolean_math();
|
Nodes: Add general Combine/Separate Color nodes
Inspired by D12936 and D12929, this patch adds general purpose
"Combine Color" and "Separate Color" nodes to Geometry, Compositor,
Shader and Texture nodes.
- Within Geometry Nodes, it replaces the existing "Combine RGB" and
"Separate RGB" nodes.
- Within Compositor Nodes, it replaces the existing
"Combine RGBA/HSVA/YCbCrA/YUVA" and "Separate RGBA/HSVA/YCbCrA/YUVA"
nodes.
- Within Texture Nodes, it replaces the existing "Combine RGBA" and
"Separate RGBA" nodes.
- Within Shader Nodes, it replaces the existing "Combine RGB/HSV" and
"Separate RGB/HSV" nodes.
Python addons have not been updated to the new nodes yet.
**New shader code**
In node_color.h, color.h and gpu_shader_material_color_util.glsl,
missing methods hsl_to_rgb and rgb_to_hsl are added by directly
converting existing C code. They always produce the same result.
**Old code**
As requested by T96219, old nodes still exist but are not displayed in
the add menu. This means Python scripts can still create them as usual.
Otherwise, versioning replaces the old nodes with the new nodes when
opening .blend files.
Differential Revision: https://developer.blender.org/D14034
2022-05-04 18:44:03 +02:00
|
|
|
register_node_type_fn_combine_color();
|
Geometry Nodes: Generalized Compare Node
Replace compare floats node with a generalized compare node. The node
allows for the comparison of float, int, string, color, and vector.
The datatypes support the following operators:
Float, Int: <, >, <=, >=, ==, !=
String: ==, !=
Color: ==, !=, lighter, darker
(using rgb_to_grayscale value as the brightness value)
Vector Supports 5 comparison modes for: ==, !=, <, >, <=, >=
Average: The average of the components of the vectors are compared.
Dot Product: The dot product of the vectors are compared.
Direction: The angle between the vectors is compared to an angle
Element-wise: The individual components of the vectors are compared.
Length: The lengths of the vectors are compared.
Differential Revision: https://developer.blender.org/D13228
2021-12-01 09:36:25 -06:00
|
|
|
register_node_type_fn_compare();
|
2021-07-05 11:52:10 -05:00
|
|
|
register_node_type_fn_float_to_int();
|
2021-10-22 14:59:15 +02:00
|
|
|
register_node_type_fn_input_bool();
|
2021-10-22 15:27:10 +02:00
|
|
|
register_node_type_fn_input_color();
|
2021-10-22 14:59:15 +02:00
|
|
|
register_node_type_fn_input_int();
|
2021-09-24 10:59:52 -05:00
|
|
|
register_node_type_fn_input_special_characters();
|
2021-02-19 16:03:14 -06:00
|
|
|
register_node_type_fn_input_string();
|
2021-02-07 17:21:21 -06:00
|
|
|
register_node_type_fn_input_vector();
|
2021-09-24 14:03:42 -05:00
|
|
|
register_node_type_fn_random_value();
|
2021-10-19 15:27:47 -05:00
|
|
|
register_node_type_fn_replace_string();
|
2021-10-02 20:04:45 -05:00
|
|
|
register_node_type_fn_rotate_euler();
|
Nodes: Add general Combine/Separate Color nodes
Inspired by D12936 and D12929, this patch adds general purpose
"Combine Color" and "Separate Color" nodes to Geometry, Compositor,
Shader and Texture nodes.
- Within Geometry Nodes, it replaces the existing "Combine RGB" and
"Separate RGB" nodes.
- Within Compositor Nodes, it replaces the existing
"Combine RGBA/HSVA/YCbCrA/YUVA" and "Separate RGBA/HSVA/YCbCrA/YUVA"
nodes.
- Within Texture Nodes, it replaces the existing "Combine RGBA" and
"Separate RGBA" nodes.
- Within Shader Nodes, it replaces the existing "Combine RGB/HSV" and
"Separate RGB/HSV" nodes.
Python addons have not been updated to the new nodes yet.
**New shader code**
In node_color.h, color.h and gpu_shader_material_color_util.glsl,
missing methods hsl_to_rgb and rgb_to_hsl are added by directly
converting existing C code. They always produce the same result.
**Old code**
As requested by T96219, old nodes still exist but are not displayed in
the add menu. This means Python scripts can still create them as usual.
Otherwise, versioning replaces the old nodes with the new nodes when
opening .blend files.
Differential Revision: https://developer.blender.org/D14034
2022-05-04 18:44:03 +02:00
|
|
|
register_node_type_fn_separate_color();
|
2021-10-24 11:19:10 +02:00
|
|
|
register_node_type_fn_slice_string();
|
2021-09-21 14:11:32 -05:00
|
|
|
register_node_type_fn_string_length();
|
|
|
|
|
register_node_type_fn_value_to_string();
|
2020-04-20 15:27:12 +02:00
|
|
|
}
|
|
|
|
|
|
2021-12-08 00:31:20 -05:00
|
|
|
void BKE_node_system_init()
|
2007-03-26 15:07:38 +00:00
|
|
|
{
|
2014-04-15 14:17:54 +10:00
|
|
|
nodetreetypes_hash = BLI_ghash_str_new("nodetreetypes_hash gh");
|
|
|
|
|
nodetypes_hash = BLI_ghash_str_new("nodetypes_hash gh");
|
|
|
|
|
nodesockettypes_hash = BLI_ghash_str_new("nodesockettypes_hash gh");
|
2013-03-18 16:34:57 +00:00
|
|
|
|
2013-03-19 13:40:16 +00:00
|
|
|
register_undefined_types();
|
|
|
|
|
|
2013-03-18 16:34:57 +00:00
|
|
|
register_standard_node_socket_types();
|
|
|
|
|
|
|
|
|
|
register_node_tree_type_cmp();
|
|
|
|
|
register_node_tree_type_sh();
|
|
|
|
|
register_node_tree_type_tex();
|
2020-12-02 13:25:25 +01:00
|
|
|
register_node_tree_type_geo();
|
2013-03-18 16:34:57 +00:00
|
|
|
|
|
|
|
|
register_node_type_frame();
|
|
|
|
|
register_node_type_reroute();
|
|
|
|
|
register_node_type_group_input();
|
|
|
|
|
register_node_type_group_output();
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2013-03-18 16:34:57 +00:00
|
|
|
registerCompositNodes();
|
|
|
|
|
registerShaderNodes();
|
|
|
|
|
registerTextureNodes();
|
2020-12-02 13:25:25 +01:00
|
|
|
registerGeometryNodes();
|
2020-04-20 15:27:12 +02:00
|
|
|
registerFunctionNodes();
|
2007-03-26 15:07:38 +00:00
|
|
|
}
|
|
|
|
|
|
2021-12-08 00:31:20 -05:00
|
|
|
void BKE_node_system_exit()
|
2007-03-26 15:07:38 +00:00
|
|
|
{
|
2013-06-24 21:11:13 +00:00
|
|
|
if (nodetypes_hash) {
|
2018-11-30 15:35:15 +11:00
|
|
|
NODE_TYPES_BEGIN (nt) {
|
2020-04-03 18:24:08 +02:00
|
|
|
if (nt->rna_ext.free) {
|
|
|
|
|
nt->rna_ext.free(nt->rna_ext.data);
|
2013-06-24 21:11:13 +00:00
|
|
|
}
|
2018-11-30 15:35:15 +11:00
|
|
|
}
|
|
|
|
|
NODE_TYPES_END;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2021-02-02 09:51:38 -06:00
|
|
|
BLI_ghash_free(nodetypes_hash, nullptr, node_free_type);
|
|
|
|
|
nodetypes_hash = nullptr;
|
2013-06-24 21:11:13 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2013-06-24 21:11:13 +00:00
|
|
|
if (nodesockettypes_hash) {
|
2018-11-30 15:35:15 +11:00
|
|
|
NODE_SOCKET_TYPES_BEGIN (st) {
|
2019-04-22 09:39:35 +10:00
|
|
|
if (st->ext_socket.free) {
|
2013-06-24 21:11:13 +00:00
|
|
|
st->ext_socket.free(st->ext_socket.data);
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
|
|
|
|
if (st->ext_interface.free) {
|
2013-06-24 21:11:13 +00:00
|
|
|
st->ext_interface.free(st->ext_interface.data);
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2018-11-30 15:35:15 +11:00
|
|
|
}
|
|
|
|
|
NODE_SOCKET_TYPES_END;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2021-02-02 09:51:38 -06:00
|
|
|
BLI_ghash_free(nodesockettypes_hash, nullptr, node_free_socket_type);
|
|
|
|
|
nodesockettypes_hash = nullptr;
|
2013-06-24 21:11:13 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2013-06-24 21:11:13 +00:00
|
|
|
if (nodetreetypes_hash) {
|
2013-09-13 08:45:20 +00:00
|
|
|
NODE_TREE_TYPES_BEGIN (nt) {
|
2020-04-03 18:24:08 +02:00
|
|
|
if (nt->rna_ext.free) {
|
|
|
|
|
nt->rna_ext.free(nt->rna_ext.data);
|
2013-06-24 21:11:13 +00:00
|
|
|
}
|
2013-09-13 08:45:20 +00:00
|
|
|
}
|
|
|
|
|
NODE_TREE_TYPES_END;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2021-02-02 09:51:38 -06:00
|
|
|
BLI_ghash_free(nodetreetypes_hash, nullptr, ntree_free_type);
|
|
|
|
|
nodetreetypes_hash = nullptr;
|
2013-06-24 21:11:13 +00:00
|
|
|
}
|
2007-03-26 15:07:38 +00:00
|
|
|
}
|
2009-08-15 16:43:03 +00:00
|
|
|
|
2013-03-26 22:37:41 +00:00
|
|
|
/* -------------------------------------------------------------------- */
|
2018-11-30 15:22:01 +11:00
|
|
|
/* NodeTree Iterator Helpers (FOREACH_NODETREE_BEGIN) */
|
2013-03-26 22:37:41 +00:00
|
|
|
|
|
|
|
|
void BKE_node_tree_iter_init(struct NodeTreeIterStore *ntreeiter, struct Main *bmain)
|
|
|
|
|
{
|
2021-02-02 09:51:38 -06:00
|
|
|
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;
|
|
|
|
|
ntreeiter->simulation = (Simulation *)bmain->simulations.first;
|
2013-03-26 22:37:41 +00:00
|
|
|
}
|
|
|
|
|
bool BKE_node_tree_iter_step(struct NodeTreeIterStore *ntreeiter,
|
|
|
|
|
bNodeTree **r_nodetree,
|
|
|
|
|
struct ID **r_id)
|
|
|
|
|
{
|
|
|
|
|
if (ntreeiter->ngroup) {
|
2021-02-02 09:51:38 -06:00
|
|
|
*r_nodetree = (bNodeTree *)ntreeiter->ngroup;
|
2013-03-26 22:37:41 +00:00
|
|
|
*r_id = (ID *)ntreeiter->ngroup;
|
2021-02-02 09:51:38 -06:00
|
|
|
ntreeiter->ngroup = (bNodeTree *)ntreeiter->ngroup->id.next;
|
2013-03-26 22:37:41 +00:00
|
|
|
}
|
|
|
|
|
else if (ntreeiter->scene) {
|
2021-02-02 09:51:38 -06:00
|
|
|
*r_nodetree = (bNodeTree *)ntreeiter->scene->nodetree;
|
2013-03-26 22:37:41 +00:00
|
|
|
*r_id = (ID *)ntreeiter->scene;
|
2021-02-02 09:51:38 -06:00
|
|
|
ntreeiter->scene = (Scene *)ntreeiter->scene->id.next;
|
2013-03-26 22:37:41 +00:00
|
|
|
}
|
|
|
|
|
else if (ntreeiter->mat) {
|
2021-02-02 09:51:38 -06:00
|
|
|
*r_nodetree = (bNodeTree *)ntreeiter->mat->nodetree;
|
2013-03-26 22:37:41 +00:00
|
|
|
*r_id = (ID *)ntreeiter->mat;
|
2021-02-02 09:51:38 -06:00
|
|
|
ntreeiter->mat = (Material *)ntreeiter->mat->id.next;
|
2013-03-26 22:37:41 +00:00
|
|
|
}
|
|
|
|
|
else if (ntreeiter->tex) {
|
2021-02-02 09:51:38 -06:00
|
|
|
*r_nodetree = (bNodeTree *)ntreeiter->tex->nodetree;
|
2013-03-26 22:37:41 +00:00
|
|
|
*r_id = (ID *)ntreeiter->tex;
|
2021-02-02 09:51:38 -06:00
|
|
|
ntreeiter->tex = (Tex *)ntreeiter->tex->id.next;
|
2013-03-26 22:37:41 +00:00
|
|
|
}
|
2019-02-27 10:46:48 +11:00
|
|
|
else if (ntreeiter->light) {
|
2021-02-02 09:51:38 -06:00
|
|
|
*r_nodetree = (bNodeTree *)ntreeiter->light->nodetree;
|
2019-02-27 10:46:48 +11:00
|
|
|
*r_id = (ID *)ntreeiter->light;
|
2021-02-02 09:51:38 -06:00
|
|
|
ntreeiter->light = (Light *)ntreeiter->light->id.next;
|
2013-03-26 22:37:41 +00:00
|
|
|
}
|
|
|
|
|
else if (ntreeiter->world) {
|
2021-02-02 09:51:38 -06:00
|
|
|
*r_nodetree = (bNodeTree *)ntreeiter->world->nodetree;
|
2013-03-26 22:37:41 +00:00
|
|
|
*r_id = (ID *)ntreeiter->world;
|
2021-02-02 09:51:38 -06:00
|
|
|
ntreeiter->world = (World *)ntreeiter->world->id.next;
|
2013-03-26 22:37:41 +00:00
|
|
|
}
|
2014-05-03 18:51:53 +09:00
|
|
|
else if (ntreeiter->linestyle) {
|
2021-02-02 09:51:38 -06:00
|
|
|
*r_nodetree = (bNodeTree *)ntreeiter->linestyle->nodetree;
|
2014-05-03 18:51:53 +09:00
|
|
|
*r_id = (ID *)ntreeiter->linestyle;
|
2021-02-02 09:51:38 -06:00
|
|
|
ntreeiter->linestyle = (FreestyleLineStyle *)ntreeiter->linestyle->id.next;
|
2014-05-03 18:51:53 +09:00
|
|
|
}
|
2020-04-20 12:56:16 +02:00
|
|
|
else if (ntreeiter->simulation) {
|
2021-02-02 09:51:38 -06:00
|
|
|
*r_nodetree = (bNodeTree *)ntreeiter->simulation->nodetree;
|
2020-04-20 12:56:16 +02:00
|
|
|
*r_id = (ID *)ntreeiter->simulation;
|
2021-02-02 09:51:38 -06:00
|
|
|
ntreeiter->simulation = (Simulation *)ntreeiter->simulation->id.next;
|
2020-04-20 12:56:16 +02:00
|
|
|
}
|
2013-03-26 22:37:41 +00:00
|
|
|
else {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2013-03-26 22:37:41 +00:00
|
|
|
return true;
|
|
|
|
|
}
|
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
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/* NodeTree kernel functions */
|
|
|
|
|
|
|
|
|
|
void BKE_nodetree_remove_layer_n(bNodeTree *ntree, Scene *scene, const int layer_index)
|
|
|
|
|
{
|
2018-01-30 18:31:32 -02:00
|
|
|
BLI_assert(layer_index != -1);
|
2020-04-03 19:15:01 +02:00
|
|
|
LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
|
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
|
|
|
if (node->type == CMP_NODE_R_LAYERS && (Scene *)node->id == scene) {
|
|
|
|
|
if (node->custom1 == layer_index) {
|
|
|
|
|
node->custom1 = 0;
|
|
|
|
|
}
|
|
|
|
|
else if (node->custom1 > layer_index) {
|
|
|
|
|
node->custom1--;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|