WIP: Compositor: Add interpolation option to scale node #119902
|
@ -19,15 +19,31 @@ void ScaleNode::convert_to_operations(NodeConverter &converter,
|
||||||
const CompositorContext &context) const
|
const CompositorContext &context) const
|
||||||
{
|
{
|
||||||
const bNode *bnode = this->get_bnode();
|
const bNode *bnode = this->get_bnode();
|
||||||
|
const NodeScaleData *data = (const NodeScaleData *)bnode->storage;
|
||||||
|
|
||||||
NodeInput *input_socket = this->get_input_socket(0);
|
NodeInput *input_socket = this->get_input_socket(0);
|
||||||
NodeInput *input_xsocket = this->get_input_socket(1);
|
NodeInput *input_xsocket = this->get_input_socket(1);
|
||||||
NodeInput *input_ysocket = this->get_input_socket(2);
|
NodeInput *input_ysocket = this->get_input_socket(2);
|
||||||
NodeOutput *output_socket = this->get_output_socket(0);
|
NodeOutput *output_socket = this->get_output_socket(0);
|
||||||
|
|
||||||
|
PixelSampler sampler = PixelSampler::Nearest;
|
||||||
|
switch (data->interpolation) {
|
||||||
|
case 0:
|
||||||
|
sampler = PixelSampler::Nearest;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
sampler = PixelSampler::Bilinear;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
sampler = PixelSampler::Bicubic;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
switch (bnode->custom1) {
|
switch (bnode->custom1) {
|
||||||
case CMP_NODE_SCALE_RELATIVE: {
|
case CMP_NODE_SCALE_RELATIVE: {
|
||||||
ScaleRelativeOperation *operation = new ScaleRelativeOperation();
|
ScaleRelativeOperation *operation = new ScaleRelativeOperation();
|
||||||
|
|
||||||
|
operation->set_sampler(sampler);
|
||||||
converter.add_operation(operation);
|
converter.add_operation(operation);
|
||||||
|
|
||||||
converter.map_input_socket(input_socket, operation->get_input_socket(0));
|
converter.map_input_socket(input_socket, operation->get_input_socket(0));
|
||||||
|
@ -44,6 +60,8 @@ void ScaleNode::convert_to_operations(NodeConverter &converter,
|
||||||
converter.add_operation(scale_factor_operation);
|
converter.add_operation(scale_factor_operation);
|
||||||
|
|
||||||
ScaleRelativeOperation *operation = new ScaleRelativeOperation();
|
ScaleRelativeOperation *operation = new ScaleRelativeOperation();
|
||||||
|
|
||||||
|
operation->set_sampler(sampler);
|
||||||
converter.add_operation(operation);
|
converter.add_operation(operation);
|
||||||
|
|
||||||
converter.map_input_socket(input_socket, operation->get_input_socket(0));
|
converter.map_input_socket(input_socket, operation->get_input_socket(0));
|
||||||
|
@ -68,6 +86,7 @@ void ScaleNode::convert_to_operations(NodeConverter &converter,
|
||||||
operation->set_offset(bnode->custom3, bnode->custom4);
|
operation->set_offset(bnode->custom3, bnode->custom4);
|
||||||
operation->set_new_width(rd->xsch * render_size_factor);
|
operation->set_new_width(rd->xsch * render_size_factor);
|
||||||
operation->set_new_height(rd->ysch * render_size_factor);
|
operation->set_new_height(rd->ysch * render_size_factor);
|
||||||
|
operation->set_sampler(sampler);
|
||||||
converter.add_operation(operation);
|
converter.add_operation(operation);
|
||||||
|
|
||||||
converter.map_input_socket(input_socket, operation->get_input_socket(0));
|
converter.map_input_socket(input_socket, operation->get_input_socket(0));
|
||||||
|
@ -80,6 +99,8 @@ void ScaleNode::convert_to_operations(NodeConverter &converter,
|
||||||
case CMP_NODE_SCALE_ABSOLUTE: {
|
case CMP_NODE_SCALE_ABSOLUTE: {
|
||||||
/* TODO: what is the use of this one.... perhaps some issues when the ui was updated... */
|
/* TODO: what is the use of this one.... perhaps some issues when the ui was updated... */
|
||||||
ScaleAbsoluteOperation *operation = new ScaleAbsoluteOperation();
|
ScaleAbsoluteOperation *operation = new ScaleAbsoluteOperation();
|
||||||
|
|
||||||
|
operation->set_sampler(sampler);
|
||||||
converter.add_operation(operation);
|
converter.add_operation(operation);
|
||||||
|
|
||||||
converter.map_input_socket(input_socket, operation->get_input_socket(0));
|
converter.map_input_socket(input_socket, operation->get_input_socket(0));
|
||||||
|
|
|
@ -23,9 +23,9 @@ class BaseScaleOperation : public MultiThreadedOperation {
|
||||||
protected:
|
protected:
|
||||||
BaseScaleOperation();
|
BaseScaleOperation();
|
||||||
|
|
||||||
PixelSampler get_effective_sampler(PixelSampler sampler)
|
PixelSampler get_effective_sampler()
|
||||||
{
|
{
|
||||||
return (sampler_ == -1) ? sampler : (PixelSampler)sampler_;
|
return (PixelSampler)sampler_;
|
||||||
}
|
}
|
||||||
|
|
||||||
int sampler_;
|
int sampler_;
|
||||||
|
|
|
@ -1418,6 +1418,13 @@ typedef struct NodeTranslateData {
|
||||||
char relative;
|
char relative;
|
||||||
} NodeTranslateData;
|
} NodeTranslateData;
|
||||||
|
|
||||||
|
typedef struct NodeScaleData {
|
||||||
|
int16_t space, frame_method;
|
||||||
|
float offset_x, offset_y;
|
||||||
|
short interpolation;
|
||||||
|
char _pad[2];
|
||||||
|
} NodeScaleData;
|
||||||
|
|
||||||
typedef struct NodePlaneTrackDeformData {
|
typedef struct NodePlaneTrackDeformData {
|
||||||
char tracking_object[64];
|
char tracking_object[64];
|
||||||
char plane_track_name[64];
|
char plane_track_name[64];
|
||||||
|
|
|
@ -6612,28 +6612,55 @@ static void def_cmp_scale(StructRNA *srna)
|
||||||
{0, nullptr, 0, nullptr, nullptr},
|
{0, nullptr, 0, nullptr, nullptr},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const EnumPropertyItem interpolation_items[] = {
|
||||||
|
{CMP_NODE_STABILIZE_INTERPOLATION_NEAREST,
|
||||||
|
"NEAREST",
|
||||||
|
0,
|
||||||
|
"Nearest",
|
||||||
|
"Use nearest interpolation"},
|
||||||
|
{CMP_NODE_STABILIZE_INTERPOLATION_BILINEAR,
|
||||||
|
"BILINEAR",
|
||||||
|
0,
|
||||||
|
"Bilinear",
|
||||||
|
"Use bilinear interpolation"},
|
||||||
|
{CMP_NODE_STABILIZE_INTERPOLATION_BICUBIC,
|
||||||
|
"BICUBIC",
|
||||||
|
0,
|
||||||
|
"Bicubic",
|
||||||
|
"Use bicubic interpolation"},
|
||||||
|
{0, nullptr, 0, nullptr, nullptr},
|
||||||
|
};
|
||||||
|
|
||||||
|
RNA_def_struct_sdna_from(srna, "NodeScaleData", "storage");
|
||||||
|
|
||||||
prop = RNA_def_property(srna, "space", PROP_ENUM, PROP_NONE);
|
prop = RNA_def_property(srna, "space", PROP_ENUM, PROP_NONE);
|
||||||
RNA_def_property_enum_sdna(prop, nullptr, "custom1");
|
RNA_def_property_enum_sdna(prop, nullptr, "space");
|
||||||
RNA_def_property_enum_items(prop, space_items);
|
RNA_def_property_enum_items(prop, space_items);
|
||||||
RNA_def_property_ui_text(prop, "Space", "Coordinate space to scale relative to");
|
RNA_def_property_ui_text(prop, "Space", "Coordinate space to scale relative to");
|
||||||
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_CompositorNodeScale_update");
|
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_CompositorNodeScale_update");
|
||||||
|
|
||||||
/* expose 2 flags as a enum of 3 items */
|
/* expose 2 flags as a enum of 3 items */
|
||||||
prop = RNA_def_property(srna, "frame_method", PROP_ENUM, PROP_NONE);
|
prop = RNA_def_property(srna, "frame_method", PROP_ENUM, PROP_NONE);
|
||||||
RNA_def_property_enum_bitflag_sdna(prop, nullptr, "custom2");
|
RNA_def_property_enum_bitflag_sdna(prop, nullptr, "frame_method");
|
||||||
RNA_def_property_enum_items(prop, space_frame_items);
|
RNA_def_property_enum_items(prop, space_frame_items);
|
||||||
RNA_def_property_ui_text(prop, "Frame Method", "How the image fits in the camera frame");
|
RNA_def_property_ui_text(prop, "Frame Method", "How the image fits in the camera frame");
|
||||||
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
|
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
|
||||||
|
|
||||||
prop = RNA_def_property(srna, "offset_x", PROP_FLOAT, PROP_NONE);
|
prop = RNA_def_property(srna, "offset_x", PROP_FLOAT, PROP_NONE);
|
||||||
RNA_def_property_float_sdna(prop, nullptr, "custom3");
|
RNA_def_property_float_sdna(prop, nullptr, "offset_x");
|
||||||
RNA_def_property_ui_text(prop, "X Offset", "Offset image horizontally (factor of image size)");
|
RNA_def_property_ui_text(prop, "X Offset", "Offset image horizontally (factor of image size)");
|
||||||
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
|
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
|
||||||
|
|
||||||
prop = RNA_def_property(srna, "offset_y", PROP_FLOAT, PROP_NONE);
|
prop = RNA_def_property(srna, "offset_y", PROP_FLOAT, PROP_NONE);
|
||||||
RNA_def_property_float_sdna(prop, nullptr, "custom4");
|
RNA_def_property_float_sdna(prop, nullptr, "offset_y");
|
||||||
RNA_def_property_ui_text(prop, "Y Offset", "Offset image vertically (factor of image size)");
|
RNA_def_property_ui_text(prop, "Y Offset", "Offset image vertically (factor of image size)");
|
||||||
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
|
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
|
||||||
|
|
||||||
|
prop = RNA_def_property(srna, "interpolation", PROP_ENUM, PROP_NONE);
|
||||||
|
RNA_def_property_enum_sdna(prop, nullptr, "interpolation");
|
||||||
|
RNA_def_property_enum_items(prop, interpolation_items);
|
||||||
|
RNA_def_property_ui_text(prop, "Interpolation", "Which interpolation method to use");
|
||||||
|
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void def_cmp_rotate(StructRNA *srna)
|
static void def_cmp_rotate(StructRNA *srna)
|
||||||
|
|
|
@ -28,6 +28,8 @@
|
||||||
|
|
||||||
namespace blender::nodes::node_composite_scale_cc {
|
namespace blender::nodes::node_composite_scale_cc {
|
||||||
|
|
||||||
|
NODE_STORAGE_FUNCS(NodeScaleData)
|
||||||
|
|
||||||
static void cmp_node_scale_declare(NodeDeclarationBuilder &b)
|
static void cmp_node_scale_declare(NodeDeclarationBuilder &b)
|
||||||
{
|
{
|
||||||
b.add_input<decl::Color>("Image")
|
b.add_input<decl::Color>("Image")
|
||||||
|
@ -46,6 +48,12 @@ static void cmp_node_scale_declare(NodeDeclarationBuilder &b)
|
||||||
b.add_output<decl::Color>("Image");
|
b.add_output<decl::Color>("Image");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void node_composit_init_scale(bNodeTree * /*ntree*/, bNode *node)
|
||||||
|
{
|
||||||
|
NodeScaleData *data = MEM_cnew<NodeScaleData>(__func__);
|
||||||
|
node->storage = data;
|
||||||
|
}
|
||||||
|
|
||||||
static void node_composite_update_scale(bNodeTree *ntree, bNode *node)
|
static void node_composite_update_scale(bNodeTree *ntree, bNode *node)
|
||||||
{
|
{
|
||||||
bool use_xy_scale = ELEM(node->custom1, CMP_NODE_SCALE_RELATIVE, CMP_NODE_SCALE_ABSOLUTE);
|
bool use_xy_scale = ELEM(node->custom1, CMP_NODE_SCALE_RELATIVE, CMP_NODE_SCALE_ABSOLUTE);
|
||||||
|
@ -60,6 +68,7 @@ static void node_composite_update_scale(bNodeTree *ntree, bNode *node)
|
||||||
|
|
||||||
static void node_composit_buts_scale(uiLayout *layout, bContext * /*C*/, PointerRNA *ptr)
|
static void node_composit_buts_scale(uiLayout *layout, bContext * /*C*/, PointerRNA *ptr)
|
||||||
{
|
{
|
||||||
|
uiItemR(layout, ptr, "interpolation", UI_ITEM_R_SPLIT_EMPTY_NAME, "", ICON_NONE);
|
||||||
uiItemR(layout, ptr, "space", UI_ITEM_R_SPLIT_EMPTY_NAME, "", ICON_NONE);
|
uiItemR(layout, ptr, "space", UI_ITEM_R_SPLIT_EMPTY_NAME, "", ICON_NONE);
|
||||||
|
|
||||||
if (RNA_enum_get(ptr, "space") == CMP_NODE_SCALE_RENDER_SIZE) {
|
if (RNA_enum_get(ptr, "space") == CMP_NODE_SCALE_RENDER_SIZE) {
|
||||||
|
@ -93,7 +102,10 @@ class ScaleOperation : public NodeOperation {
|
||||||
const float3x3 transformation = math::from_loc_rot_scale<float3x3>(
|
const float3x3 transformation = math::from_loc_rot_scale<float3x3>(
|
||||||
translation, rotation, scale);
|
translation, rotation, scale);
|
||||||
|
|
||||||
transform(context(), input, output, transformation, input.get_realization_options());
|
RealizationOptions realization_options = input.get_realization_options();
|
||||||
|
realization_options.interpolation = get_interpolation();
|
||||||
|
|
||||||
|
transform(context(), input, output, transformation, realization_options);
|
||||||
}
|
}
|
||||||
|
|
||||||
float2 get_scale()
|
float2 get_scale()
|
||||||
|
@ -113,6 +125,21 @@ class ScaleOperation : public NodeOperation {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Interpolation get_interpolation()
|
||||||
|
{
|
||||||
|
switch (node_storage(bnode()).interpolation) {
|
||||||
|
case 0:
|
||||||
|
return Interpolation::Nearest;
|
||||||
|
case 1:
|
||||||
|
return Interpolation::Bilinear;
|
||||||
|
case 2:
|
||||||
|
return Interpolation::Bicubic;
|
||||||
|
}
|
||||||
|
|
||||||
|
BLI_assert_unreachable();
|
||||||
|
return Interpolation::Nearest;
|
||||||
|
}
|
||||||
|
|
||||||
/* Scale by the input factors. */
|
/* Scale by the input factors. */
|
||||||
float2 get_scale_relative()
|
float2 get_scale_relative()
|
||||||
{
|
{
|
||||||
|
@ -201,17 +228,17 @@ class ScaleOperation : public NodeOperation {
|
||||||
|
|
||||||
CMPNodeScaleMethod get_scale_method()
|
CMPNodeScaleMethod get_scale_method()
|
||||||
{
|
{
|
||||||
return (CMPNodeScaleMethod)bnode().custom1;
|
return (CMPNodeScaleMethod)node_storage(bnode()).space;
|
||||||
}
|
}
|
||||||
|
|
||||||
CMPNodeScaleRenderSizeMethod get_scale_render_size_method()
|
CMPNodeScaleRenderSizeMethod get_scale_render_size_method()
|
||||||
{
|
{
|
||||||
return (CMPNodeScaleRenderSizeMethod)bnode().custom2;
|
return (CMPNodeScaleRenderSizeMethod)node_storage(bnode()).frame_method;
|
||||||
}
|
}
|
||||||
|
|
||||||
float2 get_offset()
|
float2 get_offset()
|
||||||
{
|
{
|
||||||
return float2(bnode().custom3, bnode().custom4);
|
return float2(node_storage(bnode()).offset_x, node_storage(bnode()).offset_y);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -233,6 +260,7 @@ void register_node_type_cmp_scale()
|
||||||
ntype.draw_buttons = file_ns::node_composit_buts_scale;
|
ntype.draw_buttons = file_ns::node_composit_buts_scale;
|
||||||
ntype.updatefunc = file_ns::node_composite_update_scale;
|
ntype.updatefunc = file_ns::node_composite_update_scale;
|
||||||
ntype.get_compositor_operation = file_ns::get_compositor_operation;
|
ntype.get_compositor_operation = file_ns::get_compositor_operation;
|
||||||
|
ntype.initfunc = file_ns::node_composit_init_scale;
|
||||||
|
|
||||||
nodeRegisterType(&ntype);
|
nodeRegisterType(&ntype);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue