Blender V5.0
node_composite_relative_to_pixel.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2025 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
5#include "BLI_assert.h"
6#include "BLI_math_vector.hh"
8
10#include "UI_resources.hh"
11
12#include "NOD_rna_define.hh"
13
14#include "COM_node_operation.hh"
16
18
20
22{
23 b.add_input<decl::Vector>("Value", "Vector Value")
24 .subtype(PROP_FACTOR)
25 .dimensions(2)
26 .default_value({0.0f, 0.0f})
27 .min(0.0f)
28 .max(1.0f)
29 .description(
30 "A value that is relative to the image size and needs to be converted to be in pixels");
31 b.add_input<decl::Float>("Value", "Float Value")
32 .default_value(0.0f)
34 .min(0.0f)
35 .max(1.0f)
36 .description(
37 "A value that is relative to the image size and needs to be converted to be in pixels");
38 b.add_input<decl::Color>("Image")
39 .compositor_realization_mode(CompositorInputRealizationMode::None)
40 .structure_type(StructureType::Dynamic);
41
42 b.add_output<decl::Float>("Value", "Float Value");
43 b.add_output<decl::Vector>("Value", "Vector Value").dimensions(2);
44}
45
51
52static void node_update(bNodeTree *ntree, bNode *node)
53{
54 const auto data_type = CMPNodeRelativeToPixelDataType(node->custom1);
55 const auto reference_dimension = CMPNodeRelativeToPixelReferenceDimension(node->custom2);
56
57 bNodeSocket *float_input = bke::node_find_socket(*node, SOCK_IN, "Float Value");
59 *ntree, *float_input, data_type == CMP_NODE_RELATIVE_TO_PIXEL_DATA_TYPE_FLOAT);
60
61 bNodeSocket *vector_input = bke::node_find_socket(*node, SOCK_IN, "Vector Value");
63 *ntree, *vector_input, data_type == CMP_NODE_RELATIVE_TO_PIXEL_DATA_TYPE_VECTOR);
64
65 /* The float output doesn't exist if the reference is per dimension, since each dimension can be
66 * different. */
67 const bool is_per_dimension = reference_dimension ==
69 bNodeSocket *float_output = bke::node_find_socket(*node, SOCK_OUT, "Float Value");
71 *ntree,
72 *float_output,
73 data_type == CMP_NODE_RELATIVE_TO_PIXEL_DATA_TYPE_FLOAT && !is_per_dimension);
74
75 /* The vector output exist if the reference is per dimension even if the data type is float,
76 * since each dimension can be different. */
77 bNodeSocket *vector_output = bke::node_find_socket(*node, SOCK_OUT, "Vector Value");
79 *ntree,
80 *vector_output,
81 data_type == CMP_NODE_RELATIVE_TO_PIXEL_DATA_TYPE_VECTOR || is_per_dimension);
82}
83
84static void node_rna(StructRNA *srna)
85{
86 static const EnumPropertyItem data_type_items[] = {
87 {CMP_NODE_RELATIVE_TO_PIXEL_DATA_TYPE_FLOAT, "FLOAT", ICON_NONE, "Float", "Float value"},
88 {CMP_NODE_RELATIVE_TO_PIXEL_DATA_TYPE_VECTOR, "VECTOR", ICON_NONE, "Vector", "Vector value"},
89 {0, nullptr, 0, nullptr, nullptr},
90 };
91
93 "data_type",
94 "Data Type",
95 "The type of data",
96 data_type_items,
99 nullptr,
100 true);
101
102 static const EnumPropertyItem reference_dimension_items[] = {
104 "PER_DIMENSION",
105 ICON_NONE,
106 "Per Dimension",
107 "The value is relative to each of the dimensions of the image independently"},
109 "X",
110 ICON_NONE,
111 "X",
112 "The value is relative to the X dimension of the image"},
114 "Y",
115 ICON_NONE,
116 "Y",
117 "The value is relative to the Y dimension of the image"},
119 "Greater",
120 ICON_NONE,
121 "Greater",
122 "The value is relative to the greater dimension of the image"},
124 "Smaller",
125 ICON_NONE,
126 "Smaller",
127 "The value is relative to the smaller dimension of the image"},
129 "Diagonal",
130 ICON_NONE,
131 "Diagonal",
132 "The value is relative to the diagonal of the image"},
133 {0, nullptr, 0, nullptr, nullptr},
134 };
135
137 srna,
138 "reference_dimension",
139 "Reference Dimension",
140 "Defines the dimension of the image that the relative value is in reference to",
141 reference_dimension_items,
144 nullptr,
145 true);
146}
147
148static void node_layout(uiLayout *layout, bContext * /*C*/, PointerRNA *ptr)
149{
150 layout->prop(ptr, "data_type", UI_ITEM_NONE, "", ICON_NONE);
151 layout->prop(ptr, "reference_dimension", UI_ITEM_NONE, "", ICON_NONE);
152}
153
154using namespace blender::compositor;
155
157 public:
159 {
160 InputDescriptor &image_descriptor = this->get_input_descriptor("Image");
161 image_descriptor.skip_type_conversion = true;
162 }
163
164 void execute() override
165 {
166 const float2 input_value = this->get_input_value();
167 const float2 reference_size = this->compute_reference_size();
168
169 const float2 value_in_pixels = input_value * reference_size;
170
171 /* The float output doesn't exist if the reference is per dimension, since each dimension can
172 * be different. */
173 const bool is_per_dimension = this->get_reference_dimension() ==
175 if (this->get_data_type() == CMP_NODE_RELATIVE_TO_PIXEL_DATA_TYPE_FLOAT && !is_per_dimension) {
176 Result &output_float_value = this->get_result("Float Value");
177 if (output_float_value.should_compute()) {
178 output_float_value.allocate_single_value();
179 /* Both values of the float2 are identical in this case, so just set the x component. */
180 output_float_value.set_single_value(value_in_pixels.x);
181 }
182 }
183
184 /* The vector output exist if the reference is per dimension even if the data type is float,
185 * since each dimension can be different. */
186 if (this->get_data_type() == CMP_NODE_RELATIVE_TO_PIXEL_DATA_TYPE_VECTOR || is_per_dimension) {
187 Result &output_vector_value = this->get_result("Vector Value");
188 if (output_vector_value.should_compute()) {
189 output_vector_value.allocate_single_value();
190 output_vector_value.set_single_value(value_in_pixels);
191 }
192 }
193 }
194
196 {
198 return float2(this->get_input("Float Value").get_single_value_default(0.0f));
199 }
200 return this->get_input("Vector Value").get_single_value_default(float2(0.0f));
201 }
202
204 {
205 const Result &input_image = this->get_input("Image");
206 if (input_image.is_single_value()) {
207 return float2(1.0f);
208 }
209
211 this->context(), input_image.domain());
212 const float2 image_size = float2(domain.size);
213 switch (this->get_reference_dimension()) {
215 return image_size;
217 return float2(image_size.x);
219 return float2(image_size.y);
221 return float2(math::reduce_max(image_size));
223 return float2(math::reduce_min(image_size));
225 return float2(math::length(image_size));
226 }
227
229 return float2(1.0f);
230 }
231
236
241};
242
244{
245 return new RelativeToPixelOperation(context, node);
246}
247
248static void register_node()
249{
250 static blender::bke::bNodeType ntype;
251
252 cmp_node_type_base(&ntype, "CompositorNodeRelativeToPixel");
253 ntype.ui_name = "Relative To Pixel";
254 ntype.ui_description =
255 "Converts values that are relative to the image size to be in terms of pixels";
257 ntype.declare = node_declare;
258 ntype.initfunc = node_init;
259 ntype.updatefunc = node_update;
262
264
265 node_rna(ntype.rna_ext.srna);
266}
268
269} // namespace blender::nodes::node_composite_relative_to_pixel_cc
#define NODE_CLASS_CONVERTER
Definition BKE_node.hh:453
#define BLI_assert_unreachable()
Definition BLI_assert.h:93
CMPNodeRelativeToPixelDataType
@ CMP_NODE_RELATIVE_TO_PIXEL_DATA_TYPE_VECTOR
@ CMP_NODE_RELATIVE_TO_PIXEL_DATA_TYPE_FLOAT
@ SOCK_OUT
@ SOCK_IN
CMPNodeRelativeToPixelReferenceDimension
@ CMP_NODE_RELATIVE_TO_PIXEL_REFERENCE_DIMENSION_DIAGONAL
@ CMP_NODE_RELATIVE_TO_PIXEL_REFERENCE_DIMENSION_PER_DIMENSION
@ CMP_NODE_RELATIVE_TO_PIXEL_REFERENCE_DIMENSION_Y
@ CMP_NODE_RELATIVE_TO_PIXEL_REFERENCE_DIMENSION_X
@ CMP_NODE_RELATIVE_TO_PIXEL_REFERENCE_DIMENSION_GREATER
@ CMP_NODE_RELATIVE_TO_PIXEL_REFERENCE_DIMENSION_SMALLER
#define NOD_REGISTER_NODE(REGISTER_FUNC)
#define NOD_inline_enum_accessors(member)
@ PROP_FACTOR
Definition RNA_types.hh:251
#define UI_ITEM_NONE
NodeOperation(Context &context, DNode node)
Result & get_result(StringRef identifier)
Definition operation.cc:39
Result & get_input(StringRef identifier) const
Definition operation.cc:138
InputDescriptor & get_input_descriptor(StringRef identifier)
Definition operation.cc:158
static Domain compute_realized_transformation_domain(Context &context, const Domain &domain, const bool realize_translation=false)
T get_single_value_default(const T &default_value) const
void set_single_value(const T &value)
const Domain & domain() const
bool is_single_value() const
Definition result.cc:758
bNodeSocket * node_find_socket(bNode &node, eNodeSocketInOut in_out, StringRef identifier)
Definition node.cc:2532
void node_register_type(bNodeType &ntype)
Definition node.cc:2416
void node_set_socket_availability(bNodeTree &ntree, bNodeSocket &sock, bool is_available)
Definition node.cc:4739
T reduce_max(const VecBase< T, Size > &a)
T length(const VecBase< T, Size > &a)
T reduce_min(const VecBase< T, Size > &a)
static void node_layout(uiLayout *layout, bContext *, PointerRNA *ptr)
static NodeOperation * get_compositor_operation(Context &context, DNode node)
PropertyRNA * RNA_def_node_enum(StructRNA *srna, const char *identifier, const char *ui_name, const char *ui_description, const EnumPropertyItem *static_items, const EnumRNAAccessors accessors, std::optional< int > default_value, const EnumPropertyItemFunc item_func, const bool allow_animation)
VecBase< float, 2 > float2
void cmp_node_type_base(blender::bke::bNodeType *ntype, std::string idname, const std::optional< int16_t > legacy_type)
#define min(a, b)
Definition sort.cc:36
StructRNA * srna
int16_t custom1
int16_t custom2
Defines a node type.
Definition BKE_node.hh:238
std::string ui_description
Definition BKE_node.hh:244
NodeGetCompositorOperationFunction get_compositor_operation
Definition BKE_node.hh:348
void(* initfunc)(bNodeTree *ntree, bNode *node)
Definition BKE_node.hh:289
void(* draw_buttons)(uiLayout *, bContext *C, PointerRNA *ptr)
Definition BKE_node.hh:259
NodeDeclareFunction declare
Definition BKE_node.hh:362
void(* updatefunc)(bNodeTree *ntree, bNode *node)
Definition BKE_node.hh:281
void prop(PointerRNA *ptr, PropertyRNA *prop, int index, int value, eUI_Item_Flag flag, std::optional< blender::StringRef > name_opt, int icon, std::optional< blender::StringRef > placeholder=std::nullopt)
PointerRNA * ptr
Definition wm_files.cc:4238