/* * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * Copyright 2012, Blender Foundation. */ #include "COM_MaskOperation.h" #include "MEM_guardedalloc.h" #include "BLI_listbase.h" #include "BLI_math.h" #include "BKE_lib_id.h" #include "BKE_mask.h" MaskOperation::MaskOperation() { this->addOutputSocket(DataType::Value); this->m_mask = nullptr; this->m_maskWidth = 0; this->m_maskHeight = 0; this->m_maskWidthInv = 0.0f; this->m_maskHeightInv = 0.0f; this->m_frame_shutter = 0.0f; this->m_frame_number = 0; this->m_rasterMaskHandleTot = 1; memset(this->m_rasterMaskHandles, 0, sizeof(this->m_rasterMaskHandles)); } void MaskOperation::initExecution() { if (this->m_mask && this->m_rasterMaskHandles[0] == nullptr) { if (this->m_rasterMaskHandleTot == 1) { this->m_rasterMaskHandles[0] = BKE_maskrasterize_handle_new(); BKE_maskrasterize_handle_init(this->m_rasterMaskHandles[0], this->m_mask, this->m_maskWidth, this->m_maskHeight, true, true, this->m_do_feather); } else { /* make a throw away copy of the mask */ const float frame = (float)this->m_frame_number - this->m_frame_shutter; const float frame_step = (this->m_frame_shutter * 2.0f) / this->m_rasterMaskHandleTot; float frame_iter = frame; Mask *mask_temp = (Mask *)BKE_id_copy_ex( nullptr, &this->m_mask->id, nullptr, LIB_ID_COPY_LOCALIZE | LIB_ID_COPY_NO_ANIMDATA); /* trick so we can get unkeyed edits to display */ { MaskLayer *masklay; MaskLayerShape *masklay_shape; for (masklay = (MaskLayer *)mask_temp->masklayers.first; masklay; masklay = masklay->next) { masklay_shape = BKE_mask_layer_shape_verify_frame(masklay, this->m_frame_number); BKE_mask_layer_shape_from_mask(masklay, masklay_shape); } } for (unsigned int i = 0; i < this->m_rasterMaskHandleTot; i++) { this->m_rasterMaskHandles[i] = BKE_maskrasterize_handle_new(); /* re-eval frame info */ BKE_mask_evaluate(mask_temp, frame_iter, true); BKE_maskrasterize_handle_init(this->m_rasterMaskHandles[i], mask_temp, this->m_maskWidth, this->m_maskHeight, true, true, this->m_do_feather); frame_iter += frame_step; } BKE_id_free(nullptr, &mask_temp->id); } } } void MaskOperation::deinitExecution() { for (unsigned int i = 0; i < this->m_rasterMaskHandleTot; i++) { if (this->m_rasterMaskHandles[i]) { BKE_maskrasterize_handle_free(this->m_rasterMaskHandles[i]); this->m_rasterMaskHandles[i] = nullptr; } } } void MaskOperation::determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]) { if (this->m_maskWidth == 0 || this->m_maskHeight == 0) { NodeOperation::determineResolution(resolution, preferredResolution); } else { unsigned int nr[2]; nr[0] = this->m_maskWidth; nr[1] = this->m_maskHeight; NodeOperation::determineResolution(resolution, nr); resolution[0] = this->m_maskWidth; resolution[1] = this->m_maskHeight; } } void MaskOperation::executePixelSampled(float output[4], float x, float y, PixelSampler /*sampler*/) { const float xy[2] = { (x * this->m_maskWidthInv) + this->m_mask_px_ofs[0], (y * this->m_maskHeightInv) + this->m_mask_px_ofs[1], }; if (this->m_rasterMaskHandleTot == 1) { if (this->m_rasterMaskHandles[0]) { output[0] = BKE_maskrasterize_handle_sample(this->m_rasterMaskHandles[0], xy); } else { output[0] = 0.0f; } } else { /* In case loop below fails. */ output[0] = 0.0f; for (unsigned int i = 0; i < this->m_rasterMaskHandleTot; i++) { if (this->m_rasterMaskHandles[i]) { output[0] += BKE_maskrasterize_handle_sample(this->m_rasterMaskHandles[i], xy); } } /* until we get better falloff */ output[0] /= this->m_rasterMaskHandleTot; } }