Compositor: Make split viewer a regular split node #114245
|
@ -71,7 +71,6 @@ class NODE_MT_category_compositor_output(Menu):
|
|||
|
||||
layout = self.layout
|
||||
node_add_menu.add_node_type(layout, "CompositorNodeComposite")
|
||||
node_add_menu.add_node_type(layout, "CompositorNodeSplitViewer")
|
||||
node_add_menu.add_node_type(layout, "CompositorNodeViewer")
|
||||
layout.separator()
|
||||
node_add_menu.add_node_type(layout, "CompositorNodeOutputFile")
|
||||
|
@ -279,6 +278,7 @@ class NODE_MT_category_compositor_utilities(Menu):
|
|||
node_add_menu.add_node_type(layout, "CompositorNodeLevels")
|
||||
node_add_menu.add_node_type(layout, "CompositorNodeNormalize")
|
||||
layout.separator()
|
||||
node_add_menu.add_node_type(layout, "CompositorNodeSplit")
|
||||
node_add_menu.add_node_type(layout, "CompositorNodeSwitch")
|
||||
node_add_menu.add_node_type(
|
||||
layout, "CompositorNodeSwitchView",
|
||||
|
|
|
@ -1017,7 +1017,8 @@ void BKE_nodetree_remove_layer_n(struct bNodeTree *ntree, struct Scene *scene, i
|
|||
#define CMP_NODE_CHROMA_MATTE 237
|
||||
#define CMP_NODE_CHANNEL_MATTE 238
|
||||
#define CMP_NODE_FLIP 239
|
||||
#define CMP_NODE_SPLITVIEWER 240
|
||||
/* Split viewer node is now a regular split node: CMP_NODE_SPLIT. */
|
||||
#define CMP_NODE_SPLITVIEWER__DEPRECATED 240
|
||||
zazizizou marked this conversation as resolved
Outdated
|
||||
// #define CMP_NODE_INDEX_MASK 241
|
||||
#define CMP_NODE_MAP_UV 242
|
||||
#define CMP_NODE_ID_MASK 243
|
||||
|
@ -1054,6 +1055,7 @@ void BKE_nodetree_remove_layer_n(struct bNodeTree *ntree, struct Scene *scene, i
|
|||
#define CMP_NODE_DESPECKLE 273
|
||||
#define CMP_NODE_ANTIALIASING 274
|
||||
#define CMP_NODE_KUWAHARA 275
|
||||
#define CMP_NODE_SPLIT 276
|
||||
|
||||
#define CMP_NODE_GLARE 301
|
||||
#define CMP_NODE_TONEMAP 302
|
||||
|
|
|
@ -993,8 +993,7 @@ void ntreeBlendReadData(BlendDataReader *reader, ID *owner_id, bNodeTree *ntree)
|
|||
}
|
||||
case CMP_NODE_IMAGE:
|
||||
case CMP_NODE_R_LAYERS:
|
||||
case CMP_NODE_VIEWER:
|
||||
case CMP_NODE_SPLITVIEWER: {
|
||||
case CMP_NODE_VIEWER: {
|
||||
ImageUser *iuser = static_cast<ImageUser *>(node->storage);
|
||||
iuser->scene = nullptr;
|
||||
break;
|
||||
|
@ -3458,7 +3457,7 @@ void ntreeSetOutput(bNodeTree *ntree)
|
|||
if (ELEM(node->type, CMP_NODE_OUTPUT_FILE, GEO_NODE_VIEWER)) {
|
||||
continue;
|
||||
}
|
||||
const bool node_is_output = ELEM(node->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER);
|
||||
const bool node_is_output = node->type == CMP_NODE_VIEWER;
|
||||
|
||||
int output = 0;
|
||||
/* there is more types having output class, each one is checked */
|
||||
|
@ -3469,7 +3468,7 @@ void ntreeSetOutput(bNodeTree *ntree)
|
|||
}
|
||||
|
||||
/* same type, exception for viewer */
|
||||
const bool tnode_is_output = ELEM(tnode->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER);
|
||||
const bool tnode_is_output = tnode->type == CMP_NODE_VIEWER;
|
||||
const bool compositor_case = is_compositor && tnode_is_output && node_is_output;
|
||||
if (tnode->type == node->type || compositor_case) {
|
||||
if (tnode->flag & NODE_DO_OUTPUT) {
|
||||
|
|
|
@ -708,7 +708,7 @@ static const char *node_get_static_idname(int type, int treetype)
|
|||
return "CompositorNodeChannelMatte";
|
||||
case CMP_NODE_FLIP:
|
||||
return "CompositorNodeFlip";
|
||||
case CMP_NODE_SPLITVIEWER:
|
||||
case CMP_NODE_SPLITVIEWER__DEPRECATED:
|
||||
return "CompositorNodeSplitViewer";
|
||||
case CMP_NODE_MAP_UV:
|
||||
return "CompositorNodeMapUV";
|
||||
|
|
|
@ -325,6 +325,33 @@ static void versioning_eevee_shadow_settings(Object *object)
|
|||
SET_FLAG_FROM_TEST(object->visibility_flag, hide_shadows, OB_HIDE_SHADOW);
|
||||
}
|
||||
|
||||
static void versioning_replace_splitviewer(bNodeTree *ntree)
|
||||
{
|
||||
/* Split viewer was replaced with a regular split node, so add a viewer node,
|
||||
* and link it to the new split node to achive the same behavior of the split viewer node. */
|
||||
|
||||
LISTBASE_FOREACH_MUTABLE (bNode *, node, &ntree->nodes) {
|
||||
if (node->type != CMP_NODE_SPLITVIEWER__DEPRECATED) {
|
||||
continue;
|
||||
}
|
||||
|
||||
STRNCPY(node->idname, "CompositorNodeSplit");
|
||||
node->type = CMP_NODE_SPLIT;
|
||||
zazizizou marked this conversation as resolved
Outdated
Omar Emara
commented
Change the type of the node directly. Most of other code can be removed then.
Change the type of the node directly. Most of other code can be removed then.
```
STRNCPY(node->idname, "CompositorNodeSplit");
node->type = CMP_NODE_SPLIT;
MEM_freeN(node->storage);
```
Habib Gahbiche
commented
I'm not sure how to achieve that. I'm not sure how to achieve that. `node` doesn't have an output socket so linking to viewer node doesn't work. So I took `version_geometry_nodes_replace_transfer_attribute_node()` from `versioning_300.cc` as a reference.
Omar Emara
commented
Can you try adding the socket using Can you try adding the socket using `nodeAddStaticSocket`?
Habib Gahbiche
commented
Change type, manually free storage and add output socket.... isn't deleting and constructing a new node cleaner at this point? :) Change type, manually free storage and add output socket.... isn't deleting and constructing a new node cleaner at this point? :)
Omar Emara
commented
You would still need to manually delete the existing node and its storage. But the main advantage is that you will not have to relink the inputs, transfer the data, or mess with typeinfo; which is most of the versioning code you have now. You would still need to manually delete the existing node and its storage. But the main advantage is that you will not have to relink the inputs, transfer the data, or mess with typeinfo; which is most of the versioning code you have now.
Habib Gahbiche
commented
Ok, I don't mind either way Ok, I don't mind either way
|
||||
MEM_freeN(node->storage);
|
||||
OmarEmaraDev marked this conversation as resolved
Omar Emara
commented
```
node->storage = nullptr;
```
|
||||
|
||||
bNode *viewer_node = nodeAddStaticNode(nullptr, ntree, CMP_NODE_VIEWER);
|
||||
/* Nodes are created stacked on top of each other, so separate them a bit. */
|
||||
viewer_node->locx = node->locx + node->width + viewer_node->width / 4.0f;
|
||||
viewer_node->locy = node->locy;
|
||||
OmarEmaraDev marked this conversation as resolved
Omar Emara
commented
```
viewer_node->flag &= ~NODE_PREVIEW;
```
|
||||
|
||||
bNodeSocket *split_out_socket = nodeAddStaticSocket(
|
||||
ntree, node, SOCK_OUT, SOCK_IMAGE, PROP_NONE, "Image", "Image");
|
||||
bNodeSocket *viewer_in_socket = nodeFindSocket(viewer_node, SOCK_IN, "Image");
|
||||
|
||||
nodeAddLink(ntree, node, split_out_socket, viewer_node, viewer_in_socket);
|
||||
}
|
||||
}
|
||||
|
||||
void do_versions_after_linking_400(FileData *fd, Main *bmain)
|
||||
{
|
||||
if (!MAIN_VERSION_FILE_ATLEAST(bmain, 400, 9)) {
|
||||
|
@ -2431,6 +2458,13 @@ void blo_do_versions_400(FileData *fd, Library * /*lib*/, Main *bmain)
|
|||
SET_FLAG_FROM_TEST(material->blend_flag, transparent_shadow, MA_BL_TRANSPARENT_SHADOW);
|
||||
}
|
||||
}
|
||||
|
||||
FOREACH_NODETREE_BEGIN (bmain, ntree, id) {
|
||||
if (ntree->type == NTREE_COMPOSIT) {
|
||||
versioning_replace_splitviewer(ntree);
|
||||
}
|
||||
}
|
||||
FOREACH_NODETREE_END;
|
||||
}
|
||||
|
||||
/* 401 6 did not require any do_version here. */
|
||||
|
|
|
@ -363,7 +363,7 @@ static void do_version_ntree_242_2(bNodeTree *ntree)
|
|||
{
|
||||
if (ntree->type == NTREE_COMPOSIT) {
|
||||
LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
|
||||
if (ELEM(node->type, CMP_NODE_IMAGE, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER)) {
|
||||
if (ELEM(node->type, CMP_NODE_IMAGE, CMP_NODE_VIEWER)) {
|
||||
/* only image had storage */
|
||||
if (node->storage) {
|
||||
NodeImageAnim *nia = static_cast<NodeImageAnim *>(node->storage);
|
||||
|
|
|
@ -122,6 +122,8 @@ if(WITH_COMPOSITOR_CPU)
|
|||
nodes/COM_RenderLayersNode.h
|
||||
nodes/COM_SceneTimeNode.cc
|
||||
nodes/COM_SceneTimeNode.h
|
||||
nodes/COM_SplitNode.cc
|
||||
nodes/COM_SplitNode.h
|
||||
nodes/COM_SwitchNode.cc
|
||||
nodes/COM_SwitchNode.h
|
||||
nodes/COM_SwitchViewNode.cc
|
||||
|
@ -136,8 +138,6 @@ if(WITH_COMPOSITOR_CPU)
|
|||
# output nodes
|
||||
nodes/COM_CompositorNode.cc
|
||||
nodes/COM_CompositorNode.h
|
||||
nodes/COM_SplitViewerNode.cc
|
||||
nodes/COM_SplitViewerNode.h
|
||||
nodes/COM_ViewLevelsNode.cc
|
||||
nodes/COM_ViewLevelsNode.h
|
||||
nodes/COM_ViewerNode.cc
|
||||
|
|
|
@ -89,7 +89,7 @@
|
|||
#include "COM_SeparateXYZNode.h"
|
||||
#include "COM_SetAlphaNode.h"
|
||||
#include "COM_SetValueOperation.h"
|
||||
#include "COM_SplitViewerNode.h"
|
||||
#include "COM_SplitNode.h"
|
||||
#include "COM_Stabilize2dNode.h"
|
||||
#include "COM_SunBeamsNode.h"
|
||||
#include "COM_SwitchNode.h"
|
||||
|
@ -212,8 +212,8 @@ Node *COM_convert_bnode(bNode *b_node)
|
|||
case CMP_NODE_VIEWER:
|
||||
node = new ViewerNode(b_node);
|
||||
break;
|
||||
case CMP_NODE_SPLITVIEWER:
|
||||
node = new SplitViewerNode(b_node);
|
||||
case CMP_NODE_SPLIT:
|
||||
node = new SplitNode(b_node);
|
||||
break;
|
||||
case CMP_NODE_INVERT:
|
||||
node = new InvertNode(b_node);
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
/* SPDX-FileCopyrightText: 2011 Blender Authors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
#include "COM_SplitNode.h"
|
||||
|
||||
#include "COM_SplitOperation.h"
|
||||
|
||||
namespace blender::compositor {
|
||||
|
||||
SplitNode::SplitNode(bNode *editor_node) : Node(editor_node)
|
||||
{
|
||||
/* pass */
|
||||
}
|
||||
|
||||
void SplitNode::convert_to_operations(NodeConverter &converter,
|
||||
const CompositorContext & /* context */) const
|
||||
{
|
||||
const bNode *node = this->get_bnode();
|
||||
|
||||
SplitOperation *split_operation = new SplitOperation();
|
||||
split_operation->set_split_percentage(node->custom1);
|
||||
split_operation->set_xsplit(node->custom2 == CMP_NODE_SPLIT_HORIZONTAL);
|
||||
zazizizou marked this conversation as resolved
Outdated
Omar Emara
commented
Prefer explicit comparison with the enum. Prefer explicit comparison with the enum.
|
||||
|
||||
converter.add_operation(split_operation);
|
||||
converter.map_input_socket(get_input_socket(0), split_operation->get_input_socket(0));
|
||||
converter.map_input_socket(get_input_socket(1), split_operation->get_input_socket(1));
|
||||
converter.map_output_socket(get_output_socket(0), split_operation->get_output_socket(0));
|
||||
|
||||
converter.add_preview(split_operation->get_output_socket());
|
||||
}
|
||||
|
||||
} // namespace blender::compositor
|
|
@ -10,12 +10,12 @@
|
|||
namespace blender::compositor {
|
||||
|
||||
/**
|
||||
* \brief SplitViewerNode
|
||||
* \brief SplitNode
|
||||
* \ingroup Node
|
||||
*/
|
||||
class SplitViewerNode : public Node {
|
||||
class SplitNode : public Node {
|
||||
public:
|
||||
SplitViewerNode(bNode *editor_node);
|
||||
SplitNode(bNode *node);
|
||||
void convert_to_operations(NodeConverter &converter,
|
||||
const CompositorContext &context) const override;
|
||||
};
|
|
@ -1,63 +0,0 @@
|
|||
/* SPDX-FileCopyrightText: 2011 Blender Authors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
#include "COM_SplitViewerNode.h"
|
||||
|
||||
#include "COM_SplitOperation.h"
|
||||
#include "COM_ViewerOperation.h"
|
||||
|
||||
namespace blender::compositor {
|
||||
|
||||
SplitViewerNode::SplitViewerNode(bNode *editor_node) : Node(editor_node)
|
||||
{
|
||||
/* pass */
|
||||
}
|
||||
|
||||
void SplitViewerNode::convert_to_operations(NodeConverter &converter,
|
||||
const CompositorContext &context) const
|
||||
{
|
||||
const bNode *editor_node = this->get_bnode();
|
||||
bool is_active = (editor_node->flag & NODE_DO_OUTPUT_RECALC || context.is_rendering()) &&
|
||||
(editor_node->flag & NODE_DO_OUTPUT);
|
||||
|
||||
NodeInput *image1Socket = this->get_input_socket(0);
|
||||
NodeInput *image2Socket = this->get_input_socket(1);
|
||||
Image *image = (Image *)this->get_bnode()->id;
|
||||
ImageUser *image_user = (ImageUser *)this->get_bnode()->storage;
|
||||
Scene *scene = context.get_scene();
|
||||
|
||||
SplitOperation *split_viewer_operation = new SplitOperation();
|
||||
split_viewer_operation->set_split_percentage(this->get_bnode()->custom1);
|
||||
split_viewer_operation->set_xsplit(!this->get_bnode()->custom2);
|
||||
|
||||
converter.add_operation(split_viewer_operation);
|
||||
converter.map_input_socket(image1Socket, split_viewer_operation->get_input_socket(0));
|
||||
converter.map_input_socket(image2Socket, split_viewer_operation->get_input_socket(1));
|
||||
|
||||
ViewerOperation *viewer_operation = new ViewerOperation();
|
||||
viewer_operation->set_image(image);
|
||||
viewer_operation->set_image_user(image_user);
|
||||
viewer_operation->set_view_settings(&scene->view_settings);
|
||||
viewer_operation->set_display_settings(&scene->display_settings);
|
||||
viewer_operation->set_render_data(context.get_render_data());
|
||||
viewer_operation->set_view_name(context.get_view_name());
|
||||
|
||||
/* defaults - the viewer node has these options but not exposed for split view
|
||||
* we could use the split to define an area of interest on one axis at least */
|
||||
viewer_operation->set_chunk_order(ChunkOrdering::Default);
|
||||
viewer_operation->setCenterX(0.5f);
|
||||
viewer_operation->setCenterY(0.5f);
|
||||
|
||||
converter.add_operation(viewer_operation);
|
||||
converter.add_link(split_viewer_operation->get_output_socket(),
|
||||
viewer_operation->get_input_socket(0));
|
||||
|
||||
converter.add_preview(split_viewer_operation->get_output_socket());
|
||||
|
||||
if (is_active) {
|
||||
converter.register_viewer(viewer_operation);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace blender::compositor
|
|
@ -13,6 +13,8 @@ SplitOperation::SplitOperation()
|
|||
this->add_output_socket(DataType::Color);
|
||||
image1Input_ = nullptr;
|
||||
image2Input_ = nullptr;
|
||||
|
||||
flags_.can_be_constant = true;
|
||||
}
|
||||
|
||||
void SplitOperation::init_execution()
|
||||
|
|
|
@ -179,7 +179,7 @@ set(GLSL_SRC
|
|||
shaders/compositor_smaa_blending_weight_calculation.glsl
|
||||
shaders/compositor_smaa_edge_detection.glsl
|
||||
shaders/compositor_smaa_neighborhood_blending.glsl
|
||||
shaders/compositor_split_viewer.glsl
|
||||
shaders/compositor_split.glsl
|
||||
shaders/compositor_summed_area_table_compute_complete_blocks.glsl
|
||||
shaders/compositor_summed_area_table_compute_complete_x_prologues.glsl
|
||||
shaders/compositor_summed_area_table_compute_complete_y_prologues.glsl
|
||||
|
@ -294,7 +294,7 @@ set(SRC_SHADER_CREATE_INFOS
|
|||
shaders/infos/compositor_realize_on_domain_info.hh
|
||||
shaders/infos/compositor_screen_lens_distortion_info.hh
|
||||
shaders/infos/compositor_smaa_info.hh
|
||||
shaders/infos/compositor_split_viewer_info.hh
|
||||
shaders/infos/compositor_split_info.hh
|
||||
shaders/infos/compositor_summed_area_table_info.hh
|
||||
shaders/infos/compositor_sun_beams_info.hh
|
||||
shaders/infos/compositor_symmetric_blur_info.hh
|
||||
|
|
|
@ -22,8 +22,7 @@ namespace blender::realtime_compositor {
|
|||
using namespace nodes::derived_node_tree_types;
|
||||
|
||||
/* Add the viewer node which is marked as NODE_DO_OUTPUT in the given context to the given stack.
|
||||
* If multiple types of viewer nodes are marked, then the preference will be CMP_NODE_VIEWER >
|
||||
* CMP_NODE_SPLITVIEWER. If no viewer nodes were found, composite nodes can be added as a fallback
|
||||
* If no viewer nodes were found, composite nodes can be added as a fallback
|
||||
* viewer node. */
|
||||
static bool add_viewer_nodes_in_context(const DTreeContext *context, Stack<DNode> &node_stack)
|
||||
{
|
||||
|
@ -34,13 +33,6 @@ static bool add_viewer_nodes_in_context(const DTreeContext *context, Stack<DNode
|
|||
}
|
||||
}
|
||||
|
||||
for (const bNode *node : context->btree().nodes_by_type("CompositorNodeSplitViewer")) {
|
||||
if (node->flag & NODE_DO_OUTPUT && !(node->flag & NODE_MUTED)) {
|
||||
node_stack.push(DNode(context, node));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/* The active Composite node was already added, no need to add it again, see the next block. */
|
||||
if (!node_stack.is_empty() && node_stack.peek()->type == CMP_NODE_COMPOSITE) {
|
||||
return false;
|
||||
|
|
|
@ -7,12 +7,13 @@
|
|||
void main()
|
||||
{
|
||||
ivec2 texel = ivec2(gl_GlobalInvocationID.xy);
|
||||
ivec2 output_size = imageSize(output_img);
|
||||
#if defined(SPLIT_HORIZONTAL)
|
||||
bool condition = (view_size.x * split_ratio) < texel.x;
|
||||
bool condition = (output_size.x * split_ratio) < texel.x;
|
||||
#elif defined(SPLIT_VERTICAL)
|
||||
bool condition = (view_size.y * split_ratio) < texel.y;
|
||||
bool condition = (output_size.y * split_ratio) < texel.y;
|
||||
#endif
|
||||
vec4 color = condition ? texture_load(first_image_tx, texel) :
|
||||
texture_load(second_image_tx, texel);
|
||||
imageStore(output_img, texel + lower_bound, color);
|
||||
imageStore(output_img, texel, color);
|
||||
}
|
|
@ -4,22 +4,20 @@
|
|||
|
||||
#include "gpu_shader_create_info.hh"
|
||||
|
||||
GPU_SHADER_CREATE_INFO(compositor_split_viewer_shared)
|
||||
GPU_SHADER_CREATE_INFO(compositor_split_shared)
|
||||
.local_group_size(16, 16)
|
||||
.push_constant(Type::FLOAT, "split_ratio")
|
||||
.push_constant(Type::IVEC2, "view_size")
|
||||
.push_constant(Type::IVEC2, "lower_bound")
|
||||
.sampler(0, ImageType::FLOAT_2D, "first_image_tx")
|
||||
.sampler(1, ImageType::FLOAT_2D, "second_image_tx")
|
||||
.image(0, GPU_RGBA16F, Qualifier::WRITE, ImageType::FLOAT_2D, "output_img")
|
||||
.compute_source("compositor_split_viewer.glsl");
|
||||
.compute_source("compositor_split.glsl");
|
||||
|
||||
GPU_SHADER_CREATE_INFO(compositor_split_viewer_horizontal)
|
||||
.additional_info("compositor_split_viewer_shared")
|
||||
GPU_SHADER_CREATE_INFO(compositor_split_horizontal)
|
||||
.additional_info("compositor_split_shared")
|
||||
.define("SPLIT_HORIZONTAL")
|
||||
.do_static_compilation(true);
|
||||
|
||||
GPU_SHADER_CREATE_INFO(compositor_split_viewer_vertical)
|
||||
.additional_info("compositor_split_viewer_shared")
|
||||
GPU_SHADER_CREATE_INFO(compositor_split_vertical)
|
||||
.additional_info("compositor_split_shared")
|
||||
.define("SPLIT_VERTICAL")
|
||||
.do_static_compilation(true);
|
|
@ -53,7 +53,7 @@ ImageUser *ntree_get_active_iuser(bNodeTree *ntree)
|
|||
{
|
||||
if (ntree) {
|
||||
LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
|
||||
if (ELEM(node->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER)) {
|
||||
if (node->type == CMP_NODE_VIEWER) {
|
||||
if (node->flag & NODE_DO_OUTPUT) {
|
||||
return static_cast<ImageUser *>(node->storage);
|
||||
}
|
||||
|
|
|
@ -133,7 +133,7 @@ static void compo_tag_output_nodes(bNodeTree *nodetree, int recalc_flags)
|
|||
node->flag |= NODE_DO_OUTPUT_RECALC;
|
||||
}
|
||||
}
|
||||
else if (ELEM(node->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER)) {
|
||||
else if (node->type == CMP_NODE_VIEWER) {
|
||||
if (recalc_flags & COM_RECALC_VIEWER) {
|
||||
node->flag |= NODE_DO_OUTPUT_RECALC;
|
||||
}
|
||||
|
@ -813,9 +813,9 @@ void ED_node_set_active(
|
|||
}
|
||||
else if (ntree->type == NTREE_COMPOSIT) {
|
||||
/* Make active viewer, currently only one is supported. */
|
||||
if (ELEM(node->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER)) {
|
||||
if (node->type == CMP_NODE_VIEWER) {
|
||||
for (bNode *node_iter : ntree->all_nodes()) {
|
||||
if (ELEM(node_iter->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER)) {
|
||||
if (node_iter->type == CMP_NODE_VIEWER) {
|
||||
node_iter->flag &= ~NODE_DO_OUTPUT;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -103,7 +103,7 @@ static bool WIDGETGROUP_node_transform_poll(const bContext *C, wmGizmoGroupType
|
|||
if (snode && snode->edittree && snode->edittree->type == NTREE_COMPOSIT) {
|
||||
bNode *node = nodeGetActive(snode->edittree);
|
||||
|
||||
if (node && ELEM(node->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER)) {
|
||||
if (node && ELEM(node->type, CMP_NODE_VIEWER)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -471,7 +471,7 @@ static bNodeSocket *node_link_viewer_get_socket(bNodeTree &ntree,
|
|||
|
||||
static bool is_viewer_node(const bNode &node)
|
||||
{
|
||||
return ELEM(node.type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER, GEO_NODE_VIEWER);
|
||||
return ELEM(node.type, CMP_NODE_VIEWER, GEO_NODE_VIEWER);
|
||||
}
|
||||
|
||||
static bool is_viewer_socket_in_viewer(const bNodeSocket &socket)
|
||||
|
|
|
@ -2365,11 +2365,11 @@ enum {
|
|||
CMP_NODE_OUTPUT_IGNORE_ALPHA = 1,
|
||||
};
|
||||
|
||||
/** Split Viewer Node. Stored in `custom2`. */
|
||||
typedef enum CMPNodeSplitViewerAxis {
|
||||
CMP_NODE_SPLIT_VIEWER_HORIZONTAL = 0,
|
||||
CMP_NODE_SPLIT_VIEWER_VERTICAL = 1,
|
||||
} CMPNodeSplitViewerAxis;
|
||||
/** Split Node. Stored in `custom2`. */
|
||||
typedef enum CMPNodeSplitAxis {
|
||||
CMP_NODE_SPLIT_HORIZONTAL = 0,
|
||||
CMP_NODE_SPLIT_VERTICAL = 1,
|
||||
} CMPNodeSplitAxis;
|
||||
|
||||
/** Color Balance Node. Stored in `custom1`. */
|
||||
typedef enum CMPNodeColorBalanceMethod {
|
||||
|
|
|
@ -6847,7 +6847,7 @@ static void def_cmp_flip(StructRNA *srna)
|
|||
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
|
||||
}
|
||||
|
||||
static void def_cmp_splitviewer(StructRNA *srna)
|
||||
static void def_cmp_split(StructRNA *srna)
|
||||
{
|
||||
PropertyRNA *prop;
|
||||
|
||||
|
|
|
@ -167,7 +167,7 @@ DefNode(CompositorNode, CMP_NODE_COLOR_SPILL, def_cmp_color_spill, "COLOR_
|
|||
DefNode(CompositorNode, CMP_NODE_CHROMA_MATTE, def_cmp_chroma_matte, "CHROMA_MATTE", ChromaMatte, "Chroma Key", "" )
|
||||
DefNode(CompositorNode, CMP_NODE_CHANNEL_MATTE, def_cmp_channel_matte, "CHANNEL_MATTE", ChannelMatte, "Channel Key", "" )
|
||||
DefNode(CompositorNode, CMP_NODE_FLIP, def_cmp_flip, "FLIP", Flip, "Flip", "" )
|
||||
DefNode(CompositorNode, CMP_NODE_SPLITVIEWER, def_cmp_splitviewer, "SPLITVIEWER", SplitViewer, "Split Viewer", "" )
|
||||
DefNode(CompositorNode, CMP_NODE_SPLIT, def_cmp_split, "SPLIT", Split, "Split", "" )
|
||||
DefNode(CompositorNode, CMP_NODE_MAP_UV, def_cmp_map_uv, "MAP_UV", MapUV, "Map UV", "" )
|
||||
zazizizou marked this conversation as resolved
Outdated
Omar Emara
commented
Omit "Node" from the names. Omit "Node" from the names.
|
||||
DefNode(CompositorNode, CMP_NODE_ID_MASK, def_cmp_id_mask, "ID_MASK", IDMask, "ID Mask", "" )
|
||||
DefNode(CompositorNode, CMP_NODE_DOUBLEEDGEMASK, def_cmp_double_edge_mask,"DOUBLEEDGEMASK", DoubleEdgeMask, "Double Edge Mask", "" )
|
||||
|
|
|
@ -99,7 +99,7 @@ set(SRC
|
|||
nodes/node_composite_sepcomb_ycca.cc
|
||||
nodes/node_composite_sepcomb_yuva.cc
|
||||
nodes/node_composite_setalpha.cc
|
||||
nodes/node_composite_split_viewer.cc
|
||||
nodes/node_composite_split.cc
|
||||
nodes/node_composite_stabilize2d.cc
|
||||
nodes/node_composite_sunbeams.cc
|
||||
nodes/node_composite_switch.cc
|
||||
|
|
|
@ -95,7 +95,7 @@ void register_composite_nodes()
|
|||
register_node_type_cmp_sepycca();
|
||||
register_node_type_cmp_sepyuva();
|
||||
register_node_type_cmp_setalpha();
|
||||
register_node_type_cmp_splitviewer();
|
||||
register_node_type_cmp_split();
|
||||
register_node_type_cmp_stabilize2d();
|
||||
register_node_type_cmp_sunbeams();
|
||||
register_node_type_cmp_switch_view();
|
||||
|
|
|
@ -91,7 +91,7 @@ void register_node_type_cmp_seprgba();
|
|||
void register_node_type_cmp_sepycca();
|
||||
void register_node_type_cmp_sepyuva();
|
||||
void register_node_type_cmp_setalpha();
|
||||
void register_node_type_cmp_splitviewer();
|
||||
void register_node_type_cmp_split();
|
||||
void register_node_type_cmp_stabilize2d();
|
||||
void register_node_type_cmp_sunbeams();
|
||||
void register_node_type_cmp_switch_view();
|
||||
|
|
|
@ -78,7 +78,7 @@ static void localize(bNodeTree *localtree, bNodeTree *ntree)
|
|||
/* move over the compbufs */
|
||||
/* right after #blender::bke::ntreeCopyTree() `oldsock` pointers are valid */
|
||||
|
||||
if (ELEM(node->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER)) {
|
||||
if (node->type == CMP_NODE_VIEWER) {
|
||||
if (node->id) {
|
||||
if (node->flag & NODE_DO_OUTPUT) {
|
||||
local_node->id = (ID *)node->id;
|
||||
|
@ -101,7 +101,7 @@ static void local_merge(Main *bmain, bNodeTree *localtree, bNodeTree *ntree)
|
|||
|
||||
LISTBASE_FOREACH (bNode *, lnode, &localtree->nodes) {
|
||||
if (bNode *orig_node = nodeFindNodebyName(ntree, lnode->name)) {
|
||||
if (ELEM(lnode->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER)) {
|
||||
zazizizou marked this conversation as resolved
Outdated
Omar Emara
commented
Replace Replace `ELEM` by a simple comparison, same for the rest of the patch.
|
||||
if (lnode->type == CMP_NODE_VIEWER) {
|
||||
if (lnode->id && (lnode->flag & NODE_DO_OUTPUT)) {
|
||||
/* image_merge does sanity check for pointers */
|
||||
BKE_image_merge(bmain, (Image *)orig_node->id, (Image *)lnode->id);
|
||||
|
|
|
@ -0,0 +1,123 @@
|
|||
/* SPDX-FileCopyrightText: 2006 Blender Authors
|
||||
Habib Gahbiche
commented
It looks like a new file has been added but it has just been renamed. Do we update the copyright date in this case? It looks like a new file has been added but it has just been renamed. Do we update the copyright date in this case?
Omar Emara
commented
I would just update that. I would just update that.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/** \file
|
||||
* \ingroup cmpnodes
|
||||
*/
|
||||
|
||||
#include "BKE_global.h"
|
||||
#include "BKE_image.h"
|
||||
|
||||
#include "UI_interface.hh"
|
||||
#include "UI_resources.hh"
|
||||
|
||||
#include "GPU_shader.h"
|
||||
#include "GPU_texture.h"
|
||||
|
||||
#include "COM_node_operation.hh"
|
||||
#include "COM_utilities.hh"
|
||||
|
||||
#include "node_composite_util.hh"
|
||||
|
||||
/* **************** SPLIT NODE ******************** */
|
||||
|
||||
namespace blender::nodes::node_composite_split_cc {
|
||||
|
||||
static void cmp_node_split_declare(NodeDeclarationBuilder &b)
|
||||
{
|
||||
b.add_input<decl::Color>("Image");
|
||||
b.add_input<decl::Color>("Image", "Image_001");
|
||||
b.add_output<decl::Color>("Image");
|
||||
}
|
||||
|
||||
static void node_composit_init_split(bNodeTree * /*ntree*/, bNode *node)
|
||||
{
|
||||
node->custom1 = 50; /* default 50% split */
|
||||
zazizizou marked this conversation as resolved
Outdated
Omar Emara
commented
Remove storage. Remove storage.
|
||||
}
|
||||
|
||||
static void node_composit_buts_split(uiLayout *layout, bContext * /*C*/, PointerRNA *ptr)
|
||||
{
|
||||
uiLayout *row, *col;
|
||||
|
||||
col = uiLayoutColumn(layout, false);
|
||||
row = uiLayoutRow(col, false);
|
||||
uiItemR(row, ptr, "axis", UI_ITEM_R_SPLIT_EMPTY_NAME | UI_ITEM_R_EXPAND, nullptr, ICON_NONE);
|
||||
uiItemR(col, ptr, "factor", UI_ITEM_R_SPLIT_EMPTY_NAME, nullptr, ICON_NONE);
|
||||
}
|
||||
|
||||
using namespace blender::realtime_compositor;
|
||||
|
||||
class SplitOperation : public NodeOperation {
|
||||
public:
|
||||
using NodeOperation::NodeOperation;
|
||||
|
||||
void execute() override
|
||||
{
|
||||
GPUShader *shader = get_split_shader();
|
||||
GPU_shader_bind(shader);
|
||||
|
||||
GPU_shader_uniform_1f(shader, "split_ratio", get_split_ratio());
|
||||
|
||||
const Result &first_image = get_input("Image");
|
||||
first_image.bind_as_texture(shader, "first_image_tx");
|
||||
const Result &second_image = get_input("Image_001");
|
||||
second_image.bind_as_texture(shader, "second_image_tx");
|
||||
|
||||
const Domain domain = compute_domain();
|
||||
Result &output_image = get_result("Image");
|
||||
output_image.allocate_texture(domain);
|
||||
output_image.bind_as_image(shader, "output_img");
|
||||
|
||||
compute_dispatch_threads_at_least(shader, domain.size);
|
||||
|
||||
first_image.unbind_as_texture();
|
||||
second_image.unbind_as_texture();
|
||||
output_image.unbind_as_image();
|
||||
GPU_shader_unbind();
|
||||
}
|
||||
|
||||
GPUShader *get_split_shader()
|
||||
{
|
||||
if (get_split_axis() == CMP_NODE_SPLIT_HORIZONTAL) {
|
||||
return context().get_shader("compositor_split_horizontal");
|
||||
}
|
||||
|
||||
return context().get_shader("compositor_split_vertical");
|
||||
}
|
||||
|
||||
CMPNodeSplitAxis get_split_axis()
|
||||
{
|
||||
return (CMPNodeSplitAxis)bnode().custom2;
|
||||
}
|
||||
|
||||
float get_split_ratio()
|
||||
{
|
||||
return bnode().custom1 / 100.0f;
|
||||
}
|
||||
};
|
||||
|
||||
static NodeOperation *get_compositor_operation(Context &context, DNode node)
|
||||
{
|
||||
return new SplitOperation(context, node);
|
||||
}
|
||||
|
||||
} // namespace blender::nodes::node_composite_split_cc
|
||||
|
||||
void register_node_type_cmp_split()
|
||||
{
|
||||
namespace file_ns = blender::nodes::node_composite_split_cc;
|
||||
|
||||
static bNodeType ntype;
|
||||
|
||||
cmp_node_type_base(&ntype, CMP_NODE_SPLIT, "Split", NODE_CLASS_CONVERTER);
|
||||
ntype.declare = file_ns::cmp_node_split_declare;
|
||||
ntype.draw_buttons = file_ns::node_composit_buts_split;
|
||||
ntype.flag |= NODE_PREVIEW;
|
||||
zazizizou marked this conversation as resolved
Outdated
Omar Emara
commented
Omit "Node" from the name. Omit "Node" from the name. `NODE_CLASS_LAYOUT` seems wrong here, maybe just `NODE_CLASS_CONVERTER` or `NODE_CLASS_OP_FILTER`.
Habib Gahbiche
commented
`CONVERTER` and `FILTER` don't sound right either... Switch node also uses `NODE_CLASS_LAYOUT`. Do you suggest I change that as well (in a separate patch) ?
Omar Emara
commented
Switch node could pass as a layout node to me, it doesn't really process anything. Switch node could pass as a layout node to me, it doesn't really process anything.
Classes don't make sense for many nodes, so I wouldn't worry too much about it.
|
||||
ntype.initfunc = file_ns::node_composit_init_split;
|
||||
ntype.get_compositor_operation = file_ns::get_compositor_operation;
|
||||
|
||||
ntype.no_muting = true;
|
||||
|
||||
zazizizou marked this conversation as resolved
Outdated
Omar Emara
commented
The node storage can be removed. The node storage can be removed.
|
||||
nodeRegisterType(&ntype);
|
||||
}
|
|
@ -1,150 +0,0 @@
|
|||
/* SPDX-FileCopyrightText: 2006 Blender Authors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/** \file
|
||||
* \ingroup cmpnodes
|
||||
*/
|
||||
|
||||
#include "BKE_global.h"
|
||||
#include "BKE_image.h"
|
||||
|
||||
#include "UI_interface.hh"
|
||||
#include "UI_resources.hh"
|
||||
|
||||
#include "GPU_shader.h"
|
||||
#include "GPU_texture.h"
|
||||
|
||||
#include "COM_node_operation.hh"
|
||||
#include "COM_utilities.hh"
|
||||
|
||||
#include "node_composite_util.hh"
|
||||
|
||||
/* **************** SPLIT VIEWER ******************** */
|
||||
|
||||
namespace blender::nodes::node_composite_split_viewer_cc {
|
||||
|
||||
static void cmp_node_split_viewer_declare(NodeDeclarationBuilder &b)
|
||||
{
|
||||
b.add_input<decl::Color>("Image");
|
||||
b.add_input<decl::Color>("Image", "Image_001");
|
||||
}
|
||||
|
||||
static void node_composit_init_splitviewer(bNodeTree * /*ntree*/, bNode *node)
|
||||
{
|
||||
ImageUser *iuser = MEM_cnew<ImageUser>(__func__);
|
||||
node->storage = iuser;
|
||||
iuser->sfra = 1;
|
||||
node->custom1 = 50; /* default 50% split */
|
||||
|
||||
node->id = (ID *)BKE_image_ensure_viewer(G.main, IMA_TYPE_COMPOSITE, "Viewer Node");
|
||||
}
|
||||
|
||||
static void node_composit_buts_splitviewer(uiLayout *layout, bContext * /*C*/, PointerRNA *ptr)
|
||||
{
|
||||
uiLayout *row, *col;
|
||||
|
||||
col = uiLayoutColumn(layout, false);
|
||||
row = uiLayoutRow(col, false);
|
||||
uiItemR(row, ptr, "axis", UI_ITEM_R_SPLIT_EMPTY_NAME | UI_ITEM_R_EXPAND, nullptr, ICON_NONE);
|
||||
uiItemR(col, ptr, "factor", UI_ITEM_R_SPLIT_EMPTY_NAME, nullptr, ICON_NONE);
|
||||
}
|
||||
|
||||
using namespace blender::realtime_compositor;
|
||||
|
||||
class ViewerOperation : public NodeOperation {
|
||||
public:
|
||||
using NodeOperation::NodeOperation;
|
||||
|
||||
void execute() override
|
||||
{
|
||||
GPUShader *shader = get_split_viewer_shader();
|
||||
GPU_shader_bind(shader);
|
||||
|
||||
/* The compositing space might be limited to a subset of the output texture, so only write into
|
||||
* that compositing region. */
|
||||
const rcti compositing_region = context().get_compositing_region();
|
||||
const int2 lower_bound = int2(compositing_region.xmin, compositing_region.ymin);
|
||||
GPU_shader_uniform_2iv(shader, "lower_bound", lower_bound);
|
||||
|
||||
GPU_shader_uniform_1f(shader, "split_ratio", get_split_ratio());
|
||||
|
||||
const int2 compositing_region_size = context().get_compositing_region_size();
|
||||
GPU_shader_uniform_2iv(shader, "view_size", compositing_region_size);
|
||||
|
||||
const Result &first_image = get_input("Image");
|
||||
first_image.bind_as_texture(shader, "first_image_tx");
|
||||
const Result &second_image = get_input("Image_001");
|
||||
second_image.bind_as_texture(shader, "second_image_tx");
|
||||
|
||||
const int2 viewer_size = compute_domain().size;
|
||||
GPUTexture *output_texture = context().get_viewer_output_texture(viewer_size);
|
||||
const int image_unit = GPU_shader_get_sampler_binding(shader, "output_img");
|
||||
GPU_texture_image_bind(output_texture, image_unit);
|
||||
|
||||
compute_dispatch_threads_at_least(shader, viewer_size);
|
||||
|
||||
first_image.unbind_as_texture();
|
||||
second_image.unbind_as_texture();
|
||||
GPU_texture_image_unbind(output_texture);
|
||||
GPU_shader_unbind();
|
||||
}
|
||||
|
||||
Domain compute_domain() override
|
||||
{
|
||||
/* The context can use the composite output and thus has a dedicated viewer of an arbitrary
|
||||
* size, so use the input directly. Otherwise, no dedicated viewer exist so the input should be
|
||||
* in the domain of the compositing region. */
|
||||
if (context().use_composite_output()) {
|
||||
return NodeOperation::compute_domain();
|
||||
}
|
||||
else {
|
||||
return Domain(context().get_compositing_region_size());
|
||||
}
|
||||
}
|
||||
|
||||
GPUShader *get_split_viewer_shader()
|
||||
{
|
||||
if (get_split_axis() == CMP_NODE_SPLIT_VIEWER_HORIZONTAL) {
|
||||
return context().get_shader("compositor_split_viewer_horizontal", ResultPrecision::Half);
|
||||
}
|
||||
|
||||
return context().get_shader("compositor_split_viewer_vertical", ResultPrecision::Half);
|
||||
}
|
||||
|
||||
CMPNodeSplitViewerAxis get_split_axis()
|
||||
{
|
||||
return (CMPNodeSplitViewerAxis)bnode().custom2;
|
||||
}
|
||||
|
||||
float get_split_ratio()
|
||||
{
|
||||
return bnode().custom1 / 100.0f;
|
||||
}
|
||||
};
|
||||
|
||||
static NodeOperation *get_compositor_operation(Context &context, DNode node)
|
||||
{
|
||||
return new ViewerOperation(context, node);
|
||||
}
|
||||
|
||||
} // namespace blender::nodes::node_composite_split_viewer_cc
|
||||
|
||||
void register_node_type_cmp_splitviewer()
|
||||
{
|
||||
namespace file_ns = blender::nodes::node_composite_split_viewer_cc;
|
||||
|
||||
static bNodeType ntype;
|
||||
|
||||
cmp_node_type_base(&ntype, CMP_NODE_SPLITVIEWER, "Split Viewer", NODE_CLASS_OUTPUT);
|
||||
ntype.declare = file_ns::cmp_node_split_viewer_declare;
|
||||
ntype.draw_buttons = file_ns::node_composit_buts_splitviewer;
|
||||
ntype.flag |= NODE_PREVIEW;
|
||||
ntype.initfunc = file_ns::node_composit_init_splitviewer;
|
||||
node_type_storage(&ntype, "ImageUser", node_free_standard_storage, node_copy_standard_storage);
|
||||
ntype.get_compositor_operation = file_ns::get_compositor_operation;
|
||||
|
||||
ntype.no_muting = true;
|
||||
|
||||
nodeRegisterType(&ntype);
|
||||
}
|
Put the comment above the define. I know other places do it the current way, but that shouldn't be.