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,7 +334,15 @@ 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
 | 
			
		||||
 
 | 
			
		||||
@@ -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.
 | 
			
		||||
@@ -91,16 +89,19 @@ public:
 | 
			
		||||
	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);
 | 
			
		||||
@@ -939,12 +949,12 @@ static void node_draw_hidden(const bContext *C, ARegion *ar, SpaceNode *snode, b
 | 
			
		||||
	/* 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);
 | 
			
		||||
 
 | 
			
		||||
@@ -2749,9 +2749,105 @@ 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];
 | 
			
		||||
 
 | 
			
		||||
@@ -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,10 +138,10 @@ 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);
 | 
			
		||||
@@ -151,7 +151,7 @@ static int ed_undo_step(bContext *C, int step, const char *undoname)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (sa && sa->spacetype == SPACE_TEXT) {
 | 
			
		||||
	if (sa && (sa->spacetype == SPACE_TEXT)) {
 | 
			
		||||
		ED_text_undo_step(C, step);
 | 
			
		||||
	}
 | 
			
		||||
	else if (obedit) {
 | 
			
		||||
@@ -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