Border for compositor viewer node feature
This adds border option to compositor, which affects on a backdrop and viewer nodes, which is useful for faster previews and tweaks. Final compositing still happens for the whole frame, but if it'll be needed it's not so difficult to support it as well. To use border there's Ctrl-B shortcut in the compositor editor, which i used to define region you want to restrict compositing to. There's also "Viewer Border" option in the N-panel in case you'll want to disable border compositing. Some areas could be cleaned a bit, like ideally it shall not be viewer image clearing in viewer_border_update RNA callback, but currently it's not so much clear how to make it the same fast as simple memset and glue it somehow to compositor. Will think of nicer solution a bit later.
This commit is contained in:
@@ -254,6 +254,7 @@ class NODE_PT_quality(bpy.types.Panel):
|
|||||||
col.prop(tree, "use_opencl")
|
col.prop(tree, "use_opencl")
|
||||||
col.prop(tree, "use_groupnode_buffer")
|
col.prop(tree, "use_groupnode_buffer")
|
||||||
col.prop(tree, "two_pass")
|
col.prop(tree, "two_pass")
|
||||||
|
col.prop(tree, "use_viewer_border")
|
||||||
col.prop(snode, "show_highlight")
|
col.prop(snode, "show_highlight")
|
||||||
col.prop(snode, "use_hidden_preview")
|
col.prop(snode, "use_hidden_preview")
|
||||||
|
|
||||||
|
|||||||
@@ -60,6 +60,7 @@ ExecutionGroup::ExecutionGroup()
|
|||||||
this->m_openCL = false;
|
this->m_openCL = false;
|
||||||
this->m_singleThreaded = false;
|
this->m_singleThreaded = false;
|
||||||
this->m_chunksFinished = 0;
|
this->m_chunksFinished = 0;
|
||||||
|
BLI_rcti_init(&this->m_viewerBorder, 0, 0, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
CompositorPriority ExecutionGroup::getRenderPriotrity()
|
CompositorPriority ExecutionGroup::getRenderPriotrity()
|
||||||
@@ -196,6 +197,7 @@ void ExecutionGroup::determineResolution(unsigned int resolution[2])
|
|||||||
resolution[0] = operation->getWidth();
|
resolution[0] = operation->getWidth();
|
||||||
resolution[1] = operation->getHeight();
|
resolution[1] = operation->getHeight();
|
||||||
this->setResolution(resolution);
|
this->setResolution(resolution);
|
||||||
|
BLI_rcti_init(&this->m_viewerBorder, 0, this->m_width, 0, this->m_height);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExecutionGroup::determineNumberOfChunks()
|
void ExecutionGroup::determineNumberOfChunks()
|
||||||
@@ -207,8 +209,10 @@ void ExecutionGroup::determineNumberOfChunks()
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
const float chunkSizef = this->m_chunkSize;
|
const float chunkSizef = this->m_chunkSize;
|
||||||
this->m_numberOfXChunks = ceil(this->m_width / chunkSizef);
|
const int border_width = BLI_rcti_size_x(&this->m_viewerBorder);
|
||||||
this->m_numberOfYChunks = ceil(this->m_height / chunkSizef);
|
const int border_height = BLI_rcti_size_y(&this->m_viewerBorder);
|
||||||
|
this->m_numberOfXChunks = ceil(border_width / chunkSizef);
|
||||||
|
this->m_numberOfYChunks = ceil(border_height / chunkSizef);
|
||||||
this->m_numberOfChunks = this->m_numberOfXChunks * this->m_numberOfYChunks;
|
this->m_numberOfChunks = this->m_numberOfXChunks * this->m_numberOfYChunks;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -245,6 +249,9 @@ void ExecutionGroup::execute(ExecutionSystem *graph)
|
|||||||
chunkorder = viewer->getChunkOrder();
|
chunkorder = viewer->getChunkOrder();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const int border_width = BLI_rcti_size_x(&this->m_viewerBorder);
|
||||||
|
const int border_height = BLI_rcti_size_y(&this->m_viewerBorder);
|
||||||
|
|
||||||
switch (chunkorder) {
|
switch (chunkorder) {
|
||||||
case COM_TO_RANDOM:
|
case COM_TO_RANDOM:
|
||||||
for (index = 0; index < 2 * this->m_numberOfChunks; index++) {
|
for (index = 0; index < 2 * this->m_numberOfChunks; index++) {
|
||||||
@@ -258,14 +265,14 @@ void ExecutionGroup::execute(ExecutionSystem *graph)
|
|||||||
case COM_TO_CENTER_OUT:
|
case COM_TO_CENTER_OUT:
|
||||||
{
|
{
|
||||||
ChunkOrderHotspot *hotspots[1];
|
ChunkOrderHotspot *hotspots[1];
|
||||||
hotspots[0] = new ChunkOrderHotspot(this->m_width * centerX, this->m_height * centerY, 0.0f);
|
hotspots[0] = new ChunkOrderHotspot(border_width * centerX, border_height * centerY, 0.0f);
|
||||||
rcti rect;
|
rcti rect;
|
||||||
ChunkOrder *chunkOrders = (ChunkOrder *)MEM_mallocN(sizeof(ChunkOrder) * this->m_numberOfChunks, __func__);
|
ChunkOrder *chunkOrders = (ChunkOrder *)MEM_mallocN(sizeof(ChunkOrder) * this->m_numberOfChunks, __func__);
|
||||||
for (index = 0; index < this->m_numberOfChunks; index++) {
|
for (index = 0; index < this->m_numberOfChunks; index++) {
|
||||||
determineChunkRect(&rect, index);
|
determineChunkRect(&rect, index);
|
||||||
chunkOrders[index].setChunkNumber(index);
|
chunkOrders[index].setChunkNumber(index);
|
||||||
chunkOrders[index].setX(rect.xmin);
|
chunkOrders[index].setX(rect.xmin - this->m_viewerBorder.xmin);
|
||||||
chunkOrders[index].setY(rect.ymin);
|
chunkOrders[index].setY(rect.ymin - this->m_viewerBorder.ymin);
|
||||||
chunkOrders[index].determineDistance(hotspots, 1);
|
chunkOrders[index].determineDistance(hotspots, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -281,10 +288,10 @@ void ExecutionGroup::execute(ExecutionSystem *graph)
|
|||||||
case COM_TO_RULE_OF_THIRDS:
|
case COM_TO_RULE_OF_THIRDS:
|
||||||
{
|
{
|
||||||
ChunkOrderHotspot *hotspots[9];
|
ChunkOrderHotspot *hotspots[9];
|
||||||
unsigned int tx = this->m_width / 6;
|
unsigned int tx = border_width / 6;
|
||||||
unsigned int ty = this->m_height / 6;
|
unsigned int ty = border_height / 6;
|
||||||
unsigned int mx = this->m_width / 2;
|
unsigned int mx = border_width / 2;
|
||||||
unsigned int my = this->m_height / 2;
|
unsigned int my = border_height / 2;
|
||||||
unsigned int bx = mx + 2 * tx;
|
unsigned int bx = mx + 2 * tx;
|
||||||
unsigned int by = my + 2 * ty;
|
unsigned int by = my + 2 * ty;
|
||||||
|
|
||||||
@@ -303,8 +310,8 @@ void ExecutionGroup::execute(ExecutionSystem *graph)
|
|||||||
for (index = 0; index < this->m_numberOfChunks; index++) {
|
for (index = 0; index < this->m_numberOfChunks; index++) {
|
||||||
determineChunkRect(&rect, index);
|
determineChunkRect(&rect, index);
|
||||||
chunkOrders[index].setChunkNumber(index);
|
chunkOrders[index].setChunkNumber(index);
|
||||||
chunkOrders[index].setX(rect.xmin);
|
chunkOrders[index].setX(rect.xmin - this->m_viewerBorder.xmin);
|
||||||
chunkOrders[index].setY(rect.ymin);
|
chunkOrders[index].setY(rect.ymin - this->m_viewerBorder.ymin);
|
||||||
chunkOrders[index].determineDistance(hotspots, 9);
|
chunkOrders[index].determineDistance(hotspots, 9);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -431,13 +438,18 @@ void ExecutionGroup::finalizeChunkExecution(int chunkNumber, MemoryBuffer **memo
|
|||||||
|
|
||||||
inline void ExecutionGroup::determineChunkRect(rcti *rect, const unsigned int xChunk, const unsigned int yChunk) const
|
inline void ExecutionGroup::determineChunkRect(rcti *rect, const unsigned int xChunk, const unsigned int yChunk) const
|
||||||
{
|
{
|
||||||
|
const int border_width = BLI_rcti_size_x(&this->m_viewerBorder);
|
||||||
|
const int border_height = BLI_rcti_size_y(&this->m_viewerBorder);
|
||||||
|
|
||||||
if (this->m_singleThreaded) {
|
if (this->m_singleThreaded) {
|
||||||
BLI_rcti_init(rect, 0, this->m_width, 0, this->m_height);
|
BLI_rcti_init(rect, this->m_viewerBorder.xmin, border_width, this->m_viewerBorder.ymin, border_height);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
const unsigned int minx = xChunk * this->m_chunkSize;
|
const unsigned int minx = xChunk * this->m_chunkSize + this->m_viewerBorder.xmin;
|
||||||
const unsigned int miny = yChunk * this->m_chunkSize;
|
const unsigned int miny = yChunk * this->m_chunkSize + this->m_viewerBorder.ymin;
|
||||||
BLI_rcti_init(rect, minx, min(minx + this->m_chunkSize, this->m_width), miny, min(miny + this->m_chunkSize, this->m_height));
|
const unsigned int width = min((unsigned int) this->m_viewerBorder.xmax, this->m_width);
|
||||||
|
const unsigned int height = min((unsigned int) this->m_viewerBorder.ymax, this->m_height);
|
||||||
|
BLI_rcti_init(rect, min(minx, this->m_width), min(minx + this->m_chunkSize, width), min(miny, this->m_height), min(miny + this->m_chunkSize, height));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -472,9 +484,9 @@ bool ExecutionGroup::scheduleAreaWhenPossible(ExecutionSystem *graph, rcti *area
|
|||||||
float chunkSizef = this->m_chunkSize;
|
float chunkSizef = this->m_chunkSize;
|
||||||
|
|
||||||
int indexx, indexy;
|
int indexx, indexy;
|
||||||
int minxchunk = floor(area->xmin / chunkSizef);
|
int minxchunk = floor((area->xmin - this->m_viewerBorder.xmin) / chunkSizef);
|
||||||
int maxxchunk = ceil((area->xmax - 1) / chunkSizef);
|
int maxxchunk = ceil((area->xmax - 1) / chunkSizef);
|
||||||
int minychunk = floor(area->ymin / chunkSizef);
|
int minychunk = floor((area->ymin - this->m_viewerBorder.ymin) / chunkSizef);
|
||||||
int maxychunk = ceil((area->ymax - 1) / chunkSizef);
|
int maxychunk = ceil((area->ymax - 1) / chunkSizef);
|
||||||
minxchunk = max(minxchunk, 0);
|
minxchunk = max(minxchunk, 0);
|
||||||
minychunk = max(minychunk, 0);
|
minychunk = max(minychunk, 0);
|
||||||
@@ -574,3 +586,13 @@ bool ExecutionGroup::isOpenCL()
|
|||||||
{
|
{
|
||||||
return this->m_openCL;
|
return this->m_openCL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ExecutionGroup::setViewerBorder(float xmin, float xmax, float ymin, float ymax)
|
||||||
|
{
|
||||||
|
NodeOperation *operation = this->getOutputNodeOperation();
|
||||||
|
|
||||||
|
if (operation->isViewerOperation()) {
|
||||||
|
BLI_rcti_init(&this->m_viewerBorder, xmin * this->m_width, xmax * this->m_width,
|
||||||
|
ymin * this->m_height, ymax * this->m_height);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -161,6 +161,12 @@ private:
|
|||||||
* @see openCL
|
* @see openCL
|
||||||
*/
|
*/
|
||||||
bool m_initialized;
|
bool m_initialized;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief denotes boundary for border compositing
|
||||||
|
* @note measured in pixel space
|
||||||
|
*/
|
||||||
|
rcti m_viewerBorder;
|
||||||
|
|
||||||
// methods
|
// methods
|
||||||
/**
|
/**
|
||||||
@@ -395,6 +401,12 @@ public:
|
|||||||
*/
|
*/
|
||||||
CompositorPriority getRenderPriotrity();
|
CompositorPriority getRenderPriotrity();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief set border for viewer operation
|
||||||
|
* @note all the coordinates are assumed to be in normalized space
|
||||||
|
*/
|
||||||
|
void setViewerBorder(float xmin, float xmax, float ymin, float ymax);
|
||||||
|
|
||||||
#ifdef WITH_CXX_GUARDEDALLOC
|
#ifdef WITH_CXX_GUARDEDALLOC
|
||||||
MEM_CXX_CLASS_ALLOC_FUNCS("COM:ExecutionGroup")
|
MEM_CXX_CLASS_ALLOC_FUNCS("COM:ExecutionGroup")
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -78,11 +78,22 @@ ExecutionSystem::ExecutionSystem(RenderData *rd, bNodeTree *editingtree, bool re
|
|||||||
this->groupOperations(); /* group operations in ExecutionGroups */
|
this->groupOperations(); /* group operations in ExecutionGroups */
|
||||||
unsigned int index;
|
unsigned int index;
|
||||||
unsigned int resolution[2];
|
unsigned int resolution[2];
|
||||||
|
|
||||||
|
rctf *viewer_border = &editingtree->viewer_border;
|
||||||
|
bool use_viewer_border = (editingtree->flag & NTREE_VIEWER_BORDER) &&
|
||||||
|
viewer_border->xmin < viewer_border->xmax &&
|
||||||
|
viewer_border->ymin < viewer_border->ymax;
|
||||||
|
|
||||||
for (index = 0; index < this->m_groups.size(); index++) {
|
for (index = 0; index < this->m_groups.size(); index++) {
|
||||||
resolution[0] = 0;
|
resolution[0] = 0;
|
||||||
resolution[1] = 0;
|
resolution[1] = 0;
|
||||||
ExecutionGroup *executionGroup = this->m_groups[index];
|
ExecutionGroup *executionGroup = this->m_groups[index];
|
||||||
executionGroup->determineResolution(resolution);
|
executionGroup->determineResolution(resolution);
|
||||||
|
|
||||||
|
if (use_viewer_border) {
|
||||||
|
executionGroup->setViewerBorder(viewer_border->xmin, viewer_border->xmax,
|
||||||
|
viewer_border->ymin, viewer_border->ymax);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef COM_DEBUG
|
#ifdef COM_DEBUG
|
||||||
|
|||||||
@@ -3320,6 +3320,7 @@ void draw_nodespace_back_pix(const bContext *C, ARegion *ar, SpaceNode *snode)
|
|||||||
/** @note draw selected info on backdrop */
|
/** @note draw selected info on backdrop */
|
||||||
if (snode->edittree) {
|
if (snode->edittree) {
|
||||||
bNode *node = snode->edittree->nodes.first;
|
bNode *node = snode->edittree->nodes.first;
|
||||||
|
rctf *viewer_border = &snode->edittree->viewer_border;
|
||||||
while (node) {
|
while (node) {
|
||||||
if (node->flag & NODE_SELECT) {
|
if (node->flag & NODE_SELECT) {
|
||||||
if (node->typeinfo->uibackdropfunc) {
|
if (node->typeinfo->uibackdropfunc) {
|
||||||
@@ -3328,6 +3329,23 @@ void draw_nodespace_back_pix(const bContext *C, ARegion *ar, SpaceNode *snode)
|
|||||||
}
|
}
|
||||||
node = node->next;
|
node = node->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((snode->edittree->flag & NTREE_VIEWER_BORDER) &&
|
||||||
|
viewer_border->xmin < viewer_border->xmax &&
|
||||||
|
viewer_border->ymin < viewer_border->ymax)
|
||||||
|
{
|
||||||
|
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
|
||||||
|
setlinestyle(3);
|
||||||
|
cpack(0x4040FF);
|
||||||
|
|
||||||
|
glRectf(x + snode->zoom * viewer_border->xmin * ibuf->x,
|
||||||
|
y + snode->zoom * viewer_border->ymin * ibuf->y,
|
||||||
|
x + snode->zoom * viewer_border->xmax * ibuf->x,
|
||||||
|
y + snode->zoom * viewer_border->ymax * ibuf->y);
|
||||||
|
|
||||||
|
setlinestyle(0);
|
||||||
|
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
glMatrixMode(GL_PROJECTION);
|
glMatrixMode(GL_PROJECTION);
|
||||||
|
|||||||
@@ -73,6 +73,8 @@
|
|||||||
|
|
||||||
#include "GPU_material.h"
|
#include "GPU_material.h"
|
||||||
|
|
||||||
|
#include "IMB_imbuf_types.h"
|
||||||
|
|
||||||
#include "node_intern.h" /* own include */
|
#include "node_intern.h" /* own include */
|
||||||
|
|
||||||
#define USE_ESC_COMPO
|
#define USE_ESC_COMPO
|
||||||
@@ -2281,3 +2283,105 @@ void NODE_OT_shader_script_update(wmOperatorType *ot)
|
|||||||
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ********************** Viewer border ******************/
|
||||||
|
|
||||||
|
static void viewer_border_corner_to_backdrop(SpaceNode *snode, ARegion *ar, int x, int y,
|
||||||
|
int backdrop_width, int backdrop_height,
|
||||||
|
float *fx, float *fy)
|
||||||
|
{
|
||||||
|
float bufx, bufy;
|
||||||
|
|
||||||
|
bufx = backdrop_width * snode->zoom;
|
||||||
|
bufy = backdrop_height * snode->zoom;
|
||||||
|
|
||||||
|
*fx = (bufx > 0.0f ? ((float) x - 0.5f * ar->winx - snode->xof) / bufx + 0.5f : 0.0f);
|
||||||
|
*fy = (bufy > 0.0f ? ((float) y - 0.5f * ar->winy - snode->yof) / bufy + 0.5f : 0.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int viewer_border_exec(bContext *C, wmOperator *op)
|
||||||
|
{
|
||||||
|
Image *ima;
|
||||||
|
void *lock;
|
||||||
|
ImBuf *ibuf;
|
||||||
|
|
||||||
|
ED_preview_kill_jobs(C);
|
||||||
|
|
||||||
|
ima = BKE_image_verify_viewer(IMA_TYPE_COMPOSITE, "Viewer Node");
|
||||||
|
ibuf = BKE_image_acquire_ibuf(ima, NULL, &lock);
|
||||||
|
|
||||||
|
if (ibuf) {
|
||||||
|
ARegion *ar = CTX_wm_region(C);
|
||||||
|
SpaceNode *snode = CTX_wm_space_node(C);
|
||||||
|
bNodeTree *btree = snode->edittree;
|
||||||
|
rcti rect;
|
||||||
|
rctf rectf;
|
||||||
|
|
||||||
|
/* get border from operator */
|
||||||
|
WM_operator_properties_border_to_rcti(op, &rect);
|
||||||
|
|
||||||
|
/* convert border to unified space within backdrop image */
|
||||||
|
viewer_border_corner_to_backdrop(snode, ar, rect.xmin, rect.ymin, ibuf->x, ibuf->y,
|
||||||
|
&rectf.xmin, &rectf.ymin);
|
||||||
|
|
||||||
|
viewer_border_corner_to_backdrop(snode, ar, rect.xmax, rect.ymax, ibuf->x, ibuf->y,
|
||||||
|
&rectf.xmax, &rectf.ymax);
|
||||||
|
|
||||||
|
/* clamp coordinates */
|
||||||
|
rectf.xmin = max_ff(rectf.xmin, 0.0f);
|
||||||
|
rectf.ymin = max_ff(rectf.ymin, 0.0f);
|
||||||
|
rectf.xmax = min_ff(rectf.xmax, 1.0f);
|
||||||
|
rectf.ymax = min_ff(rectf.ymax, 1.0f);
|
||||||
|
|
||||||
|
if (rectf.xmin < rectf.xmax && rectf.ymin < rectf.ymax) {
|
||||||
|
btree->viewer_border = rectf;
|
||||||
|
|
||||||
|
if (rectf.xmin == 0.0f && rectf.ymin == 0.0f &&
|
||||||
|
rectf.xmax == 1.0f && rectf.ymax == 1.0f)
|
||||||
|
{
|
||||||
|
btree->flag &= ~NTREE_VIEWER_BORDER;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (ibuf->rect)
|
||||||
|
memset(ibuf->rect, 0, 4 * ibuf->x * ibuf->y);
|
||||||
|
|
||||||
|
if (ibuf->rect_float)
|
||||||
|
memset(ibuf->rect_float, 0, 4 * ibuf->x * ibuf->y * sizeof(float));
|
||||||
|
|
||||||
|
ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID;
|
||||||
|
|
||||||
|
btree->flag |= NTREE_VIEWER_BORDER;
|
||||||
|
}
|
||||||
|
|
||||||
|
snode_notify(C, snode);
|
||||||
|
WM_event_add_notifier(C, NC_NODE | ND_DISPLAY, NULL);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
btree->flag &= ~NTREE_VIEWER_BORDER;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BKE_image_release_ibuf(ima, ibuf, lock);
|
||||||
|
|
||||||
|
return OPERATOR_FINISHED;
|
||||||
|
}
|
||||||
|
|
||||||
|
void NODE_OT_viewer_border(wmOperatorType *ot)
|
||||||
|
{
|
||||||
|
/* identifiers */
|
||||||
|
ot->name = "Viewer Border";
|
||||||
|
ot->description = "Set the boundaries for viewer operations";
|
||||||
|
ot->idname = "NODE_OT_viewer_border";
|
||||||
|
|
||||||
|
/* api callbacks */
|
||||||
|
ot->invoke = WM_border_select_invoke;
|
||||||
|
ot->exec = viewer_border_exec;
|
||||||
|
ot->modal = WM_border_select_modal;
|
||||||
|
ot->cancel = WM_border_select_cancel;
|
||||||
|
ot->poll = composite_node_active;
|
||||||
|
|
||||||
|
/* flags */
|
||||||
|
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
||||||
|
|
||||||
|
/* properties */
|
||||||
|
WM_operator_properties_gesture_border(ot, TRUE);
|
||||||
|
}
|
||||||
|
|||||||
@@ -217,6 +217,8 @@ void NODE_OT_clipboard_paste(struct wmOperatorType *ot);
|
|||||||
|
|
||||||
void NODE_OT_shader_script_update(struct wmOperatorType *ot);
|
void NODE_OT_shader_script_update(struct wmOperatorType *ot);
|
||||||
|
|
||||||
|
void NODE_OT_viewer_border(struct wmOperatorType *ot);
|
||||||
|
|
||||||
extern const char *node_context_dir[];
|
extern const char *node_context_dir[];
|
||||||
|
|
||||||
// XXXXXX
|
// XXXXXX
|
||||||
|
|||||||
@@ -120,6 +120,8 @@ void node_operatortypes(void)
|
|||||||
WM_operatortype_append(NODE_OT_clipboard_paste);
|
WM_operatortype_append(NODE_OT_clipboard_paste);
|
||||||
|
|
||||||
WM_operatortype_append(NODE_OT_shader_script_update);
|
WM_operatortype_append(NODE_OT_shader_script_update);
|
||||||
|
|
||||||
|
WM_operatortype_append(NODE_OT_viewer_border);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ED_operatormacros_node(void)
|
void ED_operatormacros_node(void)
|
||||||
@@ -298,5 +300,7 @@ void node_keymap(struct wmKeyConfig *keyconf)
|
|||||||
WM_keymap_add_item(keymap, "NODE_OT_clipboard_copy", CKEY, KM_PRESS, KM_CTRL, 0);
|
WM_keymap_add_item(keymap, "NODE_OT_clipboard_copy", CKEY, KM_PRESS, KM_CTRL, 0);
|
||||||
WM_keymap_add_item(keymap, "NODE_OT_clipboard_paste", VKEY, KM_PRESS, KM_CTRL, 0);
|
WM_keymap_add_item(keymap, "NODE_OT_clipboard_paste", VKEY, KM_PRESS, KM_CTRL, 0);
|
||||||
|
|
||||||
|
WM_keymap_add_item(keymap, "NODE_OT_viewer_border", BKEY, KM_PRESS, KM_CTRL, 0);
|
||||||
|
|
||||||
transform_keymap_for_space(keyconf, keymap, SPACE_NODE);
|
transform_keymap_for_space(keyconf, keymap, SPACE_NODE);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -279,6 +279,8 @@ typedef struct bNodeTree {
|
|||||||
short render_quality; /* Quality setting when rendering */
|
short render_quality; /* Quality setting when rendering */
|
||||||
int chunksize; /* tile size for compositor engine */
|
int chunksize; /* tile size for compositor engine */
|
||||||
|
|
||||||
|
rctf viewer_border;
|
||||||
|
|
||||||
ListBase inputs, outputs; /* external sockets for group nodes */
|
ListBase inputs, outputs; /* external sockets for group nodes */
|
||||||
|
|
||||||
/* execution data */
|
/* execution data */
|
||||||
@@ -313,6 +315,7 @@ typedef struct bNodeTree {
|
|||||||
#define NTREE_COM_OPENCL 2 /* use opencl */
|
#define NTREE_COM_OPENCL 2 /* use opencl */
|
||||||
#define NTREE_TWO_PASS 4 /* two pass */
|
#define NTREE_TWO_PASS 4 /* two pass */
|
||||||
#define NTREE_COM_GROUPNODE_BUFFER 8 /* use groupnode buffers */
|
#define NTREE_COM_GROUPNODE_BUFFER 8 /* use groupnode buffers */
|
||||||
|
#define NTREE_VIEWER_BORDER 16 /* use a border for viewer nodes */
|
||||||
|
|
||||||
/* XXX not nice, but needed as a temporary flags
|
/* XXX not nice, but needed as a temporary flags
|
||||||
* for group updates after library linking.
|
* for group updates after library linking.
|
||||||
|
|||||||
@@ -55,6 +55,7 @@
|
|||||||
#include "rna_internal_types.h"
|
#include "rna_internal_types.h"
|
||||||
|
|
||||||
#include "IMB_imbuf.h"
|
#include "IMB_imbuf.h"
|
||||||
|
#include "IMB_imbuf_types.h"
|
||||||
|
|
||||||
#include "WM_types.h"
|
#include "WM_types.h"
|
||||||
|
|
||||||
@@ -521,6 +522,38 @@ static void rna_Node_material_update(Main *bmain, Scene *scene, PointerRNA *ptr)
|
|||||||
node_update(bmain, scene, ntree, node);
|
node_update(bmain, scene, ntree, node);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void rna_NodeTree_update(Main *bmain, Scene *scene, PointerRNA *ptr)
|
||||||
|
{
|
||||||
|
bNodeTree *ntree = (bNodeTree *)ptr->id.data;
|
||||||
|
|
||||||
|
/* when using border, make it so no old data from outside of
|
||||||
|
* border is hanging around
|
||||||
|
* ideally shouldn't be in RNA callback, but how to teach
|
||||||
|
* compo to only clear frame when border usage is actually
|
||||||
|
* toggling
|
||||||
|
*/
|
||||||
|
if (ntree->flag & NTREE_VIEWER_BORDER) {
|
||||||
|
Image *ima = BKE_image_verify_viewer(IMA_TYPE_COMPOSITE, "Viewer Node");
|
||||||
|
void *lock;
|
||||||
|
ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, &lock);
|
||||||
|
|
||||||
|
if (ibuf) {
|
||||||
|
if (ibuf->rect)
|
||||||
|
memset(ibuf->rect, 0, 4 * ibuf->x * ibuf->y);
|
||||||
|
|
||||||
|
if (ibuf->rect_float)
|
||||||
|
memset(ibuf->rect_float, 0, 4 * ibuf->x * ibuf->y * sizeof(float));
|
||||||
|
|
||||||
|
ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID;
|
||||||
|
}
|
||||||
|
|
||||||
|
BKE_image_release_ibuf(ima, ibuf, lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
WM_main_add_notifier(NC_NODE | NA_EDITED, NULL);
|
||||||
|
WM_main_add_notifier(NC_SCENE | ND_NODES, &ntree->id);
|
||||||
|
}
|
||||||
|
|
||||||
static void rna_NodeGroup_update(Main *bmain, Scene *scene, PointerRNA *ptr)
|
static void rna_NodeGroup_update(Main *bmain, Scene *scene, PointerRNA *ptr)
|
||||||
{
|
{
|
||||||
bNodeTree *ntree = (bNodeTree *)ptr->id.data;
|
bNodeTree *ntree = (bNodeTree *)ptr->id.data;
|
||||||
@@ -4985,6 +5018,11 @@ static void rna_def_composite_nodetree(BlenderRNA *brna)
|
|||||||
RNA_def_property_boolean_sdna(prop, NULL, "flag", NTREE_TWO_PASS);
|
RNA_def_property_boolean_sdna(prop, NULL, "flag", NTREE_TWO_PASS);
|
||||||
RNA_def_property_ui_text(prop, "Two Pass", "Use two pass execution during editing: first calculate fast nodes, "
|
RNA_def_property_ui_text(prop, "Two Pass", "Use two pass execution during editing: first calculate fast nodes, "
|
||||||
"second pass calculate all nodes");
|
"second pass calculate all nodes");
|
||||||
|
|
||||||
|
prop = RNA_def_property(srna, "use_viewer_border", PROP_BOOLEAN, PROP_NONE);
|
||||||
|
RNA_def_property_boolean_sdna(prop, NULL, "flag", NTREE_VIEWER_BORDER);
|
||||||
|
RNA_def_property_ui_text(prop, "Viewer Border", "Use boundaries for viewer nodes and composite backdrop");
|
||||||
|
RNA_def_property_update(prop, NC_NODE | ND_DISPLAY, "rna_NodeTree_update");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void rna_def_shader_nodetree(BlenderRNA *brna)
|
static void rna_def_shader_nodetree(BlenderRNA *brna)
|
||||||
|
|||||||
@@ -4197,6 +4197,7 @@ static void gesture_border_modal_keymap(wmKeyConfig *keyconf)
|
|||||||
WM_modalkeymap_assign(keymap, "MARKER_OT_select_border");
|
WM_modalkeymap_assign(keymap, "MARKER_OT_select_border");
|
||||||
WM_modalkeymap_assign(keymap, "NLA_OT_select_border");
|
WM_modalkeymap_assign(keymap, "NLA_OT_select_border");
|
||||||
WM_modalkeymap_assign(keymap, "NODE_OT_select_border");
|
WM_modalkeymap_assign(keymap, "NODE_OT_select_border");
|
||||||
|
WM_modalkeymap_assign(keymap, "NODE_OT_viewer_border");
|
||||||
WM_modalkeymap_assign(keymap, "PAINT_OT_hide_show");
|
WM_modalkeymap_assign(keymap, "PAINT_OT_hide_show");
|
||||||
WM_modalkeymap_assign(keymap, "OUTLINER_OT_select_border");
|
WM_modalkeymap_assign(keymap, "OUTLINER_OT_select_border");
|
||||||
// WM_modalkeymap_assign(keymap, "SCREEN_OT_border_select"); // template
|
// WM_modalkeymap_assign(keymap, "SCREEN_OT_border_select"); // template
|
||||||
|
|||||||
Reference in New Issue
Block a user