diff --git a/release/scripts/startup/bl_ui/space_view3d.py b/release/scripts/startup/bl_ui/space_view3d.py index d7fe7ebbbf7..b525ab922d2 100644 --- a/release/scripts/startup/bl_ui/space_view3d.py +++ b/release/scripts/startup/bl_ui/space_view3d.py @@ -2584,13 +2584,13 @@ class VIEW3D_PT_background_image(Panel): rowsub = col.row() rowsub.prop(bg, "frame_method", expand=True) - if bg.view_axis != 'CAMERA': - col.prop(bg, "size") - row = col.row(align=True) row.prop(bg, "offset_x", text="X") row.prop(bg, "offset_y", text="Y") + if bg.view_axis != 'CAMERA': + col.prop(bg, "size") + class VIEW3D_PT_transform_orientations(Panel): bl_space_type = 'VIEW_3D' diff --git a/source/blender/compositor/nodes/COM_ScaleNode.cpp b/source/blender/compositor/nodes/COM_ScaleNode.cpp index 85d5644484b..870ed8f2484 100644 --- a/source/blender/compositor/nodes/COM_ScaleNode.cpp +++ b/source/blender/compositor/nodes/COM_ScaleNode.cpp @@ -65,8 +65,12 @@ void ScaleNode::convertToOperations(ExecutionSystem *graph, CompositorContext *c case CMP_SCALE_RENDERPERCENT: { const RenderData *data = &context->getScene()->r; ScaleFixedSizeOperation *operation = new ScaleFixedSizeOperation(); + + /* framing options */ operation->setIsAspect((bnode->custom2 & CMP_SCALE_RENDERSIZE_FRAME_ASPECT) != 0); operation->setIsCrop((bnode->custom2 & CMP_SCALE_RENDERSIZE_FRAME_CROP) != 0); + operation->setOffset(bnode->custom3, bnode->custom4); + operation->setNewWidth(data->xsch * data->size / 100.0f); operation->setNewHeight(data->ysch * data->size / 100.0f); inputSocket->relinkConnections(operation->getInputSocket(0), 0, graph); diff --git a/source/blender/compositor/operations/COM_ScaleOperation.cpp b/source/blender/compositor/operations/COM_ScaleOperation.cpp index aea4da920a0..45e846998af 100644 --- a/source/blender/compositor/operations/COM_ScaleOperation.cpp +++ b/source/blender/compositor/operations/COM_ScaleOperation.cpp @@ -191,6 +191,21 @@ void ScaleFixedSizeOperation::initExecution() this->relX = inputOperation->getWidth() / (float)this->newWidth; this->relY = inputOperation->getHeight() / (float)this->newHeight; + + /* *** all the options below are for a fairly special case - camera framing *** */ + if (this->offsetX != 0.0f || this->offsetY != 0.0f) { + this->is_offset = true; + + if (this->newWidth > this->newHeight) { + this->offsetX *= this->newWidth; + this->offsetY *= this->newWidth; + } + else { + this->offsetX *= this->newHeight; + this->offsetY *= this->newHeight; + } + } + if (this->is_aspect) { /* apply aspect from clip */ const float w_src = inputOperation->getWidth(); @@ -203,9 +218,6 @@ void ScaleFixedSizeOperation::initExecution() const float asp_src = w_src / h_src; const float asp_dst = w_dst / h_dst; - this->offsetX = 0.0f; - this->offsetY = 0.0f; - if (fabsf(asp_src - asp_dst) >= FLT_EPSILON) { if ((asp_src > asp_dst) == (this->is_crop == true)) { /* fit X */ @@ -219,9 +231,11 @@ void ScaleFixedSizeOperation::initExecution() this->relY /= div; this->offsetY = ((h_src - (h_src * div)) / (h_src / h_dst)) / 2.0f; } - } + this->is_offset = true; + } } + /* *** end framing options *** */ } void ScaleFixedSizeOperation::deinitExecution() @@ -236,7 +250,7 @@ void ScaleFixedSizeOperation::executePixel(float *color, float x, float y, Pixel sampler = COM_PS_BICUBIC; #endif - if (this->is_aspect) { + if (this->is_offset) { float nx = ((x - this->offsetX) * relX); float ny = ((y - this->offsetY) * relY); this->inputOperation->read(color, nx, ny, sampler, inputBuffers); diff --git a/source/blender/compositor/operations/COM_ScaleOperation.h b/source/blender/compositor/operations/COM_ScaleOperation.h index 3964a5e2f71..7089f6c10a4 100644 --- a/source/blender/compositor/operations/COM_ScaleOperation.h +++ b/source/blender/compositor/operations/COM_ScaleOperation.h @@ -69,6 +69,9 @@ class ScaleFixedSizeOperation : public NodeOperation { float offsetY; bool is_aspect; bool is_crop; + /* set from other properties on initialization, + * check if we need to apply offset */ + bool is_offset; public: ScaleFixedSizeOperation(); bool determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output); @@ -79,8 +82,9 @@ public: void deinitExecution(); void setNewWidth(int width) { this->newWidth = width; } void setNewHeight(int height) { this->newHeight = height; } - void setIsAspect(int is_aspect) { this->is_aspect = is_aspect; } - void setIsCrop(int is_crop) { this->is_crop = is_crop; } + void setIsAspect(bool is_aspect) { this->is_aspect = is_aspect; } + void setIsCrop(bool is_crop) { this->is_crop = is_crop; } + void setOffset(float x, float y) { this->offsetX = x; this->offsetY = y; } }; #endif diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c index e48dd39022e..8aa56823baf 100644 --- a/source/blender/editors/space_node/drawnode.c +++ b/source/blender/editors/space_node/drawnode.c @@ -2020,7 +2020,11 @@ static void node_composit_buts_scale(uiLayout *layout, bContext *UNUSED(C), Poin uiItemR(layout, ptr, "space", 0, "", ICON_NONE); if (RNA_enum_get(ptr, "space") == CMP_SCALE_RENDERPERCENT) { + uiLayout *row; uiItemR(layout, ptr, "frame_method", UI_ITEM_R_EXPAND, NULL, ICON_NONE); + row = uiLayoutRow(layout, TRUE); + uiItemR(row, ptr, "offset_x", 0, "X", ICON_NONE); + uiItemR(row, ptr, "offset_y", 0, "Y", ICON_NONE); } } diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c index 9567226f722..683a49a7690 100644 --- a/source/blender/makesrna/intern/rna_nodetree.c +++ b/source/blender/makesrna/intern/rna_nodetree.c @@ -2106,6 +2106,16 @@ static void def_cmp_scale(StructRNA *srna) RNA_def_property_enum_items(prop, space_frame_items); RNA_def_property_ui_text(prop, "Frame Method", "How the image fits in the camera frame"); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); + + prop = RNA_def_property(srna, "offset_x", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "custom3"); + RNA_def_property_ui_text(prop, "X Offset", "Offset image horizontally (factor of image size)"); + RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); + + prop = RNA_def_property(srna, "offset_y", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "custom4"); + RNA_def_property_ui_text(prop, "Y Offset", "Offset image vertically (factor of image size)"); + RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); } static void def_cmp_rotate(StructRNA *srna)