Make a copy of ImageFormatData that contains the effective color management settings, and pass that along to the various functions. This will make it possible to add more complex logic later. For compositing nodes, passing along view and display settings through many functions made it harder to add additional settings, so just get those from the scene now. Differential Revision: https://developer.blender.org/D14401
148 lines
6.4 KiB
C++
148 lines
6.4 KiB
C++
/* SPDX-License-Identifier: GPL-2.0-or-later
|
|
* Copyright 2011 Blender Foundation. */
|
|
|
|
#include "COM_OutputFileNode.h"
|
|
|
|
namespace blender::compositor {
|
|
|
|
OutputFileNode::OutputFileNode(bNode *editor_node) : Node(editor_node)
|
|
{
|
|
/* pass */
|
|
}
|
|
|
|
void OutputFileNode::add_input_sockets(OutputOpenExrMultiLayerOperation &operation) const
|
|
{
|
|
for (NodeInput *input : inputs_) {
|
|
NodeImageMultiFileSocket *sockdata =
|
|
(NodeImageMultiFileSocket *)input->get_bnode_socket()->storage;
|
|
/* NOTE: layer becomes an empty placeholder if the input is not linked. */
|
|
operation.add_layer(sockdata->layer, input->get_data_type(), input->is_linked());
|
|
}
|
|
}
|
|
|
|
void OutputFileNode::map_input_sockets(NodeConverter &converter,
|
|
OutputOpenExrMultiLayerOperation &operation) const
|
|
{
|
|
bool preview_added = false;
|
|
int index = 0;
|
|
for (NodeInput *input : inputs_) {
|
|
converter.map_input_socket(input, operation.get_input_socket(index++));
|
|
|
|
if (!preview_added) {
|
|
converter.add_node_input_preview(input);
|
|
preview_added = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
void OutputFileNode::add_preview_to_first_linked_input(NodeConverter &converter) const
|
|
{
|
|
NodeInput *first_socket = this->get_input_socket(0);
|
|
if (first_socket->is_linked()) {
|
|
converter.add_node_input_preview(first_socket);
|
|
}
|
|
}
|
|
|
|
void OutputFileNode::convert_to_operations(NodeConverter &converter,
|
|
const CompositorContext &context) const
|
|
{
|
|
NodeImageMultiFile *storage = (NodeImageMultiFile *)this->get_bnode()->storage;
|
|
const bool is_multiview = (context.get_render_data()->scemode & R_MULTIVIEW) != 0;
|
|
|
|
add_preview_to_first_linked_input(converter);
|
|
|
|
if (!context.is_rendering()) {
|
|
/* only output files when rendering a sequence -
|
|
* otherwise, it overwrites the output files just
|
|
* scrubbing through the timeline when the compositor updates.
|
|
*/
|
|
return;
|
|
}
|
|
|
|
if (storage->format.imtype == R_IMF_IMTYPE_MULTILAYER) {
|
|
const bool use_half_float = (storage->format.depth == R_IMF_CHAN_DEPTH_16);
|
|
/* single output operation for the multilayer file */
|
|
OutputOpenExrMultiLayerOperation *output_operation;
|
|
|
|
if (is_multiview && storage->format.views_format == R_IMF_VIEWS_MULTIVIEW) {
|
|
output_operation = new OutputOpenExrMultiLayerMultiViewOperation(context.get_scene(),
|
|
context.get_render_data(),
|
|
context.get_bnodetree(),
|
|
storage->base_path,
|
|
storage->format.exr_codec,
|
|
use_half_float,
|
|
context.get_view_name());
|
|
}
|
|
else {
|
|
output_operation = new OutputOpenExrMultiLayerOperation(context.get_scene(),
|
|
context.get_render_data(),
|
|
context.get_bnodetree(),
|
|
storage->base_path,
|
|
storage->format.exr_codec,
|
|
use_half_float,
|
|
context.get_view_name());
|
|
}
|
|
converter.add_operation(output_operation);
|
|
|
|
/* First add all inputs. Inputs are stored in a Vector and can be moved to a different
|
|
* memory address during this time. */
|
|
add_input_sockets(*output_operation);
|
|
/* After adding the sockets the memory addresses will stick. */
|
|
map_input_sockets(converter, *output_operation);
|
|
}
|
|
else { /* single layer format */
|
|
for (NodeInput *input : inputs_) {
|
|
if (input->is_linked()) {
|
|
NodeImageMultiFileSocket *sockdata =
|
|
(NodeImageMultiFileSocket *)input->get_bnode_socket()->storage;
|
|
ImageFormatData *format = (sockdata->use_node_format ? &storage->format :
|
|
&sockdata->format);
|
|
char path[FILE_MAX];
|
|
|
|
/* combine file path for the input */
|
|
BLI_join_dirfile(path, FILE_MAX, storage->base_path, sockdata->path);
|
|
|
|
NodeOperation *output_operation = nullptr;
|
|
|
|
if (is_multiview && format->views_format == R_IMF_VIEWS_MULTIVIEW) {
|
|
output_operation = new OutputOpenExrSingleLayerMultiViewOperation(
|
|
context.get_scene(),
|
|
context.get_render_data(),
|
|
context.get_bnodetree(),
|
|
input->get_data_type(),
|
|
format,
|
|
path,
|
|
context.get_view_name(),
|
|
sockdata->save_as_render);
|
|
}
|
|
else if ((!is_multiview) || (format->views_format == R_IMF_VIEWS_INDIVIDUAL)) {
|
|
output_operation = new OutputSingleLayerOperation(context.get_scene(),
|
|
context.get_render_data(),
|
|
context.get_bnodetree(),
|
|
input->get_data_type(),
|
|
format,
|
|
path,
|
|
context.get_view_name(),
|
|
sockdata->save_as_render);
|
|
}
|
|
else { /* R_IMF_VIEWS_STEREO_3D */
|
|
output_operation = new OutputStereoOperation(context.get_scene(),
|
|
context.get_render_data(),
|
|
context.get_bnodetree(),
|
|
input->get_data_type(),
|
|
format,
|
|
path,
|
|
sockdata->layer,
|
|
context.get_view_name(),
|
|
sockdata->save_as_render);
|
|
}
|
|
|
|
converter.add_operation(output_operation);
|
|
converter.map_input_socket(input, output_operation->get_input_socket(0));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
} // namespace blender::compositor
|