Merging r47307 through r47325 from trunk into soc-2011-tomato

This commit is contained in:
2012-06-01 14:08:18 +00:00
51 changed files with 655 additions and 604 deletions

View File

@@ -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[]);

View File

@@ -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 *************** */

View File

@@ -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)

View File

@@ -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);

View File

@@ -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

View File

@@ -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();
}
}

View File

@@ -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;
}

View File

@@ -334,8 +334,16 @@ public:
* @param chunkNumber the chunk to be calculated
* @return MemoryBuffer** the inputbuffers
*/
MemoryBuffer** getInputBuffers(int chunkNumber);
MemoryBuffer** getInputBuffersCPU();
/**
* @brief get all inputbuffers needed to calculate an chunk
* @note all inputbuffers must be executed
* @param chunkNumber the chunk to be calculated
* @return MemoryBuffer** the inputbuffers
*/
MemoryBuffer** getInputBuffersOpenCL(int chunkNumber);
/**
* @brief allocate the outputbuffer of a chunk
* @param chunkNumber the number of the chunk in the ExecutionGroup

View File

@@ -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)

View File

@@ -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"

View File

@@ -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];

View File

@@ -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);
}

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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;
}
}

View File

@@ -26,7 +26,6 @@ class MemoryProxy;
#ifndef _COM_MemoryProxy_h
#define _COM_MemoryProxy_h
#include "COM_ExecutionGroup.h"
#include "COM_MemoryManagerState.h"
class ExecutionGroup;
@@ -48,12 +47,6 @@ private:
*/
ExecutionGroup *executor;
/**
* @brief data of the different chunks.
* @note state is part of this class due to optimization in the MemoryManager
*/
MemoryManagerState * state;
/**
* @brief datatype of this MemoryProxy
*/
@@ -63,9 +56,14 @@ private:
* @brief channel information of this buffer
*/
ChannelInfo channelInfo[COM_NUMBER_OF_CHANNELS];
/**
* @brief the allocated memory
*/
MemoryBuffer* buffer;
public:
MemoryProxy();
~MemoryProxy();
/**
* @brief set the ExecutionGroup that can be scheduled to calculate a certain chunk.
@@ -89,18 +87,21 @@ public:
* @return WriteBufferOperation
*/
WriteBufferOperation *getWriteBufferOperation() {return this->writeBufferOperation;}
/**
* @brief set the memorymanager state of this MemoryProxy, this is set from the MemoryManager
* @param state the state to set
* @brief allocate memory of size widht x height
*/
void setState(MemoryManagerState *state) {this->state = state;}
void allocate(unsigned int width, unsigned int height);
/**
* @brief get the state of this MemoryProxy
* @return MemoryManagerState reference to the state of this MemoryProxy.
* @brief free the allocated memory
*/
MemoryManagerState *getState() {return this->state;}
void free();
/**
* @brief get the allocated memory
*/
inline MemoryBuffer* getBuffer() {return this->buffer;}
};
#endif

View File

@@ -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;

View File

@@ -1,7 +0,0 @@
#ifndef _COM_NodeProgram_h
#define _COM_NodeProgram_h
class NodeProgram{
};
#endif

View File

@@ -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);

View File

@@ -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);
}
}
}

View File

@@ -37,6 +37,7 @@ BlurBaseOperation::BlurBaseOperation(): NodeOperation()
this->data = NULL;
this->size = 1.0f;
this->deleteData = false;
this->sizeavailable=false;
}
void BlurBaseOperation::initExecution()
{

View File

@@ -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

View File

@@ -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);
}

View File

@@ -34,7 +34,7 @@ private:
public:
GaussianBokehBlurOperation();
void initExecution();
void *initializeTileData(rcti *rect, MemoryBuffer **memoryBuffers);
/**
* the inner loop of this program

View File

@@ -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);
}
}

View File

@@ -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();

View File

@@ -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);
}
}

View File

@@ -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
*/

View File

@@ -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;
/*

View File

@@ -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))

View File

@@ -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;
}

View File

@@ -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;

View File

@@ -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);
/* -------- */

View File

@@ -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)

View File

@@ -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 */

View File

@@ -46,6 +46,7 @@
#include "BLI_math.h"
#include "BLI_blenlib.h"
#include "BLI_rect.h"
#include "BLI_threads.h"
#include "BLI_utildefines.h"
@@ -81,7 +82,6 @@
/* width of socket columns in group display */
#define NODE_GROUP_FRAME 120
// XXX interface.h
extern void ui_dropshadow(rctf *rct, float radius, float aspect, int select);
@@ -496,6 +496,16 @@ void node_update_default(const bContext *C, bNodeTree *ntree, bNode *node)
node_update_basis(C, ntree, node);
}
int node_select_area_default(bNode *node, int x, int y)
{
return BLI_in_rctf(&node->totr, x, y);
}
int node_tweak_area_default(bNode *node, int x, int y)
{
return BLI_in_rctf(&node->totr, x, y);
}
int node_get_colorid(bNode *node)
{
if (node->typeinfo->nclass==NODE_CLASS_INPUT)
@@ -585,10 +595,10 @@ static void node_circle_draw(float x, float y, float size, char *col, int highli
glLineWidth(1.0f);
}
void node_socket_circle_draw(bNodeTree *UNUSED(ntree), bNodeSocket *sock, float size)
void node_socket_circle_draw(bNodeTree *UNUSED(ntree), bNodeSocket *sock, float size, int highlight)
{
bNodeSocketType *stype = ntreeGetSocketType(sock->type);
node_circle_draw(sock->locx, sock->locy, size, stype->ui_color, (sock->flag & SELECT));
node_circle_draw(sock->locx, sock->locy, size, stype->ui_color, highlight);
}
/* ************** Socket callbacks *********** */
@@ -819,7 +829,7 @@ static void node_draw_basis(const bContext *C, ARegion *ar, SpaceNode *snode, bN
if (nodeSocketIsHidden(sock))
continue;
node_socket_circle_draw(ntree, sock, NODE_SOCKSIZE);
node_socket_circle_draw(ntree, sock, NODE_SOCKSIZE, sock->flag & SELECT);
node->typeinfo->drawinputfunc(C, node->block, ntree, node, sock, IFACE_(sock->name),
sock->locx+NODE_DYS, sock->locy-NODE_DYS, node->width-NODE_DY);
@@ -830,7 +840,7 @@ static void node_draw_basis(const bContext *C, ARegion *ar, SpaceNode *snode, bN
if (nodeSocketIsHidden(sock))
continue;
node_socket_circle_draw(ntree, sock, NODE_SOCKSIZE);
node_socket_circle_draw(ntree, sock, NODE_SOCKSIZE, sock->flag & SELECT);
node->typeinfo->drawoutputfunc(C, node->block, ntree, node, sock, IFACE_(sock->name),
sock->locx-node->width+NODE_DYS, sock->locy-NODE_DYS, node->width-NODE_DY);
@@ -935,16 +945,16 @@ static void node_draw_hidden(const bContext *C, ARegion *ar, SpaceNode *snode, b
dx-= snode->aspect;
fdrawline(rct->xmax-dx, centy-4.0f, rct->xmax-dx, centy+4.0f);
fdrawline(rct->xmax-dx-3.0f*snode->aspect, centy-4.0f, rct->xmax-dx-3.0f*snode->aspect, centy+4.0f);
/* sockets */
for (sock= node->inputs.first; sock; sock= sock->next) {
if (!nodeSocketIsHidden(sock))
node_socket_circle_draw(snode->nodetree, sock, socket_size);
node_socket_circle_draw(snode->nodetree, sock, socket_size, sock->flag & SELECT);
}
for (sock= node->outputs.first; sock; sock= sock->next) {
if (!nodeSocketIsHidden(sock))
node_socket_circle_draw(snode->nodetree, sock, socket_size);
node_socket_circle_draw(snode->nodetree, sock, socket_size, sock->flag & SELECT);
}
uiEndBlock(C, node->block);

View File

@@ -1679,7 +1679,7 @@ int node_has_hidden_sockets(bNode *node)
}
void node_set_hidden_sockets(SpaceNode *snode, bNode *node, int set)
{
{
bNodeSocket *sock;
if (set==0) {
@@ -2749,14 +2749,110 @@ void NODE_OT_link_make(wmOperatorType *ot)
RNA_def_boolean(ot->srna, "replace", 0, "Replace", "Replace socket connections with the new links");
}
/* ********************** Cut Link operator ***************** */
/* ********************** Add reroute operator ***************** */
#define LINK_RESOL 12
static int add_reroute_intersect_check(bNodeLink *link, float mcoords[][2], int tot, float result[2])
{
float coord_array[LINK_RESOL+1][2];
int i, b;
if(node_link_bezier_points(NULL, NULL, link, coord_array, LINK_RESOL)) {
for(i=0; i<tot-1; i++)
for(b=0; b<LINK_RESOL; b++)
if(isect_line_line_v2(mcoords[i], mcoords[i+1], coord_array[b], coord_array[b+1]) > 0) {
result[0] = (mcoords[i][0]+mcoords[i+1][0])/2.0f;
result[1] = (mcoords[i][1]+mcoords[i+1][1])/2.0f;
return 1;
}
}
return 0;
}
static int add_reroute_exec(bContext *C, wmOperator *op)
{
SpaceNode *snode= CTX_wm_space_node(C);
ARegion *ar= CTX_wm_region(C);
float mcoords[256][2];
int i= 0;
RNA_BEGIN(op->ptr, itemptr, "path") {
float loc[2];
RNA_float_get_array(&itemptr, "loc", loc);
UI_view2d_region_to_view(&ar->v2d, (short)loc[0], (short)loc[1],
&mcoords[i][0], &mcoords[i][1]);
i++;
if(i>= 256) break;
}
RNA_END;
if(i>1) {
bNodeLink *link;
float insertPoint[2];
ED_preview_kill_jobs(C);
for(link= snode->edittree->links.first; link; link=link->next) {
if(add_reroute_intersect_check(link, mcoords, i, insertPoint)) {
bNodeTemplate ntemp;
bNode *rerouteNode;
node_deselect_all(snode);
ntemp.type = NODE_REROUTE;
rerouteNode = nodeAddNode(snode->edittree, &ntemp);
rerouteNode->locx = insertPoint[0];
rerouteNode->locy = insertPoint[1];
nodeAddLink(snode->edittree, link->fromnode, link->fromsock, rerouteNode, rerouteNode->inputs.first);
link->fromnode = rerouteNode;
link->fromsock = rerouteNode->outputs.first;
break; // add one reroute at the time.
}
}
ntreeUpdateTree(snode->edittree);
snode_notify(C, snode);
snode_dag_update(C, snode);
return OPERATOR_FINISHED;
}
return OPERATOR_CANCELLED|OPERATOR_PASS_THROUGH;
}
void NODE_OT_add_reroute(wmOperatorType *ot)
{
PropertyRNA *prop;
ot->name= "Add reroute";
ot->idname= "NODE_OT_add_reroute";
ot->invoke= WM_gesture_lines_invoke;
ot->modal= WM_gesture_lines_modal;
ot->exec= add_reroute_exec;
ot->cancel= WM_gesture_lines_cancel;
ot->poll= ED_operator_node_active;
/* flags */
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
prop= RNA_def_property(ot->srna, "path", PROP_COLLECTION, PROP_NONE);
RNA_def_property_struct_runtime(prop, &RNA_OperatorMousePath);
/* internal */
RNA_def_int(ot->srna, "cursor", BC_CROSSCURSOR, 0, INT_MAX, "Cursor", "", 0, INT_MAX);
}
/* ********************** Cut Link operator ***************** */
static int cut_links_intersect(bNodeLink *link, float mcoords[][2], int tot)
{
float coord_array[LINK_RESOL+1][2];
int i, b;
if (node_link_bezier_points(NULL, NULL, link, coord_array, LINK_RESOL)) {
for (i=0; i<tot-1; i++)

View File

@@ -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);

View File

@@ -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);

View File

@@ -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;
}

View File

@@ -138,20 +138,20 @@ static int ed_undo_step(bContext *C, int step, const char *undoname)
return ED_undo_gpencil_step(C, step, undoname);
}
if (sa && sa->spacetype == SPACE_IMAGE) {
if (sa && (sa->spacetype == SPACE_IMAGE)) {
SpaceImage *sima = (SpaceImage *)sa->spacedata.first;
if ((obact && obact->mode & OB_MODE_TEXTURE_PAINT) || sima->flag & SI_DRAWTOOL) {
if ((obact && (obact->mode & OB_MODE_TEXTURE_PAINT)) || (sima->flag & SI_DRAWTOOL)) {
if (!ED_undo_paint_step(C, UNDO_PAINT_IMAGE, step, undoname) && undoname)
if (U.uiflag & USER_GLOBALUNDO)
BKE_undo_name(C, undoname);
WM_event_add_notifier(C, NC_WINDOW, NULL);
return OPERATOR_FINISHED;
}
}
if (sa && sa->spacetype == SPACE_TEXT) {
if (sa && (sa->spacetype == SPACE_TEXT)) {
ED_text_undo_step(C, step);
}
else if (obedit) {
@@ -160,7 +160,7 @@ static int ed_undo_step(bContext *C, int step, const char *undoname)
undo_editmode_name(C, undoname);
else
undo_editmode_step(C, step);
WM_event_add_notifier(C, NC_GEOM | ND_DATA, NULL);
}
}
@@ -195,7 +195,7 @@ static int ed_undo_step(bContext *C, int step, const char *undoname)
BKE_undo_name(C, undoname);
else
BKE_undo_step(C, step);
WM_event_add_notifier(C, NC_SCENE | ND_LAYER_CONTENT, CTX_data_scene(C));
}
@@ -238,12 +238,12 @@ int ED_undo_valid(const bContext *C, const char *undoname)
if (sa && sa->spacetype == SPACE_IMAGE) {
SpaceImage *sima = (SpaceImage *)sa->spacedata.first;
if ((obact && obact->mode & OB_MODE_TEXTURE_PAINT) || sima->flag & SI_DRAWTOOL) {
if ((obact && (obact->mode & OB_MODE_TEXTURE_PAINT)) || (sima->flag & SI_DRAWTOOL)) {
return 1;
}
}
if (sa && sa->spacetype == SPACE_TEXT) {
if (sa && (sa->spacetype == SPACE_TEXT)) {
return 1;
}
else if (obedit) {
@@ -256,11 +256,11 @@ int ED_undo_valid(const bContext *C, const char *undoname)
/* if below tests fail, global undo gets executed */
if (obact && obact->mode & OB_MODE_TEXTURE_PAINT) {
if (ED_undo_paint_valid(UNDO_PAINT_IMAGE, undoname) )
if (ED_undo_paint_valid(UNDO_PAINT_IMAGE, undoname))
return 1;
}
else if (obact && obact->mode & OB_MODE_SCULPT) {
if (ED_undo_paint_valid(UNDO_PAINT_MESH, undoname) )
if (ED_undo_paint_valid(UNDO_PAINT_MESH, undoname))
return 1;
}
else if (obact && obact->mode & OB_MODE_PARTICLE_EDIT) {
@@ -276,7 +276,7 @@ int ED_undo_valid(const bContext *C, const char *undoname)
static int ed_undo_exec(bContext *C, wmOperator *UNUSED(op))
{
/* "last operator" should disappear, later we can tie ths with undo stack nicer */
/* "last operator" should disappear, later we can tie this with undo stack nicer */
WM_operator_stack_clear(CTX_wm_manager(C));
return ed_undo_step(C, 1, NULL);
}

View File

@@ -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)

View File

@@ -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);
}
}

View File

@@ -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.
*/

View File

@@ -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);
}

View File

@@ -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)

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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");