From a78dca27a22d1d434dcde6d589cc7969c5039565 Mon Sep 17 00:00:00 2001 From: Jeroen Bakker Date: Fri, 1 Jun 2012 08:01:04 +0000 Subject: [PATCH 01/10] Removed unused files in compositor --- source/blender/compositor/CMakeLists.txt | 1 - source/blender/compositor/intern/COM_NodeOperation.h | 4 ++-- source/blender/compositor/intern/COM_NodeProgram.cpp | 0 source/blender/compositor/intern/COM_NodeProgram.h | 7 ------- 4 files changed, 2 insertions(+), 10 deletions(-) delete mode 100644 source/blender/compositor/intern/COM_NodeProgram.cpp delete mode 100644 source/blender/compositor/intern/COM_NodeProgram.h diff --git a/source/blender/compositor/CMakeLists.txt b/source/blender/compositor/CMakeLists.txt index 355b5ac58c3..0b9dbfacb07 100644 --- a/source/blender/compositor/CMakeLists.txt +++ b/source/blender/compositor/CMakeLists.txt @@ -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 diff --git a/source/blender/compositor/intern/COM_NodeOperation.h b/source/blender/compositor/intern/COM_NodeOperation.h index bba3de2ec98..9222ce8d53a 100644 --- a/source/blender/compositor/intern/COM_NodeOperation.h +++ b/source/blender/compositor/intern/COM_NodeOperation.h @@ -20,8 +20,8 @@ * Monique Dewanchand */ -#ifndef _COM_NodeProgram_h -#define _COM_NodeProgram_h +#ifndef _COM_NodeOperation_h +#define _COM_NodeOperation_h class NodeOperation; diff --git a/source/blender/compositor/intern/COM_NodeProgram.cpp b/source/blender/compositor/intern/COM_NodeProgram.cpp deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/source/blender/compositor/intern/COM_NodeProgram.h b/source/blender/compositor/intern/COM_NodeProgram.h deleted file mode 100644 index a71fa2b676f..00000000000 --- a/source/blender/compositor/intern/COM_NodeProgram.h +++ /dev/null @@ -1,7 +0,0 @@ -#ifndef _COM_NodeProgram_h -#define _COM_NodeProgram_h - -class NodeProgram{ -}; - -#endif From 285a24b3e07b3441e98a0a502c42af50b9738f3a Mon Sep 17 00:00:00 2001 From: Monique Dewanchand Date: Fri, 1 Jun 2012 10:20:24 +0000 Subject: [PATCH 02/10] Replaced tile based memory manager with a single aligned buffer - should increase speed with large node setups - enables caching of buffers in the node editor (in the future) - OpenCL part still needs some work --- source/blender/compositor/CMakeLists.txt | 4 - .../compositor/intern/COM_CPUDevice.cpp | 6 +- .../compositor/intern/COM_ExecutionGroup.cpp | 31 +++- .../compositor/intern/COM_ExecutionGroup.h | 12 +- .../compositor/intern/COM_ExecutionSystem.cpp | 4 - .../intern/COM_ExecutionSystemHelper.cpp | 1 - .../compositor/intern/COM_MemoryBuffer.cpp | 20 +-- .../compositor/intern/COM_MemoryManager.cpp | 74 --------- .../compositor/intern/COM_MemoryManager.h | 146 ------------------ .../intern/COM_MemoryManagerState.cpp | 100 ------------ .../intern/COM_MemoryManagerState.h | 87 ----------- .../compositor/intern/COM_MemoryProxy.cpp | 21 ++- .../compositor/intern/COM_MemoryProxy.h | 33 ++-- .../compositor/intern/COM_NodeOperation.h | 1 + .../compositor/intern/COM_OpenCLDevice.cpp | 2 +- .../operations/COM_WriteBufferOperation.cpp | 24 +-- 16 files changed, 92 insertions(+), 474 deletions(-) delete mode 100644 source/blender/compositor/intern/COM_MemoryManager.cpp delete mode 100644 source/blender/compositor/intern/COM_MemoryManager.h delete mode 100644 source/blender/compositor/intern/COM_MemoryManagerState.cpp delete mode 100644 source/blender/compositor/intern/COM_MemoryManagerState.h diff --git a/source/blender/compositor/CMakeLists.txt b/source/blender/compositor/CMakeLists.txt index 0b9dbfacb07..dc28328e867 100644 --- a/source/blender/compositor/CMakeLists.txt +++ b/source/blender/compositor/CMakeLists.txt @@ -79,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 diff --git a/source/blender/compositor/intern/COM_CPUDevice.cpp b/source/blender/compositor/intern/COM_CPUDevice.cpp index 43ec892985a..f151afd75be 100644 --- a/source/blender/compositor/intern/COM_CPUDevice.cpp +++ b/source/blender/compositor/intern/COM_CPUDevice.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(); - } } diff --git a/source/blender/compositor/intern/COM_ExecutionGroup.cpp b/source/blender/compositor/intern/COM_ExecutionGroup.cpp index e4fefa6a904..7ac3f757d8e 100644 --- a/source/blender/compositor/intern/COM_ExecutionGroup.cpp +++ b/source/blender/compositor/intern/COM_ExecutionGroup.cpp @@ -34,7 +34,6 @@ #include "COM_ViewerOperation.h" #include #include "BLI_math.h" -#include "COM_MemoryManager.h" #include "PIL_time.h" #include "COM_ChunkOrder.h" #include @@ -362,7 +361,24 @@ void ExecutionGroup::execute(ExecutionSystem *graph) delete[] chunkOrder; } -MemoryBuffer** ExecutionGroup::getInputBuffers(int chunkNumber) +MemoryBuffer** ExecutionGroup::getInputBuffersCPU() +{ + vector 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 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); indexxnumberOfXChunks, maxxchunk) ; indexx++) { for (indexy = max(minychunk, 0); indexynumberOfYChunks, 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; } diff --git a/source/blender/compositor/intern/COM_ExecutionGroup.h b/source/blender/compositor/intern/COM_ExecutionGroup.h index adab7df4690..cbdc9bb1787 100644 --- a/source/blender/compositor/intern/COM_ExecutionGroup.h +++ b/source/blender/compositor/intern/COM_ExecutionGroup.h @@ -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 diff --git a/source/blender/compositor/intern/COM_ExecutionSystem.cpp b/source/blender/compositor/intern/COM_ExecutionSystem.cpp index 0d4c7cde68f..96d2a6f4434 100644 --- a/source/blender/compositor/intern/COM_ExecutionSystem.cpp +++ b/source/blender/compositor/intern/COM_ExecutionSystem.cpp @@ -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) diff --git a/source/blender/compositor/intern/COM_ExecutionSystemHelper.cpp b/source/blender/compositor/intern/COM_ExecutionSystemHelper.cpp index 94376f73de9..67554cd464b 100644 --- a/source/blender/compositor/intern/COM_ExecutionSystemHelper.cpp +++ b/source/blender/compositor/intern/COM_ExecutionSystemHelper.cpp @@ -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" diff --git a/source/blender/compositor/intern/COM_MemoryBuffer.cpp b/source/blender/compositor/intern/COM_MemoryBuffer.cpp index 19c2c96a8f2..d22c75c922b 100644 --- a/source/blender/compositor/intern/COM_MemoryBuffer.cpp +++ b/source/blender/compositor/intern/COM_MemoryBuffer.cpp @@ -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 ; otherYrect.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]; diff --git a/source/blender/compositor/intern/COM_MemoryManager.cpp b/source/blender/compositor/intern/COM_MemoryManager.cpp deleted file mode 100644 index 4f97b0b1e80..00000000000 --- a/source/blender/compositor/intern/COM_MemoryManager.cpp +++ /dev/null @@ -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 -#include "COM_defines.h" - -vector 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); -} diff --git a/source/blender/compositor/intern/COM_MemoryManager.h b/source/blender/compositor/intern/COM_MemoryManager.h deleted file mode 100644 index 6194d40d9a5..00000000000 --- a/source/blender/compositor/intern/COM_MemoryManager.h +++ /dev/null @@ -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. - *
-  * Allocation of the output MemoryBuffer
-  *  +----------------------------------------+
-  *  | Main device (CPU)                      |
-  *  | +----------------+   +--------------+  |
-  *  | | ExecutionGroup |   | MemoryBuffer |  |
-  *  | |                |   | Chunk a      |  |
-  *  | +----------------+   +--------------+  |
-  *  |                                        |
-  *  +----------------------------------------+
-  * 
- * @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]. - *
-  * Execute a chunk and store result to the MemoryBuffer
-  *  +----------------------------------------+
-  *  | Main device (CPU)                      |
-  *  | +----------------+   +--------------+  |
-  *  | | ExecutionGroup |   | MemoryBuffer |  |
-  *  | |                |   | Chunk a      |  |
-  *  | +----------------+   +--------------+  |
-  *  |         |                 ^            |
-  *  | +----------------+        |            |
-  *  | | NodeOperation  |--------+            |
-  *  | |                |     Write result    |
-  *  | +----------------+                     |
-  *  |                                        |
-  *  +----------------------------------------+
-  * 
- * @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. - *
-  *  Original MemoryBuffer's  Temporarily
-  *  +-------+ +-------+      MemoryBuffer
-  *  | MB A  | | MB B  |      +-------+-------+
-  *  +-------+ +-------+      | MB A  | MB B  |
-  *                       ==> +-------+-------+
-  *  +-------+ +-------+      | MB C  | MB D  |
-  *  | MB C  | | MB D  |      +-------+-------+
-  *  +-------+ +-------+
-  * 
- * @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 diff --git a/source/blender/compositor/intern/COM_MemoryManagerState.cpp b/source/blender/compositor/intern/COM_MemoryManagerState.cpp deleted file mode 100644 index 6098bf15569..00000000000 --- a/source/blender/compositor/intern/COM_MemoryManagerState.cpp +++ /dev/null @@ -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; -} diff --git a/source/blender/compositor/intern/COM_MemoryManagerState.h b/source/blender/compositor/intern/COM_MemoryManagerState.h deleted file mode 100644 index 8e8cb484d1a..00000000000 --- a/source/blender/compositor/intern/COM_MemoryManagerState.h +++ /dev/null @@ -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 -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 diff --git a/source/blender/compositor/intern/COM_MemoryProxy.cpp b/source/blender/compositor/intern/COM_MemoryProxy.cpp index 7ff4f4949f0..15df11a77d1 100644 --- a/source/blender/compositor/intern/COM_MemoryProxy.cpp +++ b/source/blender/compositor/intern/COM_MemoryProxy.cpp @@ -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, &result); +} + +void MemoryProxy::free() +{ + if (buffer) { + delete buffer; + buffer = NULL; } } + diff --git a/source/blender/compositor/intern/COM_MemoryProxy.h b/source/blender/compositor/intern/COM_MemoryProxy.h index 276ebeed1e2..e0ac72de0d3 100644 --- a/source/blender/compositor/intern/COM_MemoryProxy.h +++ b/source/blender/compositor/intern/COM_MemoryProxy.h @@ -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 diff --git a/source/blender/compositor/intern/COM_NodeOperation.h b/source/blender/compositor/intern/COM_NodeOperation.h index 9222ce8d53a..73ba5b472d7 100644 --- a/source/blender/compositor/intern/COM_NodeOperation.h +++ b/source/blender/compositor/intern/COM_NodeOperation.h @@ -33,6 +33,7 @@ class NodeOperation; #include "COM_SocketReader.h" #include "OCL_opencl.h" #include "list" +#include "BLI_threads.h" class ReadBufferOperation; diff --git a/source/blender/compositor/intern/COM_OpenCLDevice.cpp b/source/blender/compositor/intern/COM_OpenCLDevice.cpp index 0945b426a4e..692b96f40b3 100644 --- a/source/blender/compositor/intern/COM_OpenCLDevice.cpp +++ b/source/blender/compositor/intern/COM_OpenCLDevice.cpp @@ -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); diff --git a/source/blender/compositor/operations/COM_WriteBufferOperation.cpp b/source/blender/compositor/operations/COM_WriteBufferOperation.cpp index 3af914f8d0e..498add2fc87 100644 --- a/source/blender/compositor/operations/COM_WriteBufferOperation.cpp +++ b/source/blender/compositor/operations/COM_WriteBufferOperation.cpp @@ -22,10 +22,8 @@ #include "COM_WriteBufferOperation.h" #include "COM_defines.h" -#include "COM_MemoryManager.h" #include -/// @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; /* From e9093c70116b4497600e0d43b191a80262dd9630 Mon Sep 17 00:00:00 2001 From: Jeroen Bakker Date: Fri, 1 Jun 2012 10:37:38 +0000 Subject: [PATCH 03/10] Fixed crash Previous patch allocated temporarily buffers. --- source/blender/compositor/intern/COM_MemoryProxy.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/compositor/intern/COM_MemoryProxy.cpp b/source/blender/compositor/intern/COM_MemoryProxy.cpp index 15df11a77d1..3a2c690d7de 100644 --- a/source/blender/compositor/intern/COM_MemoryProxy.cpp +++ b/source/blender/compositor/intern/COM_MemoryProxy.cpp @@ -37,7 +37,7 @@ void MemoryProxy::allocate(unsigned int width, unsigned int height) result.ymin = 0; result.ymax = height; - buffer = new MemoryBuffer(this, &result); + buffer = new MemoryBuffer(this, 1, &result); } void MemoryProxy::free() From 21bf2e0cae0a19d498ac0d6a0cc2f40df32f2ad2 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 1 Jun 2012 11:03:44 +0000 Subject: [PATCH 04/10] fix crash in clip graph view (possibly own fault) --- source/blender/editors/transform/transform_generics.c | 1 + 1 file changed, 1 insertion(+) diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c index d97af562630..0f742458ed3 100644 --- a/source/blender/editors/transform/transform_generics.c +++ b/source/blender/editors/transform/transform_generics.c @@ -1108,6 +1108,7 @@ int initTransInfo(bContext *C, TransInfo *t, wmOperator *op, wmEvent *event) } else if (t->spacetype==SPACE_CLIP) { SpaceClip *sclip = sa->spacedata.first; + t->view = &ar->v2d; if (ED_space_clip_show_trackedit(sclip)) t->options |= CTX_MOVIECLIP; From 7941ebf66e15df1ca4b7b5439a5bbc90254479f4 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Fri, 1 Jun 2012 11:46:25 +0000 Subject: [PATCH 05/10] Style and typo fixes --- source/blender/editors/util/undo.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/source/blender/editors/util/undo.c b/source/blender/editors/util/undo.c index e7a9ab9ca73..65d23641ab5 100644 --- a/source/blender/editors/util/undo.c +++ b/source/blender/editors/util/undo.c @@ -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); } From 5fbeda7efd62e251dac2af881de9fe042f30a7a7 Mon Sep 17 00:00:00 2001 From: Monique Dewanchand Date: Fri, 1 Jun 2012 11:50:32 +0000 Subject: [PATCH 06/10] Optimize Gaussian blurs --- .../blender/compositor/nodes/COM_BlurNode.cpp | 14 +++++++-- .../operations/COM_BlurBaseOperation.cpp | 1 + .../operations/COM_BlurBaseOperation.h | 3 ++ .../COM_GaussianBokehBlurOperation.cpp | 31 +++++++++++++------ .../COM_GaussianBokehBlurOperation.h | 2 +- .../operations/COM_GaussianXBlurOperation.cpp | 30 +++++++++++++----- .../operations/COM_GaussianXBlurOperation.h | 9 ++++-- .../operations/COM_GaussianYBlurOperation.cpp | 30 +++++++++++++----- .../operations/COM_GaussianYBlurOperation.h | 5 +++ 9 files changed, 94 insertions(+), 31 deletions(-) diff --git a/source/blender/compositor/nodes/COM_BlurNode.cpp b/source/blender/compositor/nodes/COM_BlurNode.cpp index 90b2481cc7d..b209e36dd48 100644 --- a/source/blender/compositor/nodes/COM_BlurNode.cpp +++ b/source/blender/compositor/nodes/COM_BlurNode.cpp @@ -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); + } } } diff --git a/source/blender/compositor/operations/COM_BlurBaseOperation.cpp b/source/blender/compositor/operations/COM_BlurBaseOperation.cpp index 6e1a7e2a908..babea459d6a 100644 --- a/source/blender/compositor/operations/COM_BlurBaseOperation.cpp +++ b/source/blender/compositor/operations/COM_BlurBaseOperation.cpp @@ -37,6 +37,7 @@ BlurBaseOperation::BlurBaseOperation(): NodeOperation() this->data = NULL; this->size = 1.0f; this->deleteData = false; + this->sizeavailable=false; } void BlurBaseOperation::initExecution() { diff --git a/source/blender/compositor/operations/COM_BlurBaseOperation.h b/source/blender/compositor/operations/COM_BlurBaseOperation.h index 13e7eb52b77..24002588413 100644 --- a/source/blender/compositor/operations/COM_BlurBaseOperation.h +++ b/source/blender/compositor/operations/COM_BlurBaseOperation.h @@ -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 diff --git a/source/blender/compositor/operations/COM_GaussianBokehBlurOperation.cpp b/source/blender/compositor/operations/COM_GaussianBokehBlurOperation.cpp index af10791590b..b5d175729f3 100644 --- a/source/blender/compositor/operations/COM_GaussianBokehBlurOperation.cpp +++ b/source/blender/compositor/operations/COM_GaussianBokehBlurOperation.cpp @@ -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); } diff --git a/source/blender/compositor/operations/COM_GaussianBokehBlurOperation.h b/source/blender/compositor/operations/COM_GaussianBokehBlurOperation.h index a7a0ee74364..78c6437eac6 100644 --- a/source/blender/compositor/operations/COM_GaussianBokehBlurOperation.h +++ b/source/blender/compositor/operations/COM_GaussianBokehBlurOperation.h @@ -34,7 +34,7 @@ private: public: GaussianBokehBlurOperation(); - + void initExecution(); void *initializeTileData(rcti *rect, MemoryBuffer **memoryBuffers); /** * the inner loop of this program diff --git a/source/blender/compositor/operations/COM_GaussianXBlurOperation.cpp b/source/blender/compositor/operations/COM_GaussianXBlurOperation.cpp index 276efd90740..121bbbd45a0 100644 --- a/source/blender/compositor/operations/COM_GaussianXBlurOperation.cpp +++ b/source/blender/compositor/operations/COM_GaussianXBlurOperation.cpp @@ -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); } } diff --git a/source/blender/compositor/operations/COM_GaussianXBlurOperation.h b/source/blender/compositor/operations/COM_GaussianXBlurOperation.h index 704d063d28f..a957b8c12af 100644 --- a/source/blender/compositor/operations/COM_GaussianXBlurOperation.h +++ b/source/blender/compositor/operations/COM_GaussianXBlurOperation.h @@ -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(); diff --git a/source/blender/compositor/operations/COM_GaussianYBlurOperation.cpp b/source/blender/compositor/operations/COM_GaussianYBlurOperation.cpp index faef152dc31..1760a281785 100644 --- a/source/blender/compositor/operations/COM_GaussianYBlurOperation.cpp +++ b/source/blender/compositor/operations/COM_GaussianYBlurOperation.cpp @@ -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); } } diff --git a/source/blender/compositor/operations/COM_GaussianYBlurOperation.h b/source/blender/compositor/operations/COM_GaussianYBlurOperation.h index c9baf27b1d6..f33d38de14e 100644 --- a/source/blender/compositor/operations/COM_GaussianYBlurOperation.h +++ b/source/blender/compositor/operations/COM_GaussianYBlurOperation.h @@ -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 */ From 17935168c07937f9b1d1db1874a9f7ba5d3ae540 Mon Sep 17 00:00:00 2001 From: Lukas Toenne Date: Fri, 1 Jun 2012 12:38:03 +0000 Subject: [PATCH 07/10] Reroute nodes, by Jeroen Bakker (patch #28443). By holding shift and "cutting" a node link a new reroute helper node can be inserted. This consists of a single socket that can be used to insert additional connection points into a link. This can be used to keep a connection point in the tree when deleting a node, or to control the path of long connections for layout cleanup. --- source/blender/blenkernel/BKE_node.h | 6 + source/blender/blenkernel/intern/node.c | 3 + source/blender/editors/space_node/drawnode.c | 189 +++++++++++++++++- source/blender/editors/space_node/node_draw.c | 26 ++- source/blender/editors/space_node/node_edit.c | 104 +++++++++- .../blender/editors/space_node/node_intern.h | 5 +- source/blender/editors/space_node/node_ops.c | 2 + .../blender/editors/space_node/node_select.c | 29 ++- .../nodes/composite/node_composite_tree.c | 4 +- source/blender/nodes/intern/node_common.c | 49 +++++ .../blender/nodes/shader/node_shader_tree.c | 4 +- .../blender/nodes/texture/node_texture_tree.c | 4 +- 12 files changed, 388 insertions(+), 37 deletions(-) diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h index 9eecca1686f..d093c9108b6 100644 --- a/source/blender/blenkernel/BKE_node.h +++ b/source/blender/blenkernel/BKE_node.h @@ -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 *************** */ diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c index 02d0ef5ea6a..22286e57c0a 100644 --- a/source/blender/blenkernel/intern/node.c +++ b/source/blender/blenkernel/intern/node.c @@ -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); @@ -1914,6 +1915,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); @@ -1986,6 +1988,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); diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c index 676b1276569..0c4cf783eba 100644 --- a/source/blender/editors/space_node/drawnode.c +++ b/source/blender/editors/space_node/drawnode.c @@ -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; } } @@ -2653,6 +2757,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; @@ -2847,36 +2953,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 { @@ -2891,6 +3022,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]; @@ -2898,9 +3031,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*/ @@ -2908,6 +3042,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); @@ -2917,6 +3067,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 @@ -2946,6 +3104,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 */ diff --git a/source/blender/editors/space_node/node_draw.c b/source/blender/editors/space_node/node_draw.c index 7011d605a7e..b623e21d9cd 100644 --- a/source/blender/editors/space_node/node_draw.c +++ b/source/blender/editors/space_node/node_draw.c @@ -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); diff --git a/source/blender/editors/space_node/node_edit.c b/source/blender/editors/space_node/node_edit.c index 595a9b444f0..1b229c78e0f 100644 --- a/source/blender/editors/space_node/node_edit.c +++ b/source/blender/editors/space_node/node_edit.c @@ -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 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; iptr, "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); diff --git a/source/blender/editors/space_node/node_select.c b/source/blender/editors/space_node/node_select.c index 9098c8a4255..0a3678ca901 100644 --- a/source/blender/editors/space_node/node_select.c +++ b/source/blender/editors/space_node/node_select.c @@ -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; } diff --git a/source/blender/nodes/composite/node_composite_tree.c b/source/blender/nodes/composite/node_composite_tree.c index 5bc2e1fc004..8f8f702e8ae 100644 --- a/source/blender/nodes/composite/node_composite_tree.c +++ b/source/blender/nodes/composite/node_composite_tree.c @@ -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. */ diff --git a/source/blender/nodes/intern/node_common.c b/source/blender/nodes/intern/node_common.c index 48ffed80e41..9f458678ae0 100644 --- a/source/blender/nodes/intern/node_common.c +++ b/source/blender/nodes/intern/node_common.c @@ -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); +} diff --git a/source/blender/nodes/shader/node_shader_tree.c b/source/blender/nodes/shader/node_shader_tree.c index 4794a66d064..a1d873231e7 100644 --- a/source/blender/nodes/shader/node_shader_tree.c +++ b/source/blender/nodes/shader/node_shader_tree.c @@ -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); } diff --git a/source/blender/nodes/texture/node_texture_tree.c b/source/blender/nodes/texture/node_texture_tree.c index ba5682ee8ad..c84436a84b7 100644 --- a/source/blender/nodes/texture/node_texture_tree.c +++ b/source/blender/nodes/texture/node_texture_tree.c @@ -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); } From 719b3e26e768f03990be95e07f588b84deef9caa Mon Sep 17 00:00:00 2001 From: Konrad Kleine Date: Fri, 1 Jun 2012 13:42:18 +0000 Subject: [PATCH 08/10] Added NULL-pointer check to avoid crash in node editor. Fixes #31664 --- source/blender/nodes/intern/node_exec.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/source/blender/nodes/intern/node_exec.c b/source/blender/nodes/intern/node_exec.c index 3f77638e25a..d01ef2e2d52 100644 --- a/source/blender/nodes/intern/node_exec.c +++ b/source/blender/nodes/intern/node_exec.c @@ -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) From 1ced3560099b66d70399b4a5cfbb343b36562979 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Fri, 1 Jun 2012 13:54:44 +0000 Subject: [PATCH 09/10] Action Group Colors for Bones (Part 2) Colors used by Bone Groups are now copied/assigned to Action Groups too when they're created now. This completes the work started in r.46960 to restore this functionality from 2.48. Currently, there is no control over when/whether these colors are copied over (although it is possible to disable the display of these colors for relevant animation editors if desired). Originally I was going to make this a more generic Keying Sets feature, though that turned out to be a bit too complex to manage. Other notes: * Split out the code for copying colors to a common library function --- source/blender/blenkernel/BKE_action.h | 3 ++ source/blender/blenkernel/intern/action.c | 28 ++++++++++++++-- .../editors/animation/anim_channels_defines.c | 2 +- .../editors/animation/keyframes_general.c | 2 +- source/blender/editors/animation/keyframing.c | 33 ++++++++++++++----- .../blender/editors/include/ED_keyframing.h | 3 +- .../blender/editors/object/object_relations.c | 2 +- source/blender/makesrna/intern/rna_action.c | 4 +-- source/blender/makesrna/intern/rna_pose.c | 27 +++------------ 9 files changed, 65 insertions(+), 39 deletions(-) diff --git a/source/blender/blenkernel/BKE_action.h b/source/blender/blenkernel/BKE_action.h index c1361788379..527d85c7cf3 100644 --- a/source/blender/blenkernel/BKE_action.h +++ b/source/blender/blenkernel/BKE_action.h @@ -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[]); diff --git a/source/blender/blenkernel/intern/action.c b/source/blender/blenkernel/intern/action.c index 233647c9ec6..b3d2e3371f4 100644 --- a/source/blender/blenkernel/intern/action.c +++ b/source/blender/blenkernel/intern/action.c @@ -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) diff --git a/source/blender/editors/animation/anim_channels_defines.c b/source/blender/editors/animation/anim_channels_defines.c index 08672a22666..386313b1d3c 100644 --- a/source/blender/editors/animation/anim_channels_defines.c +++ b/source/blender/editors/animation/anim_channels_defines.c @@ -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)) diff --git a/source/blender/editors/animation/keyframes_general.c b/source/blender/editors/animation/keyframes_general.c index 05c87e98f9b..ac37b6c4141 100644 --- a/source/blender/editors/animation/keyframes_general.c +++ b/source/blender/editors/animation/keyframes_general.c @@ -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; } diff --git a/source/blender/editors/animation/keyframing.c b/source/blender/editors/animation/keyframing.c index 2a68d32557a..b8601419d51 100644 --- a/source/blender/editors/animation/keyframing.c +++ b/source/blender/editors/animation/keyframing.c @@ -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; diff --git a/source/blender/editors/include/ED_keyframing.h b/source/blender/editors/include/ED_keyframing.h index be5ad5b0c70..95fad17274e 100644 --- a/source/blender/editors/include/ED_keyframing.h +++ b/source/blender/editors/include/ED_keyframing.h @@ -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); /* -------- */ diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c index 34fb2ca6c32..85b9d78c657 100644 --- a/source/blender/editors/object/object_relations.c +++ b/source/blender/editors/object/object_relations.c @@ -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) diff --git a/source/blender/makesrna/intern/rna_action.c b/source/blender/makesrna/intern/rna_action.c index b63109ed137..00a257ab4f9 100644 --- a/source/blender/makesrna/intern/rna_action.c +++ b/source/blender/makesrna/intern/rna_action.c @@ -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) diff --git a/source/blender/makesrna/intern/rna_pose.c b/source/blender/makesrna/intern/rna_pose.c index 83d40b26cd0..5139e17b06d 100644 --- a/source/blender/makesrna/intern/rna_pose.c +++ b/source/blender/makesrna/intern/rna_pose.c @@ -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); } } From 4fc4aa383b71a7d0a86eef29fd7ffa0383893f52 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Fri, 1 Jun 2012 13:55:00 +0000 Subject: [PATCH 10/10] There's no MASK_OT_select_border in trunk yet --- source/blender/windowmanager/intern/wm_operators.c | 1 - 1 file changed, 1 deletion(-) diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c index 5ae2bcf9c4b..42787be8e02 100644 --- a/source/blender/windowmanager/intern/wm_operators.c +++ b/source/blender/windowmanager/intern/wm_operators.c @@ -3936,7 +3936,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");