Listing the "Blender Foundation" as copyright holder implied the Blender Foundation holds copyright to files which may include work from many developers. While keeping copyright on headers makes sense for isolated libraries, Blender's own code may be refactored or moved between files in a way that makes the per file copyright holders less meaningful. Copyright references to the "Blender Foundation" have been replaced with "Blender Authors", with the exception of `./extern/` since these this contains libraries which are more isolated, any changed to license headers there can be handled on a case-by-case basis. Some directories in `./intern/` have also been excluded: - `./intern/cycles/` it's own `AUTHORS` file is planned. - `./intern/opensubdiv/`. An "AUTHORS" file has been added, using the chromium projects authors file as a template. Design task: #110784 Ref !110783.
157 lines
5.0 KiB
C++
157 lines
5.0 KiB
C++
/* SPDX-FileCopyrightText: 2011 Blender Authors
|
|
*
|
|
* SPDX-License-Identifier: GPL-2.0-or-later */
|
|
|
|
#include "COM_TranslateOperation.h"
|
|
|
|
namespace blender::compositor {
|
|
|
|
TranslateOperation::TranslateOperation() : TranslateOperation(DataType::Color) {}
|
|
TranslateOperation::TranslateOperation(DataType data_type, ResizeMode resize_mode)
|
|
{
|
|
this->add_input_socket(data_type, resize_mode);
|
|
this->add_input_socket(DataType::Value, ResizeMode::None);
|
|
this->add_input_socket(DataType::Value, ResizeMode::None);
|
|
this->add_output_socket(data_type);
|
|
this->set_canvas_input_index(0);
|
|
input_operation_ = nullptr;
|
|
input_xoperation_ = nullptr;
|
|
input_yoperation_ = nullptr;
|
|
is_delta_set_ = false;
|
|
factor_x_ = 1.0f;
|
|
factor_y_ = 1.0f;
|
|
this->x_extend_mode_ = MemoryBufferExtend::Clip;
|
|
this->y_extend_mode_ = MemoryBufferExtend::Clip;
|
|
}
|
|
|
|
void TranslateOperation::init_execution()
|
|
{
|
|
input_operation_ = this->get_input_socket_reader(0);
|
|
input_xoperation_ = this->get_input_socket_reader(1);
|
|
input_yoperation_ = this->get_input_socket_reader(2);
|
|
}
|
|
|
|
void TranslateOperation::deinit_execution()
|
|
{
|
|
input_operation_ = nullptr;
|
|
input_xoperation_ = nullptr;
|
|
input_yoperation_ = nullptr;
|
|
}
|
|
|
|
void TranslateOperation::execute_pixel_sampled(float output[4],
|
|
float x,
|
|
float y,
|
|
PixelSampler /*sampler*/)
|
|
{
|
|
ensure_delta();
|
|
|
|
float original_xpos = x - this->getDeltaX();
|
|
float original_ypos = y - this->getDeltaY();
|
|
|
|
input_operation_->read_sampled(output, original_xpos, original_ypos, PixelSampler::Bilinear);
|
|
}
|
|
|
|
bool TranslateOperation::determine_depending_area_of_interest(rcti *input,
|
|
ReadBufferOperation *read_operation,
|
|
rcti *output)
|
|
{
|
|
rcti new_input;
|
|
|
|
ensure_delta();
|
|
|
|
new_input.xmin = input->xmin - this->getDeltaX();
|
|
new_input.xmax = input->xmax - this->getDeltaX();
|
|
new_input.ymin = input->ymin - this->getDeltaY();
|
|
new_input.ymax = input->ymax - this->getDeltaY();
|
|
|
|
return NodeOperation::determine_depending_area_of_interest(&new_input, read_operation, output);
|
|
}
|
|
|
|
void TranslateOperation::setFactorXY(float factorX, float factorY)
|
|
{
|
|
factor_x_ = factorX;
|
|
factor_y_ = factorY;
|
|
}
|
|
|
|
void TranslateOperation::set_wrapping(int wrapping_type)
|
|
{
|
|
switch (wrapping_type) {
|
|
case CMP_NODE_WRAP_X:
|
|
x_extend_mode_ = MemoryBufferExtend::Repeat;
|
|
break;
|
|
case CMP_NODE_WRAP_Y:
|
|
y_extend_mode_ = MemoryBufferExtend::Repeat;
|
|
break;
|
|
case CMP_NODE_WRAP_XY:
|
|
x_extend_mode_ = MemoryBufferExtend::Repeat;
|
|
y_extend_mode_ = MemoryBufferExtend::Repeat;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
void TranslateOperation::get_area_of_interest(const int input_idx,
|
|
const rcti &output_area,
|
|
rcti &r_input_area)
|
|
{
|
|
if (input_idx == 0) {
|
|
ensure_delta();
|
|
r_input_area = output_area;
|
|
if (x_extend_mode_ == MemoryBufferExtend::Clip) {
|
|
const int delta_x = this->getDeltaX();
|
|
BLI_rcti_translate(&r_input_area, -delta_x, 0);
|
|
}
|
|
if (y_extend_mode_ == MemoryBufferExtend::Clip) {
|
|
const int delta_y = this->getDeltaY();
|
|
BLI_rcti_translate(&r_input_area, 0, -delta_y);
|
|
}
|
|
}
|
|
else {
|
|
r_input_area = output_area;
|
|
}
|
|
}
|
|
|
|
void TranslateOperation::update_memory_buffer_partial(MemoryBuffer *output,
|
|
const rcti &area,
|
|
Span<MemoryBuffer *> inputs)
|
|
{
|
|
MemoryBuffer *input = inputs[0];
|
|
const int delta_x = this->getDeltaX();
|
|
const int delta_y = this->getDeltaY();
|
|
for (int y = area.ymin; y < area.ymax; y++) {
|
|
float *out = output->get_elem(area.xmin, y);
|
|
for (int x = area.xmin; x < area.xmax; x++) {
|
|
const int input_x = x - delta_x;
|
|
const int input_y = y - delta_y;
|
|
input->read(out, input_x, input_y, x_extend_mode_, y_extend_mode_);
|
|
out += output->elem_stride;
|
|
}
|
|
}
|
|
}
|
|
|
|
TranslateCanvasOperation::TranslateCanvasOperation()
|
|
: TranslateOperation(DataType::Color, ResizeMode::None)
|
|
{
|
|
}
|
|
|
|
void TranslateCanvasOperation::determine_canvas(const rcti &preferred_area, rcti &r_area)
|
|
{
|
|
const bool determined =
|
|
get_input_socket(IMAGE_INPUT_INDEX)->determine_canvas(preferred_area, r_area);
|
|
if (determined) {
|
|
NodeOperationInput *x_socket = get_input_socket(X_INPUT_INDEX);
|
|
NodeOperationInput *y_socket = get_input_socket(Y_INPUT_INDEX);
|
|
rcti unused = COM_AREA_NONE;
|
|
x_socket->determine_canvas(r_area, unused);
|
|
y_socket->determine_canvas(r_area, unused);
|
|
|
|
ensure_delta();
|
|
const float delta_x = x_extend_mode_ == MemoryBufferExtend::Clip ? getDeltaX() : 0.0f;
|
|
const float delta_y = y_extend_mode_ == MemoryBufferExtend::Clip ? getDeltaY() : 0.0f;
|
|
BLI_rcti_translate(&r_area, delta_x, delta_y);
|
|
}
|
|
}
|
|
|
|
} // namespace blender::compositor
|