68 b.use_custom_socket_order();
69 b.allow_any_socket_order();
71 b.add_default_layout();
74 const bNode *node =
b.node_or_null();
75 if (!node_tree || !node) {
98 declaration = &
b.add_input(socket_type, item.
name, identifier);
113 data->save_as_render =
true;
138 bNode *destination_node,
139 const bNode *source_node)
143 __func__, source_storage);
146 destination_node->
storage = destination_storage;
169 const int frame_number,
173 const bool is_animation_render,
178 const std::string full_file_name = file_name + file_name_suffix;
188 if (!is_animation_render) {
219 const bool save_as_render =
RNA_boolean_get(node_or_item_pointer,
"save_as_render");
222 if (!save_as_render) {
261 layout->
label(image_path, ICON_FILE_IMAGE);
288 layout, directory, file_name, file_name_suffix,
view->name,
format, scene, node);
300 const bool is_multi_layer)
304 layout->
prop(item_pointer,
"socket_type",
UI_ITEM_NONE, std::nullopt, ICON_NONE);
306 layout->
prop(item_pointer,
"vector_socket_dimensions",
UI_ITEM_NONE, std::nullopt, ICON_NONE);
309 if (is_multi_layer) {
315 const bool override_node_format =
RNA_boolean_get(item_pointer,
"override_node_format");
319 PointerRNA *format_pointer = override_node_format ? &item_format_pointer : &node_format_pointer;
321 if (override_node_format) {
322 if (
uiLayout *panel = layout->
panel(context,
"item_format",
false,
IFACE_(
"Item Format"))) {
333 const bool is_multi_layer =
RNA_enum_get(&format_pointer,
"file_format") ==
336 if (
uiLayout *panel = layout->
panel(context,
"node_format",
false,
IFACE_(
"Node Format"))) {
337 format_layout(panel, context, &format_pointer, node_pointer);
340 const char *panel_name = is_multi_layer ?
IFACE_(
"Layers") :
IFACE_(
"Images");
341 if (
uiLayout *panel = layout->
panel(context,
"file_output_items",
false, panel_name)) {
345 context, panel,
tree, node);
348 item_layout(panel, context, node_pointer, item_pointer, is_multi_layer);
352 if (
uiLayout *panel = layout->
panel(context,
"output_paths",
true,
IFACE_(
"Output Paths"))) {
356 if (is_multi_layer) {
391 row.
text =
RPT_(
"Node Unsupported");
392 row.
tooltip =
TIP_(
"The File Output node is only supported for scene compositing");
393 row.
icon = ICON_ERROR;
426 if (
result.is_single_value()) {
436 node_storage(this->
bnode()).format;
439 node_storage(this->
bnode()).save_as_render;
442 &this->
context().get_render_data());
471 const char *layer_name)
481 format, layer_name, path_view, image_path);
507 if (size ==
int2(1)) {
518 const char *write_view = store_views_in_single_file ?
"" :
view;
520 format,
"", write_view, image_path);
530 const char *pass_view = store_views_in_single_file ?
view :
"";
548 const char *pass_name,
549 const char *view_name)
558 float *buffer =
nullptr;
559 if (
result.is_single_value()) {
563 if (this->
context().use_gpu()) {
578 if (
result.meta_data.is_cryptomatte_layer()) {
579 file_output.
add_pass(pass_name, view_name,
"rgba", buffer);
582 file_output.
add_pass(pass_name, view_name,
"RGBA", buffer);
592 file_output.
add_pass(pass_name, view_name,
"XYZ", buffer);
596 file_output.
add_pass(pass_name, view_name,
"XYZW", buffer);
599 file_output.
add_pass(pass_name, view_name,
"V", buffer);
602 file_output.
add_pass(pass_name, view_name,
"XY", buffer);
654 float *buffer =
nullptr;
655 if (this->
context().use_gpu()) {
667 file_output.
add_view(view_name, 4, buffer);
670 file_output.
add_view(view_name, 4, buffer);
679 file_output.
add_view(view_name, 3, buffer);
683 file_output.
add_view(view_name, 1, buffer);
702 "File Output Vector Buffer.");
705 for (
int i = 0;
i < 3;
i++) {
707 float3_image[pixel_index * 3 +
i] = float4_image[pixel_index * 4 +
i];
721 if (
result.meta_data.is_cryptomatte_layer()) {
724 cryptomatte_layer_name);
727 if (!
result.meta_data.cryptomatte.manifest.empty()) {
730 result.meta_data.cryptomatte.manifest);
733 if (!
result.meta_data.cryptomatte.hash.empty()) {
736 result.meta_data.cryptomatte.hash);
739 if (!
result.meta_data.cryptomatte.conversion.empty()) {
742 result.meta_data.cryptomatte.conversion);
747 const char *file_name_suffix,
756 this->
context().get_frame_number(),
765 nullptr,
RPT_ERROR,
"Invalid path template in File Output node. Skipping writing file.");
778 const char *file_name = node_storage(this->
bnode()).file_name;
779 return file_name ? file_name :
"";
784 return node_storage(this->
bnode()).directory;
817 if (!this->
context().render_context()) {
SpaceNode * CTX_wm_space_node(const bContext *C)
Scene * CTX_data_scene(const bContext *C)
const char * BKE_main_blendfile_path_from_global()
#define NODE_CLASS_OUTPUT
#define NODE_STORAGE_FUNCS(StorageT)
#define CMP_NODE_OUTPUT_FILE
std::string BKE_path_template_error_to_string(const blender::bke::path_templates::Error &error, blender::StringRef path)
void BKE_add_template_variables_for_render_path(blender::bke::path_templates::VariableMap &variables, const Scene &scene)
void BKE_add_template_variables_general(blender::bke::path_templates::VariableMap &variables, const ID *path_owner_id)
void BKE_add_template_variables_for_node(blender::bke::path_templates::VariableMap &variables, const bNode &owning_node)
void BKE_report(ReportList *reports, eReportType type, const char *message)
int BKE_scene_multiview_num_views_get(const RenderData *rd)
bool BKE_scene_multiview_is_render_view_active(const RenderData *rd, const SceneRenderView *srv)
const char * BKE_scene_multiview_view_suffix_get(const RenderData *rd, const char *viewname)
#define BLI_assert_unreachable()
#define LISTBASE_FOREACH(type, var, list)
size_t BLI_path_append(char *__restrict dst, size_t dst_maxncpy, const char *__restrict file) ATTR_NONNULL(1
bool BLI_path_make_safe_filename(char *filename) ATTR_NONNULL(1)
bool BLI_path_frame(char *path, size_t path_maxncpy, int frame, int digits) ATTR_NONNULL(1)
char * BLI_strdup(const char *str) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) ATTR_MALLOC
char * BLI_strdup_null(const char *str) ATTR_WARN_UNUSED_RESULT ATTR_MALLOC
char * STRNCPY(char(&dst)[N], const char *src)
void BLO_read_string(BlendDataReader *reader, char **ptr_p)
void BLO_write_string(BlendWriter *writer, const char *data_ptr)
@ MEDIA_TYPE_MULTI_LAYER_IMAGE
@ R_IMF_IMTYPE_MULTILAYER
@ GPU_BARRIER_TEXTURE_UPDATE
void GPU_memory_barrier(GPUBarrier barrier)
size_t GPU_texture_component_len(blender::gpu::TextureFormat format)
blender::gpu::TextureFormat GPU_texture_format(const blender::gpu::Texture *texture)
void * GPU_texture_read(blender::gpu::Texture *texture, eGPUDataFormat data_format, int mip_level)
Read Guarded memory(de)allocation.
#define NOD_REGISTER_NODE(REGISTER_FUNC)
void uiTemplateImageSettings(uiLayout *layout, bContext *C, PointerRNA *imfptr, bool color_management, const char *panel_idname=nullptr)
void uiTemplateImageFormatViews(uiLayout *layout, PointerRNA *imfptr, PointerRNA *ptr)
@ UI_ITEM_R_SPLIT_EMPTY_NAME
BMesh const char void * data
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
void append(const T &value)
void fill_assign_n(const void *value, void *dst, int64_t n) const
const CPPType * type() const
constexpr const char * data() const
constexpr const char * c_str() const
virtual StringRef get_view_name() const
virtual const RenderData & get_render_data() const
virtual RenderContext * render_context() const
void add_view(const char *view_name)
void add_pass(const char *pass_name, const char *view_name, const char *channels, float *buffer)
void add_meta_data(std::string key, std::string value)
const bNode & bnode() const
NodeOperation(Context &context, DNode node)
Context & context() const
Result & get_input(StringRef identifier) const
virtual Domain compute_domain()
FileOutput & get_file_output(std::string path, ImageFormatData format, int2 size, bool save_as_render)
const Domain & domain() const
BaseSocketDeclarationBuilder & compositor_realization_mode(CompositorInputRealizationMode value)
BaseSocketDeclarationBuilder & structure_type(StructureType structure_type)
BaseSocketDeclarationBuilder & socket_name_ptr(PointerRNA ptr, StringRef property_name)
bool is_animation_render()
void execute_multi_layer()
Domain compute_domain() override
float * inflate_result(const Result &result, const int2 size)
void execute_single_layer_multi_view_exr(const Result &result, const ImageFormatData &format, const char *layer_name)
StringRefNull get_directory()
StringRefNull get_file_name()
void add_pass_for_result(FileOutput &file_output, const Result &result, const char *pass_name, const char *view_name)
void execute_single_layer()
Vector< path_templates::Error > get_image_path(const ImageFormatData &format, const char *file_name_suffix, const char *view, char *r_image_path)
void add_meta_data_for_result(FileOutput &file_output, const Result &result, const char *name)
void add_view_for_result(FileOutput &file_output, const Result &result, const char *view_name)
float * float4_to_float3_image(int2 size, float *float4_image)
bool is_multi_view_scene()
NodeOperation(Context &context, DNode node)
float length(VecOp< float, D >) RET
void * MEM_callocN(size_t len, const char *str)
void * MEM_malloc_arrayN(size_t len, size_t size, const char *str)
void * MEM_dupallocN(const void *vmemh)
void MEM_freeN(void *vmemh)
static void error(const char *str)
StringRef BKE_cryptomatte_extract_layer_name(StringRef render_pass_name)
std::string BKE_cryptomatte_meta_data_key(StringRef layer_name, StringRefNull key_name)
void node_register_type(bNodeType &ntype)
void node_type_storage(bNodeType &ntype, std::optional< StringRefNull > storagename, void(*freefunc)(bNode *node), void(*copyfunc)(bNodeTree *dest_ntree, bNode *dest_node, const bNode *src_node))
void parallel_for(const int2 range, const Function &function)
static void node_operators()
static void format_layout(uiLayout *layout, bContext *context, PointerRNA *format_pointer, PointerRNA *node_or_item_pointer)
static void node_blend_write(const bNodeTree &, const bNode &node, BlendWriter &writer)
static bool node_insert_link(bke::NodeInsertLinkParams ¶ms)
static void node_register()
static void node_layout(uiLayout *layout, bContext *, PointerRNA *node_pointer)
static Vector< path_templates::Error > compute_image_path(const StringRefNull directory, const StringRefNull file_name, const StringRefNull file_name_suffix, const char *view, const int frame_number, const ImageFormatData &format, const Scene &scene, const bNode &node, const bool is_animation_render, char *r_image_path)
static void node_extra_info(NodeExtraInfoParams ¶meters)
static void node_declare(NodeDeclarationBuilder &b)
static void output_paths_layout(uiLayout *layout, bContext *context, const StringRefNull file_name_suffix, const bNode &node, const ImageFormatData &format)
static void item_layout(uiLayout *layout, bContext *context, PointerRNA *node_pointer, PointerRNA *item_pointer, const bool is_multi_layer)
static void node_blend_read(bNodeTree &, bNode &node, BlendDataReader &reader)
static void node_init(const bContext *C, PointerRNA *node_pointer)
static void node_copy_storage(bNodeTree *, bNode *destination_node, const bNode *source_node)
static void node_layout_ex(uiLayout *layout, bContext *context, PointerRNA *node_pointer)
static NodeOperation * get_compositor_operation(Context &context, DNode node)
static void node_free_storage(bNode *node)
static void output_path_layout(uiLayout *layout, const StringRefNull directory, const StringRefNull file_name, const StringRefNull file_name_suffix, const char *view, const ImageFormatData &format, const Scene &scene, const bNode &node)
void make_common_operators()
static void draw_items_list_with_operators(const bContext *C, uiLayout *layout, const bNodeTree &tree, const bNode &node)
static void draw_active_item_props(const bNodeTree &tree, const bNode &node, const FunctionRef< void(PointerRNA *item_ptr)> draw_item)
void blend_write(BlendWriter *writer, const bNode &node)
void destruct_array(bNode &node)
void blend_read_data(BlendDataReader *reader, bNode &node)
void copy_array(const bNode &src_node, bNode &dst_node)
bool try_add_item_via_any_extend_socket(bNodeTree &ntree, bNode &extend_node, bNode &storage_node, bNodeLink &link, const std::optional< StringRef > socket_identifier=std::nullopt, typename Accessor::ItemT **r_new_item=nullptr)
CompositorInputRealizationMode
VecBase< int32_t, 2 > int2
VecBase< float, 2 > float2
void cmp_node_type_base(blender::bke::bNodeType *ntype, std::string idname, const std::optional< int16_t > legacy_type)
PointerRNA RNA_pointer_get(PointerRNA *ptr, const char *name)
bool RNA_boolean_get(PointerRNA *ptr, const char *name)
int RNA_enum_get(PointerRNA *ptr, const char *name)
char override_node_format
char vector_socket_dimensions
NodeCompositorFileOutputItem * items
NodeBlendWriteFunction blend_write_storage_content
std::string ui_description
NodeBlendDataReadFunction blend_data_read_storage_content
NodeGetCompositorOperationFunction get_compositor_operation
void(* draw_buttons_ex)(uiLayout *, bContext *C, PointerRNA *ptr)
NodeExtraInfoFunction get_extra_info
const char * enum_name_legacy
void(* draw_buttons)(uiLayout *, bContext *C, PointerRNA *ptr)
bool(* insert_link)(NodeInsertLinkParams ¶ms)
NodeDeclareFunction declare
void(* register_operators)()
void(* initfunc_api)(const bContext *C, PointerRNA *ptr)
static std::string validate_name(const StringRef name)
static StructRNA * item_srna
static std::string socket_identifier_for_item(const NodeCompositorFileOutputItem &item)
static void blend_write_item(BlendWriter *writer, const ItemT &item)
static void blend_read_data_item(BlendDataReader *reader, ItemT &item)
NodeCompositorFileOutputItem ItemT
void use_property_decorate_set(bool is_sep)
PanelLayout panel(const bContext *C, blender::StringRef idname, bool default_closed)
void label(blender::StringRef name, int icon)
uiLayout & column(bool align)
void use_property_split_set(bool value)
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)