Refactoring pipeline concept #3: Introducing PipelineFactory and PipelineRegistrar

parent 2d55cb00
......@@ -66,23 +66,23 @@ int main(int argc, char** argv) {
#endif
CampVisApplication app(argc, argv);
// app.addVisualizationPipeline("Advanced Ultrasound Visualization", new AdvancedUsVis());
// app.addVisualizationPipeline("Confidence Map Generation", new CmBatchGeneration());
// app.addVisualizationPipeline("IXPV", new IxpvDemo());
app.addVisualizationPipeline("SliceVis", new SliceVis());
// app.addVisualizationPipeline("DVRVis", new DVRVis());
// app.addVisualizationPipeline("VolumeRendererDemo", new VolumeRendererDemo());
app.addVisualizationPipeline("VolumeExplorerDemo", new VolumeExplorerDemo());
// app.addVisualizationPipeline("Advanced Ultrasound Visualization", new AdvancedUsVis(app.getDataContainer()));
// app.addVisualizationPipeline("Confidence Map Generation", new CmBatchGeneration(app.getDataContainer()));
// app.addVisualizationPipeline("IXPV", new IxpvDemo(app.getDataContainer()));
app.addVisualizationPipeline("SliceVis", new SliceVis(app.getDataContainer()));
// app.addVisualizationPipeline("DVRVis", new DVRVis(app.getDataContainer()));
// app.addVisualizationPipeline("VolumeRendererDemo", new VolumeRendererDemo(app.getDataContainer()));
app.addVisualizationPipeline("VolumeExplorerDemo", new VolumeExplorerDemo(app.getDataContainer()));
#ifdef HAS_KISSCL
// app.addVisualizationPipeline("DVR with OpenCL", new OpenCLPipeline());
// app.addVisualizationPipeline("DVR with OpenCL", new OpenCLPipeline(app.getDataContainer()));
#endif
#ifdef CAMPVIS_HAS_MODULE_SCR_MSK
app.addVisualizationPipeline("US Compounding", new UsCompounding());
app.addVisualizationPipeline("US Compounding", new UsCompounding(app.getDataContainer()));
#endif
#ifdef CAMPVIS_HAS_MODULE_COLUMBIA
app.addVisualizationPipeline("Columbia", new Columbia1());
app.addVisualizationPipeline("Columbia", new Columbia1(app.getDataContainer()));
#endif
......
......@@ -50,6 +50,7 @@
#include "core/tools/quadrenderer.h"
#include "core/pipeline/abstractpipeline.h"
#include "core/pipeline/autoevaluationpipeline.h"
#include "core/pipeline/pipelinefactory.h"
namespace campvis {
......@@ -173,6 +174,8 @@ namespace campvis {
GLJobProc.start();
_initialized = true;
LINFO(PipelineFactory::getRef().toString());
}
void CampVisApplication::deinit() {
......@@ -270,4 +273,12 @@ namespace campvis {
_mainWindow->addDockWidget(area, dock);
}
DataContainer* CampVisApplication::getDataContainer() {
return &_dataContainer;
}
const DataContainer* CampVisApplication::getDataContainer() const {
return &_dataContainer;
}
}
......@@ -38,6 +38,8 @@
#include <utility>
#include <vector>
#include "core/datastructures/datacontainer.h"
namespace tgt {
class QtThreadedCanvas;
}
......@@ -125,10 +127,25 @@ namespace campvis {
*/
int run();
/**
* Gets the DataContainer of this CampvisApplication
* \return _dataContainer
*/
DataContainer* getDataContainer();
/**
* Gets the DataContainer of this CampvisApplication
* \return _dataContainer
*/
const DataContainer* getDataContainer() const;
/// Signal emitted when the collection of pipelines has changed.
sigslot::signal0<> s_PipelinesChanged;
private:
/// The (currently) one and only DataContainer in CampvisApplication
DataContainer _dataContainer;
/// All pipelines (incuding VisualizationPipelines)
std::vector<AbstractPipeline*> _pipelines;
/// All visualisations (i.e. VisualizationPipelines with their corresponding painters/canvases)
......
......@@ -34,8 +34,8 @@
#include "tgt/glcontext.h"
#include "tgt/tgt_gl.h"
#include "core/pipeline/abstractprocessor.h"
#include "core/pipeline/visualizationprocessor.h"
#include "core/pipeline/abstractprocessor.h"
#include "core/tools/job.h"
#include "core/tools/opengljobprocessor.h"
#include "core/tools/simplejobprocessor.h"
......@@ -67,15 +67,18 @@ namespace {
namespace campvis {
const std::string AbstractPipeline::loggerCat_ = "CAMPVis.core.datastructures.AbstractPipeline";
AbstractPipeline::AbstractPipeline()
AbstractPipeline::AbstractPipeline(DataContainer* dc)
: HasPropertyCollection()
, tgt::EventHandler()
, tgt::EventListener()
, _data(dc)
, _canvas(0)
, _canvasSize("CanvasSize", "Canvas Size", tgt::ivec2(128, 128), tgt::ivec2(1, 1), tgt::ivec2(4096, 4096))
, _ignoreCanvasSizeUpdate(false)
, _renderTargetID("renderTargetID", "Render Target ID", "AbstractPipeline.renderTarget", DataNameProperty::READ)
{
tgtAssert(_data != 0, "Pointer to the DataContainer for this pipeline must not be 0!");
_enabled = true;
addProperty(&_renderTargetID);
......@@ -87,7 +90,7 @@ namespace campvis {
void AbstractPipeline::init() {
_renderTargetID.s_changed.connect<AbstractPipeline>(this, &AbstractPipeline::onPropertyChanged);
_data.s_dataAdded.connect(this, &AbstractPipeline::onDataContainerDataAdded);
_data->s_dataAdded.connect(this, &AbstractPipeline::onDataContainerDataAdded);
initAllProperties();
......@@ -116,11 +119,11 @@ namespace campvis {
}
}
_data.s_dataAdded.disconnect(this);
_data->s_dataAdded.disconnect(this);
_renderTargetID.s_changed.disconnect(this);
// clear DataContainer
_data.clear();
_data->clear();
}
void AbstractPipeline::onPropertyChanged(const AbstractProperty* prop) {
......@@ -140,11 +143,11 @@ namespace campvis {
}
const DataContainer& AbstractPipeline::getDataContainer() const {
return _data;
return *_data;
}
DataContainer& AbstractPipeline::getDataContainer() {
return _data;
return *_data;
}
void AbstractPipeline::executeProcessor(AbstractProcessor* processor, bool unlockInExtraThred) {
......@@ -153,7 +156,7 @@ namespace campvis {
if (processor->getEnabled() && !processor->isLocked()) {
// update properties if they're invalid
if (processor->hasInvalidProperties()) {
processor->updateProperties(_data);
processor->updateProperties(*_data);
#if CAMPVIS_DEBUG
if (processor->hasInvalidProperties())
LDEBUG("Processor " << processor->getName() << " still has INVALID_PROPERTIES level. Did you forget to validate the processor in updateProperties()?");
......@@ -166,7 +169,7 @@ namespace campvis {
clock_t startTime = clock();
try {
processor->process(_data);
processor->process(*_data);
}
catch (std::exception& e) {
LERROR("Caught unhandled exception while executing processor " << processor->getName() << ": " << e.what());
......
......@@ -45,6 +45,7 @@
#include "core/properties/floatingpointproperty.h"
#include "core/properties/propertycollection.h"
#include <map>
#include <vector>
namespace tgt {
......@@ -63,8 +64,11 @@ namespace campvis {
* Creates a AbstractPipeline.
* If you derive from AbstractPipeline, you will have to implement the pipeline evaluation
* logic yourself. You might want to have a look at AutoEvaluationPipeline.
*
* \param dc Pointer to the DataContainer containing local working set of data for this
* pipeline, must not be 0, must be valid the whole lifetime of this pipeline.
*/
AbstractPipeline();
AbstractPipeline(DataContainer* dc);
/**
* Virtual Destructor
......@@ -213,7 +217,8 @@ namespace campvis {
virtual void onPropertyChanged(const AbstractProperty* prop);
DataContainer _data; ///< DataContainer containing local working set of data for this Pipeline
/// Pointer to the DataContainer containing local working set of data for this Pipeline, must not be 0.
DataContainer* _data;
std::vector<AbstractProcessor*> _processors; ///< List of all processors of this pipeline
tbb::atomic<bool> _enabled; ///< flag whether this pipeline is currently enabled
......
......@@ -40,8 +40,8 @@
namespace campvis {
const std::string AutoEvaluationPipeline::loggerCat_ = "CAMPVis.core.datastructures.AutoEvaluationPipeline";
AutoEvaluationPipeline::AutoEvaluationPipeline()
: AbstractPipeline()
AutoEvaluationPipeline::AutoEvaluationPipeline(DataContainer* dc)
: AbstractPipeline(dc)
{
}
......
......@@ -41,13 +41,16 @@ namespace campvis {
* Specializtaion of AbstractPipeline performing automatic execution of invalidated processors.
* AutoEvaluationPipeline connects to the s_(in)validated signals of all of its processors and
* executes processors with invalid results using the correct threads.
*
* \param dc Pointer to the DataContainer containing local working set of data for this
* pipeline, must not be 0, must be valid the whole lifetime of this pipeline.
*/
class AutoEvaluationPipeline : public AbstractPipeline {
public:
/**
* Creates a AutoEvaluationPipeline.
*/
AutoEvaluationPipeline();
AutoEvaluationPipeline(DataContainer* dc);
/**
* Virtual Destructor
......
// ================================================================================================
//
// This file is part of the CAMPVis Software Framework.
//
// If not explicitly stated otherwise: Copyright (C) 2012, all rights reserved,
// Christian Schulte zu Berge <christian.szb@in.tum.de>
// Chair for Computer Aided Medical Procedures
// Technische Universitt Mnchen
// Boltzmannstr. 3, 85748 Garching b. Mnchen, Germany
// For a full list of authors and contributors, please refer to the file "AUTHORS.txt".
//
// The licensing of this softare is not yet resolved. Until then, redistribution in source or
// binary forms outside the CAMP chair is not permitted, unless explicitly stated in legal form.
// However, the names of the original authors and the above copyright notice must retain in its
// original state in any case.
//
// Legal disclaimer provided by the BSD license:
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
// IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// ================================================================================================
#include "digraphvisualizationpipeline.h"
#include "tgt/tgt_gl.h"
#include "tgt/glcanvas.h"
#include "tgt/glcontext.h"
#include "core/pipeline/visualizationprocessor.h"
#include "core/tools/job.h"
#include "core/tools/opengljobprocessor.h"
#include "core/tools/simplejobprocessor.h"
#include <stack>
namespace campvis {
const std::string DigraphVisualizationPipeline::loggerCat_ = "CAMPVis.core.datastructures.DigraphVisualizationPipeline";
DigraphVisualizationPipeline::DependencyNode::DependencyNode(AbstractProcessor* processor)
: _processor(processor)
{
tgtAssert(_processor != 0, "Processor must not be 0.");
if (_processor != 0) {
_isVisualizationProcessor = (dynamic_cast<VisualizationProcessor*>(_processor) != 0);
}
}
void DigraphVisualizationPipeline::DependencyNode::addDependency(DependencyNode* dependency) {
tgtAssert(dependency != 0, "DependencyNode must not be 0.");
// check for acyclicness
std::stack<DependencyNode*> nodesToVisit;
for (std::set<DependencyNode*>::const_iterator it = dependency->_dependentNodes.begin(); it != dependency->_dependentNodes.end(); ++it) {
nodesToVisit.push(*it);
}
while (! nodesToVisit.empty()) {
DependencyNode* node = nodesToVisit.top();
nodesToVisit.pop();
if (node == this) {
LERROR("Circle in dependency graph detected. DependencyNode insertion aborted.");
return;
}
for (std::set<DependencyNode*>::const_iterator it = dependency->_dependentNodes.begin(); it != dependency->_dependentNodes.end(); ++it) {
nodesToVisit.push(*it);
}
}
// add dependency
_dependentNodes.insert(dependency);
}
// ================================================================================================
DigraphVisualizationPipeline::DigraphVisualizationPipeline()
: AutoEvaluationPipeline()
{
}
DigraphVisualizationPipeline::~DigraphVisualizationPipeline() {
// delete all DependencyNodes
for (std::map<AbstractProcessor*, DependencyNode*>::iterator it = _processorNodeMap.begin(); it != _processorNodeMap.end(); ++it) {
delete it->second;
}
}
void DigraphVisualizationPipeline::addProcessor(AbstractProcessor* processor) {
tgtAssert(processor != 0, "Processor must not be 0!");
// add processor to processor list and connect signals
AutoEvaluationPipeline::addProcessor(processor);
processor->s_invalidated.connect<DigraphVisualizationPipeline>(this, &DigraphVisualizationPipeline::onProcessorInvalidated);
// create DependencyNode
std::map<AbstractProcessor*, DependencyNode*>::iterator lb = _processorNodeMap.lower_bound(processor);
if (lb == _processorNodeMap.end() || lb->first != processor) {
DependencyNode* node = new DependencyNode(processor);
_processorNodeMap.insert(lb, std::make_pair(processor, node));
}
else {
LDEBUG("Processor already added!");
}
}
void DigraphVisualizationPipeline::addProcessorDependency(AbstractProcessor* fatherProc, AbstractProcessor* childProc) {
tgtAssert(fatherProc != 0, "Father Processor must not be 0!");
tgtAssert(childProc != 0, "Child Processor must not be 0!");
// find corresponding DependencyNodes
std::map<AbstractProcessor*, DependencyNode*>::iterator fatherNode = _processorNodeMap.find(fatherProc);
std::map<AbstractProcessor*, DependencyNode*>::iterator childNode = _processorNodeMap.find(childProc);
if (fatherNode == _processorNodeMap.end() || childNode == _processorNodeMap.end()) {
tgtAssert(false, "Add processors first before defining dependencies between them!");
LERROR("Could not find DependencyNodes for at least one of the given processors. No dependency added!");
return;
}
// add dependency
fatherNode->second->addDependency(childNode->second);
}
void DigraphVisualizationPipeline::onProcessorInvalidated(AbstractProcessor* processor) {
// dirty hack - implement proper initialization...
if (_canvas == 0)
return;
// TODO: think about a more elaborate implementation, this one doesn't care about the processor graph
std::map<AbstractProcessor*, DependencyNode*>::iterator node = _processorNodeMap.find(processor);
if (node != _processorNodeMap.end()) {
if (node->second->_isVisualizationProcessor) {
GLJobProc.enqueueJob(
_canvas,
makeJobOnHeap<DigraphVisualizationPipeline, AbstractProcessor*, bool>(this, &DigraphVisualizationPipeline::executeProcessor, processor, true),
OpenGLJobProcessor::SerialJob);
}
else {
SimpleJobProc.enqueueJob(makeJob<DigraphVisualizationPipeline, AbstractProcessor*, bool>(this, &DigraphVisualizationPipeline::executeProcessor, processor, false));
}
}
else {
LWARNING("Caught invalidation of a processor that is not in the processor graph!");
}
}
}
// ================================================================================================
//
// This file is part of the CAMPVis Software Framework.
//
// If not explicitly stated otherwise: Copyright (C) 2012, all rights reserved,
// Christian Schulte zu Berge <christian.szb@in.tum.de>
// Chair for Computer Aided Medical Procedures
// Technische Universität München
// Boltzmannstr. 3, 85748 Garching b. München, Germany
// For a full list of authors and contributors, please refer to the file "AUTHORS.txt".
//
// The licensing of this softare is not yet resolved. Until then, redistribution in source or
// binary forms outside the CAMP chair is not permitted, unless explicitly stated in legal form.
// However, the names of the original authors and the above copyright notice must retain in its
// original state in any case.
//
// Legal disclaimer provided by the BSD license:
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
// IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// ================================================================================================
#include "pipelinefactory.h"
#include <sstream>
namespace campvis {
// declare one single symbol for the PipelineFactory singleton
tbb::atomic<PipelineFactory*> PipelineFactory::_singleton;
std::string PipelineFactory::toString() {
std::stringstream ss;
ss << _pipelineMap.size() << " Pipelines registered: ";
for (std::map< std::string, AbstractPipeline* (*)(DataContainer*) >::iterator it = _pipelineMap.begin(); it != _pipelineMap.end(); ++it) {
ss << it->first << ", ";
}
return ss.str();
}
}
\ No newline at end of file
......@@ -38,8 +38,8 @@
namespace campvis {
AdvancedUsVis::AdvancedUsVis()
: DigraphVisualizationPipeline()
AdvancedUsVis::AdvancedUsVis(DataContainer* dc)
: AutoEvaluationPipeline(dc)
, _camera("camera", "Camera")
, _usReader()
, _confidenceReader()
......@@ -232,14 +232,10 @@ namespace campvis {
}
}
const std::string AdvancedUsVis::getName() const {
return "AdvancedUsVis";
}
void AdvancedUsVis::onProcessorValidated(AbstractProcessor* processor) {
if (processor = &_usReader) {
// convert data
DataContainer::ScopedTypedData<ImageData> img(_data, _usReader.p_targetImageID.getValue());
DataContainer::ScopedTypedData<ImageData> img(*_data, _usReader.p_targetImageID.getValue());
if (img != 0) {
_trackballEH->reinitializeCamera(img);
}
......
......@@ -34,7 +34,8 @@
#include "core/eventhandlers/mwheeltonumericpropertyeventlistener.h"
#include "core/eventhandlers/transfuncwindowingeventlistener.h"
#include "core/eventhandlers/trackballnavigationeventlistener.h"
#include "core/pipeline/digraphvisualizationpipeline.h"
#include "core/pipeline/autoevaluationpipeline.h"
#include "core/pipeline/pipelinefactory.h"
#include "modules/devil/processors/devilimagereader.h"
#include "modules/io/processors/mhdimagereader.h"
#include "modules/io/processors/csvdimagereader.h"
......@@ -49,12 +50,12 @@
#include "modules/randomwalk/processors/confidencemapgenerator.h"
namespace campvis {
class AdvancedUsVis : public DigraphVisualizationPipeline {
class AdvancedUsVis : public AutoEvaluationPipeline {
public:
/**
* Creates a VisualizationPipeline.
*/
AdvancedUsVis();
AdvancedUsVis(DataContainer* dc);
/**
* Virtual Destructor
......@@ -68,7 +69,8 @@ namespace campvis {
virtual void deinit();
/// \see AbstractPipeline::getName()
virtual const std::string getName() const;
virtual const std::string getName() const { return getId(); };
static const std::string getId() { return "AdvancedUsVis"; };
/**
* Execute this pipeline.
......@@ -112,6 +114,10 @@ namespace campvis {
TrackballNavigationEventListener* _trackballEH;
};
/// Instantiate templated PipelineRegistrar to automatically register this pipeline.
template class PipelineRegistrar<AdvancedUsVis>;
}
#endif // ADVANCEDUSVIS_H__
......@@ -50,8 +50,8 @@
namespace campvis {
CmBatchGeneration::CmBatchGeneration()
: AutoEvaluationPipeline()
CmBatchGeneration::CmBatchGeneration(DataContainer* dc)
: AutoEvaluationPipeline(dc)
, _usReader(&_canvasSize)
, _confidenceGenerator()
, _usBlurFilter()
......@@ -137,10 +137,6 @@ namespace campvis {
}
}
const std::string CmBatchGeneration::getName() const {
return "CmBatchGeneration";
}
void CmBatchGeneration::onProcessorInvalidated(AbstractProcessor* processor) {
if (p_autoExecution.getValue())
AutoEvaluationPipeline::onProcessorInvalidated(processor);
......@@ -155,7 +151,7 @@ namespace campvis {
executeProcessor(&_usReader, false);
DataHandle dh = _data.getData(_usReader.p_targetImageID.getValue());
DataHandle dh = _data->getData(_usReader.p_targetImageID.getValue());
if (dh.getData() != 0) {
if (const ImageData* tester = dynamic_cast<const ImageData*>(dh.getData())) {
_canvasSize.setValue(tester->getSize().xy());
......@@ -177,7 +173,7 @@ namespace campvis {
void CmBatchGeneration::save(int path, const std::string& basePath) {
// get result
DataContainer::ScopedTypedData<RenderData> rd(_data, _usFusion.p_targetImageID.getValue());
DataContainer::ScopedTypedData<RenderData> rd(*_data, _usFusion.p_targetImageID.getValue());
const ImageRepresentationGL* rep = rd->getColorTexture()->getRepresentation<ImageRepresentationGL>(false);
if (rep != 0) {
#ifdef CAMPVIS_HAS_MODULE_DEVIL
......
......@@ -32,6 +32,7 @@
#include "core/datastructures/imagerepresentationlocal.h"
#include "core/pipeline/autoevaluationpipeline.h"
#include "core/pipeline/pipelinefactory.h"
#include "modules/devil/processors/devilimagereader.h"
#include "modules/io/processors/mhdimagereader.h"
#include "modules/io/processors/csvdimagereader.h"
......@@ -54,7 +55,7 @@ namespace campvis {
/**
* Creates a AutoEvaluationPipeline.
*/
CmBatchGeneration();
CmBatchGeneration(DataContainer* dc);
/**
* Virtual Destructor
......@@ -68,7 +69,8 @@ namespace campvis {
virtual void deinit();
/// \see AbstractPipeline::getName()
virtual const std::string getName() const;
virtual const std::string getName() const { return getId(); };
static const std::string getId() { return "CmBatchGeneration"; };
/**
* Execute this pipeline.
......@@ -100,6 +102,10 @@ namespace campvis {
ButtonProperty p_execute;
};
/// Instantiate templated PipelineRegistrar to automatically register this pipeline.
template class PipelineRegistrar<CmBatchGeneration>;
}
#endif // CMBATCHGENERATION_H__
......@@ -39,8 +39,8 @@
namespace campvis {
Columbia1::Columbia1()
: AutoEvaluationPipeline()
Columbia1::Columbia1(DataContainer* dc)
: AutoEvaluationPipeline(dc)
, _camera("camera", "Camera")
, _boundsData("BoundsData", "Bounds Data", "sfr", DataNameProperty::READ)
, _imageReader()
......@@ -151,14 +151,10 @@ namespace campvis {
AutoEvaluationPipeline::deinit();
}
const std::string Columbia1::getName() const {
return "Columbia1";
}
void Columbia1::onProcessorValidated(AbstractProcessor* processor) {
if (processor == &_imageSplitter) {
// update camera
DataContainer::ScopedTypedData<ImageData> img(_data, _imageSplitter.p_outputID.getValue());
DataContainer::ScopedTypedData<ImageData> img(*_data, _imageSplitter.p_outputID.getValue());
if (img != 0) {
_trackballEH->reinitializeCamera(img);
}
......
......@@ -32,6 +32,7 @@
#include "core/eventhandlers/trackballnavigationeventlistener.h"
#include "core/pipeline/autoevaluationpipeline.h"
#include "core/pipeline/pipelinefactory.h"
#include "core/properties/cameraproperty.h"
......@@ -53,7 +54,7 @@ namespace campvis {
/**
* Creates a AutoEvaluationPipeline.