2023-08-16 00:20:26 +10:00
|
|
|
/* SPDX-FileCopyrightText: 2008 Blender Authors
|
2023-05-31 16:19:06 +02:00
|
|
|
*
|
|
|
|
|
* SPDX-License-Identifier: GPL-2.0-or-later */
|
2008-12-13 18:09:49 +00:00
|
|
|
|
2019-02-18 08:08:12 +11:00
|
|
|
/** \file
|
|
|
|
|
* \ingroup spnode
|
2011-02-27 20:29:51 +00:00
|
|
|
*/
|
|
|
|
|
|
2023-09-04 12:43:56 +02:00
|
|
|
#include "AS_asset_representation.hh"
|
|
|
|
|
|
2023-12-21 10:22:51 +01:00
|
|
|
#include "BLI_listbase.h"
|
2023-09-01 21:37:11 +02:00
|
|
|
#include "BLI_string.h"
|
|
|
|
|
|
2022-11-10 13:02:15 +02:00
|
|
|
#include "DNA_ID.h"
|
2024-04-24 17:01:22 +02:00
|
|
|
#include "DNA_gpencil_legacy_types.h"
|
2023-12-21 10:22:51 +01:00
|
|
|
#include "DNA_image_types.h"
|
2011-11-02 18:55:32 +00:00
|
|
|
#include "DNA_material_types.h"
|
2023-09-24 21:06:37 +02:00
|
|
|
#include "DNA_modifier_types.h"
|
2008-12-13 18:09:49 +00:00
|
|
|
#include "DNA_node_types.h"
|
2023-09-24 21:06:37 +02:00
|
|
|
#include "DNA_object_types.h"
|
2023-12-21 10:22:51 +01:00
|
|
|
#include "DNA_screen_types.h"
|
|
|
|
|
#include "DNA_space_types.h"
|
|
|
|
|
#include "DNA_windowmanager_types.h"
|
2008-12-13 18:09:49 +00:00
|
|
|
|
|
|
|
|
#include "MEM_guardedalloc.h"
|
|
|
|
|
|
2023-11-16 11:41:55 +01:00
|
|
|
#include "BKE_asset.hh"
|
2023-09-24 21:06:37 +02:00
|
|
|
#include "BKE_compute_contexts.hh"
|
2023-11-16 11:41:55 +01:00
|
|
|
#include "BKE_context.hh"
|
2023-03-13 10:42:51 +01:00
|
|
|
#include "BKE_gpencil_legacy.h"
|
2024-03-26 12:57:30 -04:00
|
|
|
#include "BKE_idprop.hh"
|
2024-01-15 12:44:04 -05:00
|
|
|
#include "BKE_lib_id.hh"
|
2024-01-18 12:20:42 +01:00
|
|
|
#include "BKE_lib_query.hh"
|
2023-11-30 19:51:22 +01:00
|
|
|
#include "BKE_lib_remap.hh"
|
2022-12-02 11:12:51 -06:00
|
|
|
#include "BKE_node_runtime.hh"
|
2023-09-24 21:06:37 +02:00
|
|
|
#include "BKE_node_tree_zones.hh"
|
2023-09-25 17:48:21 -04:00
|
|
|
#include "BKE_screen.hh"
|
2008-12-13 18:09:49 +00:00
|
|
|
|
2023-12-21 10:22:51 +01:00
|
|
|
#include "ED_image.hh"
|
2023-08-05 02:57:52 +02:00
|
|
|
#include "ED_node.hh"
|
2023-08-08 17:36:06 +02:00
|
|
|
#include "ED_node_preview.hh"
|
2023-08-04 23:11:22 +02:00
|
|
|
#include "ED_screen.hh"
|
2023-08-05 02:57:52 +02:00
|
|
|
#include "ED_space_api.hh"
|
2008-12-13 18:09:49 +00:00
|
|
|
|
2023-08-05 02:57:52 +02:00
|
|
|
#include "UI_resources.hh"
|
|
|
|
|
#include "UI_view2d.hh"
|
2008-12-13 18:09:49 +00:00
|
|
|
|
2023-09-22 03:18:17 +02:00
|
|
|
#include "DEG_depsgraph.hh"
|
2022-11-10 13:02:15 +02:00
|
|
|
|
2023-08-28 15:01:05 +02:00
|
|
|
#include "BLO_read_write.hh"
|
2022-09-28 11:52:22 +02:00
|
|
|
|
2023-08-10 22:40:27 +02:00
|
|
|
#include "RNA_access.hh"
|
|
|
|
|
#include "RNA_define.hh"
|
|
|
|
|
#include "RNA_enum_types.hh"
|
2022-03-14 16:54:46 +01:00
|
|
|
#include "RNA_prototypes.h"
|
2009-03-19 19:03:38 +00:00
|
|
|
|
2023-08-04 23:11:22 +02:00
|
|
|
#include "WM_api.hh"
|
|
|
|
|
#include "WM_types.hh"
|
2017-05-29 22:06:59 +10:00
|
|
|
|
2021-11-12 12:12:27 -06:00
|
|
|
#include "node_intern.hh" /* own include */
|
2013-03-18 16:34:57 +00:00
|
|
|
|
2021-12-03 11:43:10 -05:00
|
|
|
using blender::float2;
|
|
|
|
|
|
2013-03-18 16:34:57 +00:00
|
|
|
/* ******************** tree path ********************* */
|
|
|
|
|
|
|
|
|
|
void ED_node_tree_start(SpaceNode *snode, bNodeTree *ntree, ID *id, ID *from)
|
|
|
|
|
{
|
2021-11-12 12:12:27 -06:00
|
|
|
LISTBASE_FOREACH_MUTABLE (bNodeTreePath *, path, &snode->treepath) {
|
2013-03-18 16:34:57 +00:00
|
|
|
MEM_freeN(path);
|
|
|
|
|
}
|
2014-02-08 06:07:10 +11:00
|
|
|
BLI_listbase_clear(&snode->treepath);
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2013-03-18 16:34:57 +00:00
|
|
|
if (ntree) {
|
2021-12-24 22:17:49 -05:00
|
|
|
bNodeTreePath *path = MEM_cnew<bNodeTreePath>("node tree path");
|
2013-03-18 16:34:57 +00:00
|
|
|
path->nodetree = ntree;
|
|
|
|
|
path->parent_key = NODE_INSTANCE_KEY_BASE;
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2013-04-17 17:12:12 +00:00
|
|
|
/* copy initial offset from bNodeTree */
|
|
|
|
|
copy_v2_v2(path->view_center, ntree->view_center);
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2019-03-26 21:16:47 +11:00
|
|
|
if (id) {
|
2023-05-09 12:50:37 +10:00
|
|
|
STRNCPY(path->display_name, id->name + 2);
|
2019-03-26 21:16:47 +11:00
|
|
|
}
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2013-03-18 16:34:57 +00:00
|
|
|
BLI_addtail(&snode->treepath, path);
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2021-02-15 19:29:09 +01:00
|
|
|
if (ntree->type != NTREE_GEOMETRY) {
|
|
|
|
|
/* This can probably be removed for all node tree types. It mainly exists because it was not
|
2023-02-12 14:37:16 +11:00
|
|
|
* possible to store id references in custom properties. Also see #36024. I don't want to
|
2021-02-15 19:29:09 +01:00
|
|
|
* remove it for all tree types in bcon3 though. */
|
|
|
|
|
id_us_ensure_real(&ntree->id);
|
|
|
|
|
}
|
2013-03-18 16:34:57 +00:00
|
|
|
}
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2013-03-18 16:34:57 +00:00
|
|
|
/* update current tree */
|
|
|
|
|
snode->nodetree = snode->edittree = ntree;
|
|
|
|
|
snode->id = id;
|
|
|
|
|
snode->from = from;
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2013-04-24 16:36:50 +00:00
|
|
|
ED_node_set_active_viewer_key(snode);
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2021-11-12 12:12:27 -06:00
|
|
|
WM_main_add_notifier(NC_SCENE | ND_NODES, nullptr);
|
2013-03-18 16:34:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ED_node_tree_push(SpaceNode *snode, bNodeTree *ntree, bNode *gnode)
|
|
|
|
|
{
|
2021-12-24 22:17:49 -05:00
|
|
|
bNodeTreePath *path = MEM_cnew<bNodeTreePath>("node tree path");
|
2021-11-12 12:12:27 -06:00
|
|
|
bNodeTreePath *prev_path = (bNodeTreePath *)snode->treepath.last;
|
2013-03-18 16:34:57 +00:00
|
|
|
path->nodetree = ntree;
|
|
|
|
|
if (gnode) {
|
2019-03-26 21:16:47 +11:00
|
|
|
if (prev_path) {
|
2013-03-18 16:34:57 +00:00
|
|
|
path->parent_key = BKE_node_instance_key(prev_path->parent_key, prev_path->nodetree, gnode);
|
2019-03-26 21:16:47 +11:00
|
|
|
}
|
|
|
|
|
else {
|
2013-03-18 16:34:57 +00:00
|
|
|
path->parent_key = NODE_INSTANCE_KEY_BASE;
|
2019-03-26 21:16:47 +11:00
|
|
|
}
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2023-05-09 12:50:37 +10:00
|
|
|
STRNCPY(path->node_name, gnode->name);
|
|
|
|
|
STRNCPY(path->display_name, gnode->name);
|
2013-03-18 16:34:57 +00:00
|
|
|
}
|
2019-03-26 21:16:47 +11:00
|
|
|
else {
|
2013-03-18 16:34:57 +00:00
|
|
|
path->parent_key = NODE_INSTANCE_KEY_BASE;
|
2019-03-26 21:16:47 +11:00
|
|
|
}
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2013-04-17 17:12:12 +00:00
|
|
|
/* copy initial offset from bNodeTree */
|
|
|
|
|
copy_v2_v2(path->view_center, ntree->view_center);
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2013-03-18 16:34:57 +00:00
|
|
|
BLI_addtail(&snode->treepath, path);
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2013-07-08 11:38:11 +00:00
|
|
|
id_us_ensure_real(&ntree->id);
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2013-03-18 16:34:57 +00:00
|
|
|
/* update current tree */
|
|
|
|
|
snode->edittree = ntree;
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2013-04-24 16:36:50 +00:00
|
|
|
ED_node_set_active_viewer_key(snode);
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2021-11-12 12:12:27 -06:00
|
|
|
WM_main_add_notifier(NC_SCENE | ND_NODES, nullptr);
|
2013-03-18 16:34:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ED_node_tree_pop(SpaceNode *snode)
|
|
|
|
|
{
|
2021-11-12 12:12:27 -06:00
|
|
|
bNodeTreePath *path = (bNodeTreePath *)snode->treepath.last;
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2013-03-18 16:34:57 +00:00
|
|
|
/* don't remove root */
|
2019-03-26 21:16:47 +11:00
|
|
|
if (path == snode->treepath.first) {
|
2013-03-18 16:34:57 +00:00
|
|
|
return;
|
2019-03-26 21:16:47 +11:00
|
|
|
}
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2013-03-18 16:34:57 +00:00
|
|
|
BLI_remlink(&snode->treepath, path);
|
|
|
|
|
MEM_freeN(path);
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2013-03-18 16:34:57 +00:00
|
|
|
/* update current tree */
|
2021-11-12 12:12:27 -06:00
|
|
|
path = (bNodeTreePath *)snode->treepath.last;
|
2013-03-18 16:34:57 +00:00
|
|
|
snode->edittree = path->nodetree;
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2013-04-24 16:36:50 +00:00
|
|
|
ED_node_set_active_viewer_key(snode);
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2013-03-18 16:34:57 +00:00
|
|
|
/* listener updates the View2D center from edittree */
|
2021-11-12 12:12:27 -06:00
|
|
|
WM_main_add_notifier(NC_SCENE | ND_NODES, nullptr);
|
2013-03-18 16:34:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int ED_node_tree_depth(SpaceNode *snode)
|
|
|
|
|
{
|
2014-11-16 13:57:58 +01:00
|
|
|
return BLI_listbase_count(&snode->treepath);
|
2013-03-18 16:34:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bNodeTree *ED_node_tree_get(SpaceNode *snode, int level)
|
|
|
|
|
{
|
|
|
|
|
bNodeTreePath *path;
|
|
|
|
|
int i;
|
2021-11-12 12:12:27 -06:00
|
|
|
for (path = (bNodeTreePath *)snode->treepath.last, i = 0; path; path = path->prev, i++) {
|
2019-03-26 21:16:47 +11:00
|
|
|
if (i == level) {
|
2013-03-18 16:34:57 +00:00
|
|
|
return path->nodetree;
|
2019-03-26 21:16:47 +11:00
|
|
|
}
|
2013-03-18 16:34:57 +00:00
|
|
|
}
|
2021-11-12 12:12:27 -06:00
|
|
|
return nullptr;
|
2013-03-18 16:34:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int ED_node_tree_path_length(SpaceNode *snode)
|
|
|
|
|
{
|
|
|
|
|
int length = 0;
|
2020-11-20 11:00:51 -05:00
|
|
|
int i = 0;
|
|
|
|
|
LISTBASE_FOREACH_INDEX (bNodeTreePath *, path, &snode->treepath, i) {
|
2021-04-01 14:36:44 +02:00
|
|
|
length += strlen(path->display_name);
|
2019-03-26 21:16:47 +11:00
|
|
|
if (i > 0) {
|
2013-03-18 16:34:57 +00:00
|
|
|
length += 1; /* for separator char */
|
2019-03-26 21:16:47 +11:00
|
|
|
}
|
2013-03-18 16:34:57 +00:00
|
|
|
}
|
|
|
|
|
return length;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ED_node_tree_path_get(SpaceNode *snode, char *value)
|
|
|
|
|
{
|
2020-11-20 11:00:51 -05:00
|
|
|
int i = 0;
|
2023-06-19 11:37:05 +10:00
|
|
|
#ifndef NDEBUG
|
|
|
|
|
const char *value_orig = value;
|
|
|
|
|
#endif
|
|
|
|
|
/* Note that the caller ensures there is enough space available. */
|
2020-11-20 11:00:51 -05:00
|
|
|
LISTBASE_FOREACH_INDEX (bNodeTreePath *, path, &snode->treepath, i) {
|
2023-06-19 11:37:05 +10:00
|
|
|
const int len = strlen(path->display_name);
|
|
|
|
|
if (i != 0) {
|
|
|
|
|
*value++ = '/';
|
2013-03-18 16:34:57 +00:00
|
|
|
}
|
2023-06-19 11:37:05 +10:00
|
|
|
memcpy(value, path->display_name, len);
|
|
|
|
|
value += len;
|
2013-03-18 16:34:57 +00:00
|
|
|
}
|
2023-06-19 11:37:05 +10:00
|
|
|
*value = '\0';
|
|
|
|
|
BLI_assert(ptrdiff_t(ED_node_tree_path_length(snode)) == ptrdiff_t(value - value_orig));
|
2013-03-18 16:34:57 +00:00
|
|
|
}
|
|
|
|
|
|
2013-04-24 16:36:50 +00:00
|
|
|
void ED_node_set_active_viewer_key(SpaceNode *snode)
|
|
|
|
|
{
|
2021-11-12 12:12:27 -06:00
|
|
|
bNodeTreePath *path = (bNodeTreePath *)snode->treepath.last;
|
2013-04-24 16:36:50 +00:00
|
|
|
if (snode->nodetree && path) {
|
2022-11-10 13:02:15 +02:00
|
|
|
/* A change in active viewer may result in the change of the output node used by the
|
|
|
|
|
* compositor, so we need to get notified about such changes. */
|
2022-12-02 10:32:50 +02:00
|
|
|
if (snode->nodetree->active_viewer_key.value != path->parent_key.value &&
|
|
|
|
|
snode->nodetree->type == NTREE_COMPOSIT)
|
|
|
|
|
{
|
2022-11-10 13:02:15 +02:00
|
|
|
DEG_id_tag_update(&snode->nodetree->id, ID_RECALC_NTREE_OUTPUT);
|
|
|
|
|
WM_main_add_notifier(NC_NODE, nullptr);
|
|
|
|
|
}
|
|
|
|
|
|
2013-04-24 16:36:50 +00:00
|
|
|
snode->nodetree->active_viewer_key = path->parent_key;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-01-20 10:36:56 -06:00
|
|
|
void ED_node_cursor_location_get(const SpaceNode *snode, float value[2])
|
|
|
|
|
{
|
|
|
|
|
copy_v2_v2(value, snode->runtime->cursor);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ED_node_cursor_location_set(SpaceNode *snode, const float value[2])
|
|
|
|
|
{
|
|
|
|
|
copy_v2_v2(snode->runtime->cursor, value);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
namespace blender::ed::space_node {
|
|
|
|
|
|
2021-12-03 11:43:10 -05:00
|
|
|
float2 space_node_group_offset(const SpaceNode &snode)
|
2013-03-18 16:34:57 +00:00
|
|
|
{
|
2021-12-03 11:43:10 -05:00
|
|
|
const bNodeTreePath *path = (bNodeTreePath *)snode.treepath.last;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2013-04-17 17:12:12 +00:00
|
|
|
if (path && path->prev) {
|
2021-12-03 11:43:10 -05:00
|
|
|
return float2(path->view_center) - float2(path->prev->view_center);
|
2019-03-26 21:16:47 +11:00
|
|
|
}
|
2021-12-03 11:43:10 -05:00
|
|
|
return float2(0);
|
2013-03-18 16:34:57 +00:00
|
|
|
}
|
|
|
|
|
|
2023-09-26 20:30:46 +02:00
|
|
|
static const bNode *group_node_by_name(const bNodeTree &ntree, StringRef name)
|
|
|
|
|
{
|
|
|
|
|
for (const bNode *node : ntree.group_nodes()) {
|
|
|
|
|
if (node->name == name) {
|
|
|
|
|
return node;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::optional<int32_t> find_nested_node_id_in_root(const SpaceNode &snode, const bNode &query_node)
|
|
|
|
|
{
|
|
|
|
|
BLI_assert(snode.edittree->runtime->nodes_by_id.contains(const_cast<bNode *>(&query_node)));
|
|
|
|
|
|
|
|
|
|
std::optional<int32_t> id_in_node;
|
|
|
|
|
const char *group_node_name = nullptr;
|
|
|
|
|
const bNode *node = &query_node;
|
|
|
|
|
LISTBASE_FOREACH_BACKWARD (const bNodeTreePath *, path, &snode.treepath) {
|
|
|
|
|
const bNodeTree *ntree = path->nodetree;
|
|
|
|
|
if (group_node_name) {
|
|
|
|
|
node = group_node_by_name(*ntree, group_node_name);
|
|
|
|
|
}
|
|
|
|
|
bool found = false;
|
|
|
|
|
for (const bNestedNodeRef &ref : ntree->nested_node_refs_span()) {
|
|
|
|
|
if (node->is_group()) {
|
|
|
|
|
if (ref.path.node_id == node->identifier && ref.path.id_in_node == id_in_node) {
|
|
|
|
|
group_node_name = path->node_name;
|
|
|
|
|
id_in_node = ref.id;
|
|
|
|
|
found = true;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (ref.path.node_id == node->identifier) {
|
|
|
|
|
group_node_name = path->node_name;
|
|
|
|
|
id_in_node = ref.id;
|
|
|
|
|
found = true;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (!found) {
|
|
|
|
|
return std::nullopt;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return id_in_node;
|
|
|
|
|
}
|
|
|
|
|
|
2023-09-24 21:06:37 +02:00
|
|
|
std::optional<ObjectAndModifier> get_modifier_for_node_editor(const SpaceNode &snode)
|
|
|
|
|
{
|
|
|
|
|
if (snode.id == nullptr) {
|
|
|
|
|
return std::nullopt;
|
|
|
|
|
}
|
|
|
|
|
if (GS(snode.id->name) != ID_OB) {
|
|
|
|
|
return std::nullopt;
|
|
|
|
|
}
|
|
|
|
|
const Object *object = reinterpret_cast<Object *>(snode.id);
|
|
|
|
|
const NodesModifierData *used_modifier = nullptr;
|
|
|
|
|
if (snode.flag & SNODE_PIN) {
|
|
|
|
|
LISTBASE_FOREACH (const ModifierData *, md, &object->modifiers) {
|
|
|
|
|
if (md->type == eModifierType_Nodes) {
|
|
|
|
|
const NodesModifierData *nmd = reinterpret_cast<const NodesModifierData *>(md);
|
|
|
|
|
/* Would be good to store the name of the pinned modifier in the node editor. */
|
|
|
|
|
if (nmd->node_group == snode.nodetree) {
|
|
|
|
|
used_modifier = nmd;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
LISTBASE_FOREACH (const ModifierData *, md, &object->modifiers) {
|
|
|
|
|
if (md->type == eModifierType_Nodes) {
|
|
|
|
|
const NodesModifierData *nmd = reinterpret_cast<const NodesModifierData *>(md);
|
|
|
|
|
if (nmd->node_group == snode.nodetree) {
|
|
|
|
|
if (md->flag & eModifierFlag_Active) {
|
|
|
|
|
used_modifier = nmd;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (used_modifier == nullptr) {
|
|
|
|
|
return std::nullopt;
|
|
|
|
|
}
|
|
|
|
|
return ObjectAndModifier{object, used_modifier};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool push_compute_context_for_tree_path(const SpaceNode &snode,
|
|
|
|
|
ComputeContextBuilder &compute_context_builder)
|
|
|
|
|
{
|
|
|
|
|
Vector<const bNodeTreePath *> tree_path;
|
|
|
|
|
LISTBASE_FOREACH (const bNodeTreePath *, item, &snode.treepath) {
|
|
|
|
|
tree_path.append(item);
|
|
|
|
|
}
|
|
|
|
|
if (tree_path.is_empty()) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (const int i : tree_path.index_range().drop_back(1)) {
|
|
|
|
|
bNodeTree *tree = tree_path[i]->nodetree;
|
|
|
|
|
const char *group_node_name = tree_path[i + 1]->node_name;
|
|
|
|
|
const bNode *group_node = nodeFindNodebyName(tree, group_node_name);
|
|
|
|
|
if (group_node == nullptr) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
const bke::bNodeTreeZones *tree_zones = tree->zones();
|
|
|
|
|
if (tree_zones == nullptr) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
const Vector<const bke::bNodeTreeZone *> zone_stack = tree_zones->get_zone_stack_for_node(
|
|
|
|
|
group_node->identifier);
|
|
|
|
|
for (const bke::bNodeTreeZone *zone : zone_stack) {
|
|
|
|
|
switch (zone->output_node->type) {
|
|
|
|
|
case GEO_NODE_SIMULATION_OUTPUT: {
|
|
|
|
|
compute_context_builder.push<bke::SimulationZoneComputeContext>(*zone->output_node);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case GEO_NODE_REPEAT_OUTPUT: {
|
2023-09-27 11:09:39 +02:00
|
|
|
const auto &storage = *static_cast<const NodeGeometryRepeatOutput *>(
|
|
|
|
|
zone->output_node->storage);
|
2023-09-24 21:06:37 +02:00
|
|
|
compute_context_builder.push<bke::RepeatZoneComputeContext>(*zone->output_node,
|
2023-09-27 11:09:39 +02:00
|
|
|
storage.inspection_index);
|
2023-09-24 21:06:37 +02:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2023-11-21 14:12:07 +01:00
|
|
|
compute_context_builder.push<bke::GroupNodeComputeContext>(*group_node, *tree);
|
2023-09-24 21:06:37 +02:00
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2008-12-13 18:09:49 +00:00
|
|
|
/* ******************** default callbacks for node space ***************** */
|
|
|
|
|
|
2022-10-03 17:37:25 -05:00
|
|
|
static SpaceLink *node_create(const ScrArea * /*area*/, const Scene * /*scene*/)
|
2008-12-13 18:09:49 +00:00
|
|
|
{
|
2021-12-24 22:17:49 -05:00
|
|
|
SpaceNode *snode = MEM_cnew<SpaceNode>("initnode");
|
2012-07-01 09:54:44 +00:00
|
|
|
snode->spacetype = SPACE_NODE;
|
|
|
|
|
|
2013-01-29 12:03:38 +00:00
|
|
|
snode->flag = SNODE_SHOW_GPENCIL | SNODE_USE_ALPHA;
|
2021-12-01 21:45:41 -05:00
|
|
|
snode->overlay.flag = (SN_OVERLAY_SHOW_OVERLAYS | SN_OVERLAY_SHOW_WIRE_COLORS |
|
2023-07-12 16:14:12 +02:00
|
|
|
SN_OVERLAY_SHOW_PATH | SN_OVERLAY_SHOW_PREVIEWS);
|
2012-12-17 02:34:53 +00:00
|
|
|
|
2011-02-10 10:24:05 +00:00
|
|
|
/* backdrop */
|
|
|
|
|
snode->zoom = 1.0f;
|
2012-07-01 09:54:44 +00:00
|
|
|
|
2013-03-18 16:34:57 +00:00
|
|
|
/* select the first tree type for valid type */
|
2013-09-13 08:45:20 +00:00
|
|
|
NODE_TREE_TYPES_BEGIN (treetype) {
|
2023-06-19 11:37:05 +10:00
|
|
|
STRNCPY(snode->tree_idname, treetype->idname);
|
2013-03-18 16:34:57 +00:00
|
|
|
break;
|
2013-09-13 08:45:20 +00:00
|
|
|
}
|
|
|
|
|
NODE_TREE_TYPES_END;
|
2013-03-18 16:34:57 +00:00
|
|
|
|
2008-12-13 18:09:49 +00:00
|
|
|
/* header */
|
2021-12-24 22:17:49 -05:00
|
|
|
ARegion *region = MEM_cnew<ARegion>("header for node");
|
2012-07-01 09:54:44 +00:00
|
|
|
|
2020-03-06 16:56:42 +01:00
|
|
|
BLI_addtail(&snode->regionbase, region);
|
|
|
|
|
region->regiontype = RGN_TYPE_HEADER;
|
|
|
|
|
region->alignment = (U.uiflag & USER_HEADER_BOTTOM) ? RGN_ALIGN_BOTTOM : RGN_ALIGN_TOP;
|
2012-07-01 09:54:44 +00:00
|
|
|
|
2009-11-11 08:12:54 +00:00
|
|
|
/* buttons/list view */
|
2021-12-24 22:17:49 -05:00
|
|
|
region = MEM_cnew<ARegion>("buttons for node");
|
2012-07-01 09:54:44 +00:00
|
|
|
|
2020-03-06 16:56:42 +01:00
|
|
|
BLI_addtail(&snode->regionbase, region);
|
|
|
|
|
region->regiontype = RGN_TYPE_UI;
|
|
|
|
|
region->alignment = RGN_ALIGN_RIGHT;
|
2012-07-01 09:54:44 +00:00
|
|
|
|
2013-04-13 17:36:31 +00:00
|
|
|
/* toolbar */
|
2021-12-24 22:17:49 -05:00
|
|
|
region = MEM_cnew<ARegion>("node tools");
|
2013-04-13 17:36:31 +00:00
|
|
|
|
2020-03-06 16:56:42 +01:00
|
|
|
BLI_addtail(&snode->regionbase, region);
|
|
|
|
|
region->regiontype = RGN_TYPE_TOOLS;
|
|
|
|
|
region->alignment = RGN_ALIGN_LEFT;
|
2013-04-13 17:36:31 +00:00
|
|
|
|
2020-03-06 16:56:42 +01:00
|
|
|
region->flag = RGN_FLAG_HIDDEN;
|
2013-04-13 17:36:31 +00:00
|
|
|
|
2015-11-28 17:14:45 +01:00
|
|
|
/* main region */
|
2021-12-24 22:17:49 -05:00
|
|
|
region = MEM_cnew<ARegion>("main region for node");
|
2012-07-01 09:54:44 +00:00
|
|
|
|
2020-03-06 16:56:42 +01:00
|
|
|
BLI_addtail(&snode->regionbase, region);
|
|
|
|
|
region->regiontype = RGN_TYPE_WINDOW;
|
2012-07-01 09:54:44 +00:00
|
|
|
|
2020-03-06 16:56:42 +01:00
|
|
|
region->v2d.tot.xmin = -12.8f * U.widget_unit;
|
|
|
|
|
region->v2d.tot.ymin = -12.8f * U.widget_unit;
|
|
|
|
|
region->v2d.tot.xmax = 38.4f * U.widget_unit;
|
|
|
|
|
region->v2d.tot.ymax = 38.4f * U.widget_unit;
|
Holiday coding log :)
Nice formatted version (pictures soon):
http://wiki.blender.org/index.php/Dev:Ref/Release_Notes/2.66/Usability
Short list of main changes:
- Transparent region option (over main region), added code to blend in/out such panels.
- Min size window now 640 x 480
- Fixed DPI for ui - lots of cleanup and changes everywhere. Icon image need correct size still, layer-in-use icon needs remake.
- Macbook retina support, use command line --no-native-pixels to disable it
- Timeline Marker label was drawing wrong
- Trackpad and magic mouse: supports zoom (hold ctrl)
- Fix for splash position: removed ghost function and made window size update after creation immediate
- Fast undo buffer save now adds UI as well. Could be checked for regular file save even...
Quit.blend and temp file saving use this now.
- Dixed filename in window on reading quit.blend or temp saves, and they now add a warning in window title: "(Recovered)"
- New Userpref option "Keep Session" - this always saves quit.blend, and loads on start.
This allows keeping UI and data without actual saves, until you actually save.
When you load startup.blend and quit, it recognises the quit.blend as a startup (no file name in header)
- Added 3D view copy/paste buffers (selected objects). Shortcuts ctrl-c, ctrl-v (OSX, cmd-c, cmd-v).
Coded partial file saving for it. Could be used for other purposes. Todo: use OS clipboards.
- User preferences (themes, keymaps, user settings) now can be saved as a separate file.
Old option is called "Save Startup File" the new one "Save User Settings".
To visualise this difference, the 'save startup file' button has been removed from user preferences window. That option is available as CTRL+U and in File menu still.
- OSX: fixed bug that stopped giving mouse events outside window.
This also fixes "Continuous Grab" for OSX. (error since 2009)
2012-12-12 18:58:11 +00:00
|
|
|
|
2020-03-06 16:56:42 +01:00
|
|
|
region->v2d.cur = region->v2d.tot;
|
2012-07-01 09:54:44 +00:00
|
|
|
|
2020-03-06 16:56:42 +01:00
|
|
|
region->v2d.min[0] = 1.0f;
|
|
|
|
|
region->v2d.min[1] = 1.0f;
|
2012-07-01 09:54:44 +00:00
|
|
|
|
2020-03-06 16:56:42 +01:00
|
|
|
region->v2d.max[0] = 32000.0f;
|
|
|
|
|
region->v2d.max[1] = 32000.0f;
|
2012-07-01 09:54:44 +00:00
|
|
|
|
2021-11-17 01:42:42 +01:00
|
|
|
region->v2d.minzoom = 0.05f;
|
2020-03-06 16:56:42 +01:00
|
|
|
region->v2d.maxzoom = 2.31f;
|
2012-07-01 09:54:44 +00:00
|
|
|
|
2020-03-06 16:56:42 +01:00
|
|
|
region->v2d.scroll = (V2D_SCROLL_RIGHT | V2D_SCROLL_BOTTOM);
|
|
|
|
|
region->v2d.keepzoom = V2D_LIMITZOOM | V2D_KEEPASPECT;
|
|
|
|
|
region->v2d.keeptot = 0;
|
2012-07-01 09:54:44 +00:00
|
|
|
|
2008-12-13 18:09:49 +00:00
|
|
|
return (SpaceLink *)snode;
|
|
|
|
|
}
|
|
|
|
|
|
2013-03-18 16:34:57 +00:00
|
|
|
static void node_free(SpaceLink *sl)
|
2012-07-01 09:54:44 +00:00
|
|
|
{
|
2013-03-18 18:25:05 +00:00
|
|
|
SpaceNode *snode = (SpaceNode *)sl;
|
2023-10-20 20:31:08 +02:00
|
|
|
BLI_freelistN(&snode->treepath);
|
|
|
|
|
MEM_delete(snode->runtime);
|
2008-12-13 18:09:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* spacetype; init callback */
|
2022-10-03 17:37:25 -05:00
|
|
|
static void node_init(wmWindowManager * /*wm*/, ScrArea *area)
|
2008-12-13 18:09:49 +00:00
|
|
|
{
|
2021-01-19 16:43:08 -06:00
|
|
|
SpaceNode *snode = (SpaceNode *)area->spacedata.first;
|
|
|
|
|
|
2021-11-12 12:12:27 -06:00
|
|
|
if (snode->runtime == nullptr) {
|
2021-12-24 22:17:49 -05:00
|
|
|
snode->runtime = MEM_new<SpaceNode_Runtime>(__func__);
|
2021-01-19 16:43:08 -06:00
|
|
|
}
|
2008-12-13 18:09:49 +00:00
|
|
|
}
|
|
|
|
|
|
2023-08-08 17:36:06 +02:00
|
|
|
static void node_exit(wmWindowManager *wm, ScrArea *area)
|
|
|
|
|
{
|
|
|
|
|
SpaceNode *snode = static_cast<SpaceNode *>(area->spacedata.first);
|
|
|
|
|
|
|
|
|
|
if (snode->runtime) {
|
|
|
|
|
free_previews(*wm, *snode);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-12-21 15:18:56 +01:00
|
|
|
static bool any_node_uses_id(const bNodeTree *ntree, const ID *id)
|
|
|
|
|
{
|
|
|
|
|
if (ELEM(nullptr, ntree, id)) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2022-12-02 11:12:51 -06:00
|
|
|
for (const bNode *node : ntree->all_nodes()) {
|
2021-12-21 15:18:56 +01:00
|
|
|
if (node->id == id) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2022-05-05 17:33:10 +10:00
|
|
|
/**
|
|
|
|
|
* Tag the space to recalculate the compositing tree using auto-compositing pipeline.
|
|
|
|
|
*
|
2022-05-06 17:56:59 +10:00
|
|
|
* Will check the space to be using a compositing tree, and check whether auto-compositing
|
|
|
|
|
* is enabled. If the checks do not pass then the function has no affect.
|
|
|
|
|
*/
|
2022-05-05 17:33:10 +10:00
|
|
|
static void node_area_tag_recalc_auto_compositing(SpaceNode *snode, ScrArea *area)
|
|
|
|
|
{
|
|
|
|
|
if (!ED_node_is_compositor(snode)) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (snode->flag & SNODE_AUTO_RENDER) {
|
|
|
|
|
snode->runtime->recalc_auto_compositing = true;
|
|
|
|
|
ED_area_tag_refresh(area);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Tag the space to recalculate the current tree.
|
|
|
|
|
*
|
|
|
|
|
* For all node trees this will do `snode_set_context()` which takes care of setting an active
|
|
|
|
|
* tree. This will be done in the area refresh callback.
|
|
|
|
|
*
|
2022-05-06 17:56:59 +10:00
|
|
|
* For compositor tree this will additionally start of the compositor job.
|
|
|
|
|
*/
|
2022-05-05 17:33:10 +10:00
|
|
|
static void node_area_tag_tree_recalc(SpaceNode *snode, ScrArea *area)
|
|
|
|
|
{
|
|
|
|
|
if (ED_node_is_compositor(snode)) {
|
|
|
|
|
snode->runtime->recalc_regular_compositing = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ED_area_tag_refresh(area);
|
|
|
|
|
}
|
|
|
|
|
|
2021-01-19 12:59:00 +11:00
|
|
|
static void node_area_listener(const wmSpaceTypeListenerParams *params)
|
2.5
Added WM Jobs manager
- WM can manage threaded jobs for you; just provide a couple
of components to get it work:
- customdata, free callback for it
- timer step, notifier code
- start callback, update callback
- Once started, each job runs an own timer, and will for
every time step check necessary updates, or close the
job when ready.
- No drawing happens in jobs, that's for notifiers!
- Every job stores an owner pointer, and based on this owner
it will prevent multiple jobs to enter the stack.
Instead it will re-use a running job, signal it to stop
and allow caller to re-initialize it even.
- Check new wm_jobs.c for more explanation. Jobs API is still
under construction.
Fun: BLI_addtail(&wm->jobs, steve); :)
Put Node shader previews back using wmJobs
- Preview calculating is now fully threaded (1 thread still)
- Thanks to new event system + notifiers, you can see
previews update even while dragging sliders!
- Currently it only starts when you change a node setting.
Warning: the thread render shares Node data, so don't delete
nodes while it renders! This topic is on the todo to make safe.
Also:
- bug in region initialize (do_versions) showed channel list in
node editor wrong.
- flagged the channel list 'hidden' now, it was really in the
way! This is for later to work on anyway.
- recoded Render API callbacks so it gets handlers passed on,
no globals to use anymore, remember?
- previewrender code gets now so much nicer! Will remove a lot
of stuff from code soon.
2009-01-22 14:59:49 +00:00
|
|
|
{
|
2021-01-18 17:28:47 -06:00
|
|
|
ScrArea *area = params->area;
|
2022-08-27 12:50:43 +10:00
|
|
|
const wmNotifier *wmn = params->notifier;
|
2021-01-18 17:28:47 -06:00
|
|
|
|
2021-07-03 23:08:40 +10:00
|
|
|
/* NOTE: #ED_area_tag_refresh will re-execute compositor. */
|
2021-11-12 12:12:27 -06:00
|
|
|
SpaceNode *snode = (SpaceNode *)area->spacedata.first;
|
2014-02-24 13:21:43 +01:00
|
|
|
/* shaderfrom is only used for new shading nodes, otherwise all shaders are from objects */
|
Remove Blender Internal and legacy viewport from Blender 2.8.
Brecht authored this commit, but he gave me the honours to actually
do it. Here it goes; Blender Internal. Bye bye, you did great!
* Point density, voxel data, ocean, environment map textures were removed,
as these only worked within BI rendering. Note that the ocean modifier
and the Cycles point density shader node continue to work.
* Dynamic paint using material shading was removed, as this only worked
with BI. If we ever wanted to support this again probably it should go
through the baking API.
* GPU shader export through the Python API was removed. This only worked
for the old BI GLSL shaders, which no longer exists. Doing something
similar for Eevee would be significantly more complicated because it
uses a lot of multiplass rendering and logic outside the shader, it's
probably impractical.
* Collada material import / export code is mostly gone, as it only worked
for BI materials. We need to add Cycles / Eevee material support at some
point.
* The mesh noise operator was removed since it only worked with BI
material texture slots. A displacement modifier can be used instead.
* The delete texture paint slot operator was removed since it only worked
for BI material texture slots. Could be added back with node support.
* Not all legacy viewport features are supported in the new viewport, but
their code was removed. If we need to bring anything back we can look at
older git revisions.
* There is some legacy viewport code that I could not remove yet, and some
that I probably missed.
* Shader node execution code was left mostly intact, even though it is not
used anywhere now. We may eventually use this to replace the texture
nodes with Cycles / Eevee shader nodes.
* The Cycles Bake panel now includes settings for baking multires normal
and displacement maps. The underlying code needs to be merged properly,
and we plan to add back support for multires AO baking and add support
to Cycles baking for features like vertex color, displacement, and other
missing baking features.
* This commit removes DNA and the Python API for BI material, lamp, world
and scene settings. This breaks a lot of addons.
* There is more DNA that can be removed or renamed, where Cycles or Eevee
are reusing some old BI properties but the names are not really correct
anymore.
* Texture slots for materials, lamps and world were removed. They remain
for brushes, particles and freestyle linestyles.
* 'BLENDER_RENDER' remains in the COMPAT_ENGINES of UI panels. Cycles and
other renderers use this to find all panels to show, minus a few panels
that they have their own replacement for.
2018-04-19 17:34:44 +02:00
|
|
|
short shader_type = snode->shaderfrom;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2.5
Added WM Jobs manager
- WM can manage threaded jobs for you; just provide a couple
of components to get it work:
- customdata, free callback for it
- timer step, notifier code
- start callback, update callback
- Once started, each job runs an own timer, and will for
every time step check necessary updates, or close the
job when ready.
- No drawing happens in jobs, that's for notifiers!
- Every job stores an owner pointer, and based on this owner
it will prevent multiple jobs to enter the stack.
Instead it will re-use a running job, signal it to stop
and allow caller to re-initialize it even.
- Check new wm_jobs.c for more explanation. Jobs API is still
under construction.
Fun: BLI_addtail(&wm->jobs, steve); :)
Put Node shader previews back using wmJobs
- Preview calculating is now fully threaded (1 thread still)
- Thanks to new event system + notifiers, you can see
previews update even while dragging sliders!
- Currently it only starts when you change a node setting.
Warning: the thread render shares Node data, so don't delete
nodes while it renders! This topic is on the todo to make safe.
Also:
- bug in region initialize (do_versions) showed channel list in
node editor wrong.
- flagged the channel list 'hidden' now, it was really in the
way! This is for later to work on anyway.
- recoded Render API callbacks so it gets handlers passed on,
no globals to use anymore, remember?
- previewrender code gets now so much nicer! Will remove a lot
of stuff from code soon.
2009-01-22 14:59:49 +00:00
|
|
|
/* preview renders */
|
2012-04-28 06:31:57 +00:00
|
|
|
switch (wmn->category) {
|
2.5
Added WM Jobs manager
- WM can manage threaded jobs for you; just provide a couple
of components to get it work:
- customdata, free callback for it
- timer step, notifier code
- start callback, update callback
- Once started, each job runs an own timer, and will for
every time step check necessary updates, or close the
job when ready.
- No drawing happens in jobs, that's for notifiers!
- Every job stores an owner pointer, and based on this owner
it will prevent multiple jobs to enter the stack.
Instead it will re-use a running job, signal it to stop
and allow caller to re-initialize it even.
- Check new wm_jobs.c for more explanation. Jobs API is still
under construction.
Fun: BLI_addtail(&wm->jobs, steve); :)
Put Node shader previews back using wmJobs
- Preview calculating is now fully threaded (1 thread still)
- Thanks to new event system + notifiers, you can see
previews update even while dragging sliders!
- Currently it only starts when you change a node setting.
Warning: the thread render shares Node data, so don't delete
nodes while it renders! This topic is on the todo to make safe.
Also:
- bug in region initialize (do_versions) showed channel list in
node editor wrong.
- flagged the channel list 'hidden' now, it was really in the
way! This is for later to work on anyway.
- recoded Render API callbacks so it gets handlers passed on,
no globals to use anymore, remember?
- previewrender code gets now so much nicer! Will remove a lot
of stuff from code soon.
2009-01-22 14:59:49 +00:00
|
|
|
case NC_SCENE:
|
2010-01-27 05:42:17 +00:00
|
|
|
switch (wmn->data) {
|
2013-07-19 10:40:43 +00:00
|
|
|
case ND_NODES: {
|
2020-04-03 13:25:03 +02:00
|
|
|
ARegion *region = BKE_area_find_region_type(area, RGN_TYPE_WINDOW);
|
2021-11-12 12:12:27 -06:00
|
|
|
bNodeTreePath *path = (bNodeTreePath *)snode->treepath.last;
|
2013-03-18 16:34:57 +00:00
|
|
|
/* shift view to node tree center */
|
2020-03-06 16:56:42 +01:00
|
|
|
if (region && path) {
|
|
|
|
|
UI_view2d_center_set(®ion->v2d, path->view_center[0], path->view_center[1]);
|
2019-03-26 21:16:47 +11:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2022-05-05 17:33:10 +10:00
|
|
|
node_area_tag_tree_recalc(snode, area);
|
2013-03-18 16:34:57 +00:00
|
|
|
break;
|
|
|
|
|
}
|
2010-01-27 05:42:17 +00:00
|
|
|
case ND_FRAME:
|
2022-05-05 17:33:10 +10:00
|
|
|
node_area_tag_tree_recalc(snode, area);
|
2010-01-27 05:42:17 +00:00
|
|
|
break;
|
2023-03-21 08:27:05 +01:00
|
|
|
case ND_COMPO_RESULT: {
|
2020-04-03 13:25:03 +02:00
|
|
|
ED_area_tag_redraw(area);
|
2023-03-21 08:27:05 +01:00
|
|
|
/* Backdrop image offset is calculated during compositing so gizmos need to be updated
|
|
|
|
|
* afterwards. */
|
|
|
|
|
const ARegion *region = BKE_area_find_region_type(area, RGN_TYPE_WINDOW);
|
|
|
|
|
WM_gizmomap_tag_refresh(region->gizmo_map);
|
2011-09-22 12:45:25 +00:00
|
|
|
break;
|
2023-03-21 08:27:05 +01:00
|
|
|
}
|
2011-02-07 16:41:57 +00:00
|
|
|
case ND_TRANSFORM_DONE:
|
2022-05-05 17:33:10 +10:00
|
|
|
node_area_tag_recalc_auto_compositing(snode, area);
|
2011-02-07 16:41:57 +00:00
|
|
|
break;
|
2010-01-27 05:42:17 +00:00
|
|
|
}
|
2009-01-27 17:12:40 +00:00
|
|
|
break;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2009-08-18 14:31:13 +00:00
|
|
|
/* future: add ID checks? */
|
2.5
Added WM Jobs manager
- WM can manage threaded jobs for you; just provide a couple
of components to get it work:
- customdata, free callback for it
- timer step, notifier code
- start callback, update callback
- Once started, each job runs an own timer, and will for
every time step check necessary updates, or close the
job when ready.
- No drawing happens in jobs, that's for notifiers!
- Every job stores an owner pointer, and based on this owner
it will prevent multiple jobs to enter the stack.
Instead it will re-use a running job, signal it to stop
and allow caller to re-initialize it even.
- Check new wm_jobs.c for more explanation. Jobs API is still
under construction.
Fun: BLI_addtail(&wm->jobs, steve); :)
Put Node shader previews back using wmJobs
- Preview calculating is now fully threaded (1 thread still)
- Thanks to new event system + notifiers, you can see
previews update even while dragging sliders!
- Currently it only starts when you change a node setting.
Warning: the thread render shares Node data, so don't delete
nodes while it renders! This topic is on the todo to make safe.
Also:
- bug in region initialize (do_versions) showed channel list in
node editor wrong.
- flagged the channel list 'hidden' now, it was really in the
way! This is for later to work on anyway.
- recoded Render API callbacks so it gets handlers passed on,
no globals to use anymore, remember?
- previewrender code gets now so much nicer! Will remove a lot
of stuff from code soon.
2009-01-22 14:59:49 +00:00
|
|
|
case NC_MATERIAL:
|
2013-03-18 16:34:57 +00:00
|
|
|
if (ED_node_is_shader(snode)) {
|
2019-03-26 21:16:47 +11:00
|
|
|
if (wmn->data == ND_SHADING) {
|
2022-05-05 17:33:10 +10:00
|
|
|
node_area_tag_tree_recalc(snode, area);
|
2019-03-26 21:16:47 +11:00
|
|
|
}
|
|
|
|
|
else if (wmn->data == ND_SHADING_DRAW) {
|
2022-05-05 17:33:10 +10:00
|
|
|
node_area_tag_tree_recalc(snode, area);
|
2019-03-26 21:16:47 +11:00
|
|
|
}
|
|
|
|
|
else if (wmn->data == ND_SHADING_LINKS) {
|
2022-05-05 17:33:10 +10:00
|
|
|
node_area_tag_tree_recalc(snode, area);
|
2019-03-26 21:16:47 +11:00
|
|
|
}
|
2011-01-04 16:31:36 +00:00
|
|
|
}
|
2.5
Added WM Jobs manager
- WM can manage threaded jobs for you; just provide a couple
of components to get it work:
- customdata, free callback for it
- timer step, notifier code
- start callback, update callback
- Once started, each job runs an own timer, and will for
every time step check necessary updates, or close the
job when ready.
- No drawing happens in jobs, that's for notifiers!
- Every job stores an owner pointer, and based on this owner
it will prevent multiple jobs to enter the stack.
Instead it will re-use a running job, signal it to stop
and allow caller to re-initialize it even.
- Check new wm_jobs.c for more explanation. Jobs API is still
under construction.
Fun: BLI_addtail(&wm->jobs, steve); :)
Put Node shader previews back using wmJobs
- Preview calculating is now fully threaded (1 thread still)
- Thanks to new event system + notifiers, you can see
previews update even while dragging sliders!
- Currently it only starts when you change a node setting.
Warning: the thread render shares Node data, so don't delete
nodes while it renders! This topic is on the todo to make safe.
Also:
- bug in region initialize (do_versions) showed channel list in
node editor wrong.
- flagged the channel list 'hidden' now, it was really in the
way! This is for later to work on anyway.
- recoded Render API callbacks so it gets handlers passed on,
no globals to use anymore, remember?
- previewrender code gets now so much nicer! Will remove a lot
of stuff from code soon.
2009-01-22 14:59:49 +00:00
|
|
|
break;
|
2009-08-18 14:31:13 +00:00
|
|
|
case NC_TEXTURE:
|
2013-03-18 16:34:57 +00:00
|
|
|
if (ED_node_is_shader(snode) || ED_node_is_texture(snode)) {
|
2019-03-26 21:16:47 +11:00
|
|
|
if (wmn->data == ND_NODES) {
|
2022-05-05 17:33:10 +10:00
|
|
|
node_area_tag_tree_recalc(snode, area);
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2019-03-26 21:16:47 +11:00
|
|
|
}
|
2009-08-18 14:31:13 +00:00
|
|
|
break;
|
2012-01-24 20:10:37 +00:00
|
|
|
case NC_WORLD:
|
2013-03-18 16:34:57 +00:00
|
|
|
if (ED_node_is_shader(snode) && shader_type == SNODE_SHADER_WORLD) {
|
2022-05-05 17:33:10 +10:00
|
|
|
node_area_tag_tree_recalc(snode, area);
|
2012-01-24 20:10:37 +00:00
|
|
|
}
|
|
|
|
|
break;
|
2011-10-20 14:55:02 +00:00
|
|
|
case NC_OBJECT:
|
2013-03-18 16:34:57 +00:00
|
|
|
if (ED_node_is_shader(snode)) {
|
2019-03-26 21:16:47 +11:00
|
|
|
if (wmn->data == ND_OB_SHADING) {
|
2022-05-05 17:33:10 +10:00
|
|
|
node_area_tag_tree_recalc(snode, area);
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2019-03-26 21:16:47 +11:00
|
|
|
}
|
2020-12-02 13:35:07 +01:00
|
|
|
else if (ED_node_is_geometry(snode)) {
|
|
|
|
|
/* Rather strict check: only redraw when the reference matches the current editor's ID. */
|
|
|
|
|
if (wmn->data == ND_MODIFIER) {
|
2021-11-12 12:12:27 -06:00
|
|
|
if (wmn->reference == snode->id || snode->id == nullptr) {
|
2022-05-05 17:33:10 +10:00
|
|
|
node_area_tag_tree_recalc(snode, area);
|
2020-12-02 13:35:07 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2011-10-20 14:55:02 +00:00
|
|
|
break;
|
2.5
Notifiers
---------
Various fixes for wrong use of notifiers, and some new notifiers
to make things a bit more clear and consistent, with two notable
changes:
* Geometry changes are now done with NC_GEOM, rather than
NC_OBJECT|ND_GEOM_, so an object does need to be available.
* Space data now use NC_SPACE|ND_SPACE_*, instead of data
notifiers or even NC_WINDOW in some cases. Note that NC_SPACE
should only be used for notifying about changes in space data,
we don't want to go back to allqueue(REDRAW..).
Depsgraph
---------
The dependency graph now has a different flush call:
DAG_object_flush_update(scene, ob, flag)
is replaced by:
DAG_id_flush_update(id, flag)
It still works basically the same, one difference is that it now
also accepts object data (e.g. Mesh), again to avoid requiring an
Object to be available. Other ID types will simply do nothing at
the moment.
Docs
----
I made some guidelines for how/when to do which kinds of updates
and notifiers. I can't specify totally exact how to make these
decisions, but these are basically the guidelines I use. So, new
and updated docs are here:
http://wiki.blender.org/index.php/BlenderDev/Blender2.5/NotifiersUpdates
http://wiki.blender.org/index.php/BlenderDev/Blender2.5/DataNotifiers
2009-09-04 20:51:09 +00:00
|
|
|
case NC_SPACE:
|
2019-03-26 21:16:47 +11:00
|
|
|
if (wmn->data == ND_SPACE_NODE) {
|
2022-05-05 17:33:10 +10:00
|
|
|
node_area_tag_tree_recalc(snode, area);
|
2019-03-26 21:16:47 +11:00
|
|
|
}
|
|
|
|
|
else if (wmn->data == ND_SPACE_NODE_VIEW) {
|
2020-04-03 13:25:03 +02:00
|
|
|
ED_area_tag_redraw(area);
|
2019-03-26 21:16:47 +11:00
|
|
|
}
|
2.5
Notifiers
---------
Various fixes for wrong use of notifiers, and some new notifiers
to make things a bit more clear and consistent, with two notable
changes:
* Geometry changes are now done with NC_GEOM, rather than
NC_OBJECT|ND_GEOM_, so an object does need to be available.
* Space data now use NC_SPACE|ND_SPACE_*, instead of data
notifiers or even NC_WINDOW in some cases. Note that NC_SPACE
should only be used for notifying about changes in space data,
we don't want to go back to allqueue(REDRAW..).
Depsgraph
---------
The dependency graph now has a different flush call:
DAG_object_flush_update(scene, ob, flag)
is replaced by:
DAG_id_flush_update(id, flag)
It still works basically the same, one difference is that it now
also accepts object data (e.g. Mesh), again to avoid requiring an
Object to be available. Other ID types will simply do nothing at
the moment.
Docs
----
I made some guidelines for how/when to do which kinds of updates
and notifiers. I can't specify totally exact how to make these
decisions, but these are basically the guidelines I use. So, new
and updated docs are here:
http://wiki.blender.org/index.php/BlenderDev/Blender2.5/NotifiersUpdates
http://wiki.blender.org/index.php/BlenderDev/Blender2.5/DataNotifiers
2009-09-04 20:51:09 +00:00
|
|
|
break;
|
2009-11-12 01:22:51 +00:00
|
|
|
case NC_NODE:
|
2019-03-26 21:16:47 +11:00
|
|
|
if (wmn->action == NA_EDITED) {
|
2023-12-01 15:13:04 +01:00
|
|
|
if (ELEM(wmn->reference, snode->nodetree, snode->id, nullptr) || snode->id == nullptr) {
|
2023-11-17 08:52:47 +01:00
|
|
|
node_area_tag_tree_recalc(snode, area);
|
|
|
|
|
}
|
2019-03-26 21:16:47 +11:00
|
|
|
}
|
|
|
|
|
else if (wmn->action == NA_SELECTED) {
|
2020-04-03 13:25:03 +02:00
|
|
|
ED_area_tag_redraw(area);
|
2019-03-26 21:16:47 +11:00
|
|
|
}
|
2009-11-12 01:22:51 +00:00
|
|
|
break;
|
2011-07-17 08:38:04 +00:00
|
|
|
case NC_SCREEN:
|
2012-04-28 06:31:57 +00:00
|
|
|
switch (wmn->data) {
|
2011-07-17 08:38:04 +00:00
|
|
|
case ND_ANIMPLAY:
|
2022-05-05 17:33:10 +10:00
|
|
|
node_area_tag_tree_recalc(snode, area);
|
2011-07-17 08:38:04 +00:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
break;
|
2012-06-04 16:42:58 +00:00
|
|
|
case NC_MASK:
|
|
|
|
|
if (wmn->action == NA_EDITED) {
|
2013-03-18 16:34:57 +00:00
|
|
|
if (snode->nodetree && snode->nodetree->type == NTREE_COMPOSIT) {
|
2022-05-05 17:33:10 +10:00
|
|
|
node_area_tag_tree_recalc(snode, area);
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2012-06-04 16:42:58 +00:00
|
|
|
}
|
|
|
|
|
break;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2010-09-13 06:08:26 +00:00
|
|
|
case NC_IMAGE:
|
|
|
|
|
if (wmn->action == NA_EDITED) {
|
2013-03-18 16:34:57 +00:00
|
|
|
if (ED_node_is_compositor(snode)) {
|
2021-12-21 15:18:56 +01:00
|
|
|
/* Without this check drawing on an image could become very slow when the compositor is
|
|
|
|
|
* open. */
|
|
|
|
|
if (any_node_uses_id(snode->nodetree, (ID *)wmn->reference)) {
|
2022-05-05 17:33:10 +10:00
|
|
|
node_area_tag_tree_recalc(snode, area);
|
2019-03-26 21:16:47 +11:00
|
|
|
}
|
2012-10-18 09:48:51 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-10-18 09:48:51 +00:00
|
|
|
case NC_MOVIECLIP:
|
|
|
|
|
if (wmn->action == NA_EDITED) {
|
2013-03-18 16:34:57 +00:00
|
|
|
if (ED_node_is_compositor(snode)) {
|
2021-12-21 15:18:56 +01:00
|
|
|
if (any_node_uses_id(snode->nodetree, (ID *)wmn->reference)) {
|
2022-05-05 17:33:10 +10:00
|
|
|
node_area_tag_tree_recalc(snode, area);
|
2019-03-26 21:16:47 +11:00
|
|
|
}
|
2010-09-13 06:08:26 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2014-07-11 16:51:04 +09:00
|
|
|
case NC_LINESTYLE:
|
|
|
|
|
if (ED_node_is_shader(snode) && shader_type == SNODE_SHADER_LINESTYLE) {
|
2022-05-05 17:33:10 +10:00
|
|
|
node_area_tag_tree_recalc(snode, area);
|
2014-07-11 16:51:04 +09:00
|
|
|
}
|
|
|
|
|
break;
|
2014-09-16 14:28:58 +06:00
|
|
|
case NC_WM:
|
2014-09-18 09:37:49 +10:00
|
|
|
if (wmn->data == ND_UNDO) {
|
2022-05-05 17:33:10 +10:00
|
|
|
node_area_tag_tree_recalc(snode, area);
|
2014-09-16 14:28:58 +06:00
|
|
|
}
|
|
|
|
|
break;
|
Grease Pencil - Storyboarding Features (merge from GPencil_EditStrokes branch)
This merge-commit brings in a number of new features and workflow/UI improvements for
working with Grease Pencil. While these were originally targetted at improving
the workflow for creating 3D storyboards in Blender using the Grease Pencil,
many of these changes should also prove useful in other workflows too.
The main highlights here are:
1) It is now possible to edit Grease Pencil strokes
- Use D Tab, or toggle the "Enable Editing" toggles in the Toolbar/Properties regions
to enter "Stroke Edit Mode". In this mode, many common editing tools will
operate on Grease Pencil stroke points instead.
- Tools implemented include Select, Select All/Border/Circle/Linked/More/Less,
Grab, Rotate, Scale, Bend, Shear, To Sphere, Mirror, Duplicate, Delete.
- Proportional Editing works when using the transform tools
2) Grease Pencil stroke settings can now be animated
NOTE: Currently drivers don't work, but if time allows, this may still be
added before the release.
3) Strokes can be drawn with "filled" interiors, using a separate set of
colour/opacity settings to the ones used for the lines themselves.
This makes use of OpenGL filled polys, which has the limitation of only
being able to fill convex shapes. Some artifacts may be visible on concave
shapes (e.g. pacman's mouth will be overdrawn)
4) "Volumetric Strokes" - An alternative drawing technique for stroke drawing
has been added which draws strokes as a series of screen-aligned discs.
While this was originally a partial experimental technique at getting better
quality 3D lines, the effects possible using this technique were interesting
enough to warrant making this a dedicated feature. Best results when partial
opacity and large stroke widths are used.
5) Improved Onion Skinning Support
- Different colours can be selected for the before/after ghosts. To do so,
enable the "colour wheel" toggle beside the Onion Skinning toggle, and set
the colours accordingly.
- Different numbers of ghosts can be shown before/after the current frame
6) Grease Pencil datablocks are now attached to the scene by default instead of
the active object.
- For a long time, the object-attachment has proved to be quite problematic
for users to keep track of. Now that this is done at scene level, it is
easier for most users to use.
- An exception for old files (and for any addons which may benefit from object
attachment instead), is that if the active object has a Grease Pencil datablock,
that will be used instead.
- It is not currently possible to choose object-attachment from the UI, but
it is simple to do this from the console instead, by doing:
context.active_object.grease_pencil = bpy.data.grease_pencil["blah"]
7) Various UI Cleanups
- The layers UI has been cleaned up to use a list instead of the nested-panels
design. Apart from saving space, this is also much nicer to look at now.
- The UI code is now all defined in Python. To support this, it has been necessary
to add some new context properties to make it easier to access these settings.
e.g. "gpencil_data" for the datablock
"active_gpencil_layer" and "active_gpencil_frame" for active data,
"editable_gpencil_strokes" for the strokes that can be edited
- The "stroke placement/alignment" settings (previously "Drawing Settings" at the
bottom of the Grease Pencil panel in the Properties Region) is now located in
the toolbar. These were more toolsettings than properties for how GPencil got drawn.
- "Use Sketching Sessions" has been renamed "Continuous Drawing", as per a
suggestion for an earlier discussion on developer.blender.org
- By default, the painting operator will wait for a mouse button to be pressed
before it starts creating the stroke. This is to make it easier to include
this operator in various toolbars/menus/etc. To get it immediately starting
(as when you hold down DKEy to draw), set "wait_for_input" to False.
- GPencil Layers can be rearranged in the "Grease Pencil" mode of the Action Editor
- Toolbar panels have been added to all the other editors which support these.
8) Pie menus for quick-access to tools
A set of experimental pie menus has been included for quick access to many
tools and settings. It is not necessary to use these to get things done,
but they have been designed to help make certain common tasks easier.
- Ctrl-D = The main pie menu. Reveals tools in a context sensitive and
spatially stable manner.
- D Q = "Quick Settings" pie. This allows quick access to the active
layer's settings. Notably, colours, thickness, and turning
onion skinning on/off.
2014-12-01 01:52:06 +13:00
|
|
|
case NC_GPENCIL:
|
|
|
|
|
if (ELEM(wmn->action, NA_EDITED, NA_SELECTED)) {
|
2020-04-03 13:25:03 +02:00
|
|
|
ED_area_tag_redraw(area);
|
Grease Pencil - Storyboarding Features (merge from GPencil_EditStrokes branch)
This merge-commit brings in a number of new features and workflow/UI improvements for
working with Grease Pencil. While these were originally targetted at improving
the workflow for creating 3D storyboards in Blender using the Grease Pencil,
many of these changes should also prove useful in other workflows too.
The main highlights here are:
1) It is now possible to edit Grease Pencil strokes
- Use D Tab, or toggle the "Enable Editing" toggles in the Toolbar/Properties regions
to enter "Stroke Edit Mode". In this mode, many common editing tools will
operate on Grease Pencil stroke points instead.
- Tools implemented include Select, Select All/Border/Circle/Linked/More/Less,
Grab, Rotate, Scale, Bend, Shear, To Sphere, Mirror, Duplicate, Delete.
- Proportional Editing works when using the transform tools
2) Grease Pencil stroke settings can now be animated
NOTE: Currently drivers don't work, but if time allows, this may still be
added before the release.
3) Strokes can be drawn with "filled" interiors, using a separate set of
colour/opacity settings to the ones used for the lines themselves.
This makes use of OpenGL filled polys, which has the limitation of only
being able to fill convex shapes. Some artifacts may be visible on concave
shapes (e.g. pacman's mouth will be overdrawn)
4) "Volumetric Strokes" - An alternative drawing technique for stroke drawing
has been added which draws strokes as a series of screen-aligned discs.
While this was originally a partial experimental technique at getting better
quality 3D lines, the effects possible using this technique were interesting
enough to warrant making this a dedicated feature. Best results when partial
opacity and large stroke widths are used.
5) Improved Onion Skinning Support
- Different colours can be selected for the before/after ghosts. To do so,
enable the "colour wheel" toggle beside the Onion Skinning toggle, and set
the colours accordingly.
- Different numbers of ghosts can be shown before/after the current frame
6) Grease Pencil datablocks are now attached to the scene by default instead of
the active object.
- For a long time, the object-attachment has proved to be quite problematic
for users to keep track of. Now that this is done at scene level, it is
easier for most users to use.
- An exception for old files (and for any addons which may benefit from object
attachment instead), is that if the active object has a Grease Pencil datablock,
that will be used instead.
- It is not currently possible to choose object-attachment from the UI, but
it is simple to do this from the console instead, by doing:
context.active_object.grease_pencil = bpy.data.grease_pencil["blah"]
7) Various UI Cleanups
- The layers UI has been cleaned up to use a list instead of the nested-panels
design. Apart from saving space, this is also much nicer to look at now.
- The UI code is now all defined in Python. To support this, it has been necessary
to add some new context properties to make it easier to access these settings.
e.g. "gpencil_data" for the datablock
"active_gpencil_layer" and "active_gpencil_frame" for active data,
"editable_gpencil_strokes" for the strokes that can be edited
- The "stroke placement/alignment" settings (previously "Drawing Settings" at the
bottom of the Grease Pencil panel in the Properties Region) is now located in
the toolbar. These were more toolsettings than properties for how GPencil got drawn.
- "Use Sketching Sessions" has been renamed "Continuous Drawing", as per a
suggestion for an earlier discussion on developer.blender.org
- By default, the painting operator will wait for a mouse button to be pressed
before it starts creating the stroke. This is to make it easier to include
this operator in various toolbars/menus/etc. To get it immediately starting
(as when you hold down DKEy to draw), set "wait_for_input" to False.
- GPencil Layers can be rearranged in the "Grease Pencil" mode of the Action Editor
- Toolbar panels have been added to all the other editors which support these.
8) Pie menus for quick-access to tools
A set of experimental pie menus has been included for quick access to many
tools and settings. It is not necessary to use these to get things done,
but they have been designed to help make certain common tasks easier.
- Ctrl-D = The main pie menu. Reveals tools in a context sensitive and
spatially stable manner.
- D Q = "Quick Settings" pie. This allows quick access to the active
layer's settings. Notably, colours, thickness, and turning
onion skinning on/off.
2014-12-01 01:52:06 +13:00
|
|
|
}
|
|
|
|
|
break;
|
2.5
Added WM Jobs manager
- WM can manage threaded jobs for you; just provide a couple
of components to get it work:
- customdata, free callback for it
- timer step, notifier code
- start callback, update callback
- Once started, each job runs an own timer, and will for
every time step check necessary updates, or close the
job when ready.
- No drawing happens in jobs, that's for notifiers!
- Every job stores an owner pointer, and based on this owner
it will prevent multiple jobs to enter the stack.
Instead it will re-use a running job, signal it to stop
and allow caller to re-initialize it even.
- Check new wm_jobs.c for more explanation. Jobs API is still
under construction.
Fun: BLI_addtail(&wm->jobs, steve); :)
Put Node shader previews back using wmJobs
- Preview calculating is now fully threaded (1 thread still)
- Thanks to new event system + notifiers, you can see
previews update even while dragging sliders!
- Currently it only starts when you change a node setting.
Warning: the thread render shares Node data, so don't delete
nodes while it renders! This topic is on the todo to make safe.
Also:
- bug in region initialize (do_versions) showed channel list in
node editor wrong.
- flagged the channel list 'hidden' now, it was really in the
way! This is for later to work on anyway.
- recoded Render API callbacks so it gets handlers passed on,
no globals to use anymore, remember?
- previewrender code gets now so much nicer! Will remove a lot
of stuff from code soon.
2009-01-22 14:59:49 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-12-21 10:22:51 +01:00
|
|
|
/* Returns true if an image editor exists that views the compositor result. */
|
|
|
|
|
static bool is_compositor_viewer_image_visible(const bContext *C)
|
|
|
|
|
{
|
|
|
|
|
wmWindowManager *window_manager = CTX_wm_manager(C);
|
|
|
|
|
LISTBASE_FOREACH (wmWindow *, window, &window_manager->windows) {
|
|
|
|
|
bScreen *screen = WM_window_get_active_screen(window);
|
|
|
|
|
LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
|
|
|
|
|
SpaceLink *space_link = static_cast<SpaceLink *>(area->spacedata.first);
|
|
|
|
|
if (!space_link || space_link->spacetype != SPACE_IMAGE) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
const SpaceImage *space_image = reinterpret_cast<const SpaceImage *>(space_link);
|
|
|
|
|
Image *image = ED_space_image(space_image);
|
|
|
|
|
if (image && image->source == IMA_SRC_VIEWER) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2022-09-02 14:21:35 -05:00
|
|
|
static void node_area_refresh(const bContext *C, ScrArea *area)
|
2.5
Added WM Jobs manager
- WM can manage threaded jobs for you; just provide a couple
of components to get it work:
- customdata, free callback for it
- timer step, notifier code
- start callback, update callback
- Once started, each job runs an own timer, and will for
every time step check necessary updates, or close the
job when ready.
- No drawing happens in jobs, that's for notifiers!
- Every job stores an owner pointer, and based on this owner
it will prevent multiple jobs to enter the stack.
Instead it will re-use a running job, signal it to stop
and allow caller to re-initialize it even.
- Check new wm_jobs.c for more explanation. Jobs API is still
under construction.
Fun: BLI_addtail(&wm->jobs, steve); :)
Put Node shader previews back using wmJobs
- Preview calculating is now fully threaded (1 thread still)
- Thanks to new event system + notifiers, you can see
previews update even while dragging sliders!
- Currently it only starts when you change a node setting.
Warning: the thread render shares Node data, so don't delete
nodes while it renders! This topic is on the todo to make safe.
Also:
- bug in region initialize (do_versions) showed channel list in
node editor wrong.
- flagged the channel list 'hidden' now, it was really in the
way! This is for later to work on anyway.
- recoded Render API callbacks so it gets handlers passed on,
no globals to use anymore, remember?
- previewrender code gets now so much nicer! Will remove a lot
of stuff from code soon.
2009-01-22 14:59:49 +00:00
|
|
|
{
|
|
|
|
|
/* default now: refresh node is starting preview */
|
2021-11-12 12:12:27 -06:00
|
|
|
SpaceNode *snode = (SpaceNode *)area->spacedata.first;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2021-12-03 16:25:17 -05:00
|
|
|
snode_set_context(*C);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2013-03-19 13:40:16 +00:00
|
|
|
if (snode->nodetree) {
|
2021-12-15 14:27:38 -06:00
|
|
|
if (snode->nodetree->type == NTREE_COMPOSIT) {
|
2012-07-01 09:54:44 +00:00
|
|
|
Scene *scene = (Scene *)snode->id;
|
2012-03-24 06:38:07 +00:00
|
|
|
if (scene->use_nodes) {
|
2011-02-07 16:41:57 +00:00
|
|
|
/* recalc is set on 3d view changes for auto compo */
|
2022-05-05 17:33:10 +10:00
|
|
|
if (snode->runtime->recalc_auto_compositing) {
|
|
|
|
|
snode->runtime->recalc_auto_compositing = false;
|
|
|
|
|
snode->runtime->recalc_regular_compositing = false;
|
2022-09-02 14:21:35 -05:00
|
|
|
node_render_changed_exec((bContext *)C, nullptr);
|
2011-02-07 16:41:57 +00:00
|
|
|
}
|
2022-05-05 17:33:10 +10:00
|
|
|
else if (snode->runtime->recalc_regular_compositing) {
|
|
|
|
|
snode->runtime->recalc_regular_compositing = false;
|
2023-12-21 10:22:51 +01:00
|
|
|
/* Only start compositing if its result will be visible either in the backdrop or in a
|
|
|
|
|
* viewer image. */
|
|
|
|
|
if (snode->flag & SNODE_BACKDRAW || is_compositor_viewer_image_visible(C)) {
|
|
|
|
|
ED_node_composite_job(C, snode->nodetree, scene);
|
|
|
|
|
}
|
2012-08-03 20:56:04 +00:00
|
|
|
}
|
2011-02-07 16:41:57 +00:00
|
|
|
}
|
2009-01-27 17:12:40 +00:00
|
|
|
}
|
2.5
Added WM Jobs manager
- WM can manage threaded jobs for you; just provide a couple
of components to get it work:
- customdata, free callback for it
- timer step, notifier code
- start callback, update callback
- Once started, each job runs an own timer, and will for
every time step check necessary updates, or close the
job when ready.
- No drawing happens in jobs, that's for notifiers!
- Every job stores an owner pointer, and based on this owner
it will prevent multiple jobs to enter the stack.
Instead it will re-use a running job, signal it to stop
and allow caller to re-initialize it even.
- Check new wm_jobs.c for more explanation. Jobs API is still
under construction.
Fun: BLI_addtail(&wm->jobs, steve); :)
Put Node shader previews back using wmJobs
- Preview calculating is now fully threaded (1 thread still)
- Thanks to new event system + notifiers, you can see
previews update even while dragging sliders!
- Currently it only starts when you change a node setting.
Warning: the thread render shares Node data, so don't delete
nodes while it renders! This topic is on the todo to make safe.
Also:
- bug in region initialize (do_versions) showed channel list in
node editor wrong.
- flagged the channel list 'hidden' now, it was really in the
way! This is for later to work on anyway.
- recoded Render API callbacks so it gets handlers passed on,
no globals to use anymore, remember?
- previewrender code gets now so much nicer! Will remove a lot
of stuff from code soon.
2009-01-22 14:59:49 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2008-12-13 18:09:49 +00:00
|
|
|
static SpaceLink *node_duplicate(SpaceLink *sl)
|
|
|
|
|
{
|
2013-03-18 18:25:05 +00:00
|
|
|
SpaceNode *snode = (SpaceNode *)sl;
|
2021-11-12 12:12:27 -06:00
|
|
|
SpaceNode *snoden = (SpaceNode *)MEM_dupallocN(snode);
|
2012-07-01 09:54:44 +00:00
|
|
|
|
2013-12-09 11:54:00 +01:00
|
|
|
BLI_duplicatelist(&snoden->treepath, &snode->treepath);
|
|
|
|
|
|
2021-11-19 15:36:32 -05:00
|
|
|
snoden->runtime = nullptr;
|
2013-12-09 11:54:00 +01:00
|
|
|
|
2021-07-03 23:08:40 +10:00
|
|
|
/* NOTE: no need to set node tree user counts,
|
2013-12-09 11:54:00 +01:00
|
|
|
* the editor only keeps at least 1 (id_us_ensure_real),
|
|
|
|
|
* which is already done by the original SpaceNode.
|
|
|
|
|
*/
|
2012-07-01 09:54:44 +00:00
|
|
|
|
2008-12-13 18:09:49 +00:00
|
|
|
return (SpaceLink *)snoden;
|
|
|
|
|
}
|
|
|
|
|
|
2009-11-11 08:12:54 +00:00
|
|
|
/* add handlers, stuff you only do once or on area/region changes */
|
2020-03-06 16:56:42 +01:00
|
|
|
static void node_buttons_region_init(wmWindowManager *wm, ARegion *region)
|
2009-01-13 19:28:18 +00:00
|
|
|
{
|
2009-11-11 08:12:54 +00:00
|
|
|
wmKeyMap *keymap;
|
|
|
|
|
|
2020-03-06 16:56:42 +01:00
|
|
|
ED_region_panels_init(wm, region);
|
2012-07-01 09:54:44 +00:00
|
|
|
|
2023-09-14 13:32:42 +10:00
|
|
|
keymap = WM_keymap_ensure(wm->defaultconf, "Node Generic", SPACE_NODE, RGN_TYPE_WINDOW);
|
2020-03-06 16:56:42 +01:00
|
|
|
WM_event_add_keymap_handler(®ion->handlers, keymap);
|
2009-01-13 19:28:18 +00:00
|
|
|
}
|
|
|
|
|
|
2020-03-06 16:56:42 +01:00
|
|
|
static void node_buttons_region_draw(const bContext *C, ARegion *region)
|
2009-01-13 19:28:18 +00:00
|
|
|
{
|
2020-03-06 16:56:42 +01:00
|
|
|
ED_region_panels(C, region);
|
2009-01-13 19:28:18 +00:00
|
|
|
}
|
|
|
|
|
|
2012-12-12 12:50:39 +00:00
|
|
|
/* add handlers, stuff you only do once or on area/region changes */
|
2020-03-06 16:56:42 +01:00
|
|
|
static void node_toolbar_region_init(wmWindowManager *wm, ARegion *region)
|
2012-12-12 12:50:39 +00:00
|
|
|
{
|
|
|
|
|
wmKeyMap *keymap;
|
|
|
|
|
|
2020-03-06 16:56:42 +01:00
|
|
|
ED_region_panels_init(wm, region);
|
2012-12-12 12:50:39 +00:00
|
|
|
|
2023-09-14 13:32:42 +10:00
|
|
|
keymap = WM_keymap_ensure(wm->defaultconf, "Node Generic", SPACE_NODE, RGN_TYPE_WINDOW);
|
2020-03-06 16:56:42 +01:00
|
|
|
WM_event_add_keymap_handler(®ion->handlers, keymap);
|
2012-12-12 12:50:39 +00:00
|
|
|
}
|
|
|
|
|
|
2020-03-06 16:56:42 +01:00
|
|
|
static void node_toolbar_region_draw(const bContext *C, ARegion *region)
|
2012-12-12 12:50:39 +00:00
|
|
|
{
|
2020-03-06 16:56:42 +01:00
|
|
|
ED_region_panels(C, region);
|
2012-12-12 12:50:39 +00:00
|
|
|
}
|
|
|
|
|
|
2020-04-03 13:25:03 +02:00
|
|
|
static void node_cursor(wmWindow *win, ScrArea *area, ARegion *region)
|
2012-05-22 14:13:33 +00:00
|
|
|
{
|
2021-11-12 12:12:27 -06:00
|
|
|
SpaceNode *snode = (SpaceNode *)area->spacedata.first;
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2013-09-05 13:03:03 +00:00
|
|
|
/* convert mouse coordinates to v2d space */
|
2020-03-06 16:56:42 +01:00
|
|
|
UI_view2d_region_to_view(®ion->v2d,
|
2021-10-20 23:45:30 +11:00
|
|
|
win->eventstate->xy[0] - region->winrct.xmin,
|
|
|
|
|
win->eventstate->xy[1] - region->winrct.ymin,
|
2021-01-19 16:43:08 -06:00
|
|
|
&snode->runtime->cursor[0],
|
|
|
|
|
&snode->runtime->cursor[1]);
|
2012-07-01 09:54:44 +00:00
|
|
|
|
2021-01-19 16:43:08 -06:00
|
|
|
/* here snode->runtime->cursor is used to detect the node edge for sizing */
|
2023-11-25 15:23:31 +01:00
|
|
|
node_set_cursor(*win, *region, *snode, snode->runtime->cursor);
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2021-01-19 16:43:08 -06:00
|
|
|
/* XXX snode->runtime->cursor is in placing new nodes space */
|
2023-03-17 04:19:05 +01:00
|
|
|
snode->runtime->cursor[0] /= UI_SCALE_FAC;
|
|
|
|
|
snode->runtime->cursor[1] /= UI_SCALE_FAC;
|
2012-05-22 14:13:33 +00:00
|
|
|
}
|
|
|
|
|
|
2015-11-28 17:14:45 +01:00
|
|
|
/* Initialize main region, setting handlers. */
|
2020-03-06 16:56:42 +01:00
|
|
|
static void node_main_region_init(wmWindowManager *wm, ARegion *region)
|
2008-12-13 18:09:49 +00:00
|
|
|
{
|
2009-09-17 21:36:02 +00:00
|
|
|
wmKeyMap *keymap;
|
2010-05-12 04:25:33 +00:00
|
|
|
ListBase *lb;
|
2012-07-01 09:54:44 +00:00
|
|
|
|
2020-03-06 16:56:42 +01:00
|
|
|
UI_view2d_region_reinit(®ion->v2d, V2D_COMMONVIEW_CUSTOM, region->winx, region->winy);
|
2012-07-01 09:54:44 +00:00
|
|
|
|
2009-11-11 08:12:54 +00:00
|
|
|
/* own keymaps */
|
2023-09-14 13:32:42 +10:00
|
|
|
keymap = WM_keymap_ensure(wm->defaultconf, "Node Generic", SPACE_NODE, RGN_TYPE_WINDOW);
|
2020-03-06 16:56:42 +01:00
|
|
|
WM_event_add_keymap_handler(®ion->handlers, keymap);
|
2012-07-01 09:54:44 +00:00
|
|
|
|
2023-09-14 13:32:42 +10:00
|
|
|
keymap = WM_keymap_ensure(wm->defaultconf, "Node Editor", SPACE_NODE, RGN_TYPE_WINDOW);
|
2020-03-06 16:56:42 +01:00
|
|
|
WM_event_add_keymap_handler_v2d_mask(®ion->handlers, keymap);
|
2012-07-01 09:54:44 +00:00
|
|
|
|
2010-05-12 04:25:33 +00:00
|
|
|
/* add drop boxes */
|
|
|
|
|
lb = WM_dropboxmap_find("Node Editor", SPACE_NODE, RGN_TYPE_WINDOW);
|
2012-07-01 09:54:44 +00:00
|
|
|
|
2020-03-06 16:56:42 +01:00
|
|
|
WM_event_add_dropbox_handler(®ion->handlers, lb);
|
2021-07-08 13:05:33 +02:00
|
|
|
|
|
|
|
|
/* The backdrop image gizmo needs to change together with the view. So always refresh gizmos on
|
|
|
|
|
* region size changes. */
|
|
|
|
|
WM_gizmomap_tag_refresh(region->gizmo_map);
|
2008-12-13 18:09:49 +00:00
|
|
|
}
|
|
|
|
|
|
2020-03-06 16:56:42 +01:00
|
|
|
static void node_main_region_draw(const bContext *C, ARegion *region)
|
2008-12-13 18:09:49 +00:00
|
|
|
{
|
2021-12-03 16:25:17 -05:00
|
|
|
node_draw_space(*C, *region);
|
2008-12-13 18:09:49 +00:00
|
|
|
}
|
|
|
|
|
|
2010-05-12 04:25:33 +00:00
|
|
|
/* ************* dropboxes ************* */
|
|
|
|
|
|
2023-09-04 12:43:56 +02:00
|
|
|
static bool node_group_drop_poll(bContext *C, wmDrag *drag, const wmEvent * /*event*/)
|
2021-02-15 19:35:24 +01:00
|
|
|
{
|
2023-09-04 12:43:56 +02:00
|
|
|
SpaceNode *snode = CTX_wm_space_node(C);
|
|
|
|
|
|
2023-09-06 13:51:18 +02:00
|
|
|
if (snode->edittree == nullptr) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2023-09-04 12:43:56 +02:00
|
|
|
if (!WM_drag_is_ID_type(drag, ID_NT)) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (drag->type == WM_DRAG_ID) {
|
|
|
|
|
const bNodeTree *node_tree = reinterpret_cast<const bNodeTree *>(
|
|
|
|
|
WM_drag_get_local_ID(drag, ID_NT));
|
|
|
|
|
if (!node_tree) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
return node_tree->type == snode->edittree->type;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (drag->type == WM_DRAG_ASSET) {
|
|
|
|
|
const wmDragAsset *asset_data = WM_drag_get_asset_data(drag, ID_NT);
|
|
|
|
|
if (!asset_data) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
const AssetMetaData *metadata = &asset_data->asset->get_metadata();
|
|
|
|
|
const IDProperty *tree_type = BKE_asset_metadata_idprop_find(metadata, "type");
|
|
|
|
|
if (!tree_type || IDP_Int(tree_type) != snode->edittree->type) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return true;
|
2021-02-15 19:35:24 +01:00
|
|
|
}
|
|
|
|
|
|
2023-08-14 13:12:33 +02:00
|
|
|
static bool node_object_drop_poll(bContext *C, wmDrag *drag, const wmEvent * /*event*/)
|
2021-03-15 14:57:00 +00:00
|
|
|
{
|
2023-08-14 13:12:33 +02:00
|
|
|
return WM_drag_is_ID_type(drag, ID_OB) && !UI_but_active_drop_name(C);
|
2021-03-15 14:57:00 +00:00
|
|
|
}
|
|
|
|
|
|
2023-08-14 13:12:33 +02:00
|
|
|
static bool node_collection_drop_poll(bContext *C, wmDrag *drag, const wmEvent * /*event*/)
|
2021-03-15 14:57:00 +00:00
|
|
|
{
|
2023-08-14 13:12:33 +02:00
|
|
|
return WM_drag_is_ID_type(drag, ID_GR) && !UI_but_active_drop_name(C);
|
2021-03-15 14:57:00 +00:00
|
|
|
}
|
|
|
|
|
|
2024-04-26 16:40:16 +02:00
|
|
|
static bool node_id_im_drop_poll(bContext * /*C*/, wmDrag *drag, const wmEvent * /*event*/)
|
2010-05-12 04:25:33 +00:00
|
|
|
{
|
2021-01-24 20:39:09 +01:00
|
|
|
return WM_drag_is_ID_type(drag, ID_IM);
|
2010-05-12 04:25:33 +00:00
|
|
|
}
|
|
|
|
|
|
2022-10-03 17:37:25 -05:00
|
|
|
static bool node_mask_drop_poll(bContext * /*C*/, wmDrag *drag, const wmEvent * /*event*/)
|
2013-07-22 19:24:39 +00:00
|
|
|
{
|
2021-01-24 20:39:09 +01:00
|
|
|
return WM_drag_is_ID_type(drag, ID_MSK);
|
2013-07-22 19:24:39 +00:00
|
|
|
}
|
|
|
|
|
|
2023-08-29 15:51:18 +02:00
|
|
|
static bool node_material_drop_poll(bContext *C, wmDrag *drag, const wmEvent * /*event*/)
|
|
|
|
|
{
|
|
|
|
|
return WM_drag_is_ID_type(drag, ID_MA) && !UI_but_active_drop_name(C);
|
|
|
|
|
}
|
|
|
|
|
|
2023-07-28 12:16:52 +02:00
|
|
|
static void node_group_drop_copy(bContext *C, wmDrag *drag, wmDropBox *drop)
|
2021-02-15 19:35:24 +01:00
|
|
|
{
|
2023-07-28 12:16:52 +02:00
|
|
|
ID *id = WM_drag_get_local_ID_or_import_from_asset(C, drag, 0);
|
2021-02-15 19:35:24 +01:00
|
|
|
|
2024-01-22 13:47:13 +01:00
|
|
|
RNA_int_set(drop->ptr, "session_uid", int(id->session_uid));
|
2023-08-24 15:12:00 +02:00
|
|
|
|
|
|
|
|
RNA_boolean_set(drop->ptr, "show_datablock_in_node", (drag->type != WM_DRAG_ASSET));
|
2021-02-15 19:35:24 +01:00
|
|
|
}
|
|
|
|
|
|
2023-07-28 12:16:52 +02:00
|
|
|
static void node_id_drop_copy(bContext *C, wmDrag *drag, wmDropBox *drop)
|
2013-07-22 19:24:39 +00:00
|
|
|
{
|
2023-07-28 12:16:52 +02:00
|
|
|
ID *id = WM_drag_get_local_ID_or_import_from_asset(C, drag, 0);
|
2013-07-22 19:24:39 +00:00
|
|
|
|
2024-01-22 13:47:13 +01:00
|
|
|
RNA_int_set(drop->ptr, "session_uid", int(id->session_uid));
|
2013-07-22 19:24:39 +00:00
|
|
|
}
|
|
|
|
|
|
2024-04-26 16:40:16 +02:00
|
|
|
static void node_id_im_drop_copy(bContext *C, wmDrag *drag, wmDropBox *drop)
|
2010-05-12 04:25:33 +00:00
|
|
|
{
|
2023-07-28 12:16:52 +02:00
|
|
|
ID *id = WM_drag_get_local_ID_or_import_from_asset(C, drag, 0);
|
2012-03-24 06:38:07 +00:00
|
|
|
if (id) {
|
2024-01-22 13:47:13 +01:00
|
|
|
RNA_int_set(drop->ptr, "session_uid", int(id->session_uid));
|
2014-11-30 15:05:03 +01:00
|
|
|
RNA_struct_property_unset(drop->ptr, "filepath");
|
2023-02-27 16:31:31 +01:00
|
|
|
return;
|
2010-05-12 04:25:33 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* this region dropbox definition */
|
2021-11-12 12:12:27 -06:00
|
|
|
static void node_dropboxes()
|
2010-05-12 04:25:33 +00:00
|
|
|
{
|
2012-07-01 09:54:44 +00:00
|
|
|
ListBase *lb = WM_dropboxmap_find("Node Editor", SPACE_NODE, RGN_TYPE_WINDOW);
|
|
|
|
|
|
2021-03-15 14:57:00 +00:00
|
|
|
WM_dropbox_add(lb,
|
|
|
|
|
"NODE_OT_add_object",
|
|
|
|
|
node_object_drop_poll,
|
|
|
|
|
node_id_drop_copy,
|
2021-08-02 15:09:15 +02:00
|
|
|
WM_drag_free_imported_drag_ID,
|
2021-11-12 12:12:27 -06:00
|
|
|
nullptr);
|
2021-03-15 14:57:00 +00:00
|
|
|
WM_dropbox_add(lb,
|
|
|
|
|
"NODE_OT_add_collection",
|
|
|
|
|
node_collection_drop_poll,
|
|
|
|
|
node_id_drop_copy,
|
2021-08-02 15:09:15 +02:00
|
|
|
WM_drag_free_imported_drag_ID,
|
2021-11-12 12:12:27 -06:00
|
|
|
nullptr);
|
2021-02-16 15:24:22 +01:00
|
|
|
WM_dropbox_add(lb,
|
|
|
|
|
"NODE_OT_add_group",
|
|
|
|
|
node_group_drop_poll,
|
|
|
|
|
node_group_drop_copy,
|
2021-08-02 15:09:15 +02:00
|
|
|
WM_drag_free_imported_drag_ID,
|
2021-11-12 12:12:27 -06:00
|
|
|
nullptr);
|
2021-02-16 15:24:22 +01:00
|
|
|
WM_dropbox_add(lb,
|
|
|
|
|
"NODE_OT_add_file",
|
2024-04-26 16:40:16 +02:00
|
|
|
node_id_im_drop_poll,
|
|
|
|
|
node_id_im_drop_copy,
|
2021-08-02 15:09:15 +02:00
|
|
|
WM_drag_free_imported_drag_ID,
|
2021-11-12 12:12:27 -06:00
|
|
|
nullptr);
|
2021-02-16 15:24:22 +01:00
|
|
|
WM_dropbox_add(lb,
|
|
|
|
|
"NODE_OT_add_mask",
|
|
|
|
|
node_mask_drop_poll,
|
|
|
|
|
node_id_drop_copy,
|
2021-08-02 15:09:15 +02:00
|
|
|
WM_drag_free_imported_drag_ID,
|
2021-11-12 12:12:27 -06:00
|
|
|
nullptr);
|
2023-08-29 15:51:18 +02:00
|
|
|
WM_dropbox_add(lb,
|
|
|
|
|
"NODE_OT_add_material",
|
|
|
|
|
node_material_drop_poll,
|
|
|
|
|
node_id_drop_copy,
|
|
|
|
|
WM_drag_free_imported_drag_ID,
|
|
|
|
|
nullptr);
|
2010-05-12 04:25:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* ************* end drop *********** */
|
|
|
|
|
|
2008-12-13 18:09:49 +00:00
|
|
|
/* add handlers, stuff you only do once or on area/region changes */
|
2022-10-03 17:37:25 -05:00
|
|
|
static void node_header_region_init(wmWindowManager * /*wm*/, ARegion *region)
|
2008-12-13 18:09:49 +00:00
|
|
|
{
|
2020-03-06 16:56:42 +01:00
|
|
|
ED_region_header_init(region);
|
2008-12-13 18:09:49 +00:00
|
|
|
}
|
|
|
|
|
|
2020-03-06 16:56:42 +01:00
|
|
|
static void node_header_region_draw(const bContext *C, ARegion *region)
|
2008-12-13 18:09:49 +00:00
|
|
|
{
|
2010-03-22 09:30:00 +00:00
|
|
|
/* find and set the context */
|
2021-12-03 16:25:17 -05:00
|
|
|
snode_set_context(*C);
|
2009-08-19 00:55:30 +00:00
|
|
|
|
2020-03-06 16:56:42 +01:00
|
|
|
ED_region_header(C, region);
|
2008-12-13 18:09:49 +00:00
|
|
|
}
|
|
|
|
|
|
2015-11-28 17:14:45 +01:00
|
|
|
/* used for header + main region */
|
2021-01-19 12:59:00 +11:00
|
|
|
static void node_region_listener(const wmRegionListenerParams *params)
|
2008-12-13 18:09:49 +00:00
|
|
|
{
|
2021-01-18 17:28:47 -06:00
|
|
|
ARegion *region = params->region;
|
2022-08-27 12:50:43 +10:00
|
|
|
const wmNotifier *wmn = params->notifier;
|
2020-03-06 16:56:42 +01:00
|
|
|
wmGizmoMap *gzmap = region->gizmo_map;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2008-12-13 18:09:49 +00:00
|
|
|
/* context changes */
|
2012-04-28 06:31:57 +00:00
|
|
|
switch (wmn->category) {
|
2009-11-12 01:22:51 +00:00
|
|
|
case NC_SPACE:
|
2017-05-29 22:06:59 +10:00
|
|
|
switch (wmn->data) {
|
|
|
|
|
case ND_SPACE_NODE:
|
2020-03-06 16:56:42 +01:00
|
|
|
ED_region_tag_redraw(region);
|
2017-05-29 22:06:59 +10:00
|
|
|
break;
|
|
|
|
|
case ND_SPACE_NODE_VIEW:
|
2018-07-15 14:24:10 +02:00
|
|
|
WM_gizmomap_tag_refresh(gzmap);
|
2017-05-29 22:06:59 +10:00
|
|
|
break;
|
|
|
|
|
}
|
2009-11-12 01:22:51 +00:00
|
|
|
break;
|
2010-01-27 11:56:14 +00:00
|
|
|
case NC_SCREEN:
|
Main Workspace Integration
This commit does the main integration of workspaces, which is a design we agreed on during the 2.8 UI workshop (see https://wiki.blender.org/index.php/Dev:2.8/UI/Workshop_Writeup)
Workspaces should generally be stable, I'm not aware of any remaining bugs (or I've forgotten them :) ). If you find any, let me know!
(Exception: mode switching button might get out of sync with actual mode in some cases, would consider that a limitation/ToDo. Needs to be resolved at some point.)
== Main Changes/Features
* Introduces the new Workspaces as data-blocks.
* Allow storing a number of custom workspaces as part of the user configuration. Needs further work to allow adding and deleting individual workspaces.
* Bundle a default workspace configuration with Blender (current screen-layouts converted to workspaces).
* Pressing button to add a workspace spawns a menu to select between "Duplicate Current" and the workspaces from the user configuration. If no workspaces are stored in the user configuration, the default workspaces are listed instead.
* Store screen-layouts (`bScreen`) per workspace.
* Store an active screen-layout per workspace. Changing the workspace will enable this layout.
* Store active mode in workspace. Changing the workspace will also enter the mode of the new workspace. (Note that we still store the active mode in the object, moving this completely to workspaces is a separate project.)
* Store an active render layer per workspace.
* Moved mode switch from 3D View header to Info Editor header.
* Store active scene in window (not directly workspace related, but overlaps quite a bit).
* Removed 'Use Global Scene' User Preference option.
* Compatibility with old files - a new workspace is created for every screen-layout of old files. Old Blender versions should be able to read files saved with workspace support as well.
* Default .blend only contains one workspace ("General").
* Support appending workspaces.
Opening files without UI and commandline rendering should work fine.
Note that the UI is temporary! We plan to introduce a new global topbar
that contains the workspace options and tabs for switching workspaces.
== Technical Notes
* Workspaces are data-blocks.
* Adding and removing `bScreen`s should be done through `ED_workspace_layout` API now.
* A workspace can be active in multiple windows at the same time.
* The mode menu (which is now in the Info Editor header) doesn't display "Grease Pencil Edit" mode anymore since its availability depends on the active editor. Will be fixed by making Grease Pencil an own object type (as planned).
* The button to change the active workspace object mode may get out of sync with the mode of the active object. Will either be resolved by moving mode out of object data, or we'll disable workspace modes again (there's a `#define USE_WORKSPACE_MODE` for that).
* Screen-layouts (`bScreen`) are IDs and thus stored in a main list-base. Had to add a wrapper `WorkSpaceLayout` so we can store them in a list-base within workspaces, too. On the long run we could completely replace `bScreen` by workspace structs.
* `WorkSpace` types use some special compiler trickery to allow marking structs and struct members as private. BKE_workspace API should be used for accessing those.
* Added scene operators `SCENE_OT_`. Was previously done through screen operators.
== BPY API Changes
* Removed `Screen.scene`, added `Window.scene`
* Removed `UserPreferencesView.use_global_scene`
* Added `Context.workspace`, `Window.workspace` and `BlendData.workspaces`
* Added `bpy.types.WorkSpace` containing `screens`, `object_mode` and `render_layer`
* Added Screen.layout_name for the layout name that'll be displayed in the UI (may differ from internal name)
== What's left?
* There are a few open design questions (T50521). We should find the needed answers and implement them.
* Allow adding and removing individual workspaces from workspace configuration (needs UI design).
* Get the override system ready and support overrides per workspace.
* Support custom UI setups as part of workspaces (hidden panels, hidden buttons, customizable toolbars, etc).
* Allow enabling add-ons per workspace.
* Support custom workspace keymaps.
* Remove special exception for workspaces in linking code (so they're always appended, never linked). Depends on a few things, so best to solve later.
* Get the topbar done.
* Workspaces need a proper icon, current one is just a placeholder :)
Reviewed By: campbellbarton, mont29
Tags: #user_interface, #bf_blender_2.8
Maniphest Tasks: T50521
Differential Revision: https://developer.blender.org/D2451
2017-06-01 19:56:58 +02:00
|
|
|
if (wmn->data == ND_LAYOUTSET || wmn->action == NA_EDITED) {
|
2018-07-15 14:24:10 +02:00
|
|
|
WM_gizmomap_tag_refresh(gzmap);
|
2017-05-29 22:06:59 +10:00
|
|
|
}
|
2012-07-03 16:04:26 +00:00
|
|
|
switch (wmn->data) {
|
|
|
|
|
case ND_ANIMPLAY:
|
Main Workspace Integration
This commit does the main integration of workspaces, which is a design we agreed on during the 2.8 UI workshop (see https://wiki.blender.org/index.php/Dev:2.8/UI/Workshop_Writeup)
Workspaces should generally be stable, I'm not aware of any remaining bugs (or I've forgotten them :) ). If you find any, let me know!
(Exception: mode switching button might get out of sync with actual mode in some cases, would consider that a limitation/ToDo. Needs to be resolved at some point.)
== Main Changes/Features
* Introduces the new Workspaces as data-blocks.
* Allow storing a number of custom workspaces as part of the user configuration. Needs further work to allow adding and deleting individual workspaces.
* Bundle a default workspace configuration with Blender (current screen-layouts converted to workspaces).
* Pressing button to add a workspace spawns a menu to select between "Duplicate Current" and the workspaces from the user configuration. If no workspaces are stored in the user configuration, the default workspaces are listed instead.
* Store screen-layouts (`bScreen`) per workspace.
* Store an active screen-layout per workspace. Changing the workspace will enable this layout.
* Store active mode in workspace. Changing the workspace will also enter the mode of the new workspace. (Note that we still store the active mode in the object, moving this completely to workspaces is a separate project.)
* Store an active render layer per workspace.
* Moved mode switch from 3D View header to Info Editor header.
* Store active scene in window (not directly workspace related, but overlaps quite a bit).
* Removed 'Use Global Scene' User Preference option.
* Compatibility with old files - a new workspace is created for every screen-layout of old files. Old Blender versions should be able to read files saved with workspace support as well.
* Default .blend only contains one workspace ("General").
* Support appending workspaces.
Opening files without UI and commandline rendering should work fine.
Note that the UI is temporary! We plan to introduce a new global topbar
that contains the workspace options and tabs for switching workspaces.
== Technical Notes
* Workspaces are data-blocks.
* Adding and removing `bScreen`s should be done through `ED_workspace_layout` API now.
* A workspace can be active in multiple windows at the same time.
* The mode menu (which is now in the Info Editor header) doesn't display "Grease Pencil Edit" mode anymore since its availability depends on the active editor. Will be fixed by making Grease Pencil an own object type (as planned).
* The button to change the active workspace object mode may get out of sync with the mode of the active object. Will either be resolved by moving mode out of object data, or we'll disable workspace modes again (there's a `#define USE_WORKSPACE_MODE` for that).
* Screen-layouts (`bScreen`) are IDs and thus stored in a main list-base. Had to add a wrapper `WorkSpaceLayout` so we can store them in a list-base within workspaces, too. On the long run we could completely replace `bScreen` by workspace structs.
* `WorkSpace` types use some special compiler trickery to allow marking structs and struct members as private. BKE_workspace API should be used for accessing those.
* Added scene operators `SCENE_OT_`. Was previously done through screen operators.
== BPY API Changes
* Removed `Screen.scene`, added `Window.scene`
* Removed `UserPreferencesView.use_global_scene`
* Added `Context.workspace`, `Window.workspace` and `BlendData.workspaces`
* Added `bpy.types.WorkSpace` containing `screens`, `object_mode` and `render_layer`
* Added Screen.layout_name for the layout name that'll be displayed in the UI (may differ from internal name)
== What's left?
* There are a few open design questions (T50521). We should find the needed answers and implement them.
* Allow adding and removing individual workspaces from workspace configuration (needs UI design).
* Get the override system ready and support overrides per workspace.
* Support custom UI setups as part of workspaces (hidden panels, hidden buttons, customizable toolbars, etc).
* Allow enabling add-ons per workspace.
* Support custom workspace keymaps.
* Remove special exception for workspaces in linking code (so they're always appended, never linked). Depends on a few things, so best to solve later.
* Get the topbar done.
* Workspaces need a proper icon, current one is just a placeholder :)
Reviewed By: campbellbarton, mont29
Tags: #user_interface, #bf_blender_2.8
Maniphest Tasks: T50521
Differential Revision: https://developer.blender.org/D2451
2017-06-01 19:56:58 +02:00
|
|
|
case ND_LAYER:
|
2020-03-06 16:56:42 +01:00
|
|
|
ED_region_tag_redraw(region);
|
2012-07-03 16:04:26 +00:00
|
|
|
break;
|
|
|
|
|
}
|
2010-01-27 11:56:14 +00:00
|
|
|
break;
|
2017-06-18 16:26:09 +02:00
|
|
|
case NC_WM:
|
2019-03-26 21:16:47 +11:00
|
|
|
if (wmn->data == ND_JOB) {
|
2020-03-06 16:56:42 +01:00
|
|
|
ED_region_tag_redraw(region);
|
2019-03-26 21:16:47 +11:00
|
|
|
}
|
2017-06-18 16:26:09 +02:00
|
|
|
break;
|
2008-12-28 00:08:34 +00:00
|
|
|
case NC_SCENE:
|
2020-03-06 16:56:42 +01:00
|
|
|
ED_region_tag_redraw(region);
|
2017-05-29 22:06:59 +10:00
|
|
|
if (wmn->data == ND_RENDER_RESULT) {
|
2018-07-15 14:24:10 +02:00
|
|
|
WM_gizmomap_tag_refresh(gzmap);
|
2017-05-29 22:06:59 +10:00
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case NC_NODE:
|
2020-03-06 16:56:42 +01:00
|
|
|
ED_region_tag_redraw(region);
|
2017-05-29 22:06:59 +10:00
|
|
|
if (ELEM(wmn->action, NA_EDITED, NA_SELECTED)) {
|
2018-07-15 14:24:10 +02:00
|
|
|
WM_gizmomap_tag_refresh(gzmap);
|
2017-05-29 22:06:59 +10:00
|
|
|
}
|
|
|
|
|
break;
|
2008-12-28 00:08:34 +00:00
|
|
|
case NC_MATERIAL:
|
2009-08-18 14:31:13 +00:00
|
|
|
case NC_TEXTURE:
|
2013-02-14 17:09:19 +00:00
|
|
|
case NC_WORLD:
|
2014-07-11 16:51:04 +09:00
|
|
|
case NC_LINESTYLE:
|
2020-03-06 16:56:42 +01:00
|
|
|
ED_region_tag_redraw(region);
|
2009-08-18 14:31:13 +00:00
|
|
|
break;
|
2011-11-02 18:55:32 +00:00
|
|
|
case NC_OBJECT:
|
2019-03-26 21:16:47 +11:00
|
|
|
if (wmn->data == ND_OB_SHADING) {
|
2020-03-06 16:56:42 +01:00
|
|
|
ED_region_tag_redraw(region);
|
2019-03-26 21:16:47 +11:00
|
|
|
}
|
2011-11-02 18:55:32 +00:00
|
|
|
break;
|
2009-12-10 09:58:10 +00:00
|
|
|
case NC_ID:
|
2023-02-16 16:26:23 +01:00
|
|
|
if (ELEM(wmn->action, NA_RENAME, NA_EDITED)) {
|
2020-03-06 16:56:42 +01:00
|
|
|
ED_region_tag_redraw(region);
|
2019-03-26 21:16:47 +11:00
|
|
|
}
|
2009-12-10 09:58:10 +00:00
|
|
|
break;
|
2012-10-05 19:51:11 +00:00
|
|
|
case NC_GPENCIL:
|
2019-03-26 21:16:47 +11:00
|
|
|
if (wmn->action == NA_EDITED) {
|
2020-03-06 16:56:42 +01:00
|
|
|
ED_region_tag_redraw(region);
|
2019-03-26 21:16:47 +11:00
|
|
|
}
|
|
|
|
|
else if (wmn->data & ND_GPENCIL_EDITMODE) {
|
2020-03-06 16:56:42 +01:00
|
|
|
ED_region_tag_redraw(region);
|
2019-03-26 21:16:47 +11:00
|
|
|
}
|
2012-10-05 19:51:11 +00:00
|
|
|
break;
|
Geometry Nodes: viewport preview
This adds support for showing geometry passed to the Viewer in the 3d
viewport (instead of just in the spreadsheet). The "viewer geometry"
bypasses the group output. So it is not necessary to change the final
output of the node group to be able to see the intermediate geometry.
**Activation and deactivation of a viewer node**
* A viewer node is activated by clicking on it.
* Ctrl+shift+click on any node/socket connects it to the viewer and
makes it active.
* Ctrl+shift+click in empty space deactivates the active viewer.
* When the active viewer is not visible anymore (e.g. another object
is selected, or the current node group is exit), it is deactivated.
* Clicking on the icon in the header of the Viewer node toggles whether
its active or not.
**Pinning**
* The spreadsheet still allows pinning the active viewer as before.
When pinned, the spreadsheet still references the viewer node even
when it becomes inactive.
* The viewport does not support pinning at the moment. It always shows
the active viewer.
**Attribute**
* When a field is linked to the second input of the viewer node it is
displayed as an overlay in the viewport.
* When possible the correct domain for the attribute is determined
automatically. This does not work in all cases. It falls back to the
face corner domain on meshes and the point domain on curves. When
necessary, the domain can be picked manually.
* The spreadsheet now only shows the "Viewer" column for the domain
that is selected in the Viewer node.
* Instance attributes are visualized as a constant color per instance.
**Viewport Options**
* The attribute overlay opacity can be controlled with the "Viewer Node"
setting in the overlays popover.
* A viewport can be configured not to show intermediate viewer-geometry
by disabling the "Viewer Node" option in the "View" menu.
**Implementation Details**
* The "spreadsheet context path" was generalized to a "viewer path" that
is used in more places now.
* The viewer node itself determines the attribute domain, evaluates the
field and stores the result in a `.viewer` attribute.
* A new "viewer attribute' overlay displays the data from the `.viewer`
attribute.
* The ground truth for the active viewer node is stored in the workspace
now. Node editors, spreadsheets and viewports retrieve the active
viewer from there unless they are pinned.
* The depsgraph object iterator has a new "viewer path" setting. When set,
the viewed geometry of the corresponding object is part of the iterator
instead of the final evaluated geometry.
* To support the instance attribute overlay `DupliObject` was extended
to contain the information necessary for drawing the overlay.
* The ctrl+shift+click operator has been refactored so that it can make
existing links to viewers active again.
* The auto-domain-detection in the Viewer node works by checking the
"preferred domain" for every field input. If there is not exactly one
preferred domain, the fallback is used.
Known limitations:
* Loose edges of meshes don't have the attribute overlay. This could be
added separately if necessary.
* Some attributes are hard to visualize as a color directly. For example,
the values might have to be normalized or some should be drawn as arrays.
For now, we encourage users to build node groups that generate appropriate
viewer-geometry. We might include some of that functionality in future versions.
Support for displaying attribute values as text in the viewport is planned as well.
* There seems to be an issue with the attribute overlay for pointclouds on
nvidia gpus, to be investigated.
Differential Revision: https://developer.blender.org/D15954
2022-09-28 17:54:59 +02:00
|
|
|
case NC_VIEWER_PATH:
|
|
|
|
|
ED_region_tag_redraw(region);
|
|
|
|
|
break;
|
2008-12-28 00:08:34 +00:00
|
|
|
}
|
2008-12-13 18:09:49 +00:00
|
|
|
}
|
|
|
|
|
|
2022-01-20 15:10:28 -06:00
|
|
|
} // namespace blender::ed::space_node
|
|
|
|
|
|
|
|
|
|
/* Outside of blender namespace to avoid Python documentation build error with `ctypes`. */
|
2022-05-18 19:24:08 +10:00
|
|
|
extern "C" {
|
2019-03-17 17:52:05 +01:00
|
|
|
const char *node_context_dir[] = {
|
2021-11-12 12:12:27 -06:00
|
|
|
"selected_nodes", "active_node", "light", "material", "world", nullptr};
|
2022-05-18 19:24:08 +10:00
|
|
|
};
|
2022-01-20 15:10:28 -06:00
|
|
|
|
|
|
|
|
namespace blender::ed::space_node {
|
|
|
|
|
|
Cleanup: Use enum for return values in context callbacks
Define enum `eContextResult` and use its values for returns, instead of
just returning 1, 0, or -1 (and always having some comment that explains
what -1 means).
This also cleans up the mixup between returning `0` and `false`, and `1`
and `true`. An inconsistency was discovered during this cleanup, and
marked with `TODO(sybren)`. It's not fixed here, as it would consititute
a functional change.
The enum isn't used everywhere, as enums in C and C++ can have different
storage sizes. To prevent issues, callback functions are still declared
as returning`int`. To at least make things easier to understand for
humans, I marked those with `int /*eContextResult*/`.
This is a followup of D9090, and is intended to unify how context
callbacks return values. This will make it easier to extend the approach
in D9090 to those functions.
No functional changes.
Differential Revision: https://developer.blender.org/D9095
2020-10-02 18:56:25 +02:00
|
|
|
static int /*eContextResult*/ node_context(const bContext *C,
|
|
|
|
|
const char *member,
|
|
|
|
|
bContextDataResult *result)
|
2009-01-02 23:58:03 +00:00
|
|
|
{
|
2012-07-01 09:54:44 +00:00
|
|
|
SpaceNode *snode = CTX_wm_space_node(C);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-03-24 06:38:07 +00:00
|
|
|
if (CTX_data_dir(member)) {
|
2011-02-15 14:38:43 +00:00
|
|
|
CTX_data_dir_set(result, node_context_dir);
|
Cleanup: Use enum for return values in context callbacks
Define enum `eContextResult` and use its values for returns, instead of
just returning 1, 0, or -1 (and always having some comment that explains
what -1 means).
This also cleans up the mixup between returning `0` and `false`, and `1`
and `true`. An inconsistency was discovered during this cleanup, and
marked with `TODO(sybren)`. It's not fixed here, as it would consititute
a functional change.
The enum isn't used everywhere, as enums in C and C++ can have different
storage sizes. To prevent issues, callback functions are still declared
as returning`int`. To at least make things easier to understand for
humans, I marked those with `int /*eContextResult*/`.
This is a followup of D9090, and is intended to unify how context
callbacks return values. This will make it easier to extend the approach
in D9090 to those functions.
No functional changes.
Differential Revision: https://developer.blender.org/D9095
2020-10-02 18:56:25 +02:00
|
|
|
return CTX_RESULT_OK;
|
2009-06-20 14:55:28 +00:00
|
|
|
}
|
2020-07-03 17:20:08 +02:00
|
|
|
if (CTX_data_equals(member, "selected_nodes")) {
|
2012-03-24 06:38:07 +00:00
|
|
|
if (snode->edittree) {
|
2023-10-10 10:57:51 +02:00
|
|
|
for (bNode *node : snode->edittree->all_nodes()) {
|
2012-03-24 06:38:07 +00:00
|
|
|
if (node->flag & NODE_SELECT) {
|
2011-09-05 21:01:50 +00:00
|
|
|
CTX_data_list_add(result, &snode->edittree->id, &RNA_Node, node);
|
|
|
|
|
}
|
2009-01-02 23:58:03 +00:00
|
|
|
}
|
|
|
|
|
}
|
2010-04-24 19:26:05 +00:00
|
|
|
CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
|
Cleanup: Use enum for return values in context callbacks
Define enum `eContextResult` and use its values for returns, instead of
just returning 1, 0, or -1 (and always having some comment that explains
what -1 means).
This also cleans up the mixup between returning `0` and `false`, and `1`
and `true`. An inconsistency was discovered during this cleanup, and
marked with `TODO(sybren)`. It's not fixed here, as it would consititute
a functional change.
The enum isn't used everywhere, as enums in C and C++ can have different
storage sizes. To prevent issues, callback functions are still declared
as returning`int`. To at least make things easier to understand for
humans, I marked those with `int /*eContextResult*/`.
This is a followup of D9090, and is intended to unify how context
callbacks return values. This will make it easier to extend the approach
in D9090 to those functions.
No functional changes.
Differential Revision: https://developer.blender.org/D9095
2020-10-02 18:56:25 +02:00
|
|
|
return CTX_RESULT_OK;
|
2009-01-02 23:58:03 +00:00
|
|
|
}
|
2020-07-03 17:20:08 +02:00
|
|
|
if (CTX_data_equals(member, "active_node")) {
|
2012-03-24 06:38:07 +00:00
|
|
|
if (snode->edittree) {
|
2012-06-11 18:43:48 +00:00
|
|
|
bNode *node = nodeGetActive(snode->edittree);
|
|
|
|
|
CTX_data_pointer_set(result, &snode->edittree->id, &RNA_Node, node);
|
2011-09-05 21:01:50 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2011-09-05 21:01:50 +00:00
|
|
|
CTX_data_type_set(result, CTX_DATA_TYPE_POINTER);
|
Cleanup: Use enum for return values in context callbacks
Define enum `eContextResult` and use its values for returns, instead of
just returning 1, 0, or -1 (and always having some comment that explains
what -1 means).
This also cleans up the mixup between returning `0` and `false`, and `1`
and `true`. An inconsistency was discovered during this cleanup, and
marked with `TODO(sybren)`. It's not fixed here, as it would consititute
a functional change.
The enum isn't used everywhere, as enums in C and C++ can have different
storage sizes. To prevent issues, callback functions are still declared
as returning`int`. To at least make things easier to understand for
humans, I marked those with `int /*eContextResult*/`.
This is a followup of D9090, and is intended to unify how context
callbacks return values. This will make it easier to extend the approach
in D9090 to those functions.
No functional changes.
Differential Revision: https://developer.blender.org/D9095
2020-10-02 18:56:25 +02:00
|
|
|
return CTX_RESULT_OK;
|
2011-09-05 21:01:50 +00:00
|
|
|
}
|
2020-07-03 17:20:08 +02:00
|
|
|
if (CTX_data_equals(member, "node_previews")) {
|
2013-03-18 16:34:57 +00:00
|
|
|
if (snode->nodetree) {
|
|
|
|
|
CTX_data_pointer_set(
|
|
|
|
|
result, &snode->nodetree->id, &RNA_NodeInstanceHash, snode->nodetree->previews);
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2013-03-18 16:34:57 +00:00
|
|
|
CTX_data_type_set(result, CTX_DATA_TYPE_POINTER);
|
Cleanup: Use enum for return values in context callbacks
Define enum `eContextResult` and use its values for returns, instead of
just returning 1, 0, or -1 (and always having some comment that explains
what -1 means).
This also cleans up the mixup between returning `0` and `false`, and `1`
and `true`. An inconsistency was discovered during this cleanup, and
marked with `TODO(sybren)`. It's not fixed here, as it would consititute
a functional change.
The enum isn't used everywhere, as enums in C and C++ can have different
storage sizes. To prevent issues, callback functions are still declared
as returning`int`. To at least make things easier to understand for
humans, I marked those with `int /*eContextResult*/`.
This is a followup of D9090, and is intended to unify how context
callbacks return values. This will make it easier to extend the approach
in D9090 to those functions.
No functional changes.
Differential Revision: https://developer.blender.org/D9095
2020-10-02 18:56:25 +02:00
|
|
|
return CTX_RESULT_OK;
|
2013-03-18 16:34:57 +00:00
|
|
|
}
|
2020-07-03 17:20:08 +02:00
|
|
|
if (CTX_data_equals(member, "material")) {
|
2019-03-17 17:52:05 +01:00
|
|
|
if (snode->id && GS(snode->id->name) == ID_MA) {
|
|
|
|
|
CTX_data_id_pointer_set(result, snode->id);
|
|
|
|
|
}
|
Cleanup: Use enum for return values in context callbacks
Define enum `eContextResult` and use its values for returns, instead of
just returning 1, 0, or -1 (and always having some comment that explains
what -1 means).
This also cleans up the mixup between returning `0` and `false`, and `1`
and `true`. An inconsistency was discovered during this cleanup, and
marked with `TODO(sybren)`. It's not fixed here, as it would consititute
a functional change.
The enum isn't used everywhere, as enums in C and C++ can have different
storage sizes. To prevent issues, callback functions are still declared
as returning`int`. To at least make things easier to understand for
humans, I marked those with `int /*eContextResult*/`.
This is a followup of D9090, and is intended to unify how context
callbacks return values. This will make it easier to extend the approach
in D9090 to those functions.
No functional changes.
Differential Revision: https://developer.blender.org/D9095
2020-10-02 18:56:25 +02:00
|
|
|
return CTX_RESULT_OK;
|
2019-03-17 17:52:05 +01:00
|
|
|
}
|
2020-07-03 17:20:08 +02:00
|
|
|
if (CTX_data_equals(member, "light")) {
|
2019-03-17 17:52:05 +01:00
|
|
|
if (snode->id && GS(snode->id->name) == ID_LA) {
|
|
|
|
|
CTX_data_id_pointer_set(result, snode->id);
|
|
|
|
|
}
|
Cleanup: Use enum for return values in context callbacks
Define enum `eContextResult` and use its values for returns, instead of
just returning 1, 0, or -1 (and always having some comment that explains
what -1 means).
This also cleans up the mixup between returning `0` and `false`, and `1`
and `true`. An inconsistency was discovered during this cleanup, and
marked with `TODO(sybren)`. It's not fixed here, as it would consititute
a functional change.
The enum isn't used everywhere, as enums in C and C++ can have different
storage sizes. To prevent issues, callback functions are still declared
as returning`int`. To at least make things easier to understand for
humans, I marked those with `int /*eContextResult*/`.
This is a followup of D9090, and is intended to unify how context
callbacks return values. This will make it easier to extend the approach
in D9090 to those functions.
No functional changes.
Differential Revision: https://developer.blender.org/D9095
2020-10-02 18:56:25 +02:00
|
|
|
return CTX_RESULT_OK;
|
2019-03-17 17:52:05 +01:00
|
|
|
}
|
2020-07-03 17:20:08 +02:00
|
|
|
if (CTX_data_equals(member, "world")) {
|
2019-03-17 17:52:05 +01:00
|
|
|
if (snode->id && GS(snode->id->name) == ID_WO) {
|
|
|
|
|
CTX_data_id_pointer_set(result, snode->id);
|
|
|
|
|
}
|
Cleanup: Use enum for return values in context callbacks
Define enum `eContextResult` and use its values for returns, instead of
just returning 1, 0, or -1 (and always having some comment that explains
what -1 means).
This also cleans up the mixup between returning `0` and `false`, and `1`
and `true`. An inconsistency was discovered during this cleanup, and
marked with `TODO(sybren)`. It's not fixed here, as it would consititute
a functional change.
The enum isn't used everywhere, as enums in C and C++ can have different
storage sizes. To prevent issues, callback functions are still declared
as returning`int`. To at least make things easier to understand for
humans, I marked those with `int /*eContextResult*/`.
This is a followup of D9090, and is intended to unify how context
callbacks return values. This will make it easier to extend the approach
in D9090 to those functions.
No functional changes.
Differential Revision: https://developer.blender.org/D9095
2020-10-02 18:56:25 +02:00
|
|
|
return CTX_RESULT_OK;
|
2019-03-17 17:52:05 +01:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
Cleanup: Use enum for return values in context callbacks
Define enum `eContextResult` and use its values for returns, instead of
just returning 1, 0, or -1 (and always having some comment that explains
what -1 means).
This also cleans up the mixup between returning `0` and `false`, and `1`
and `true`. An inconsistency was discovered during this cleanup, and
marked with `TODO(sybren)`. It's not fixed here, as it would consititute
a functional change.
The enum isn't used everywhere, as enums in C and C++ can have different
storage sizes. To prevent issues, callback functions are still declared
as returning`int`. To at least make things easier to understand for
humans, I marked those with `int /*eContextResult*/`.
This is a followup of D9090, and is intended to unify how context
callbacks return values. This will make it easier to extend the approach
in D9090 to those functions.
No functional changes.
Differential Revision: https://developer.blender.org/D9095
2020-10-02 18:56:25 +02:00
|
|
|
return CTX_RESULT_MEMBER_NOT_FOUND;
|
2009-01-02 23:58:03 +00:00
|
|
|
}
|
|
|
|
|
|
2021-11-12 12:12:27 -06:00
|
|
|
static void node_widgets()
|
2017-05-29 22:06:59 +10:00
|
|
|
{
|
2021-11-13 13:07:13 +11:00
|
|
|
/* Create the widget-map for the area here. */
|
2021-11-12 12:12:27 -06:00
|
|
|
wmGizmoMapType_Params params{SPACE_NODE, RGN_TYPE_WINDOW};
|
|
|
|
|
wmGizmoMapType *gzmap_type = WM_gizmomaptype_ensure(¶ms);
|
2018-07-15 14:24:10 +02:00
|
|
|
WM_gizmogrouptype_append_and_link(gzmap_type, NODE_GGT_backdrop_transform);
|
|
|
|
|
WM_gizmogrouptype_append_and_link(gzmap_type, NODE_GGT_backdrop_crop);
|
|
|
|
|
WM_gizmogrouptype_append_and_link(gzmap_type, NODE_GGT_backdrop_sun_beams);
|
|
|
|
|
WM_gizmogrouptype_append_and_link(gzmap_type, NODE_GGT_backdrop_corner_pin);
|
2017-05-29 22:06:59 +10:00
|
|
|
}
|
|
|
|
|
|
2024-03-06 19:18:43 -05:00
|
|
|
static void node_id_remap(ID *old_id, ID *new_id, SpaceNode *snode)
|
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
|
|
|
{
|
2022-01-26 11:06:25 +01:00
|
|
|
if (snode->id == old_id) {
|
2020-05-11 17:24:56 +02:00
|
|
|
/* nasty DNA logic for SpaceNode:
|
|
|
|
|
* ideally should be handled by editor code, but would be bad level call
|
|
|
|
|
*/
|
|
|
|
|
BLI_freelistN(&snode->treepath);
|
|
|
|
|
|
2021-11-12 12:12:27 -06:00
|
|
|
/* XXX Untested in case new_id != nullptr... */
|
2022-01-26 11:06:25 +01:00
|
|
|
snode->id = new_id;
|
2021-11-12 12:12:27 -06:00
|
|
|
snode->from = nullptr;
|
|
|
|
|
snode->nodetree = nullptr;
|
|
|
|
|
snode->edittree = nullptr;
|
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
|
|
|
}
|
2022-01-26 11:06:25 +01:00
|
|
|
else if (GS(old_id->name) == ID_OB) {
|
|
|
|
|
if (snode->from == old_id) {
|
|
|
|
|
if (new_id == nullptr) {
|
|
|
|
|
snode->flag &= ~SNODE_PIN;
|
|
|
|
|
}
|
|
|
|
|
snode->from = new_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
|
|
|
}
|
2023-03-08 12:35:58 +01:00
|
|
|
else if (GS(old_id->name) == ID_GD_LEGACY) {
|
2022-01-26 11:06:25 +01:00
|
|
|
if ((ID *)snode->gpd == old_id) {
|
|
|
|
|
snode->gpd = (bGPdata *)new_id;
|
|
|
|
|
id_us_min(old_id);
|
|
|
|
|
id_us_plus(new_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
|
|
|
}
|
2022-01-26 11:06:25 +01:00
|
|
|
else if (GS(old_id->name) == ID_NT) {
|
2023-11-30 15:48:42 +01:00
|
|
|
|
2024-03-04 10:36:21 -05:00
|
|
|
if (snode->geometry_nodes_tool_tree) {
|
|
|
|
|
if (&snode->geometry_nodes_tool_tree->id == old_id) {
|
|
|
|
|
snode->geometry_nodes_tool_tree = reinterpret_cast<bNodeTree *>(new_id);
|
|
|
|
|
}
|
2023-11-30 15:48:42 +01:00
|
|
|
}
|
|
|
|
|
|
2022-01-26 11:06:25 +01:00
|
|
|
bNodeTreePath *path, *path_next;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2022-01-26 11:06:25 +01:00
|
|
|
for (path = (bNodeTreePath *)snode->treepath.first; path; path = path->next) {
|
|
|
|
|
if ((ID *)path->nodetree == old_id) {
|
|
|
|
|
path->nodetree = (bNodeTree *)new_id;
|
|
|
|
|
id_us_ensure_real(new_id);
|
|
|
|
|
}
|
|
|
|
|
if (path == snode->treepath.first) {
|
|
|
|
|
/* first nodetree in path is same as snode->nodetree */
|
|
|
|
|
snode->nodetree = path->nodetree;
|
|
|
|
|
}
|
|
|
|
|
if (path->nodetree == nullptr) {
|
|
|
|
|
break;
|
|
|
|
|
}
|
2016-11-18 22:36:52 +01:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2022-01-26 11:06:25 +01:00
|
|
|
/* remaining path entries are invalid, remove */
|
|
|
|
|
for (; path; path = path_next) {
|
|
|
|
|
path_next = path->next;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2022-01-26 11:06:25 +01:00
|
|
|
BLI_remlink(&snode->treepath, path);
|
|
|
|
|
MEM_freeN(path);
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2022-01-26 11:06:25 +01:00
|
|
|
/* edittree is just the last in the path,
|
|
|
|
|
* set this directly since the path may have been shortened above */
|
|
|
|
|
if (snode->treepath.last) {
|
|
|
|
|
path = (bNodeTreePath *)snode->treepath.last;
|
|
|
|
|
snode->edittree = path->nodetree;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
snode->edittree = nullptr;
|
|
|
|
|
}
|
2016-11-18 22:36:52 +01: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
|
|
|
}
|
|
|
|
|
|
2024-02-13 15:36:38 +01:00
|
|
|
static void node_id_remap(ScrArea * /*area*/,
|
|
|
|
|
SpaceLink *slink,
|
|
|
|
|
const blender::bke::id::IDRemapper &mappings)
|
2022-01-26 11:06:25 +01:00
|
|
|
{
|
|
|
|
|
/* Although we should be able to perform all the mappings in a single go this lead to issues when
|
|
|
|
|
* running the python test cases. Somehow the nodetree/edittree weren't updated to the new
|
|
|
|
|
* pointers that generated a SEGFAULT.
|
|
|
|
|
*
|
|
|
|
|
* To move forward we should perhaps remove snode->edittree and snode->nodetree as they are just
|
|
|
|
|
* copies of pointers. All usages should be calling a function that will receive the appropriate
|
|
|
|
|
* instance.
|
|
|
|
|
*
|
2022-01-28 09:24:11 +01:00
|
|
|
* We could also move a remap address at a time to use the IDRemapper as that should get closer
|
2022-01-26 11:06:25 +01:00
|
|
|
* to cleaner code. See {D13615} for more information about this topic.
|
|
|
|
|
*/
|
2024-03-06 19:18:43 -05:00
|
|
|
mappings.iter([&](ID *old_id, ID *new_id) {
|
|
|
|
|
node_id_remap(old_id, new_id, reinterpret_cast<SpaceNode *>(slink));
|
|
|
|
|
});
|
2022-01-26 11:06:25 +01:00
|
|
|
}
|
|
|
|
|
|
2023-08-17 14:42:04 +02:00
|
|
|
static void node_foreach_id(SpaceLink *space_link, LibraryForeachIDData *data)
|
|
|
|
|
{
|
|
|
|
|
SpaceNode *snode = reinterpret_cast<SpaceNode *>(space_link);
|
|
|
|
|
const int data_flags = BKE_lib_query_foreachid_process_flags_get(data);
|
|
|
|
|
const bool is_readonly = (data_flags & IDWALK_READONLY) != 0;
|
|
|
|
|
const bool allow_pointer_access = (data_flags & IDWALK_NO_ORIG_POINTERS_ACCESS) == 0;
|
2023-08-22 18:57:42 +02:00
|
|
|
bool is_embedded_nodetree = snode->id != nullptr && allow_pointer_access &&
|
|
|
|
|
ntreeFromID(snode->id) == snode->nodetree;
|
2023-08-17 14:42:04 +02:00
|
|
|
|
|
|
|
|
BKE_LIB_FOREACHID_PROCESS_ID(data, snode->id, IDWALK_CB_NOP);
|
|
|
|
|
BKE_LIB_FOREACHID_PROCESS_ID(data, snode->from, IDWALK_CB_NOP);
|
|
|
|
|
|
|
|
|
|
bNodeTreePath *path = static_cast<bNodeTreePath *>(snode->treepath.first);
|
|
|
|
|
BLI_assert(path == nullptr || path->nodetree == snode->nodetree);
|
|
|
|
|
|
|
|
|
|
if (is_embedded_nodetree) {
|
|
|
|
|
BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, snode->nodetree, IDWALK_CB_EMBEDDED_NOT_OWNING);
|
|
|
|
|
if (path != nullptr) {
|
|
|
|
|
BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, path->nodetree, IDWALK_CB_EMBEDDED_NOT_OWNING);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Embedded ID pointers are not remapped (besides exceptions), ensure it still matches
|
|
|
|
|
* actual data. Note that `snode->id` was already processed (and therefore potentially
|
|
|
|
|
* remapped) above. */
|
|
|
|
|
if (!is_readonly) {
|
|
|
|
|
snode->nodetree = (snode->id == nullptr) ? nullptr : ntreeFromID(snode->id);
|
|
|
|
|
if (path != nullptr) {
|
|
|
|
|
path->nodetree = snode->nodetree;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, snode->nodetree, IDWALK_CB_USER_ONE);
|
|
|
|
|
if (path != nullptr) {
|
|
|
|
|
BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, path->nodetree, IDWALK_CB_USER_ONE);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-09-27 15:47:22 +02:00
|
|
|
BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, snode->geometry_nodes_tool_tree, IDWALK_CB_USER_ONE);
|
|
|
|
|
|
2023-08-17 14:42:04 +02:00
|
|
|
/* Both `snode->id` and `snode->nodetree` have been remapped now, so their data can be
|
|
|
|
|
* accessed. */
|
|
|
|
|
BLI_assert(snode->id == nullptr || snode->nodetree == nullptr ||
|
|
|
|
|
(snode->nodetree->id.flag & LIB_EMBEDDED_DATA) == 0 ||
|
|
|
|
|
snode->nodetree == ntreeFromID(snode->id));
|
|
|
|
|
|
2023-08-22 18:57:42 +02:00
|
|
|
/* This is mainly here for readfile case ('lib_link' process), as in such case there is no access
|
|
|
|
|
* to original data allowed, so no way to know whether the SpaceNode nodetree pointer is an
|
|
|
|
|
* embedded one or not. */
|
|
|
|
|
if (!is_readonly && snode->id && !snode->nodetree) {
|
|
|
|
|
is_embedded_nodetree = true;
|
|
|
|
|
snode->nodetree = ntreeFromID(snode->id);
|
|
|
|
|
if (path != nullptr) {
|
|
|
|
|
path->nodetree = snode->nodetree;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-08-17 14:42:04 +02:00
|
|
|
if (path != nullptr) {
|
|
|
|
|
for (path = path->next; path != nullptr; path = path->next) {
|
|
|
|
|
BLI_assert(path->nodetree != nullptr);
|
2023-08-22 18:57:42 +02:00
|
|
|
if (allow_pointer_access) {
|
2023-08-17 14:42:04 +02:00
|
|
|
BLI_assert((path->nodetree->id.flag & LIB_EMBEDDED_DATA) == 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, path->nodetree, IDWALK_CB_USER_ONE);
|
|
|
|
|
|
|
|
|
|
if (path->nodetree == nullptr) {
|
|
|
|
|
BLI_assert(!is_readonly);
|
|
|
|
|
/* Remaining path entries are invalid, remove them. */
|
|
|
|
|
for (bNodeTreePath *path_next; path; path = path_next) {
|
|
|
|
|
path_next = path->next;
|
|
|
|
|
BLI_remlink(&snode->treepath, path);
|
|
|
|
|
MEM_freeN(path);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
BLI_assert(path == nullptr);
|
|
|
|
|
|
|
|
|
|
if (!is_readonly) {
|
|
|
|
|
/* `edittree` is just the last in the path, set this directly since the path may have
|
|
|
|
|
* been shortened above. */
|
|
|
|
|
if (snode->treepath.last != nullptr) {
|
|
|
|
|
path = static_cast<bNodeTreePath *>(snode->treepath.last);
|
|
|
|
|
snode->edittree = path->nodetree;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
snode->edittree = nullptr;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
/* Only process this pointer in readonly case, otherwise could lead to a bad
|
|
|
|
|
* double-remapping e.g. */
|
|
|
|
|
if (is_embedded_nodetree && snode->edittree == snode->nodetree) {
|
|
|
|
|
BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, snode->edittree, IDWALK_CB_EMBEDDED_NOT_OWNING);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, snode->edittree, IDWALK_CB_NOP);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-04-03 13:25:03 +02:00
|
|
|
static int node_space_subtype_get(ScrArea *area)
|
2018-05-29 09:19:06 +02:00
|
|
|
{
|
2021-11-12 12:12:27 -06:00
|
|
|
SpaceNode *snode = (SpaceNode *)area->spacedata.first;
|
2018-05-29 09:19:06 +02:00
|
|
|
return rna_node_tree_idname_to_enum(snode->tree_idname);
|
|
|
|
|
}
|
|
|
|
|
|
2020-04-03 13:25:03 +02:00
|
|
|
static void node_space_subtype_set(ScrArea *area, int value)
|
2018-05-29 09:19:06 +02:00
|
|
|
{
|
2021-11-12 12:12:27 -06:00
|
|
|
SpaceNode *snode = (SpaceNode *)area->spacedata.first;
|
2018-05-29 09:19:06 +02:00
|
|
|
ED_node_set_tree_type(snode, rna_node_tree_type_from_enum(value));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void node_space_subtype_item_extend(bContext *C, EnumPropertyItem **item, int *totitem)
|
|
|
|
|
{
|
|
|
|
|
bool free;
|
|
|
|
|
const EnumPropertyItem *item_src = RNA_enum_node_tree_types_itemf_impl(C, &free);
|
2020-11-18 00:19:29 +01:00
|
|
|
RNA_enum_items_add(item, totitem, item_src);
|
2018-05-29 09:19:06 +02:00
|
|
|
if (free) {
|
|
|
|
|
MEM_freeN((void *)item_src);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-04-27 14:42:21 +10:00
|
|
|
static void node_space_blend_read_data(BlendDataReader *reader, SpaceLink *sl)
|
2022-09-28 11:52:22 +02:00
|
|
|
{
|
|
|
|
|
SpaceNode *snode = (SpaceNode *)sl;
|
|
|
|
|
|
|
|
|
|
if (snode->gpd) {
|
2024-04-24 17:01:22 +02:00
|
|
|
BLO_read_struct(reader, bGPdata, &snode->gpd);
|
2022-09-28 11:52:22 +02:00
|
|
|
BKE_gpencil_blend_read_data(reader, snode->gpd);
|
|
|
|
|
}
|
|
|
|
|
|
2024-04-24 17:01:22 +02:00
|
|
|
BLO_read_struct_list(reader, bNodeTreePath, &snode->treepath);
|
2022-09-28 11:52:22 +02:00
|
|
|
snode->edittree = nullptr;
|
|
|
|
|
snode->runtime = nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
2023-04-27 14:42:21 +10:00
|
|
|
static void node_space_blend_write(BlendWriter *writer, SpaceLink *sl)
|
2022-09-28 11:52:22 +02:00
|
|
|
{
|
|
|
|
|
SpaceNode *snode = (SpaceNode *)sl;
|
|
|
|
|
BLO_write_struct(writer, SpaceNode, snode);
|
|
|
|
|
|
|
|
|
|
LISTBASE_FOREACH (bNodeTreePath *, path, &snode->treepath) {
|
|
|
|
|
BLO_write_struct(writer, bNodeTreePath, path);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-01-20 10:36:56 -06:00
|
|
|
} // namespace blender::ed::space_node
|
|
|
|
|
|
2021-12-08 00:31:20 -05:00
|
|
|
void ED_spacetype_node()
|
2008-12-13 18:09:49 +00:00
|
|
|
{
|
2022-01-20 10:36:56 -06:00
|
|
|
using namespace blender::ed::space_node;
|
|
|
|
|
|
2024-02-02 20:59:20 +01:00
|
|
|
std::unique_ptr<SpaceType> st = std::make_unique<SpaceType>();
|
2008-12-13 18:09:49 +00:00
|
|
|
ARegionType *art;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-07-01 09:54:44 +00:00
|
|
|
st->spaceid = SPACE_NODE;
|
2022-09-10 16:51:15 +10:00
|
|
|
STRNCPY(st->name, "Node");
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-08-04 14:39:53 +02:00
|
|
|
st->create = node_create;
|
2012-07-01 09:54:44 +00:00
|
|
|
st->free = node_free;
|
|
|
|
|
st->init = node_init;
|
2023-08-08 17:36:06 +02:00
|
|
|
st->exit = node_exit;
|
2012-07-01 09:54:44 +00:00
|
|
|
st->duplicate = node_duplicate;
|
|
|
|
|
st->operatortypes = node_operatortypes;
|
|
|
|
|
st->keymap = node_keymap;
|
|
|
|
|
st->listener = node_area_listener;
|
|
|
|
|
st->refresh = node_area_refresh;
|
|
|
|
|
st->context = node_context;
|
2010-05-12 04:25:33 +00:00
|
|
|
st->dropboxes = node_dropboxes;
|
2018-07-14 23:49:00 +02:00
|
|
|
st->gizmos = node_widgets;
|
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
|
|
|
st->id_remap = node_id_remap;
|
2023-08-17 14:42:04 +02:00
|
|
|
st->foreach_id = node_foreach_id;
|
2018-05-29 09:19:06 +02:00
|
|
|
st->space_subtype_item_extend = node_space_subtype_item_extend;
|
|
|
|
|
st->space_subtype_get = node_space_subtype_get;
|
|
|
|
|
st->space_subtype_set = node_space_subtype_set;
|
2023-04-27 14:42:21 +10:00
|
|
|
st->blend_read_data = node_space_blend_read_data;
|
2023-03-11 18:07:59 +01:00
|
|
|
st->blend_read_after_liblink = nullptr;
|
2023-04-27 14:42:21 +10:00
|
|
|
st->blend_write = node_space_blend_write;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2008-12-13 18:09:49 +00:00
|
|
|
/* regions: main window */
|
2021-12-24 22:17:49 -05:00
|
|
|
art = MEM_cnew<ARegionType>("spacetype node region");
|
2008-12-13 18:09:49 +00:00
|
|
|
art->regionid = RGN_TYPE_WINDOW;
|
2015-11-28 17:14:45 +01:00
|
|
|
art->init = node_main_region_init;
|
|
|
|
|
art->draw = node_main_region_draw;
|
2019-02-20 14:29:29 +11:00
|
|
|
art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_GIZMO | ED_KEYMAP_TOOL | ED_KEYMAP_VIEW2D |
|
|
|
|
|
ED_KEYMAP_FRAMES | ED_KEYMAP_GPENCIL;
|
2012-07-01 09:54:44 +00:00
|
|
|
art->listener = node_region_listener;
|
2012-05-22 14:13:33 +00:00
|
|
|
art->cursor = node_cursor;
|
2014-04-01 11:34:00 +11:00
|
|
|
art->event_cursor = true;
|
2020-03-13 01:19:22 +11:00
|
|
|
art->clip_gizmo_events_by_ui = true;
|
2023-05-25 11:24:11 +02:00
|
|
|
art->lock = 1;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2008-12-13 18:09:49 +00:00
|
|
|
BLI_addhead(&st->regiontypes, art);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2008-12-13 18:09:49 +00:00
|
|
|
/* regions: header */
|
2021-12-24 22:17:49 -05:00
|
|
|
art = MEM_cnew<ARegionType>("spacetype node region");
|
2008-12-13 18:09:49 +00:00
|
|
|
art->regionid = RGN_TYPE_HEADER;
|
2012-07-01 09:54:44 +00:00
|
|
|
art->prefsizey = HEADERY;
|
|
|
|
|
art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_VIEW2D | ED_KEYMAP_FRAMES | ED_KEYMAP_HEADER;
|
|
|
|
|
art->listener = node_region_listener;
|
2015-11-28 17:14:45 +01:00
|
|
|
art->init = node_header_region_init;
|
|
|
|
|
art->draw = node_header_region_draw;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2008-12-13 18:09:49 +00:00
|
|
|
BLI_addhead(&st->regiontypes, art);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2023-05-24 11:21:18 +10:00
|
|
|
/* regions: list-view/buttons */
|
2021-12-24 22:17:49 -05:00
|
|
|
art = MEM_cnew<ARegionType>("spacetype node region");
|
2009-11-11 08:12:54 +00:00
|
|
|
art->regionid = RGN_TYPE_UI;
|
2019-05-15 16:17:23 +02:00
|
|
|
art->prefsizex = UI_SIDEBAR_PANEL_WIDTH;
|
2012-07-01 09:54:44 +00:00
|
|
|
art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_FRAMES;
|
|
|
|
|
art->listener = node_region_listener;
|
2019-05-17 10:58:43 +10:00
|
|
|
art->message_subscribe = ED_area_do_mgs_subscribe_for_tool_ui;
|
2015-11-28 17:14:45 +01:00
|
|
|
art->init = node_buttons_region_init;
|
|
|
|
|
art->draw = node_buttons_region_draw;
|
2008-12-13 18:09:49 +00:00
|
|
|
BLI_addhead(&st->regiontypes, art);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-12-12 12:50:39 +00:00
|
|
|
/* regions: toolbar */
|
2021-12-24 22:17:49 -05:00
|
|
|
art = MEM_cnew<ARegionType>("spacetype view3d tools region");
|
2012-12-12 12:50:39 +00:00
|
|
|
art->regionid = RGN_TYPE_TOOLS;
|
2023-06-08 18:27:59 +02:00
|
|
|
art->prefsizex = int(UI_TOOLBAR_WIDTH);
|
2012-12-12 12:50:39 +00:00
|
|
|
art->prefsizey = 50; /* XXX */
|
|
|
|
|
art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_FRAMES;
|
|
|
|
|
art->listener = node_region_listener;
|
2018-11-27 18:39:29 +11:00
|
|
|
art->message_subscribe = ED_region_generic_tools_region_message_subscribe;
|
|
|
|
|
art->snap_size = ED_region_generic_tools_region_snap_size;
|
2015-11-28 17:14:45 +01:00
|
|
|
art->init = node_toolbar_region_init;
|
|
|
|
|
art->draw = node_toolbar_region_draw;
|
2012-12-12 12:50:39 +00:00
|
|
|
BLI_addhead(&st->regiontypes, art);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2022-11-01 16:09:49 +01:00
|
|
|
WM_menutype_add(MEM_new<MenuType>(__func__, add_catalog_assets_menu_type()));
|
2023-09-14 17:35:24 +02:00
|
|
|
WM_menutype_add(MEM_new<MenuType>(__func__, add_unassigned_assets_menu_type()));
|
2022-11-01 16:09:49 +01:00
|
|
|
WM_menutype_add(MEM_new<MenuType>(__func__, add_root_catalogs_menu_type()));
|
|
|
|
|
|
2024-02-02 20:59:20 +01:00
|
|
|
BKE_spacetype_register(std::move(st));
|
2008-12-13 18:09:49 +00:00
|
|
|
}
|