diff options
8 files changed, 167 insertions, 10 deletions
diff --git a/source/blender/compositor/nodes/COM_TranslateNode.cpp b/source/blender/compositor/nodes/COM_TranslateNode.cpp index c805f8f8baa..1d21b23fa74 100644 --- a/source/blender/compositor/nodes/COM_TranslateNode.cpp +++ b/source/blender/compositor/nodes/COM_TranslateNode.cpp @@ -37,10 +37,15 @@ void TranslateNode::convertToOperations(ExecutionSystem *graph, CompositorContex InputSocket *inputYSocket = this->getInputSocket(2); OutputSocket *outputSocket = this->getOutputSocket(0); TranslateOperation *operation = new TranslateOperation(); - + + bNode *editorNode = this->getbNode(); + NodeTranslateData *data = (NodeTranslateData *)editorNode->storage; + operation->setWrapping(data->wrap_axis); + inputSocket->relinkConnections(operation->getInputSocket(0), 0, graph); inputXSocket->relinkConnections(operation->getInputSocket(1), 1, graph); inputYSocket->relinkConnections(operation->getInputSocket(2), 2, graph); outputSocket->relinkConnections(operation->getOutputSocket(0)); graph->addOperation(operation); } + diff --git a/source/blender/compositor/operations/COM_TranslateOperation.cpp b/source/blender/compositor/operations/COM_TranslateOperation.cpp index 761f55a1455..c34931471c7 100644 --- a/source/blender/compositor/operations/COM_TranslateOperation.cpp +++ b/source/blender/compositor/operations/COM_TranslateOperation.cpp @@ -15,9 +15,10 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * - * Contributor: - * Jeroen Bakker + * Contributor: + * Jeroen Bakker * Monique Dewanchand + * Thomas Beck (plasmasolutions.de) */ #include "COM_TranslateOperation.h" @@ -40,6 +41,12 @@ void TranslateOperation::initExecution() this->m_inputXOperation = this->getInputSocketReader(1); this->m_inputYOperation = this->getInputSocketReader(2); + ensureDelta(); + + //Calculate the relative offset once per execution, no need to do this per pixel + this->m_relativeOffsetX = fmodf(this->getDeltaX(), this->getWidth()); + this->m_relativeOffsetY = fmodf(this->getDeltaY(), this->getHeight()); + } void TranslateOperation::deinitExecution() @@ -53,18 +60,113 @@ void TranslateOperation::deinitExecution() void TranslateOperation::executePixel(float output[4], float x, float y, PixelSampler sampler) { ensureDelta(); - this->m_inputOperation->read(output, x - this->getDeltaX(), y - this->getDeltaY(), sampler); + + float originalXPos = x - this->getDeltaX(); + float originalYPos = y - this->getDeltaY(); + + switch(m_wrappingType) { + case 0: + //Intentionally empty, originalXPos and originalYPos have been set before + break; + case 1: + // wrap only on the x-axis + originalXPos = this->getWrappedOriginalXPos(x); + break; + case 2: + // wrap only on the y-axis + originalYPos = this->getWrappedOriginalYPos(y); + break; + case 3: + // wrap on both + originalXPos = this->getWrappedOriginalXPos(x); + originalYPos = this->getWrappedOriginalYPos(y); + break; + } + + this->m_inputOperation->read(output, originalXPos , originalYPos, sampler); + } bool TranslateOperation::determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output) { - ensureDelta(); rcti newInput; - - newInput.xmax = input->xmax - this->getDeltaX(); + + ensureDelta(); + newInput.xmin = input->xmin - this->getDeltaX(); - newInput.ymax = input->ymax - this->getDeltaY(); + newInput.xmax = input->xmax - this->getDeltaX(); newInput.ymin = input->ymin - this->getDeltaY(); - + newInput.ymax = input->ymax - this->getDeltaY(); + + if (m_wrappingType == 1 || m_wrappingType == 3){ + // wrap only on the x-axis if tile is wrapping + newInput.xmin = getWrappedOriginalXPos(input->xmin); + newInput.xmax = getWrappedOriginalXPos(input->xmax); + if(newInput.xmin > newInput.xmax){ + newInput.xmin = 0; + newInput.xmax = this->getWidth(); + } + } + if(m_wrappingType == 2 || m_wrappingType == 3) { + // wrap only on the y-axis if tile is wrapping + newInput.ymin = getWrappedOriginalYPos(input->ymin); + newInput.ymax = getWrappedOriginalYPos(input->ymax); + if (newInput.ymin > newInput.ymax){ + newInput.ymin = 0; + newInput.ymax = this->getHeight(); + } + } + + return NodeOperation::determineDependingAreaOfInterest(&newInput, readOperation, output); } + +void TranslateOperation::setWrapping(char wrapping_type) +{ + m_wrappingType = wrapping_type; +} + +float TranslateOperation::getWrappedOriginalXPos(float x) +{ + float originalXPos = 0; + + // Positive offset: Append image data from the left + if ( this->m_relativeOffsetX > 0 ) { + if ( x < this->m_relativeOffsetX ) + originalXPos = this->getWidth() - this->m_relativeOffsetX + x; + else + originalXPos = x - this->m_relativeOffsetX; + } else { + // Negative offset: Append image data from the right + if (x < (this->getWidth() + this->m_relativeOffsetX)) + originalXPos = x - this->m_relativeOffsetX; + else + originalXPos = x - (this->getWidth() + this->m_relativeOffsetX); + } + + while (originalXPos < 0) originalXPos += this->m_width; + return fmodf(originalXPos, this->getWidth()); +} + + +float TranslateOperation::getWrappedOriginalYPos(float y) +{ + float originalYPos = 0; + + // Positive offset: Append image data from the bottom + if ( this->m_relativeOffsetY > 0 ) { + if ( y < this->m_relativeOffsetY ) + originalYPos = this->getHeight()- this->m_relativeOffsetY + y; + else + originalYPos = y - this->m_relativeOffsetY; + } else { + // Negative offset: Append image data from the top + if (y < (this->getHeight() + this->m_relativeOffsetY)) + originalYPos = y - this->m_relativeOffsetY; + else + originalYPos = y - (this->getHeight() + this->m_relativeOffsetY); + } + + while (originalYPos < 0) originalYPos += this->m_height; + return fmodf(originalYPos, this->getHeight()); +} diff --git a/source/blender/compositor/operations/COM_TranslateOperation.h b/source/blender/compositor/operations/COM_TranslateOperation.h index faaadb1ced2..d93f09e2ab6 100644 --- a/source/blender/compositor/operations/COM_TranslateOperation.h +++ b/source/blender/compositor/operations/COM_TranslateOperation.h @@ -33,6 +33,9 @@ private: float m_deltaX; float m_deltaY; bool m_isDeltaSet; + float m_relativeOffsetX; + float m_relativeOffsetY; + char m_wrappingType; public: TranslateOperation(); bool determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output); @@ -54,6 +57,10 @@ public: this->m_isDeltaSet = true; } } + + void setWrapping(char wrapping_type); + float getWrappedOriginalXPos(float x); + float getWrappedOriginalYPos(float y); }; #endif diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c index 1ec77bf58ed..d2bb51981de 100644 --- a/source/blender/editors/space_node/drawnode.c +++ b/source/blender/editors/space_node/drawnode.c @@ -2379,6 +2379,11 @@ static void node_composit_buts_stabilize2d(uiLayout *layout, bContext *C, Pointe uiItemR(layout, ptr, "filter_type", 0, "", ICON_NONE); } +static void node_composit_buts_translate(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) +{ + uiItemR(layout, ptr, "wrap_axis", 0, NULL, ICON_NONE); +} + static void node_composit_buts_transform(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { uiItemR(layout, ptr, "filter_type", 0, "", ICON_NONE); @@ -2931,6 +2936,9 @@ static void node_composit_set_butfunc(bNodeType *ntype) case CMP_NODE_TRANSFORM: ntype->uifunc = node_composit_buts_transform; break; + case CMP_NODE_TRANSLATE: + ntype->uifunc = node_composit_buts_translate; + break; case CMP_NODE_MOVIEDISTORTION: ntype->uifunc = node_composit_buts_moviedistortion; break; diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h index a05ff66e683..83d884be1cc 100644 --- a/source/blender/makesdna/DNA_node_types.h +++ b/source/blender/makesdna/DNA_node_types.h @@ -711,6 +711,11 @@ typedef struct NodeTrackPosData { char track_name[64]; } NodeTrackPosData; +typedef struct NodeTranslateData { + char wrap_axis, pad[7]; +} NodeTranslateData; + + typedef struct NodeShaderScript { int mode; int flag; diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c index fe5b6e15f44..f5e3867cfe4 100644 --- a/source/blender/makesrna/intern/rna_nodetree.c +++ b/source/blender/makesrna/intern/rna_nodetree.c @@ -4225,6 +4225,28 @@ static void def_cmp_trackpos(StructRNA *srna) RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); } +static void def_cmp_translate(StructRNA *srna) +{ + static EnumPropertyItem translate_items[] = { + {0, "NONE", 0, "None", "No wrapping on x and y"}, + {1, "XAXIS", 0, "X-Axis", "Wrap all pixels on the x-Axis"}, + {2, "YAXIS", 0, "Y-Axis", "Wrap all pixels on the y-Axis"}, + {3, "BOTH", 0, "Both axes", "Wrap all pixels on the both axes"}, + {0, NULL, 0, NULL, NULL} + }; + + PropertyRNA *prop; + + RNA_def_struct_sdna_from(srna, "NodeTranslateData", "storage"); + + prop = RNA_def_property(srna, "wrap_axis", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "wrap_axis"); + RNA_def_property_enum_items(prop, translate_items); + RNA_def_property_ui_text(prop, "Wrapping", "Wrap image on a specific axis"); + RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); +} + + /* -- Texture Nodes --------------------------------------------------------- */ static void def_tex_output(StructRNA *srna) diff --git a/source/blender/makesrna/intern/rna_nodetree_types.h b/source/blender/makesrna/intern/rna_nodetree_types.h index 46f2306f284..d6e0ce2f11a 100644 --- a/source/blender/makesrna/intern/rna_nodetree_types.h +++ b/source/blender/makesrna/intern/rna_nodetree_types.h @@ -127,7 +127,7 @@ DefNode( CompositorNode, CMP_NODE_R_LAYERS, def_cmp_render_layers, "R_LAY DefNode( CompositorNode, CMP_NODE_COMPOSITE, 0, "COMPOSITE", Composite, "Composite", "" ) DefNode( CompositorNode, CMP_NODE_OUTPUT_FILE, def_cmp_output_file, "OUTPUT_FILE", OutputFile, "File Output", "" ) DefNode( CompositorNode, CMP_NODE_TEXTURE, def_texture, "TEXTURE", Texture, "Texture", "" ) -DefNode( CompositorNode, CMP_NODE_TRANSLATE, 0, "TRANSLATE", Translate, "Translate", "" ) +DefNode( CompositorNode, CMP_NODE_TRANSLATE, def_cmp_translate, "TRANSLATE", Translate, "Translate", "" ) DefNode( CompositorNode, CMP_NODE_ZCOMBINE, def_cmp_zcombine, "ZCOMBINE", Zcombine, "Z Combine", "" ) DefNode( CompositorNode, CMP_NODE_COMBRGBA, 0, "COMBRGBA", CombRGBA, "Combine RGBA", "" ) DefNode( CompositorNode, CMP_NODE_DILATEERODE, def_cmp_dilate_erode, "DILATEERODE", DilateErode, "Dilate/Erode", "" ) diff --git a/source/blender/nodes/composite/nodes/node_composite_translate.c b/source/blender/nodes/composite/nodes/node_composite_translate.c index 7c7c6304d27..60b32563569 100644 --- a/source/blender/nodes/composite/nodes/node_composite_translate.c +++ b/source/blender/nodes/composite/nodes/node_composite_translate.c @@ -46,6 +46,12 @@ static bNodeSocketTemplate cmp_node_translate_out[] = { { -1, 0, "" } }; +static void node_composit_init_translate(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp)) +{ + NodeTranslateData *data = MEM_callocN(sizeof(NodeTranslateData), "node translate data"); + node->storage = data; +} + void register_node_type_cmp_translate(bNodeTreeType *ttype) { static bNodeType ntype; @@ -53,6 +59,8 @@ void register_node_type_cmp_translate(bNodeTreeType *ttype) node_type_base(ttype, &ntype, CMP_NODE_TRANSLATE, "Translate", NODE_CLASS_DISTORT, NODE_OPTIONS); node_type_socket_templates(&ntype, cmp_node_translate_in, cmp_node_translate_out); node_type_size(&ntype, 140, 100, 320); + node_type_init(&ntype, node_composit_init_translate); + node_type_storage(&ntype, "NodeTranslateData", node_free_standard_storage, node_copy_standard_storage); nodeRegisterType(ttype, &ntype); } |