Merging r47307 through r47325 from trunk into soc-2011-tomato
This commit is contained in:
@@ -112,6 +112,9 @@ struct bActionGroup *get_active_actiongroup(struct bAction *act);
|
||||
/* Make the given Action Group the active one */
|
||||
void set_active_action_group(struct bAction *act, struct bActionGroup *agrp, short select);
|
||||
|
||||
/* Sync colors used for action/bone group with theme settings */
|
||||
void action_group_colors_sync(struct bActionGroup *grp);
|
||||
|
||||
/* Add a new action group with the given name to the action */
|
||||
struct bActionGroup *action_groups_add_new(struct bAction *act, const char name[]);
|
||||
|
||||
|
||||
@@ -156,6 +156,10 @@ typedef struct bNodeType {
|
||||
const char *(*labelfunc)(struct bNode *);
|
||||
/// Optional custom resize handle polling.
|
||||
int (*resize_area_func)(struct bNode *node, int x, int y);
|
||||
/// Optional selection area polling.
|
||||
int (*select_area_func)(struct bNode *node, int x, int y);
|
||||
/// Optional tweak area polling (for grabbing).
|
||||
int (*tweak_area_func)(struct bNode *node, int x, int y);
|
||||
|
||||
/// Called when the node is updated in the editor.
|
||||
void (*updatefunc)(struct bNodeTree *ntree, struct bNode *node);
|
||||
@@ -434,6 +438,7 @@ void node_type_compatibility(struct bNodeType *ntype, short compatibility);
|
||||
#define NODE_FORLOOP 3
|
||||
#define NODE_WHILELOOP 4
|
||||
#define NODE_FRAME 5
|
||||
#define NODE_REROUTE 6
|
||||
|
||||
/* look up a socket on a group node by the internal group socket */
|
||||
struct bNodeSocket *node_group_find_input(struct bNode *gnode, struct bNodeSocket *gsock);
|
||||
@@ -449,6 +454,7 @@ int node_group_ungroup(struct bNodeTree *ntree, struct bNode *gnode);
|
||||
|
||||
/* in node_common.c */
|
||||
void register_node_type_frame(struct bNodeTreeType *ttype);
|
||||
void register_node_type_reroute(struct bNodeTreeType *ttype);
|
||||
|
||||
/* ************** SHADER NODES *************** */
|
||||
|
||||
|
||||
@@ -252,6 +252,31 @@ void set_active_action_group(bAction *act, bActionGroup *agrp, short select)
|
||||
}
|
||||
}
|
||||
|
||||
/* Sync colors used for action/bone group with theme settings */
|
||||
void action_group_colors_sync(bActionGroup *grp)
|
||||
{
|
||||
/* only do color copying if using a custom color (i.e. not default color) */
|
||||
if (grp->customCol) {
|
||||
if (grp->customCol > 0) {
|
||||
/* copy theme colors on-to group's custom color in case user tries to edit color */
|
||||
bTheme *btheme = U.themes.first;
|
||||
ThemeWireColor *col_set = &btheme->tarm[(grp->customCol - 1)];
|
||||
|
||||
memcpy(&grp->cs, col_set, sizeof(ThemeWireColor));
|
||||
}
|
||||
else {
|
||||
/* init custom colors with a generic multi-color rgb set, if not initialized already
|
||||
* (for custom color set) */
|
||||
if (grp->cs.solid[0] == 0) {
|
||||
/* define for setting colors in theme below */
|
||||
rgba_char_args_set(grp->cs.solid, 0xff, 0x00, 0x00, 255);
|
||||
rgba_char_args_set(grp->cs.select, 0x81, 0xe6, 0x14, 255);
|
||||
rgba_char_args_set(grp->cs.active, 0x18, 0xb6, 0xe0, 255);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Add a new action group with the given name to the action */
|
||||
bActionGroup *action_groups_add_new(bAction *act, const char name[])
|
||||
{
|
||||
@@ -409,10 +434,9 @@ void action_groups_clear_tempflags(bAction *act)
|
||||
|
||||
/* *************** Pose channels *************** */
|
||||
|
||||
/* usually used within a loop, so we got a N^2 slowdown */
|
||||
bPoseChannel *BKE_pose_channel_find_name(const bPose *pose, const char *name)
|
||||
{
|
||||
if (ELEM(NULL, pose, name) || (name[0] == 0))
|
||||
if (ELEM(NULL, pose, name) || (name[0] == '\0'))
|
||||
return NULL;
|
||||
|
||||
if (pose->chanhash)
|
||||
|
||||
@@ -1822,6 +1822,7 @@ void nodeRegisterType(bNodeTreeType *ttype, bNodeType *ntype)
|
||||
static void registerCompositNodes(bNodeTreeType *ttype)
|
||||
{
|
||||
register_node_type_frame(ttype);
|
||||
register_node_type_reroute(ttype);
|
||||
|
||||
register_node_type_cmp_group(ttype);
|
||||
// register_node_type_cmp_forloop(ttype);
|
||||
@@ -1918,6 +1919,7 @@ static void registerCompositNodes(bNodeTreeType *ttype)
|
||||
static void registerShaderNodes(bNodeTreeType *ttype)
|
||||
{
|
||||
register_node_type_frame(ttype);
|
||||
register_node_type_reroute(ttype);
|
||||
|
||||
register_node_type_sh_group(ttype);
|
||||
//register_node_type_sh_forloop(ttype);
|
||||
@@ -1990,6 +1992,7 @@ static void registerShaderNodes(bNodeTreeType *ttype)
|
||||
static void registerTextureNodes(bNodeTreeType *ttype)
|
||||
{
|
||||
register_node_type_frame(ttype);
|
||||
register_node_type_reroute(ttype);
|
||||
|
||||
register_node_type_tex_group(ttype);
|
||||
// register_node_type_tex_forloop(ttype);
|
||||
|
||||
@@ -65,7 +65,6 @@ set(SRC
|
||||
intern/COM_NodeBase.h
|
||||
intern/COM_NodeOperation.cpp
|
||||
intern/COM_NodeOperation.h
|
||||
intern/COM_NodeProgram.h
|
||||
intern/COM_Socket.cpp
|
||||
intern/COM_Socket.h
|
||||
intern/COM_SocketReader.cpp
|
||||
@@ -80,10 +79,6 @@ set(SRC
|
||||
intern/COM_MemoryProxy.h
|
||||
intern/COM_MemoryBuffer.cpp
|
||||
intern/COM_MemoryBuffer.h
|
||||
intern/COM_MemoryManager.cpp
|
||||
intern/COM_MemoryManager.h
|
||||
intern/COM_MemoryManagerState.cpp
|
||||
intern/COM_MemoryManagerState.h
|
||||
intern/COM_WorkScheduler.cpp
|
||||
intern/COM_WorkScheduler.h
|
||||
intern/COM_WorkPackage.cpp
|
||||
|
||||
@@ -29,14 +29,10 @@ void CPUDevice::execute(WorkPackage *work)
|
||||
rcti rect;
|
||||
|
||||
executionGroup->determineChunkRect(&rect, chunkNumber);
|
||||
MemoryBuffer ** inputBuffers = executionGroup->getInputBuffers(chunkNumber);
|
||||
MemoryBuffer * outputBuffer = executionGroup->allocateOutputBuffer(chunkNumber, &rect);
|
||||
MemoryBuffer ** inputBuffers = executionGroup->getInputBuffersCPU();
|
||||
|
||||
executionGroup->getOutputNodeOperation()->executeRegion(&rect, chunkNumber, inputBuffers);
|
||||
|
||||
executionGroup->finalizeChunkExecution(chunkNumber, inputBuffers);
|
||||
if (outputBuffer != NULL) {
|
||||
outputBuffer->setCreatedState();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -34,7 +34,6 @@
|
||||
#include "COM_ViewerOperation.h"
|
||||
#include <stdlib.h>
|
||||
#include "BLI_math.h"
|
||||
#include "COM_MemoryManager.h"
|
||||
#include "PIL_time.h"
|
||||
#include "COM_ChunkOrder.h"
|
||||
#include <algorithm>
|
||||
@@ -362,7 +361,24 @@ void ExecutionGroup::execute(ExecutionSystem *graph)
|
||||
delete[] chunkOrder;
|
||||
}
|
||||
|
||||
MemoryBuffer** ExecutionGroup::getInputBuffers(int chunkNumber)
|
||||
MemoryBuffer** ExecutionGroup::getInputBuffersCPU()
|
||||
{
|
||||
vector<MemoryProxy*> memoryproxies;
|
||||
unsigned int index;
|
||||
|
||||
this->determineDependingMemoryProxies(&memoryproxies);
|
||||
MemoryBuffer **memoryBuffers = new MemoryBuffer*[this->cachedMaxReadBufferOffset];
|
||||
for (index = 0 ; index < this->cachedMaxReadBufferOffset ; index ++) {
|
||||
memoryBuffers[index] = NULL;
|
||||
}
|
||||
for (index = 0 ; index < this->cachedReadOperations.size(); index ++) {
|
||||
ReadBufferOperation *readOperation = (ReadBufferOperation*)this->cachedReadOperations[index];
|
||||
memoryBuffers[readOperation->getOffset()] = readOperation->getMemoryProxy()->getBuffer();
|
||||
}
|
||||
return memoryBuffers;
|
||||
}
|
||||
|
||||
MemoryBuffer** ExecutionGroup::getInputBuffersOpenCL(int chunkNumber)
|
||||
{
|
||||
rcti rect;
|
||||
vector<MemoryProxy*> memoryproxies;
|
||||
@@ -385,6 +401,8 @@ MemoryBuffer** ExecutionGroup::getInputBuffers(int chunkNumber)
|
||||
return memoryBuffers;
|
||||
}
|
||||
|
||||
// @todo: for opencl the memory buffers size needs to be same as the needed size
|
||||
// currently this method is not called, but will be when opencl nodes are created
|
||||
MemoryBuffer *ExecutionGroup::constructConsolidatedMemoryBuffer(MemoryProxy *memoryProxy, rcti *rect)
|
||||
{
|
||||
// find all chunks inside the rect
|
||||
@@ -399,8 +417,7 @@ MemoryBuffer *ExecutionGroup::constructConsolidatedMemoryBuffer(MemoryProxy *mem
|
||||
const int maxychunk = ceil((rect->ymax-1)/chunkSizef);
|
||||
|
||||
if (maxxchunk== minxchunk+1 && maxychunk == minychunk+1) {
|
||||
const int chunkNumber = minxchunk+minychunk*numberOfXChunks;
|
||||
MemoryBuffer *result = MemoryManager::getMemoryBuffer(memoryProxy, chunkNumber);
|
||||
MemoryBuffer *result =memoryProxy->getBuffer();
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -420,7 +437,7 @@ MemoryBuffer *ExecutionGroup::constructConsolidatedMemoryBuffer(MemoryProxy *mem
|
||||
for (indexx = max(minxchunk, 0); indexx<min((int)this->numberOfXChunks, maxxchunk) ; indexx++) {
|
||||
for (indexy = max(minychunk, 0); indexy<min((int)this->numberOfYChunks, maxychunk) ; indexy++) {
|
||||
int chunkNumber = indexx+indexy*this->numberOfXChunks;
|
||||
MemoryBuffer *chunkBuffer = MemoryManager::getMemoryBuffer(memoryProxy, chunkNumber);
|
||||
MemoryBuffer *chunkBuffer = memoryProxy->getBuffer();
|
||||
result->copyContentFrom(chunkBuffer);
|
||||
}
|
||||
}
|
||||
@@ -432,8 +449,6 @@ void ExecutionGroup::finalizeChunkExecution(int chunkNumber, MemoryBuffer** memo
|
||||
{
|
||||
if (this->chunkExecutionStates[chunkNumber] == COM_ES_SCHEDULED)
|
||||
this->chunkExecutionStates[chunkNumber] = COM_ES_EXECUTED;
|
||||
else
|
||||
throw "Threading inconsistency";
|
||||
|
||||
this->chunksFinished++;
|
||||
if (memoryBuffers) {
|
||||
@@ -477,7 +492,7 @@ MemoryBuffer *ExecutionGroup::allocateOutputBuffer(int chunkNumber, rcti *rect)
|
||||
NodeOperation * operation = this->getOutputNodeOperation();
|
||||
if (operation->isWriteBufferOperation()) {
|
||||
WriteBufferOperation *writeOperation = (WriteBufferOperation*)operation;
|
||||
outputBuffer = MemoryManager::allocateMemoryBuffer(writeOperation->getMemoryProxy(), chunkNumber, rect);
|
||||
// @todo outputBuffer = MemoryManager::allocateMemoryBuffer(writeOperation->getMemoryProxy(), chunkNumber, rect);
|
||||
}
|
||||
return outputBuffer;
|
||||
}
|
||||
|
||||
@@ -334,8 +334,16 @@ public:
|
||||
* @param chunkNumber the chunk to be calculated
|
||||
* @return MemoryBuffer** the inputbuffers
|
||||
*/
|
||||
MemoryBuffer** getInputBuffers(int chunkNumber);
|
||||
|
||||
MemoryBuffer** getInputBuffersCPU();
|
||||
|
||||
/**
|
||||
* @brief get all inputbuffers needed to calculate an chunk
|
||||
* @note all inputbuffers must be executed
|
||||
* @param chunkNumber the chunk to be calculated
|
||||
* @return MemoryBuffer** the inputbuffers
|
||||
*/
|
||||
MemoryBuffer** getInputBuffersOpenCL(int chunkNumber);
|
||||
|
||||
/**
|
||||
* @brief allocate the outputbuffer of a chunk
|
||||
* @param chunkNumber the number of the chunk in the ExecutionGroup
|
||||
|
||||
@@ -31,7 +31,6 @@
|
||||
#include "COM_NodeBase.h"
|
||||
#include "COM_WorkScheduler.h"
|
||||
#include "COM_ReadBufferOperation.h"
|
||||
#include "COM_MemoryManager.h"
|
||||
#include "stdio.h"
|
||||
#include "COM_GroupNode.h"
|
||||
#include "COM_WriteBufferOperation.h"
|
||||
@@ -114,8 +113,6 @@ void ExecutionSystem::execute()
|
||||
order ++;
|
||||
}
|
||||
}
|
||||
|
||||
MemoryManager::initialize();
|
||||
unsigned int index;
|
||||
|
||||
for (index = 0 ; index < this->operations.size() ; index ++) {
|
||||
@@ -156,7 +153,6 @@ void ExecutionSystem::execute()
|
||||
ExecutionGroup * executionGroup = this->groups[index];
|
||||
executionGroup->deinitExecution();
|
||||
}
|
||||
MemoryManager::clear();
|
||||
}
|
||||
|
||||
void ExecutionSystem::addOperation(NodeOperation *operation)
|
||||
|
||||
@@ -31,7 +31,6 @@
|
||||
#include "COM_NodeBase.h"
|
||||
#include "COM_WorkScheduler.h"
|
||||
#include "COM_ReadBufferOperation.h"
|
||||
#include "COM_MemoryManager.h"
|
||||
#include "stdio.h"
|
||||
#include "COM_GroupNode.h"
|
||||
#include "COM_WriteBufferOperation.h"
|
||||
|
||||
@@ -44,7 +44,7 @@ MemoryBuffer::MemoryBuffer(MemoryProxy * memoryProxy, unsigned int chunkNumber,
|
||||
BLI_init_rcti(&this->rect, rect->xmin, rect->xmax, rect->ymin, rect->ymax);
|
||||
this->memoryProxy = memoryProxy;
|
||||
this->chunkNumber = chunkNumber;
|
||||
this->buffer = (float*)MEM_mallocN(sizeof(float)*determineBufferSize()*4, "COM_MemoryBuffer");
|
||||
this->buffer = (float*)MEM_mallocN(sizeof(float)*determineBufferSize()*COM_NUMBER_OF_CHANNELS, "COM_MemoryBuffer");
|
||||
this->state = COM_MB_ALLOCATED;
|
||||
this->datatype = COM_DT_COLOR;
|
||||
this->chunkWidth = this->rect.xmax - this->rect.xmin;
|
||||
@@ -55,7 +55,7 @@ MemoryBuffer::MemoryBuffer(MemoryProxy * memoryProxy, rcti *rect)
|
||||
BLI_init_rcti(&this->rect, rect->xmin, rect->xmax, rect->ymin, rect->ymax);
|
||||
this->memoryProxy = memoryProxy;
|
||||
this->chunkNumber = -1;
|
||||
this->buffer = (float*)MEM_mallocN(sizeof(float)*determineBufferSize()*4, "COM_MemoryBuffer");
|
||||
this->buffer = (float*)MEM_mallocN(sizeof(float)*determineBufferSize()*COM_NUMBER_OF_CHANNELS, "COM_MemoryBuffer");
|
||||
this->state = COM_MB_TEMPORARILY;
|
||||
this->datatype = COM_DT_COLOR;
|
||||
this->chunkWidth = this->rect.xmax - this->rect.xmin;
|
||||
@@ -63,12 +63,12 @@ MemoryBuffer::MemoryBuffer(MemoryProxy * memoryProxy, rcti *rect)
|
||||
MemoryBuffer *MemoryBuffer::duplicate()
|
||||
{
|
||||
MemoryBuffer *result = new MemoryBuffer(this->memoryProxy, &this->rect);
|
||||
memcpy(result->buffer, this->buffer, this->determineBufferSize()*4*sizeof(float));
|
||||
memcpy(result->buffer, this->buffer, this->determineBufferSize()*COM_NUMBER_OF_CHANNELS*sizeof(float));
|
||||
return result;
|
||||
}
|
||||
void MemoryBuffer::clear()
|
||||
{
|
||||
memset(this->buffer, 0, this->determineBufferSize()*4*sizeof(float));
|
||||
memset(this->buffer, 0, this->determineBufferSize()*COM_NUMBER_OF_CHANNELS*sizeof(float));
|
||||
}
|
||||
|
||||
float *MemoryBuffer::convertToValueBuffer()
|
||||
@@ -77,7 +77,7 @@ float *MemoryBuffer::convertToValueBuffer()
|
||||
int i;
|
||||
int offset4;
|
||||
float *result = new float[size];
|
||||
for (i = 0, offset4 = 0 ; i < size ; i ++, offset4 +=4) {
|
||||
for (i = 0, offset4 = 0 ; i < size ; i ++, offset4 +=COM_NUMBER_OF_CHANNELS) {
|
||||
result[i] = this->buffer[offset4];
|
||||
}
|
||||
|
||||
@@ -107,9 +107,9 @@ void MemoryBuffer::copyContentFrom(MemoryBuffer *otherBuffer)
|
||||
|
||||
|
||||
for (otherY = minY ; otherY<maxY ; otherY ++) {
|
||||
otherOffset = ((otherY-otherBuffer->rect.ymin) * otherBuffer->chunkWidth + minX-otherBuffer->rect.xmin)*4;
|
||||
offset = ((otherY - this->rect.ymin) * this->chunkWidth + minX-this->rect.xmin)*4;
|
||||
memcpy(&this->buffer[offset], &otherBuffer->buffer[otherOffset], (maxX-minX) * 4*sizeof(float));
|
||||
otherOffset = ((otherY-otherBuffer->rect.ymin) * otherBuffer->chunkWidth + minX-otherBuffer->rect.xmin)*COM_NUMBER_OF_CHANNELS;
|
||||
offset = ((otherY - this->rect.ymin) * this->chunkWidth + minX-this->rect.xmin)*COM_NUMBER_OF_CHANNELS;
|
||||
memcpy(&this->buffer[offset], &otherBuffer->buffer[otherOffset], (maxX-minX) * COM_NUMBER_OF_CHANNELS*sizeof(float));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -119,7 +119,7 @@ void MemoryBuffer::read(float *result, int x, int y)
|
||||
y>=this->rect.ymin && y < this->rect.ymax) {
|
||||
int dx = x-this->rect.xmin;
|
||||
int dy = y-this->rect.ymin;
|
||||
int offset = (this->chunkWidth*dy+dx)*4;
|
||||
int offset = (this->chunkWidth*dy+dx)*COM_NUMBER_OF_CHANNELS;
|
||||
result[0] = this->buffer[offset];
|
||||
result[1] = this->buffer[offset+1];
|
||||
result[2] = this->buffer[offset+2];
|
||||
@@ -136,7 +136,7 @@ void MemoryBuffer::writePixel(int x, int y, float color[4])
|
||||
{
|
||||
if (x>=this->rect.xmin && x < this->rect.xmax &&
|
||||
y>=this->rect.ymin && y < this->rect.ymax) {
|
||||
int offset = (this->chunkWidth*y+x)*4;
|
||||
int offset = (this->chunkWidth*y+x)*COM_NUMBER_OF_CHANNELS;
|
||||
this->buffer[offset] = color[0];
|
||||
this->buffer[offset+1] = color[1];
|
||||
this->buffer[offset+2] = color[2];
|
||||
|
||||
@@ -1,74 +0,0 @@
|
||||
/*
|
||||
* Copyright 2011, Blender Foundation.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Contributor:
|
||||
* Jeroen Bakker
|
||||
* Monique Dewanchand
|
||||
*/
|
||||
|
||||
#include "COM_MemoryManager.h"
|
||||
#include "BLI_threads.h"
|
||||
#include <stdio.h>
|
||||
#include "COM_defines.h"
|
||||
|
||||
vector<MemoryBuffer*> buffers;
|
||||
|
||||
ThreadMutex mutex;
|
||||
|
||||
MemoryBuffer *MemoryManager::allocateMemoryBuffer(MemoryProxy *id, unsigned int chunkNumber, rcti *rect)
|
||||
{
|
||||
MemoryBuffer *result = new MemoryBuffer(id, chunkNumber, rect);
|
||||
MemoryManagerState * state = MemoryManager::getState(id);
|
||||
state->addMemoryBuffer(result);
|
||||
BLI_mutex_lock(&mutex);
|
||||
buffers.push_back(result);
|
||||
BLI_mutex_unlock(&mutex);
|
||||
return result;
|
||||
}
|
||||
|
||||
void MemoryManager::addMemoryProxy(MemoryProxy *memoryProxy)
|
||||
{
|
||||
MemoryManagerState * state = MemoryManager::getState(memoryProxy);
|
||||
if (!state) {
|
||||
state = new MemoryManagerState(memoryProxy);
|
||||
memoryProxy->setState(state);
|
||||
}
|
||||
}
|
||||
MemoryBuffer *MemoryManager::getMemoryBuffer(MemoryProxy *id, unsigned int chunkNumber)
|
||||
{
|
||||
MemoryManagerState * state = MemoryManager::getState(id);
|
||||
if (!state) {
|
||||
return NULL;
|
||||
}
|
||||
MemoryBuffer *buffer = state->getMemoryBuffer(chunkNumber);
|
||||
if (!buffer) return NULL;
|
||||
return buffer;
|
||||
}
|
||||
|
||||
MemoryManagerState *MemoryManager::getState(MemoryProxy *memoryProxy)
|
||||
{
|
||||
return memoryProxy->getState();
|
||||
}
|
||||
void MemoryManager::initialize()
|
||||
{
|
||||
BLI_mutex_init(&mutex);
|
||||
}
|
||||
void MemoryManager::clear()
|
||||
{
|
||||
buffers.clear();
|
||||
BLI_mutex_end(&mutex);
|
||||
}
|
||||
@@ -1,146 +0,0 @@
|
||||
/*
|
||||
* Copyright 2011, Blender Foundation.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Contributor:
|
||||
* Jeroen Bakker
|
||||
* Monique Dewanchand
|
||||
*/
|
||||
|
||||
#ifndef _COM_MemoryManager_h_
|
||||
#define _COM_MemoryManager_h_
|
||||
|
||||
#include "COM_MemoryBuffer.h"
|
||||
#include "COM_MemoryProxy.h"
|
||||
#include "COM_ExecutionGroup.h"
|
||||
#include "COM_MemoryManagerState.h"
|
||||
|
||||
/**
|
||||
* @page memorymanager The Memory Manager
|
||||
* The compositor has its own MemoryManager. The goal of the MemoryManager is to manage the memory allocated by chunks.
|
||||
* During execution new chunks will be created [MemoryManager.allocateMemoryBuffer] When calculation is finished the MemoryBuffer will get the state [MemoryBufferState.COM_MB_AVAILABLE].
|
||||
* From now on other ExecutionGroup and NodeOperations may read from the MemoryBuffer.
|
||||
* The MemoryManager also has the capability to save MemoryBuffer's to disk in order to free some memory.
|
||||
*
|
||||
* @section S_MEM Memory manager
|
||||
* The memory manager synchronize and optimize data across devices.
|
||||
* Only one NodeOperation running on a device is able to write to a MemoryBuffer. This MemoryBuffer is only allocated on the main-device memory (CPU).
|
||||
* The MemoryBuffer.state will be [MemoryBufferState.COM_MB_ALLOCATED]. As soon as the chunk has been executed the state changes to [MemoryBufferState.COM_MB_AVAILABLE]. This MemoryBuffer can now be used as inputBuffer of ExecutionGroup's.
|
||||
* When needed the MemoryBuffer will be stored to a file. This will save memory that can be used by other tiles.
|
||||
* @subsection S_MEM_1 Step one
|
||||
* When a chunk of an ExecutionGroup is being executed by a device, the MemoryBuffer is allocated on the CPU.
|
||||
* <pre>
|
||||
* Allocation of the output MemoryBuffer
|
||||
* +----------------------------------------+
|
||||
* | Main device (CPU) |
|
||||
* | +----------------+ +--------------+ |
|
||||
* | | ExecutionGroup | | MemoryBuffer | |
|
||||
* | | | | Chunk a | |
|
||||
* | +----------------+ +--------------+ |
|
||||
* | |
|
||||
* +----------------------------------------+
|
||||
* </pre>
|
||||
* @see MemoryManager.allocateMemoryBuffer
|
||||
*
|
||||
* @subsection S_MEM_2 Step two
|
||||
* The Device will execute the ExecutionGroup. This differs per type of Device. CPUDevice will call the NodeOperation.executeRegion method of the outputnode of the ExecutionGroup.
|
||||
* The [NodeOperation.executeRegion] writes the result to the allocated MemoryBuffer. When finished the state of the MemoryBuffer will be set to [MemoryBufferState.COM_MB_AVAILABLE].
|
||||
* <pre>
|
||||
* Execute a chunk and store result to the MemoryBuffer
|
||||
* +----------------------------------------+
|
||||
* | Main device (CPU) |
|
||||
* | +----------------+ +--------------+ |
|
||||
* | | ExecutionGroup | | MemoryBuffer | |
|
||||
* | | | | Chunk a | |
|
||||
* | +----------------+ +--------------+ |
|
||||
* | | ^ |
|
||||
* | +----------------+ | |
|
||||
* | | NodeOperation |--------+ |
|
||||
* | | | Write result |
|
||||
* | +----------------+ |
|
||||
* | |
|
||||
* +----------------------------------------+
|
||||
* </pre>
|
||||
* @subsection S_MEM_3 Step 3
|
||||
* Other Chunks that depend on the MemoryBuffer can now use it.
|
||||
* When a MemoryBuffer is being used its number of users are increased. When a 'user' is finished the number of users are decreased, If a MemoryBuffer has no users, the system can decide to store the data to disk and free some memory.
|
||||
* @see MemoryBuffer.numberOfUsers
|
||||
* @see MemoryBuffer.saveToDisk
|
||||
*
|
||||
* @subsection S_MEM_CON Temporarily MemoryBuffers
|
||||
* Nodes like blur nodes can depend on multiple MemoryBuffer of the same MemoryProxy. These multiple buffers will be consolidated temporarily to a new MemoryBuffer.
|
||||
* When execution is finished this temporarily memory buffer is deallicated.
|
||||
* <pre>
|
||||
* Original MemoryBuffer's Temporarily
|
||||
* +-------+ +-------+ MemoryBuffer
|
||||
* | MB A | | MB B | +-------+-------+
|
||||
* +-------+ +-------+ | MB A | MB B |
|
||||
* ==> +-------+-------+
|
||||
* +-------+ +-------+ | MB C | MB D |
|
||||
* | MB C | | MB D | +-------+-------+
|
||||
* +-------+ +-------+
|
||||
* </pre>
|
||||
* @see ExecutionGroup.constructConsolidatedMemoryBuffer constructs the temporarily MemoryBuffer
|
||||
* @see MemoryBuffer.state state is MemoryManagerState.COM_MB_TEMPORARILY
|
||||
* @see ExecutionGroup.finalizeChunkExecution deallocate the temporarily MemoryBuffer
|
||||
* @note this MemoryBuffer is not managed by the MemoryManager
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief the memory manager for the compostor
|
||||
* @ingroup Memory
|
||||
*/
|
||||
class MemoryManager {
|
||||
private:
|
||||
/**
|
||||
* @brief retrieve the state of a certain MemoryProxy;
|
||||
* @param memoryProxy the MemoryProxy to retrieve the state from
|
||||
*/
|
||||
static MemoryManagerState *getState(MemoryProxy *memoryProxy);
|
||||
public:
|
||||
/**
|
||||
* @brief allocate a memory buffer
|
||||
* @param memoryProxy the MemoryProxy to get a chunk from
|
||||
* @param chunkNumber number of the chunk to receive
|
||||
* @param rect size + position of the chunk
|
||||
*/
|
||||
static MemoryBuffer *allocateMemoryBuffer(MemoryProxy *memoryProxy, unsigned int chunkNumber, rcti *rect);
|
||||
|
||||
/**
|
||||
* @brief get a memory buffer
|
||||
* @param memoryProxy the MemoryProxy to get a chunk from
|
||||
* @param chunkNumber number of the chunk to receive
|
||||
* @param addUser must we add a user to the chunk.
|
||||
*/
|
||||
static MemoryBuffer *getMemoryBuffer(MemoryProxy *memoryProxy, unsigned int chunkNumber);
|
||||
|
||||
/**
|
||||
* @brief add a MemoryProxy to the scope of the memory manager
|
||||
* @param memoryProxy the MemoryProxy to add
|
||||
*/
|
||||
static void addMemoryProxy(MemoryProxy *memoryProxy);
|
||||
|
||||
/**
|
||||
* @brief clear the memory manager
|
||||
*/
|
||||
static void clear();
|
||||
|
||||
/**
|
||||
* @brief initialize the memory manager.
|
||||
*/
|
||||
static void initialize();
|
||||
};
|
||||
#endif
|
||||
@@ -1,100 +0,0 @@
|
||||
/*
|
||||
* Copyright 2011, Blender Foundation.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Contributor:
|
||||
* Jeroen Bakker
|
||||
* Monique Dewanchand
|
||||
*/
|
||||
|
||||
#include "COM_MemoryManagerState.h"
|
||||
|
||||
MemoryManagerState::MemoryManagerState(MemoryProxy *memoryProxy)
|
||||
{
|
||||
this->memoryProxy = memoryProxy;
|
||||
this->currentSize = 0;
|
||||
this->chunkBuffers = NULL;
|
||||
BLI_mutex_init(&this->mutex);
|
||||
}
|
||||
|
||||
MemoryProxy * MemoryManagerState::getMemoryProxy()
|
||||
{
|
||||
return this->memoryProxy;
|
||||
}
|
||||
|
||||
MemoryManagerState::~MemoryManagerState()
|
||||
{
|
||||
this->memoryProxy = NULL;
|
||||
unsigned int index;
|
||||
for (index = 0 ; index < this->currentSize; index ++) {
|
||||
MemoryBuffer *buffer = this->chunkBuffers[index];
|
||||
if (buffer) {
|
||||
delete buffer;
|
||||
}
|
||||
}
|
||||
delete [] this->chunkBuffers;
|
||||
BLI_mutex_end(&this->mutex);
|
||||
}
|
||||
|
||||
void MemoryManagerState::addMemoryBuffer(MemoryBuffer *buffer)
|
||||
{
|
||||
BLI_mutex_lock(&this->mutex);
|
||||
unsigned int chunkNumber = buffer->getChunkNumber();
|
||||
unsigned int index;
|
||||
while (this->currentSize <= chunkNumber) {
|
||||
unsigned int newSize = this->currentSize + 1000;
|
||||
MemoryBuffer** newbuffer = new MemoryBuffer*[newSize];
|
||||
MemoryBuffer** oldbuffer = this->chunkBuffers;
|
||||
|
||||
for (index = 0 ; index < this->currentSize ; index++) {
|
||||
newbuffer[index] = oldbuffer[index];
|
||||
}
|
||||
for (index = currentSize ; index < newSize; index++) {
|
||||
newbuffer[index] = NULL;
|
||||
}
|
||||
|
||||
this->chunkBuffers = newbuffer;
|
||||
this->currentSize = newSize;
|
||||
if (oldbuffer) delete oldbuffer;
|
||||
}
|
||||
|
||||
if (this->chunkBuffers[chunkNumber] == NULL) {
|
||||
this->chunkBuffers[chunkNumber] = buffer;
|
||||
}
|
||||
else {
|
||||
throw "ALREADY ALLOCATED!";
|
||||
}
|
||||
BLI_mutex_unlock(&this->mutex);
|
||||
}
|
||||
|
||||
MemoryBuffer *MemoryManagerState::getMemoryBuffer(unsigned int chunkNumber)
|
||||
{
|
||||
MemoryBuffer *result = NULL;
|
||||
if (chunkNumber< this->currentSize) {
|
||||
result = this->chunkBuffers[chunkNumber];
|
||||
if (result) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
BLI_mutex_lock(&this->mutex);
|
||||
if (chunkNumber< this->currentSize) {
|
||||
result = this->chunkBuffers[chunkNumber];
|
||||
}
|
||||
|
||||
BLI_mutex_unlock(&this->mutex);
|
||||
return result;
|
||||
}
|
||||
@@ -1,87 +0,0 @@
|
||||
/*
|
||||
* Copyright 2011, Blender Foundation.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Contributor:
|
||||
* Jeroen Bakker
|
||||
* Monique Dewanchand
|
||||
*/
|
||||
|
||||
class MemoryManagerState;
|
||||
|
||||
#ifndef _COM_MemoryManagerState_h_
|
||||
#define _COM_MemoryManagerState_h_
|
||||
|
||||
#include "COM_MemoryProxy.h"
|
||||
#include "COM_MemoryBuffer.h"
|
||||
#include <vector>
|
||||
extern "C" {
|
||||
#include "BLI_threads.h"
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief State of a MemoryProxy in the MemoryManager.
|
||||
* @ingroup Memory
|
||||
*/
|
||||
class MemoryManagerState {
|
||||
private:
|
||||
/**
|
||||
* @brief reference to the MemoryProxy of this state
|
||||
*/
|
||||
MemoryProxy *memoryProxy;
|
||||
|
||||
/**
|
||||
* @brief list of all chunkbuffers
|
||||
*/
|
||||
MemoryBuffer** chunkBuffers;
|
||||
|
||||
/**
|
||||
* @brief size of the chunkBuffers
|
||||
*/
|
||||
unsigned int currentSize;
|
||||
|
||||
/**
|
||||
* @brief lock to this memory for multithreading
|
||||
*/
|
||||
ThreadMutex mutex;
|
||||
public:
|
||||
/**
|
||||
* @brief creates a new MemoryManagerState for a certain MemoryProxy.
|
||||
*/
|
||||
MemoryManagerState(MemoryProxy * memoryProxy);
|
||||
/**
|
||||
* @brief destructor
|
||||
*/
|
||||
~MemoryManagerState();
|
||||
|
||||
/**
|
||||
* @brief get the reference to the MemoryProxy this state belongs to.
|
||||
*/
|
||||
MemoryProxy *getMemoryProxy();
|
||||
|
||||
/**
|
||||
* @brief add a new memorybuffer to the state
|
||||
*/
|
||||
void addMemoryBuffer(MemoryBuffer *buffer);
|
||||
|
||||
/**
|
||||
* @brief get the MemoryBuffer assiciated to a chunk.
|
||||
* @param chunkNumber the chunknumber
|
||||
*/
|
||||
MemoryBuffer *getMemoryBuffer(unsigned int chunkNumber);
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -25,15 +25,26 @@
|
||||
|
||||
MemoryProxy::MemoryProxy()
|
||||
{
|
||||
this->state = NULL;
|
||||
this->writeBufferOperation = NULL;
|
||||
this->executor = NULL;
|
||||
}
|
||||
|
||||
MemoryProxy::~MemoryProxy()
|
||||
void MemoryProxy::allocate(unsigned int width, unsigned int height)
|
||||
{
|
||||
if (this->state) {
|
||||
delete this->state;
|
||||
this->state = NULL;
|
||||
rcti result;
|
||||
result.xmin = 0;
|
||||
result.xmax = width;
|
||||
result.ymin = 0;
|
||||
result.ymax = height;
|
||||
|
||||
buffer = new MemoryBuffer(this, 1, &result);
|
||||
}
|
||||
|
||||
void MemoryProxy::free()
|
||||
{
|
||||
if (buffer) {
|
||||
delete buffer;
|
||||
buffer = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -26,7 +26,6 @@ class MemoryProxy;
|
||||
#ifndef _COM_MemoryProxy_h
|
||||
#define _COM_MemoryProxy_h
|
||||
#include "COM_ExecutionGroup.h"
|
||||
#include "COM_MemoryManagerState.h"
|
||||
|
||||
class ExecutionGroup;
|
||||
|
||||
@@ -48,12 +47,6 @@ private:
|
||||
*/
|
||||
ExecutionGroup *executor;
|
||||
|
||||
/**
|
||||
* @brief data of the different chunks.
|
||||
* @note state is part of this class due to optimization in the MemoryManager
|
||||
*/
|
||||
MemoryManagerState * state;
|
||||
|
||||
/**
|
||||
* @brief datatype of this MemoryProxy
|
||||
*/
|
||||
@@ -63,9 +56,14 @@ private:
|
||||
* @brief channel information of this buffer
|
||||
*/
|
||||
ChannelInfo channelInfo[COM_NUMBER_OF_CHANNELS];
|
||||
|
||||
/**
|
||||
* @brief the allocated memory
|
||||
*/
|
||||
MemoryBuffer* buffer;
|
||||
|
||||
public:
|
||||
MemoryProxy();
|
||||
~MemoryProxy();
|
||||
|
||||
/**
|
||||
* @brief set the ExecutionGroup that can be scheduled to calculate a certain chunk.
|
||||
@@ -89,18 +87,21 @@ public:
|
||||
* @return WriteBufferOperation
|
||||
*/
|
||||
WriteBufferOperation *getWriteBufferOperation() {return this->writeBufferOperation;}
|
||||
|
||||
|
||||
/**
|
||||
* @brief set the memorymanager state of this MemoryProxy, this is set from the MemoryManager
|
||||
* @param state the state to set
|
||||
* @brief allocate memory of size widht x height
|
||||
*/
|
||||
void setState(MemoryManagerState *state) {this->state = state;}
|
||||
|
||||
void allocate(unsigned int width, unsigned int height);
|
||||
|
||||
/**
|
||||
* @brief get the state of this MemoryProxy
|
||||
* @return MemoryManagerState reference to the state of this MemoryProxy.
|
||||
* @brief free the allocated memory
|
||||
*/
|
||||
MemoryManagerState *getState() {return this->state;}
|
||||
void free();
|
||||
|
||||
/**
|
||||
* @brief get the allocated memory
|
||||
*/
|
||||
inline MemoryBuffer* getBuffer() {return this->buffer;}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -20,8 +20,8 @@
|
||||
* Monique Dewanchand
|
||||
*/
|
||||
|
||||
#ifndef _COM_NodeProgram_h
|
||||
#define _COM_NodeProgram_h
|
||||
#ifndef _COM_NodeOperation_h
|
||||
#define _COM_NodeOperation_h
|
||||
|
||||
class NodeOperation;
|
||||
|
||||
@@ -33,6 +33,7 @@ class NodeOperation;
|
||||
#include "COM_SocketReader.h"
|
||||
#include "OCL_opencl.h"
|
||||
#include "list"
|
||||
#include "BLI_threads.h"
|
||||
|
||||
class ReadBufferOperation;
|
||||
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
#ifndef _COM_NodeProgram_h
|
||||
#define _COM_NodeProgram_h
|
||||
|
||||
class NodeProgram{
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -53,7 +53,7 @@ void OpenCLDevice::execute(WorkPackage *work)
|
||||
rcti rect;
|
||||
|
||||
executionGroup->determineChunkRect(&rect, chunkNumber);
|
||||
MemoryBuffer ** inputBuffers = executionGroup->getInputBuffers(chunkNumber);
|
||||
MemoryBuffer ** inputBuffers = executionGroup->getInputBuffersOpenCL(chunkNumber);
|
||||
MemoryBuffer * outputBuffer = executionGroup->allocateOutputBuffer(chunkNumber, &rect);
|
||||
|
||||
executionGroup->getOutputNodeOperation()->executeOpenCLRegion(this->context, this->program, this->queue, &rect, chunkNumber, inputBuffers);
|
||||
|
||||
@@ -37,10 +37,11 @@ void BlurNode::convertToOperations(ExecutionSystem *graph, CompositorContext * c
|
||||
{
|
||||
bNode *editorNode = this->getbNode();
|
||||
NodeBlurData * data = (NodeBlurData*)editorNode->storage;
|
||||
#if 0
|
||||
InputSocket * inputSizeSocket = this->getInputSocket(1);
|
||||
bool connectedSizeSocket = inputSizeSocket->isConnected();
|
||||
|
||||
const bNodeSocket *sock = this->getInputSocket(1)->getbNodeSocket();
|
||||
const float size = ((const bNodeSocketValueFloat*)sock->default_value)->value;
|
||||
#endif
|
||||
|
||||
CompositorQuality quality = context->getQuality();
|
||||
|
||||
@@ -71,6 +72,11 @@ void BlurNode::convertToOperations(ExecutionSystem *graph, CompositorContext * c
|
||||
addLink(graph, operationx->getOutputSocket(), operationy->getInputSocket(0));
|
||||
addLink(graph, operationx->getInputSocket(1)->getConnection()->getFromSocket(), operationy->getInputSocket(1));
|
||||
addPreviewOperation(graph, operationy->getOutputSocket(), 5);
|
||||
|
||||
if (!connectedSizeSocket) {
|
||||
operationx->setSize(size);
|
||||
operationy->setSize(size);
|
||||
}
|
||||
}
|
||||
else {
|
||||
GaussianBokehBlurOperation *operation = new GaussianBokehBlurOperation();
|
||||
@@ -81,5 +87,9 @@ void BlurNode::convertToOperations(ExecutionSystem *graph, CompositorContext * c
|
||||
graph->addOperation(operation);
|
||||
this->getOutputSocket(0)->relinkConnections(operation->getOutputSocket());
|
||||
addPreviewOperation(graph, operation->getOutputSocket(), 5);
|
||||
|
||||
if (!connectedSizeSocket) {
|
||||
operation->setSize(size);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,6 +37,7 @@ BlurBaseOperation::BlurBaseOperation(): NodeOperation()
|
||||
this->data = NULL;
|
||||
this->size = 1.0f;
|
||||
this->deleteData = false;
|
||||
this->sizeavailable=false;
|
||||
}
|
||||
void BlurBaseOperation::initExecution()
|
||||
{
|
||||
|
||||
@@ -39,6 +39,7 @@ protected:
|
||||
float *make_gausstab(int rad);
|
||||
float size;
|
||||
bool deleteData;
|
||||
bool sizeavailable;
|
||||
void updateSize(MemoryBuffer **memoryBuffers);
|
||||
public:
|
||||
/**
|
||||
@@ -54,5 +55,7 @@ public:
|
||||
void setData(NodeBlurData *data) {this->data = data;}
|
||||
|
||||
void deleteDataWhenFinished() {this->deleteData = true;}
|
||||
|
||||
void setSize(float size) {this->size = size; sizeavailable = true;}
|
||||
};
|
||||
#endif
|
||||
|
||||
@@ -34,11 +34,20 @@ GaussianBokehBlurOperation::GaussianBokehBlurOperation(): BlurBaseOperation()
|
||||
|
||||
void *GaussianBokehBlurOperation::initializeTileData(rcti *rect, MemoryBuffer **memoryBuffers)
|
||||
{
|
||||
updateGauss(memoryBuffers);
|
||||
if (!sizeavailable) {
|
||||
updateGauss(memoryBuffers);
|
||||
}
|
||||
void *buffer = getInputOperation(0)->initializeTileData(NULL, memoryBuffers);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
void GaussianBokehBlurOperation::initExecution()
|
||||
{
|
||||
if (this->sizeavailable) {
|
||||
updateGauss(NULL);
|
||||
}
|
||||
}
|
||||
|
||||
void GaussianBokehBlurOperation::updateGauss(MemoryBuffer **memoryBuffers)
|
||||
{
|
||||
if (this->gausstab == NULL) {
|
||||
@@ -51,8 +60,9 @@ void GaussianBokehBlurOperation::updateGauss(MemoryBuffer **memoryBuffers)
|
||||
int j, i;
|
||||
const float width = this->getWidth();
|
||||
const float height = this->getHeight();
|
||||
updateSize(memoryBuffers);
|
||||
|
||||
if (!sizeavailable) {
|
||||
updateSize(memoryBuffers);
|
||||
}
|
||||
radxf = size*(float)this->data->sizex;
|
||||
if (radxf>width/2.0f)
|
||||
radxf = width/2.0f;
|
||||
@@ -163,19 +173,20 @@ bool GaussianBokehBlurOperation::determineDependingAreaOfInterest(rcti *input, R
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
if (this->gausstab) {
|
||||
if (this->sizeavailable && this->gausstab != NULL) {
|
||||
newInput.xmin = 0;
|
||||
newInput.ymin = 0;
|
||||
newInput.xmax = this->getWidth();
|
||||
newInput.ymax = this->getHeight();
|
||||
}
|
||||
else {
|
||||
int addx = radx;
|
||||
int addy = rady;
|
||||
newInput.xmax = input->xmax + addx;
|
||||
newInput.xmin = input->xmin - addx;
|
||||
newInput.ymax = input->ymax + addy;
|
||||
newInput.ymin = input->ymin - addy;
|
||||
}
|
||||
else {
|
||||
newInput.xmin = 0;
|
||||
newInput.ymin = 0;
|
||||
newInput.xmax = this->getWidth();
|
||||
newInput.ymax = this->getHeight();
|
||||
|
||||
}
|
||||
return BlurBaseOperation::determineDependingAreaOfInterest(&newInput, readOperation, output);
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@ private:
|
||||
|
||||
public:
|
||||
GaussianBokehBlurOperation();
|
||||
|
||||
void initExecution();
|
||||
void *initializeTileData(rcti *rect, MemoryBuffer **memoryBuffers);
|
||||
/**
|
||||
* the inner loop of this program
|
||||
|
||||
@@ -36,11 +36,25 @@ GaussianXBlurOperation::GaussianXBlurOperation(): BlurBaseOperation()
|
||||
|
||||
void *GaussianXBlurOperation::initializeTileData(rcti *rect, MemoryBuffer **memoryBuffers)
|
||||
{
|
||||
updateGauss(memoryBuffers);
|
||||
if (!this->sizeavailable) {
|
||||
updateGauss(memoryBuffers);
|
||||
}
|
||||
void *buffer = getInputOperation(0)->initializeTileData(NULL, memoryBuffers);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
void GaussianXBlurOperation::initExecution()
|
||||
{
|
||||
if (this->sizeavailable) {
|
||||
float rad = size*this->data->sizex;
|
||||
if (rad<1)
|
||||
rad = 1;
|
||||
|
||||
this->rad = rad;
|
||||
this->gausstab = BlurBaseOperation::make_gausstab(rad);
|
||||
}
|
||||
}
|
||||
|
||||
void GaussianXBlurOperation::updateGauss(MemoryBuffer **memoryBuffers)
|
||||
{
|
||||
if (this->gausstab == NULL) {
|
||||
@@ -118,18 +132,18 @@ bool GaussianXBlurOperation::determineDependingAreaOfInterest(rcti *input, ReadB
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
if (this->gausstab == NULL) {
|
||||
newInput.xmax = this->getWidth();
|
||||
newInput.xmin = 0;
|
||||
newInput.ymax = this->getHeight();
|
||||
newInput.ymin = 0;
|
||||
}
|
||||
else {
|
||||
if (this->sizeavailable && this->gausstab != NULL) {
|
||||
newInput.xmax = input->xmax + rad;
|
||||
newInput.xmin = input->xmin - rad;
|
||||
newInput.ymax = input->ymax;
|
||||
newInput.ymin = input->ymin;
|
||||
}
|
||||
else {
|
||||
newInput.xmax = this->getWidth();
|
||||
newInput.xmin = 0;
|
||||
newInput.ymax = this->getHeight();
|
||||
newInput.ymin = 0;
|
||||
}
|
||||
return NodeOperation::determineDependingAreaOfInterest(&newInput, readOperation, output);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,12 +34,17 @@ public:
|
||||
GaussianXBlurOperation();
|
||||
|
||||
/**
|
||||
* the inner loop of this program
|
||||
*@brief the inner loop of this program
|
||||
*/
|
||||
void executePixel(float *color, int x, int y, MemoryBuffer *inputBuffers[], void *data);
|
||||
|
||||
/**
|
||||
* Deinitialize the execution
|
||||
*@brief initialize the execution
|
||||
*/
|
||||
void initExecution();
|
||||
|
||||
/**
|
||||
*@brief Deinitialize the execution
|
||||
*/
|
||||
void deinitExecution();
|
||||
|
||||
|
||||
@@ -35,11 +35,25 @@ GaussianYBlurOperation::GaussianYBlurOperation(): BlurBaseOperation()
|
||||
|
||||
void *GaussianYBlurOperation::initializeTileData(rcti *rect, MemoryBuffer **memoryBuffers)
|
||||
{
|
||||
updateGauss(memoryBuffers);
|
||||
if (!this->sizeavailable) {
|
||||
updateGauss(memoryBuffers);
|
||||
}
|
||||
void *buffer = getInputOperation(0)->initializeTileData(NULL, memoryBuffers);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
void GaussianYBlurOperation::initExecution()
|
||||
{
|
||||
if (this->sizeavailable) {
|
||||
float rad = size*this->data->sizex;
|
||||
if (rad<1)
|
||||
rad = 1;
|
||||
|
||||
this->rad = rad;
|
||||
this->gausstab = BlurBaseOperation::make_gausstab(rad);
|
||||
}
|
||||
}
|
||||
|
||||
void GaussianYBlurOperation::updateGauss(MemoryBuffer **memoryBuffers)
|
||||
{
|
||||
if (this->gausstab == NULL) {
|
||||
@@ -115,18 +129,18 @@ bool GaussianYBlurOperation::determineDependingAreaOfInterest(rcti *input, ReadB
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
if (this->gausstab == NULL) {
|
||||
newInput.xmax = this->getWidth();
|
||||
newInput.xmin = 0;
|
||||
newInput.ymax = this->getHeight();
|
||||
newInput.ymin = 0;
|
||||
}
|
||||
else {
|
||||
if (this->sizeavailable && this->gausstab != NULL) {
|
||||
newInput.xmax = input->xmax;
|
||||
newInput.xmin = input->xmin;
|
||||
newInput.ymax = input->ymax + rad;
|
||||
newInput.ymin = input->ymin - rad;
|
||||
}
|
||||
else {
|
||||
newInput.xmax = this->getWidth();
|
||||
newInput.xmin = 0;
|
||||
newInput.ymax = this->getHeight();
|
||||
newInput.ymin = 0;
|
||||
}
|
||||
return NodeOperation::determineDependingAreaOfInterest(&newInput, readOperation, output);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,6 +38,11 @@ public:
|
||||
*/
|
||||
void executePixel(float *color, int x, int y, MemoryBuffer *inputBuffers[], void *data);
|
||||
|
||||
/**
|
||||
*@brief initialize the execution
|
||||
*/
|
||||
void initExecution();
|
||||
|
||||
/**
|
||||
* Deinitialize the execution
|
||||
*/
|
||||
|
||||
@@ -22,10 +22,8 @@
|
||||
|
||||
#include "COM_WriteBufferOperation.h"
|
||||
#include "COM_defines.h"
|
||||
#include "COM_MemoryManager.h"
|
||||
#include <stdio.h>
|
||||
|
||||
/// @TODO: writebuffers don't have an actual data type set.
|
||||
WriteBufferOperation::WriteBufferOperation() :NodeOperation()
|
||||
{
|
||||
this->addInputSocket(COM_DT_COLOR);
|
||||
@@ -46,20 +44,23 @@ void WriteBufferOperation::executePixel(float *color, float x, float y, PixelSam
|
||||
{
|
||||
input->read(color, x, y, sampler, inputBuffers);
|
||||
}
|
||||
|
||||
void WriteBufferOperation::initExecution()
|
||||
{
|
||||
this->input = this->getInputOperation(0);
|
||||
MemoryManager::addMemoryProxy(this->memoryProxy);
|
||||
this->input = this->getInputOperation(0);
|
||||
this->memoryProxy->allocate(this->width, this->height);
|
||||
}
|
||||
|
||||
void WriteBufferOperation::deinitExecution()
|
||||
{
|
||||
this->input = NULL;
|
||||
this->memoryProxy->free();
|
||||
}
|
||||
|
||||
|
||||
void WriteBufferOperation::executeRegion(rcti *rect, unsigned int tileNumber, MemoryBuffer** memoryBuffers)
|
||||
{
|
||||
MemoryBuffer *memoryBuffer = MemoryManager::getMemoryBuffer(this->getMemoryProxy(), tileNumber);
|
||||
//MemoryBuffer *memoryBuffer = MemoryManager::getMemoryBuffer(this->getMemoryProxy(), tileNumber);
|
||||
MemoryBuffer *memoryBuffer = this->memoryProxy->getBuffer();
|
||||
float *buffer = memoryBuffer->getBuffer();
|
||||
if (this->input->isComplex()) {
|
||||
void *data = this->input->initializeTileData(rect, memoryBuffers);
|
||||
@@ -67,14 +68,14 @@ void WriteBufferOperation::executeRegion(rcti *rect, unsigned int tileNumber, Me
|
||||
int y1 = rect->ymin;
|
||||
int x2 = rect->xmax;
|
||||
int y2 = rect->ymax;
|
||||
int offset4 = 0;
|
||||
int x;
|
||||
int y;
|
||||
bool breaked = false;
|
||||
for (y = y1 ; y < y2 && (!breaked) ; y++) {
|
||||
int offset4 = (y*memoryBuffer->getWidth()+x1)*COM_NUMBER_OF_CHANNELS;
|
||||
for (x = x1 ; x < x2; x++) {
|
||||
input->read(&(buffer[offset4]), x, y, memoryBuffers, data);
|
||||
offset4 +=4;
|
||||
offset4 +=COM_NUMBER_OF_CHANNELS;
|
||||
|
||||
}
|
||||
if (tree->test_break && tree->test_break(tree->tbh)) {
|
||||
@@ -92,14 +93,15 @@ void WriteBufferOperation::executeRegion(rcti *rect, unsigned int tileNumber, Me
|
||||
int y1 = rect->ymin;
|
||||
int x2 = rect->xmax;
|
||||
int y2 = rect->ymax;
|
||||
int offset4 = 0;
|
||||
|
||||
int x;
|
||||
int y;
|
||||
bool breaked = false;
|
||||
for (y = y1 ; y < y2 && (!breaked) ; y++) {
|
||||
int offset4 = (y*memoryBuffer->getWidth()+x1)*COM_NUMBER_OF_CHANNELS;
|
||||
for (x = x1 ; x < x2 ; x++) {
|
||||
input->read(&(buffer[offset4]), x, y, COM_PS_NEAREST, memoryBuffers);
|
||||
offset4 +=4;
|
||||
offset4 +=COM_NUMBER_OF_CHANNELS;
|
||||
}
|
||||
if (tree->test_break && tree->test_break(tree->tbh)) {
|
||||
breaked = true;
|
||||
@@ -111,7 +113,7 @@ void WriteBufferOperation::executeRegion(rcti *rect, unsigned int tileNumber, Me
|
||||
|
||||
void WriteBufferOperation::executeOpenCLRegion(cl_context context, cl_program program, cl_command_queue queue, rcti *rect, unsigned int chunkNumber, MemoryBuffer** inputMemoryBuffers)
|
||||
{
|
||||
MemoryBuffer *outputMemoryBuffer = MemoryManager::getMemoryBuffer(this->getMemoryProxy(), chunkNumber);
|
||||
MemoryBuffer *outputMemoryBuffer = this->getMemoryProxy()->getBuffer();// @todo wrong implementation needs revision
|
||||
float *outputFloatBuffer = outputMemoryBuffer->getBuffer();
|
||||
cl_int error;
|
||||
/*
|
||||
|
||||
@@ -3060,7 +3060,7 @@ static void achannel_setting_slider_shapekey_cb(bContext *C, void *key_poin, voi
|
||||
/* find or create new F-Curve */
|
||||
// XXX is the group name for this ok?
|
||||
bAction *act = verify_adt_action((ID *)key, 1);
|
||||
FCurve *fcu = verify_fcurve(act, NULL, rna_path, 0, 1);
|
||||
FCurve *fcu = verify_fcurve(act, NULL, &ptr, rna_path, 0, 1);
|
||||
|
||||
/* set the special 'replace' flag if on a keyframe */
|
||||
if (fcurve_frame_has_keyframe(fcu, cfra, 0))
|
||||
|
||||
@@ -671,7 +671,7 @@ static void paste_animedit_keys_fcurve(FCurve *fcu, tAnimCopybufItem *aci, float
|
||||
BezTriple *bezt;
|
||||
int i;
|
||||
|
||||
/* First de-select existing FCuvre */
|
||||
/* First de-select existing FCurve's keyframes */
|
||||
for (i = 0, bezt = fcu->bezt; i < fcu->totvert; i++, bezt++) {
|
||||
bezt->f2 &= ~SELECT;
|
||||
}
|
||||
|
||||
@@ -150,9 +150,10 @@ bAction *verify_adt_action(ID *id, short add)
|
||||
/* Get (or add relevant data to be able to do so) F-Curve from the Active Action,
|
||||
* for the given Animation Data block. This assumes that all the destinations are valid.
|
||||
*/
|
||||
FCurve *verify_fcurve(bAction *act, const char group[], const char rna_path[], const int array_index, short add)
|
||||
FCurve *verify_fcurve(bAction *act, const char group[], PointerRNA *ptr,
|
||||
const char rna_path[], const int array_index, short add)
|
||||
{
|
||||
bActionGroup *grp;
|
||||
bActionGroup *agrp;
|
||||
FCurve *fcu;
|
||||
|
||||
/* sanity checks */
|
||||
@@ -183,14 +184,30 @@ FCurve *verify_fcurve(bAction *act, const char group[], const char rna_path[], c
|
||||
/* if a group name has been provided, try to add or find a group, then add F-Curve to it */
|
||||
if (group) {
|
||||
/* try to find group */
|
||||
grp = BKE_action_group_find_name(act, group);
|
||||
agrp = BKE_action_group_find_name(act, group);
|
||||
|
||||
/* no matching groups, so add one */
|
||||
if (grp == NULL)
|
||||
grp = action_groups_add_new(act, group);
|
||||
if (agrp == NULL) {
|
||||
agrp = action_groups_add_new(act, group);
|
||||
|
||||
/* sync bone group colors if applicable */
|
||||
if (ptr && (ptr->type == &RNA_PoseBone)) {
|
||||
Object *ob = (Object *)ptr->id.data;
|
||||
bPoseChannel *pchan = (bPoseChannel *)ptr->data;
|
||||
bPose *pose = ob->pose;
|
||||
bActionGroup *grp;
|
||||
|
||||
/* find bone group (if present), and use the color from that */
|
||||
grp = (bActionGroup *)BLI_findlink(&pose->agroups, (pchan->agrp_index - 1));
|
||||
if (grp) {
|
||||
agrp->customCol = grp->customCol;
|
||||
action_group_colors_sync(agrp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* add F-Curve to group */
|
||||
action_groups_add_channel(act, grp, fcu);
|
||||
action_groups_add_channel(act, agrp, fcu);
|
||||
}
|
||||
else {
|
||||
/* just add F-Curve to end of Action's list */
|
||||
@@ -939,7 +956,7 @@ short insert_keyframe(ReportList *reports, ID *id, bAction *act, const char grou
|
||||
* - if we're replacing keyframes only, DO NOT create new F-Curves if they do not exist yet
|
||||
* but still try to get the F-Curve if it exists...
|
||||
*/
|
||||
fcu = verify_fcurve(act, group, rna_path, array_index, (flag & INSERTKEY_REPLACE) == 0);
|
||||
fcu = verify_fcurve(act, group, &ptr, rna_path, array_index, (flag & INSERTKEY_REPLACE) == 0);
|
||||
|
||||
/* we may not have a F-Curve when we're replacing only... */
|
||||
if (fcu) {
|
||||
@@ -1027,7 +1044,7 @@ short delete_keyframe(ReportList *reports, ID *id, bAction *act, const char grou
|
||||
|
||||
/* will only loop once unless the array index was -1 */
|
||||
for (; array_index < array_index_max; array_index++) {
|
||||
FCurve *fcu = verify_fcurve(act, group, rna_path, array_index, 0);
|
||||
FCurve *fcu = verify_fcurve(act, group, &ptr, rna_path, array_index, 0);
|
||||
short found = -1;
|
||||
int i;
|
||||
|
||||
|
||||
@@ -75,7 +75,8 @@ struct bAction *verify_adt_action(struct ID *id, short add);
|
||||
/* Get (or add relevant data to be able to do so) F-Curve from the given Action.
|
||||
* This assumes that all the destinations are valid.
|
||||
*/
|
||||
struct FCurve *verify_fcurve(struct bAction *act, const char group[], const char rna_path[], const int array_index, short add);
|
||||
struct FCurve *verify_fcurve(struct bAction *act, const char group[], struct PointerRNA *ptr,
|
||||
const char rna_path[], const int array_index, short add);
|
||||
|
||||
/* -------- */
|
||||
|
||||
|
||||
@@ -542,7 +542,7 @@ int ED_object_parent_set(ReportList *reports, Main *bmain, Scene *scene, Object
|
||||
if (partype == PAR_FOLLOW) {
|
||||
/* get or create F-Curve */
|
||||
bAction *act = verify_adt_action(&cu->id, 1);
|
||||
FCurve *fcu = verify_fcurve(act, NULL, "eval_time", 0, 1);
|
||||
FCurve *fcu = verify_fcurve(act, NULL, NULL, "eval_time", 0, 1);
|
||||
|
||||
/* setup dummy 'generator' modifier here to get 1-1 correspondence still working */
|
||||
if (!fcu->bezt && !fcu->fpt && !fcu->modifiers.first)
|
||||
|
||||
@@ -681,9 +681,9 @@ static void draw_group_socket(const bContext *C, SpaceNode *snode, bNodeTree *nt
|
||||
|
||||
/* node and group socket circles */
|
||||
if (sock)
|
||||
node_socket_circle_draw(ntree, sock, socket_size);
|
||||
node_socket_circle_draw(ntree, sock, socket_size, sock->flag & SELECT);
|
||||
if (gsock)
|
||||
node_socket_circle_draw(ngroup, gsock, socket_size);
|
||||
node_socket_circle_draw(ngroup, gsock, socket_size, gsock->flag & SELECT);
|
||||
|
||||
/* socket name */
|
||||
offset = (in_out == SOCK_IN ? col1 : cor3);
|
||||
@@ -1048,6 +1048,105 @@ static void node_buts_frame_details(uiLayout *layout, bContext *UNUSED(C), Point
|
||||
uiItemR(layout, ptr, "shrink", 0, "Shrink", ICON_NONE);
|
||||
}
|
||||
|
||||
|
||||
#define NODE_REROUTE_SIZE 8.0f
|
||||
|
||||
static void node_update_reroute(const bContext *UNUSED(C), bNodeTree *UNUSED(ntree), bNode *node)
|
||||
{
|
||||
bNodeSocket *nsock;
|
||||
float locx, locy;
|
||||
float size = NODE_REROUTE_SIZE;
|
||||
|
||||
/* get "global" coords */
|
||||
nodeToView(node, 0.0f, 0.0f, &locx, &locy);
|
||||
|
||||
/* reroute node has exactly one input and one output, both in the same place */
|
||||
nsock= node->outputs.first;
|
||||
nsock->locx= locx;
|
||||
nsock->locy= locy;
|
||||
|
||||
nsock= node->inputs.first;
|
||||
nsock->locx= locx;
|
||||
nsock->locy= locy;
|
||||
|
||||
node->width = size*2;
|
||||
node->totr.xmin= locx - size;
|
||||
node->totr.xmax= locx + size;
|
||||
node->totr.ymax= locy + size;
|
||||
node->totr.ymin= locy - size;
|
||||
}
|
||||
|
||||
static void node_draw_reroute(const bContext *C, ARegion *ar, SpaceNode *UNUSED(snode), bNodeTree *ntree, bNode *node)
|
||||
{
|
||||
bNodeSocket *sock;
|
||||
#if 0 /* UNUSED */
|
||||
rctf *rct= &node->totr;
|
||||
float size = NODE_REROUTE_SIZE;
|
||||
#endif
|
||||
float socket_size= NODE_SOCKSIZE;
|
||||
|
||||
/* skip if out of view */
|
||||
if (node->totr.xmax < ar->v2d.cur.xmin || node->totr.xmin > ar->v2d.cur.xmax ||
|
||||
node->totr.ymax < ar->v2d.cur.ymin || node->totr.ymin > ar->v2d.cur.ymax) {
|
||||
|
||||
uiEndBlock(C, node->block);
|
||||
node->block= NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
/* XXX only kept for debugging
|
||||
* selection state is indicated by socket outline below!
|
||||
*/
|
||||
#if 0
|
||||
/* body */
|
||||
uiSetRoundBox(15);
|
||||
UI_ThemeColor4(TH_NODE);
|
||||
glEnable(GL_BLEND);
|
||||
uiRoundBox(rct->xmin, rct->ymin, rct->xmax, rct->ymax, size);
|
||||
glDisable(GL_BLEND);
|
||||
|
||||
/* outline active and selected emphasis */
|
||||
if( node->flag & (NODE_ACTIVE|SELECT) ) {
|
||||
glEnable(GL_BLEND);
|
||||
glEnable( GL_LINE_SMOOTH );
|
||||
/* using different shades of TH_TEXT_HI for the empasis, like triangle */
|
||||
if( node->flag & NODE_ACTIVE )
|
||||
UI_ThemeColorShadeAlpha(TH_TEXT_HI, 0, -40);
|
||||
else
|
||||
UI_ThemeColorShadeAlpha(TH_TEXT_HI, -20, -120);
|
||||
uiDrawBox(GL_LINE_LOOP, rct->xmin, rct->ymin, rct->xmax, rct->ymax, size);
|
||||
|
||||
glDisable( GL_LINE_SMOOTH );
|
||||
glDisable(GL_BLEND);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* only draw input socket. as they all are placed on the same position.
|
||||
* highlight also if node itself is selected, since we don't display the node body separately!
|
||||
*/
|
||||
for(sock= node->inputs.first; sock; sock= sock->next) {
|
||||
node_socket_circle_draw(ntree, sock, socket_size, (sock->flag & SELECT) || (node->flag & SELECT));
|
||||
}
|
||||
|
||||
uiEndBlock(C, node->block);
|
||||
uiDrawBlock(C, node->block);
|
||||
node->block= NULL;
|
||||
}
|
||||
|
||||
/* Special tweak area for reroute node.
|
||||
* Since this node is quite small, we use a larger tweak area for grabbing than for selection.
|
||||
*/
|
||||
static int node_tweak_area_reroute(bNode *node, int x, int y)
|
||||
{
|
||||
/* square of tweak radius */
|
||||
static const float tweak_radius_sq = 576; /* 24*24 */
|
||||
|
||||
bNodeSocket *sock = node->inputs.first;
|
||||
float dx = sock->locx - x;
|
||||
float dy = sock->locy - y;
|
||||
return (dx*dx + dy*dy <= tweak_radius_sq);
|
||||
}
|
||||
|
||||
static void node_common_set_butfunc(bNodeType *ntype)
|
||||
{
|
||||
switch (ntype->type) {
|
||||
@@ -1072,6 +1171,11 @@ static void node_common_set_butfunc(bNodeType *ntype)
|
||||
ntype->uifuncbut = node_buts_frame_details;
|
||||
ntype->resize_area_func = node_resize_area_frame;
|
||||
break;
|
||||
case NODE_REROUTE:
|
||||
ntype->drawfunc= node_draw_reroute;
|
||||
ntype->drawupdatefunc= node_update_reroute;
|
||||
ntype->tweak_area_func= node_tweak_area_reroute;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2696,6 +2800,8 @@ void ED_init_node_butfuncs(void)
|
||||
/* default ui functions */
|
||||
ntype->drawfunc = node_draw_default;
|
||||
ntype->drawupdatefunc = node_update_default;
|
||||
ntype->select_area_func = node_select_area_default;
|
||||
ntype->tweak_area_func = node_tweak_area_default;
|
||||
ntype->uifunc = NULL;
|
||||
ntype->uifuncbut = NULL;
|
||||
ntype->drawinputfunc = node_draw_input_default;
|
||||
@@ -2890,36 +2996,61 @@ static void draw_nodespace_back_tex(ScrArea *sa, SpaceNode *snode)
|
||||
int node_link_bezier_points(View2D *v2d, SpaceNode *snode, bNodeLink *link, float coord_array[][2], int resol)
|
||||
{
|
||||
float dist, vec[4][2];
|
||||
|
||||
float deltax, deltay;
|
||||
int toreroute, fromreroute;
|
||||
/* in v0 and v3 we put begin/end points */
|
||||
if (link->fromsock) {
|
||||
vec[0][0] = link->fromsock->locx;
|
||||
vec[0][1] = link->fromsock->locy;
|
||||
fromreroute = (link->fromnode && link->fromnode->type == NODE_REROUTE);
|
||||
}
|
||||
else {
|
||||
if (snode == NULL) return 0;
|
||||
vec[0][0] = snode->mx;
|
||||
vec[0][1] = snode->my;
|
||||
fromreroute = 0;
|
||||
}
|
||||
if (link->tosock) {
|
||||
vec[3][0] = link->tosock->locx;
|
||||
vec[3][1] = link->tosock->locy;
|
||||
toreroute = (link->tonode && link->tonode->type == NODE_REROUTE);
|
||||
}
|
||||
else {
|
||||
if (snode == NULL) return 0;
|
||||
vec[3][0] = snode->mx;
|
||||
vec[3][1] = snode->my;
|
||||
toreroute = 0;
|
||||
}
|
||||
|
||||
dist = UI_GetThemeValue(TH_NODE_CURVING) * 0.10f * ABS(vec[0][0] - vec[3][0]);
|
||||
|
||||
deltax = vec[3][0] - vec[0][0];
|
||||
deltay = vec[3][1] - vec[0][1];
|
||||
/* check direction later, for top sockets */
|
||||
vec[1][0] = vec[0][0] + dist;
|
||||
vec[1][1] = vec[0][1];
|
||||
|
||||
vec[2][0] = vec[3][0] - dist;
|
||||
vec[2][1] = vec[3][1];
|
||||
|
||||
if (fromreroute) {
|
||||
if (ABS(deltax)>ABS(deltay)) {
|
||||
vec[1][1]= vec[0][1];
|
||||
vec[1][0]= vec[0][0]+(deltax>0?dist:-dist);
|
||||
} else {
|
||||
vec[1][0]= vec[0][0];
|
||||
vec[1][1]= vec[0][1]+(deltay>0?dist:-dist);
|
||||
}
|
||||
} else {
|
||||
vec[1][0] = vec[0][0] + dist;
|
||||
vec[1][1] = vec[0][1];
|
||||
}
|
||||
if (toreroute) {
|
||||
if (ABS(deltax)>ABS(deltay)) {
|
||||
vec[2][1]= vec[3][1];
|
||||
vec[2][0]= vec[3][0]+ (deltax>0?-dist:dist);
|
||||
} else {
|
||||
vec[2][0]= vec[3][0];
|
||||
vec[2][1]= vec[3][1]+(deltay>0?-dist:dist);
|
||||
}
|
||||
|
||||
} else {
|
||||
vec[2][0] = vec[3][0] - dist;
|
||||
vec[2][1] = vec[3][1];
|
||||
}
|
||||
if (v2d && MIN4(vec[0][0], vec[1][0], vec[2][0], vec[3][0]) > v2d->cur.xmax) ; /* clipped */
|
||||
else if (v2d && MAX4(vec[0][0], vec[1][0], vec[2][0], vec[3][0]) < v2d->cur.xmin) ; /* clipped */
|
||||
else {
|
||||
@@ -2934,6 +3065,8 @@ int node_link_bezier_points(View2D *v2d, SpaceNode *snode, bNodeLink *link, floa
|
||||
}
|
||||
|
||||
#define LINK_RESOL 24
|
||||
#define LINK_ARROW 12 /* position of arrow on the link, LINK_RESOL/2 */
|
||||
#define ARROW_SIZE 7
|
||||
void node_draw_link_bezier(View2D *v2d, SpaceNode *snode, bNodeLink *link, int th_col1, int do_shaded, int th_col2, int do_triple, int th_col3)
|
||||
{
|
||||
float coord_array[LINK_RESOL + 1][2];
|
||||
@@ -2941,9 +3074,10 @@ void node_draw_link_bezier(View2D *v2d, SpaceNode *snode, bNodeLink *link, int t
|
||||
if (node_link_bezier_points(v2d, snode, link, coord_array, LINK_RESOL)) {
|
||||
float dist, spline_step = 0.0f;
|
||||
int i;
|
||||
|
||||
int drawarrow;
|
||||
/* store current linewidth */
|
||||
float linew;
|
||||
float arrow[2], arrow1[2], arrow2[2];
|
||||
glGetFloatv(GL_LINE_WIDTH, &linew);
|
||||
|
||||
/* we can reuse the dist variable here to increment the GL curve eval amount*/
|
||||
@@ -2951,6 +3085,22 @@ void node_draw_link_bezier(View2D *v2d, SpaceNode *snode, bNodeLink *link, int t
|
||||
|
||||
glEnable(GL_LINE_SMOOTH);
|
||||
|
||||
drawarrow = (link->tonode && (link->tonode->type == NODE_REROUTE)) && (link->fromnode && (link->fromnode->type == NODE_REROUTE));
|
||||
if (drawarrow) {
|
||||
// draw arrow in line segment LINK_ARROW
|
||||
float dx, dy, len;
|
||||
dx = coord_array[LINK_ARROW][0]-coord_array[LINK_ARROW-1][0];
|
||||
dy = coord_array[LINK_ARROW][1]-coord_array[LINK_ARROW-1][1];
|
||||
len = sqrtf(dx*dx+dy*dy);
|
||||
dx = dx /len*ARROW_SIZE;
|
||||
dy = dy /len*ARROW_SIZE;
|
||||
arrow1[0] = coord_array[LINK_ARROW][0]-dx+dy;
|
||||
arrow1[1] = coord_array[LINK_ARROW][1]-dy-dx;
|
||||
arrow2[0] = coord_array[LINK_ARROW][0]-dx-dy;
|
||||
arrow2[1] = coord_array[LINK_ARROW][1]-dy+dx;
|
||||
arrow[0] = coord_array[LINK_ARROW][0];
|
||||
arrow[1] = coord_array[LINK_ARROW][1];
|
||||
}
|
||||
if (do_triple) {
|
||||
UI_ThemeColorShadeAlpha(th_col3, -80, -120);
|
||||
glLineWidth(4.0f);
|
||||
@@ -2960,6 +3110,14 @@ void node_draw_link_bezier(View2D *v2d, SpaceNode *snode, bNodeLink *link, int t
|
||||
glVertex2fv(coord_array[i]);
|
||||
}
|
||||
glEnd();
|
||||
if (drawarrow) {
|
||||
glBegin(GL_LINE_STRIP);
|
||||
glVertex2fv(arrow1);
|
||||
glVertex2fv(arrow);
|
||||
glVertex2fv(arrow);
|
||||
glVertex2fv(arrow2);
|
||||
glEnd();
|
||||
}
|
||||
}
|
||||
|
||||
/* XXX using GL_LINES for shaded node lines is a workaround
|
||||
@@ -2989,6 +3147,15 @@ void node_draw_link_bezier(View2D *v2d, SpaceNode *snode, bNodeLink *link, int t
|
||||
glEnd();
|
||||
}
|
||||
|
||||
if (drawarrow) {
|
||||
glBegin(GL_LINE_STRIP);
|
||||
glVertex2fv(arrow1);
|
||||
glVertex2fv(arrow);
|
||||
glVertex2fv(arrow);
|
||||
glVertex2fv(arrow2);
|
||||
glEnd();
|
||||
}
|
||||
|
||||
glDisable(GL_LINE_SMOOTH);
|
||||
|
||||
/* restore previuos linewidth */
|
||||
|
||||
@@ -46,6 +46,7 @@
|
||||
|
||||
#include "BLI_math.h"
|
||||
#include "BLI_blenlib.h"
|
||||
#include "BLI_rect.h"
|
||||
#include "BLI_threads.h"
|
||||
#include "BLI_utildefines.h"
|
||||
|
||||
@@ -81,7 +82,6 @@
|
||||
|
||||
/* width of socket columns in group display */
|
||||
#define NODE_GROUP_FRAME 120
|
||||
|
||||
// XXX interface.h
|
||||
extern void ui_dropshadow(rctf *rct, float radius, float aspect, int select);
|
||||
|
||||
@@ -496,6 +496,16 @@ void node_update_default(const bContext *C, bNodeTree *ntree, bNode *node)
|
||||
node_update_basis(C, ntree, node);
|
||||
}
|
||||
|
||||
int node_select_area_default(bNode *node, int x, int y)
|
||||
{
|
||||
return BLI_in_rctf(&node->totr, x, y);
|
||||
}
|
||||
|
||||
int node_tweak_area_default(bNode *node, int x, int y)
|
||||
{
|
||||
return BLI_in_rctf(&node->totr, x, y);
|
||||
}
|
||||
|
||||
int node_get_colorid(bNode *node)
|
||||
{
|
||||
if (node->typeinfo->nclass==NODE_CLASS_INPUT)
|
||||
@@ -585,10 +595,10 @@ static void node_circle_draw(float x, float y, float size, char *col, int highli
|
||||
glLineWidth(1.0f);
|
||||
}
|
||||
|
||||
void node_socket_circle_draw(bNodeTree *UNUSED(ntree), bNodeSocket *sock, float size)
|
||||
void node_socket_circle_draw(bNodeTree *UNUSED(ntree), bNodeSocket *sock, float size, int highlight)
|
||||
{
|
||||
bNodeSocketType *stype = ntreeGetSocketType(sock->type);
|
||||
node_circle_draw(sock->locx, sock->locy, size, stype->ui_color, (sock->flag & SELECT));
|
||||
node_circle_draw(sock->locx, sock->locy, size, stype->ui_color, highlight);
|
||||
}
|
||||
|
||||
/* ************** Socket callbacks *********** */
|
||||
@@ -819,7 +829,7 @@ static void node_draw_basis(const bContext *C, ARegion *ar, SpaceNode *snode, bN
|
||||
if (nodeSocketIsHidden(sock))
|
||||
continue;
|
||||
|
||||
node_socket_circle_draw(ntree, sock, NODE_SOCKSIZE);
|
||||
node_socket_circle_draw(ntree, sock, NODE_SOCKSIZE, sock->flag & SELECT);
|
||||
|
||||
node->typeinfo->drawinputfunc(C, node->block, ntree, node, sock, IFACE_(sock->name),
|
||||
sock->locx+NODE_DYS, sock->locy-NODE_DYS, node->width-NODE_DY);
|
||||
@@ -830,7 +840,7 @@ static void node_draw_basis(const bContext *C, ARegion *ar, SpaceNode *snode, bN
|
||||
if (nodeSocketIsHidden(sock))
|
||||
continue;
|
||||
|
||||
node_socket_circle_draw(ntree, sock, NODE_SOCKSIZE);
|
||||
node_socket_circle_draw(ntree, sock, NODE_SOCKSIZE, sock->flag & SELECT);
|
||||
|
||||
node->typeinfo->drawoutputfunc(C, node->block, ntree, node, sock, IFACE_(sock->name),
|
||||
sock->locx-node->width+NODE_DYS, sock->locy-NODE_DYS, node->width-NODE_DY);
|
||||
@@ -935,16 +945,16 @@ static void node_draw_hidden(const bContext *C, ARegion *ar, SpaceNode *snode, b
|
||||
dx-= snode->aspect;
|
||||
fdrawline(rct->xmax-dx, centy-4.0f, rct->xmax-dx, centy+4.0f);
|
||||
fdrawline(rct->xmax-dx-3.0f*snode->aspect, centy-4.0f, rct->xmax-dx-3.0f*snode->aspect, centy+4.0f);
|
||||
|
||||
|
||||
/* sockets */
|
||||
for (sock= node->inputs.first; sock; sock= sock->next) {
|
||||
if (!nodeSocketIsHidden(sock))
|
||||
node_socket_circle_draw(snode->nodetree, sock, socket_size);
|
||||
node_socket_circle_draw(snode->nodetree, sock, socket_size, sock->flag & SELECT);
|
||||
}
|
||||
|
||||
for (sock= node->outputs.first; sock; sock= sock->next) {
|
||||
if (!nodeSocketIsHidden(sock))
|
||||
node_socket_circle_draw(snode->nodetree, sock, socket_size);
|
||||
node_socket_circle_draw(snode->nodetree, sock, socket_size, sock->flag & SELECT);
|
||||
}
|
||||
|
||||
uiEndBlock(C, node->block);
|
||||
|
||||
@@ -1679,7 +1679,7 @@ int node_has_hidden_sockets(bNode *node)
|
||||
}
|
||||
|
||||
void node_set_hidden_sockets(SpaceNode *snode, bNode *node, int set)
|
||||
{
|
||||
{
|
||||
bNodeSocket *sock;
|
||||
|
||||
if (set==0) {
|
||||
@@ -2749,14 +2749,110 @@ void NODE_OT_link_make(wmOperatorType *ot)
|
||||
RNA_def_boolean(ot->srna, "replace", 0, "Replace", "Replace socket connections with the new links");
|
||||
}
|
||||
|
||||
/* ********************** Cut Link operator ***************** */
|
||||
|
||||
/* ********************** Add reroute operator ***************** */
|
||||
#define LINK_RESOL 12
|
||||
static int add_reroute_intersect_check(bNodeLink *link, float mcoords[][2], int tot, float result[2])
|
||||
{
|
||||
float coord_array[LINK_RESOL+1][2];
|
||||
int i, b;
|
||||
|
||||
if(node_link_bezier_points(NULL, NULL, link, coord_array, LINK_RESOL)) {
|
||||
|
||||
for(i=0; i<tot-1; i++)
|
||||
for(b=0; b<LINK_RESOL; b++)
|
||||
if(isect_line_line_v2(mcoords[i], mcoords[i+1], coord_array[b], coord_array[b+1]) > 0) {
|
||||
result[0] = (mcoords[i][0]+mcoords[i+1][0])/2.0f;
|
||||
result[1] = (mcoords[i][1]+mcoords[i+1][1])/2.0f;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int add_reroute_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
SpaceNode *snode= CTX_wm_space_node(C);
|
||||
ARegion *ar= CTX_wm_region(C);
|
||||
float mcoords[256][2];
|
||||
int i= 0;
|
||||
|
||||
RNA_BEGIN(op->ptr, itemptr, "path") {
|
||||
float loc[2];
|
||||
|
||||
RNA_float_get_array(&itemptr, "loc", loc);
|
||||
UI_view2d_region_to_view(&ar->v2d, (short)loc[0], (short)loc[1],
|
||||
&mcoords[i][0], &mcoords[i][1]);
|
||||
i++;
|
||||
if(i>= 256) break;
|
||||
}
|
||||
RNA_END;
|
||||
|
||||
if(i>1) {
|
||||
bNodeLink *link;
|
||||
float insertPoint[2];
|
||||
|
||||
ED_preview_kill_jobs(C);
|
||||
|
||||
for(link= snode->edittree->links.first; link; link=link->next) {
|
||||
if(add_reroute_intersect_check(link, mcoords, i, insertPoint)) {
|
||||
bNodeTemplate ntemp;
|
||||
bNode *rerouteNode;
|
||||
|
||||
node_deselect_all(snode);
|
||||
|
||||
ntemp.type = NODE_REROUTE;
|
||||
rerouteNode = nodeAddNode(snode->edittree, &ntemp);
|
||||
rerouteNode->locx = insertPoint[0];
|
||||
rerouteNode->locy = insertPoint[1];
|
||||
|
||||
nodeAddLink(snode->edittree, link->fromnode, link->fromsock, rerouteNode, rerouteNode->inputs.first);
|
||||
link->fromnode = rerouteNode;
|
||||
link->fromsock = rerouteNode->outputs.first;
|
||||
|
||||
break; // add one reroute at the time.
|
||||
}
|
||||
}
|
||||
|
||||
ntreeUpdateTree(snode->edittree);
|
||||
snode_notify(C, snode);
|
||||
snode_dag_update(C, snode);
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
return OPERATOR_CANCELLED|OPERATOR_PASS_THROUGH;
|
||||
}
|
||||
|
||||
void NODE_OT_add_reroute(wmOperatorType *ot)
|
||||
{
|
||||
PropertyRNA *prop;
|
||||
|
||||
ot->name= "Add reroute";
|
||||
ot->idname= "NODE_OT_add_reroute";
|
||||
|
||||
ot->invoke= WM_gesture_lines_invoke;
|
||||
ot->modal= WM_gesture_lines_modal;
|
||||
ot->exec= add_reroute_exec;
|
||||
ot->cancel= WM_gesture_lines_cancel;
|
||||
|
||||
ot->poll= ED_operator_node_active;
|
||||
|
||||
/* flags */
|
||||
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
|
||||
|
||||
prop= RNA_def_property(ot->srna, "path", PROP_COLLECTION, PROP_NONE);
|
||||
RNA_def_property_struct_runtime(prop, &RNA_OperatorMousePath);
|
||||
/* internal */
|
||||
RNA_def_int(ot->srna, "cursor", BC_CROSSCURSOR, 0, INT_MAX, "Cursor", "", 0, INT_MAX);
|
||||
}
|
||||
|
||||
|
||||
/* ********************** Cut Link operator ***************** */
|
||||
static int cut_links_intersect(bNodeLink *link, float mcoords[][2], int tot)
|
||||
{
|
||||
float coord_array[LINK_RESOL+1][2];
|
||||
int i, b;
|
||||
|
||||
|
||||
if (node_link_bezier_points(NULL, NULL, link, coord_array, LINK_RESOL)) {
|
||||
|
||||
for (i=0; i<tot-1; i++)
|
||||
|
||||
@@ -70,11 +70,13 @@ void node_menus_register(void);
|
||||
|
||||
/* node_draw.c */
|
||||
int node_get_colorid(struct bNode *node);
|
||||
void node_socket_circle_draw(struct bNodeTree *ntree, struct bNodeSocket *sock, float size);
|
||||
void node_socket_circle_draw(struct bNodeTree *ntree, struct bNodeSocket *sock, float size, int highlight);
|
||||
int node_get_resize_cursor(int directions);
|
||||
void node_draw_shadow(struct SpaceNode *snode, struct bNode *node, float radius);
|
||||
void node_draw_default(const struct bContext *C, struct ARegion *ar, struct SpaceNode *snode, struct bNodeTree *ntree, struct bNode *node);
|
||||
void node_update_default(const struct bContext *C, struct bNodeTree *ntree, struct bNode *node);
|
||||
int node_select_area_default(struct bNode *node, int x, int y);
|
||||
int node_tweak_area_default(struct bNode *node, int x, int y);
|
||||
void node_update_nodetree(const struct bContext *C, struct bNodeTree *ntree, float offsetx, float offsety);
|
||||
void node_draw_nodetree(const struct bContext *C, struct ARegion *ar, struct SpaceNode *snode, struct bNodeTree *ntree);
|
||||
void drawnodespace(const bContext *C, ARegion *ar, View2D *v2d);
|
||||
@@ -144,6 +146,7 @@ void NODE_OT_link(struct wmOperatorType *ot);
|
||||
void NODE_OT_link_make(struct wmOperatorType *ot);
|
||||
void NODE_OT_links_cut(struct wmOperatorType *ot);
|
||||
void NODE_OT_links_detach(struct wmOperatorType *ot);
|
||||
void NODE_OT_add_reroute(struct wmOperatorType *ot);
|
||||
|
||||
void NODE_OT_group_make(struct wmOperatorType *ot);
|
||||
void NODE_OT_group_ungroup(struct wmOperatorType *ot);
|
||||
|
||||
@@ -79,6 +79,7 @@ void node_operatortypes(void)
|
||||
WM_operatortype_append(NODE_OT_link_make);
|
||||
WM_operatortype_append(NODE_OT_links_cut);
|
||||
WM_operatortype_append(NODE_OT_links_detach);
|
||||
WM_operatortype_append(NODE_OT_add_reroute);
|
||||
|
||||
WM_operatortype_append(NODE_OT_group_make);
|
||||
WM_operatortype_append(NODE_OT_group_ungroup);
|
||||
@@ -218,6 +219,7 @@ void node_keymap(struct wmKeyConfig *keyconf)
|
||||
RNA_boolean_set(kmi->ptr, "detach", TRUE);
|
||||
WM_keymap_add_item(keymap, "NODE_OT_resize", LEFTMOUSE, KM_PRESS, 0, 0);
|
||||
|
||||
WM_keymap_add_item(keymap, "NODE_OT_add_reroute", LEFTMOUSE, KM_PRESS, KM_SHIFT, 0);
|
||||
WM_keymap_add_item(keymap, "NODE_OT_links_cut", LEFTMOUSE, KM_PRESS, KM_CTRL, 0);
|
||||
WM_keymap_add_item(keymap, "NODE_OT_select_link_viewer", LEFTMOUSE, KM_PRESS, KM_SHIFT|KM_CTRL, 0);
|
||||
|
||||
|
||||
@@ -38,6 +38,7 @@
|
||||
|
||||
#include "BKE_context.h"
|
||||
#include "BKE_main.h"
|
||||
#include "BKE_node.h"
|
||||
|
||||
#include "BLI_rect.h"
|
||||
#include "BLI_utildefines.h"
|
||||
@@ -58,14 +59,28 @@
|
||||
|
||||
/* ****** helpers ****** */
|
||||
|
||||
static bNode *node_under_mouse(bNodeTree *ntree, int mx, int my)
|
||||
static bNode *node_under_mouse_select(bNodeTree *ntree, int mx, int my)
|
||||
{
|
||||
bNode *node;
|
||||
|
||||
for (node=ntree->nodes.last; node; node=node->prev) {
|
||||
/* node body (header and scale are in other operators) */
|
||||
if (BLI_in_rctf(&node->totr, mx, my))
|
||||
return node;
|
||||
if (node->typeinfo->select_area_func) {
|
||||
if (node->typeinfo->select_area_func(node, mx, my))
|
||||
return node;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static bNode *node_under_mouse_tweak(bNodeTree *ntree, int mx, int my)
|
||||
{
|
||||
bNode *node;
|
||||
|
||||
for(node=ntree->nodes.last; node; node=node->prev) {
|
||||
if (node->typeinfo->tweak_area_func) {
|
||||
if (node->typeinfo->tweak_area_func(node, mx, my))
|
||||
return node;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
@@ -350,7 +365,7 @@ static int node_mouse_select(Main *bmain, SpaceNode *snode, ARegion *ar, const i
|
||||
}
|
||||
else {
|
||||
/* find the closest visible node */
|
||||
node = node_under_mouse(snode->edittree, mx, my);
|
||||
node = node_under_mouse_select(snode->edittree, mx, my);
|
||||
|
||||
if (node) {
|
||||
node_toggle(node);
|
||||
@@ -363,7 +378,7 @@ static int node_mouse_select(Main *bmain, SpaceNode *snode, ARegion *ar, const i
|
||||
else { /* extend==0 */
|
||||
|
||||
/* find the closest visible node */
|
||||
node = node_under_mouse(snode->edittree, mx, my);
|
||||
node = node_under_mouse_select(snode->edittree, mx, my);
|
||||
|
||||
if (node) {
|
||||
for (tnode=snode->edittree->nodes.first; tnode; tnode=tnode->next)
|
||||
@@ -490,7 +505,7 @@ static int node_border_select_invoke(bContext *C, wmOperator *op, wmEvent *event
|
||||
|
||||
UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &mx, &my);
|
||||
|
||||
if (node_under_mouse(snode->edittree, mx, my))
|
||||
if (node_under_mouse_tweak(snode->edittree, mx, my))
|
||||
return OPERATOR_CANCELLED|OPERATOR_PASS_THROUGH;
|
||||
}
|
||||
|
||||
|
||||
@@ -138,20 +138,20 @@ static int ed_undo_step(bContext *C, int step, const char *undoname)
|
||||
return ED_undo_gpencil_step(C, step, undoname);
|
||||
}
|
||||
|
||||
if (sa && sa->spacetype == SPACE_IMAGE) {
|
||||
if (sa && (sa->spacetype == SPACE_IMAGE)) {
|
||||
SpaceImage *sima = (SpaceImage *)sa->spacedata.first;
|
||||
|
||||
if ((obact && obact->mode & OB_MODE_TEXTURE_PAINT) || sima->flag & SI_DRAWTOOL) {
|
||||
if ((obact && (obact->mode & OB_MODE_TEXTURE_PAINT)) || (sima->flag & SI_DRAWTOOL)) {
|
||||
if (!ED_undo_paint_step(C, UNDO_PAINT_IMAGE, step, undoname) && undoname)
|
||||
if (U.uiflag & USER_GLOBALUNDO)
|
||||
BKE_undo_name(C, undoname);
|
||||
|
||||
|
||||
WM_event_add_notifier(C, NC_WINDOW, NULL);
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
}
|
||||
|
||||
if (sa && sa->spacetype == SPACE_TEXT) {
|
||||
if (sa && (sa->spacetype == SPACE_TEXT)) {
|
||||
ED_text_undo_step(C, step);
|
||||
}
|
||||
else if (obedit) {
|
||||
@@ -160,7 +160,7 @@ static int ed_undo_step(bContext *C, int step, const char *undoname)
|
||||
undo_editmode_name(C, undoname);
|
||||
else
|
||||
undo_editmode_step(C, step);
|
||||
|
||||
|
||||
WM_event_add_notifier(C, NC_GEOM | ND_DATA, NULL);
|
||||
}
|
||||
}
|
||||
@@ -195,7 +195,7 @@ static int ed_undo_step(bContext *C, int step, const char *undoname)
|
||||
BKE_undo_name(C, undoname);
|
||||
else
|
||||
BKE_undo_step(C, step);
|
||||
|
||||
|
||||
WM_event_add_notifier(C, NC_SCENE | ND_LAYER_CONTENT, CTX_data_scene(C));
|
||||
}
|
||||
|
||||
@@ -238,12 +238,12 @@ int ED_undo_valid(const bContext *C, const char *undoname)
|
||||
if (sa && sa->spacetype == SPACE_IMAGE) {
|
||||
SpaceImage *sima = (SpaceImage *)sa->spacedata.first;
|
||||
|
||||
if ((obact && obact->mode & OB_MODE_TEXTURE_PAINT) || sima->flag & SI_DRAWTOOL) {
|
||||
if ((obact && (obact->mode & OB_MODE_TEXTURE_PAINT)) || (sima->flag & SI_DRAWTOOL)) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (sa && sa->spacetype == SPACE_TEXT) {
|
||||
if (sa && (sa->spacetype == SPACE_TEXT)) {
|
||||
return 1;
|
||||
}
|
||||
else if (obedit) {
|
||||
@@ -256,11 +256,11 @@ int ED_undo_valid(const bContext *C, const char *undoname)
|
||||
/* if below tests fail, global undo gets executed */
|
||||
|
||||
if (obact && obact->mode & OB_MODE_TEXTURE_PAINT) {
|
||||
if (ED_undo_paint_valid(UNDO_PAINT_IMAGE, undoname) )
|
||||
if (ED_undo_paint_valid(UNDO_PAINT_IMAGE, undoname))
|
||||
return 1;
|
||||
}
|
||||
else if (obact && obact->mode & OB_MODE_SCULPT) {
|
||||
if (ED_undo_paint_valid(UNDO_PAINT_MESH, undoname) )
|
||||
if (ED_undo_paint_valid(UNDO_PAINT_MESH, undoname))
|
||||
return 1;
|
||||
}
|
||||
else if (obact && obact->mode & OB_MODE_PARTICLE_EDIT) {
|
||||
@@ -276,7 +276,7 @@ int ED_undo_valid(const bContext *C, const char *undoname)
|
||||
|
||||
static int ed_undo_exec(bContext *C, wmOperator *UNUSED(op))
|
||||
{
|
||||
/* "last operator" should disappear, later we can tie ths with undo stack nicer */
|
||||
/* "last operator" should disappear, later we can tie this with undo stack nicer */
|
||||
WM_operator_stack_clear(CTX_wm_manager(C));
|
||||
return ed_undo_step(C, 1, NULL);
|
||||
}
|
||||
|
||||
@@ -104,12 +104,12 @@ static FCurve *rna_Action_fcurve_new(bAction *act, ReportList *reports, const ch
|
||||
}
|
||||
|
||||
/* annoying, check if this exists */
|
||||
if (verify_fcurve(act, group, data_path, index, 0)) {
|
||||
if (verify_fcurve(act, group, NULL, data_path, index, 0)) {
|
||||
BKE_reportf(reports, RPT_ERROR, "F-Curve '%s[%d]' already exists in action '%s'", data_path,
|
||||
index, act->id.name + 2);
|
||||
return NULL;
|
||||
}
|
||||
return verify_fcurve(act, group, data_path, index, 1);
|
||||
return verify_fcurve(act, group, NULL, data_path, index, 1);
|
||||
}
|
||||
|
||||
static void rna_Action_fcurve_remove(bAction *act, ReportList *reports, FCurve *fcu)
|
||||
|
||||
@@ -139,31 +139,12 @@ void rna_ActionGroup_colorset_set(PointerRNA *ptr, int value)
|
||||
{
|
||||
bActionGroup *grp = ptr->data;
|
||||
|
||||
/* if valid value, set the new enum value, then copy the relevant colors? */
|
||||
if ((value >= -1) && (value < 21))
|
||||
/* ensure only valid values get set */
|
||||
if ((value >= -1) && (value < 21)) {
|
||||
grp->customCol = value;
|
||||
else
|
||||
return;
|
||||
|
||||
/* only do color copying if using a custom color (i.e. not default color) */
|
||||
if (grp->customCol) {
|
||||
if (grp->customCol > 0) {
|
||||
/* copy theme colors on-to group's custom color in case user tries to edit color */
|
||||
bTheme *btheme = U.themes.first;
|
||||
ThemeWireColor *col_set = &btheme->tarm[(grp->customCol - 1)];
|
||||
|
||||
memcpy(&grp->cs, col_set, sizeof(ThemeWireColor));
|
||||
}
|
||||
else {
|
||||
/* init custom colors with a generic multi-color rgb set, if not initialized already
|
||||
* (for custom color set) */
|
||||
if (grp->cs.solid[0] == 0) {
|
||||
/* define for setting colors in theme below */
|
||||
rgba_char_args_set(grp->cs.solid, 0xff, 0x00, 0x00, 255);
|
||||
rgba_char_args_set(grp->cs.select, 0x81, 0xe6, 0x14, 255);
|
||||
rgba_char_args_set(grp->cs.active, 0x18, 0xb6, 0xe0, 255);
|
||||
}
|
||||
}
|
||||
/* sync colors stored with theme colors based on the index specified */
|
||||
action_group_colors_sync(grp);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -162,11 +162,11 @@ static void localize(bNodeTree *localtree, bNodeTree *ntree)
|
||||
}
|
||||
}
|
||||
|
||||
/* replace muted nodes by internal links */
|
||||
/* replace muted nodes and reroute nodes by internal links */
|
||||
for (node= localtree->nodes.first; node; node= node_next) {
|
||||
node_next = node->next;
|
||||
|
||||
if (node->flag & NODE_MUTED) {
|
||||
if (node->flag & NODE_MUTED || node->type == NODE_REROUTE) {
|
||||
/* make sure the update tag isn't lost when removing the muted node.
|
||||
* propagate this to all downstream nodes.
|
||||
*/
|
||||
|
||||
@@ -835,3 +835,52 @@ void register_node_type_frame(bNodeTreeType *ttype)
|
||||
ntype->needs_free = 1;
|
||||
nodeRegisterType(ttype, ntype);
|
||||
}
|
||||
|
||||
|
||||
/* **************** REROUTE ******************** */
|
||||
|
||||
static bNodeSocketTemplate node_reroute_in[]= {
|
||||
{ SOCK_RGBA, 1, "Input", 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
|
||||
{ -1, 0, "" }
|
||||
};
|
||||
static bNodeSocketTemplate node_reroute_out[]= {
|
||||
{ SOCK_RGBA, 0, "Output", 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
|
||||
{ -1, 0, "" }
|
||||
};
|
||||
|
||||
/* simple, only a single input and output here */
|
||||
ListBase node_reroute_internal_connect(bNodeTree *ntree, bNode *node)
|
||||
{
|
||||
bNodeLink *link;
|
||||
ListBase ret;
|
||||
|
||||
ret.first = ret.last = NULL;
|
||||
|
||||
/* Security check! */
|
||||
if(!ntree)
|
||||
return ret;
|
||||
|
||||
link = MEM_callocN(sizeof(bNodeLink), "internal node link");
|
||||
link->fromnode = node;
|
||||
link->fromsock = node->inputs.first;
|
||||
link->tonode = node;
|
||||
link->tosock = node->outputs.first;
|
||||
/* internal link is always valid */
|
||||
link->flag |= NODE_LINK_VALID;
|
||||
BLI_addtail(&ret, link);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void register_node_type_reroute(bNodeTreeType *ttype)
|
||||
{
|
||||
/* frame type is used for all tree types, needs dynamic allocation */
|
||||
bNodeType *ntype= MEM_callocN(sizeof(bNodeType), "frame node type");
|
||||
|
||||
node_type_base(ttype, ntype, NODE_REROUTE, "Reroute", NODE_CLASS_LAYOUT, 0);
|
||||
node_type_socket_templates(ntype, node_reroute_in, node_reroute_out);
|
||||
node_type_internal_connect(ntype, node_reroute_internal_connect);
|
||||
|
||||
ntype->needs_free = 1;
|
||||
nodeRegisterType(ttype, ntype);
|
||||
}
|
||||
|
||||
@@ -46,7 +46,9 @@
|
||||
/* for a given socket, find the actual stack entry */
|
||||
bNodeStack *node_get_socket_stack(bNodeStack *stack, bNodeSocket *sock)
|
||||
{
|
||||
return stack + sock->stack_index;
|
||||
if (stack && sock)
|
||||
return stack + sock->stack_index;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void node_get_stack(bNode *node, bNodeStack *stack, bNodeStack **in, bNodeStack **out)
|
||||
|
||||
@@ -99,11 +99,11 @@ static void localize(bNodeTree *localtree, bNodeTree *UNUSED(ntree))
|
||||
{
|
||||
bNode *node, *node_next;
|
||||
|
||||
/* replace muted nodes by internal links */
|
||||
/* replace muted nodes and reroute nodes by internal links */
|
||||
for (node= localtree->nodes.first; node; node= node_next) {
|
||||
node_next = node->next;
|
||||
|
||||
if (node->flag & NODE_MUTED) {
|
||||
if (node->flag & NODE_MUTED || node->type == NODE_REROUTE) {
|
||||
nodeInternalRelink(localtree, node);
|
||||
nodeFreeNode(localtree, node);
|
||||
}
|
||||
|
||||
@@ -81,11 +81,11 @@ static void localize(bNodeTree *localtree, bNodeTree *UNUSED(ntree))
|
||||
{
|
||||
bNode *node, *node_next;
|
||||
|
||||
/* replace muted nodes by internal links */
|
||||
/* replace muted nodes and reroute nodes by internal links */
|
||||
for (node= localtree->nodes.first; node; node= node_next) {
|
||||
node_next = node->next;
|
||||
|
||||
if (node->flag & NODE_MUTED) {
|
||||
if (node->flag & NODE_MUTED || node->type == NODE_REROUTE) {
|
||||
nodeInternalRelink(localtree, node);
|
||||
nodeFreeNode(localtree, node);
|
||||
}
|
||||
|
||||
@@ -3937,7 +3937,6 @@ static void gesture_border_modal_keymap(wmKeyConfig *keyconf)
|
||||
WM_modalkeymap_assign(keymap, "UV_OT_select_border");
|
||||
WM_modalkeymap_assign(keymap, "CLIP_OT_select_border");
|
||||
WM_modalkeymap_assign(keymap, "CLIP_OT_graph_select_border");
|
||||
WM_modalkeymap_assign(keymap, "MASK_OT_select_border");
|
||||
WM_modalkeymap_assign(keymap, "VIEW2D_OT_zoom_border");
|
||||
WM_modalkeymap_assign(keymap, "VIEW3D_OT_clip_border");
|
||||
WM_modalkeymap_assign(keymap, "VIEW3D_OT_render_border");
|
||||
|
||||
Reference in New Issue
Block a user