Starting from 2021-07-01, all LRZ GitLab users will be required to explicitly accept the GitLab Terms of Service. Please see the detailed information at https://doku.lrz.de/display/PUBLIC/GitLab and make sure that your projects conform to the requirements.

Commit 96ede32e authored by Christian Schulte zu Berge's avatar Christian Schulte zu Berge
Browse files

Merge remote-tracking branch 'remotes/origin/luascriptingext' into development

parents 85d0ed1b efa1e0a7
......@@ -278,6 +278,9 @@ namespace campvis {
//if (! _luaVmState->injectObjectPointerToTableField(pipeline, "campvis::AutoEvaluationPipeline *", "pipelines", name))
LERROR("Could not inject the pipeline into the Lua VM.");
if (! _luaVmState->injectObjectPointerToTableField(pipeline, "campvis::AutoEvaluationPipeline *", "pipelines", pipeline->getName()))
LERROR("Could not inject the pipeline into the Lua VM.");
_luaVmState->execString("inspect(pipelines)");
#endif
......
......@@ -219,7 +219,7 @@ namespace campvis {
_mainLayout->addWidget(_infoWidget, 0, 1, 3, 1);
qRegisterMetaType<QtDataHandle>("QtDataHandle");
qRegisterMetaType<cgt::vec4>("tgt_vec4");
qRegisterMetaType<cgt::vec4>("cgt_vec4");
connect(
_dctWidget->selectionModel(), SIGNAL(selectionChanged(const QItemSelection&, const QItemSelection&)),
this, SLOT(onDCTWidgetSelectionModelSelectionChanged(const QItemSelection&, const QItemSelection&)));
......
......@@ -39,6 +39,12 @@
#include "modules/pipelinefactory.h"
#include <QScrollBar>
#include <QFileDialog>
#include <fstream>
#include "scripting/luagen/properties/propertycollectionluascriptgenerator.h"
#include "scripting/luagen/properties/abstractpropertylua.h"
namespace campvis {
......@@ -103,6 +109,26 @@ namespace campvis {
_containerWidget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Maximum);
_cwLayout->addWidget(_pipelineWidget, 1, 0, 1, 2);
_btnExecute = new QPushButton("Execute Selected Pipeline/Processor", _containerWidget);
_cwLayout->addWidget(_btnExecute, 2, 0, 1, 2);
_btnShowDataContainerInspector = new QPushButton("Inspect DataContainer of Selected Pipeline", _containerWidget);
_cwLayout->addWidget(_btnShowDataContainerInspector, 3, 0, 1, 2);
#ifdef CAMPVIS_HAS_SCRIPTING
_btnLuaLoad = new QPushButton("Load Script", _containerWidget);
_cwLayout->addWidget(_btnLuaLoad, 4, 0, 1, 2);
_btnLuaSave = new QPushButton("Save Script", _containerWidget);
_cwLayout->addWidget(_btnLuaSave, 5, 0, 1, 2);
connect(
_btnLuaLoad, SIGNAL(clicked()),
this, SLOT(onBtnLuaLoadClicked()));
connect(
_btnLuaSave, SIGNAL(clicked()),
this, SLOT(onBtnLuaSaveClicked()));
#else
#endif
_containerWidget->setLayout(_cwLayout);
ui.pipelineTreeDock->setWidget(_containerWidget);
......@@ -120,12 +146,6 @@ namespace campvis {
rightLayout->setSpacing(4);
_pipelinePropertiesWidget->setLayout(rightLayout);
_btnExecute = new QPushButton("Execute Selected Pipeline/Processor", _pipelinePropertiesWidget);
rightLayout->addWidget(_btnExecute);
_btnShowDataContainerInspector = new QPushButton("Inspect DataContainer of Selected Pipeline", _pipelinePropertiesWidget);
rightLayout->addWidget(_btnShowDataContainerInspector);
_propCollectionWidget = new PropertyCollectionWidget(this);
rightLayout->addWidget(_propCollectionWidget);
rightLayout->addStretch();
......@@ -168,6 +188,7 @@ namespace campvis {
_application->s_PipelinesChanged.connect(this, &MainWindow::onPipelinesChanged);
_application->s_DataContainersChanged.connect(this, &MainWindow::onDataContainersChanged);
}
void MainWindow::populateMainMenu() {
......@@ -236,11 +257,13 @@ namespace campvis {
}
emit updatePropCollectionWidget(ptr, &_selectedPipeline->getDataContainer());
}
else {
emit updatePropCollectionWidget(0, 0);
_selectedDataContainer = 0;
}
}
else {
emit updatePropCollectionWidget(0, 0);
......@@ -265,6 +288,53 @@ namespace campvis {
}
}
void MainWindow::onBtnLuaLoadClicked() {
#ifdef CAMPVIS_HAS_SCRIPTING
const QString dialogCaption = QString::fromStdString("Select File");
const QString directory = QString::fromStdString(".");
const QString fileFilter = tr("All files (*)");
QString filename = QFileDialog::getOpenFileName(QWidget::parentWidget(), dialogCaption, directory, fileFilter);
if (filename != nullptr && _application->getLuaVmState() != nullptr) {
_application->getLuaVmState()->execFile(filename.toStdString());
}
#endif
}
void MainWindow::onBtnLuaSaveClicked() {
#ifdef CAMPVIS_HAS_SCRIPTING
const QString dialogCaption = QString::fromStdString("Save File as");
const QString directory = QString::fromStdString(".");
const QString fileFilter = tr("All files (*)");
QString filename = QFileDialog::getSaveFileName(QWidget::parentWidget(), dialogCaption, directory, fileFilter);
if (filename != nullptr) {
if (_selectedProcessor != 0 && _selectedPipeline != 0) {
PropertyCollectionLuaScriptGenerator* _pcLua = new PropertyCollectionLuaScriptGenerator();
std::string pipeScript = "pipeline = pipelines[\"" + _selectedPipeline->getName()+"\"]\n\n";
for (size_t i = 0; i < _selectedPipeline->getProcessors().size(); i++) {
pipeScript += "proc = pipeline:getProcessor(" + StringUtils::toString(i) + ")\n";
AbstractProcessor* proc = _selectedPipeline->getProcessor(i);
_pcLua->updatePropCollection(proc, &_selectedPipeline->getDataContainer());
std::string res = _pcLua->getLuaScript(std::string(""), std::string("proc:"));
pipeScript += res;
}
if (pipeScript != "pipeline = pipelines[\"" + _selectedPipeline->getName()+"\"]\n\n") {
std::ofstream file;
file.open(filename.toStdString());
file << pipeScript.c_str();
file.close();
}
delete _pcLua;
}
}
#endif
}
void MainWindow::onBtnShowDataContainerInspectorClicked() {
if (_selectedPipeline != 0) {
if (_dcInspectorWindow == 0) {
......
......@@ -112,7 +112,7 @@ namespace campvis {
* \param index Index of the selected item
*/
void onPipelineWidgetItemClicked(const QModelIndex& index);
/**
* Slot to be called when _btnExecute was clicked.
*/
......@@ -123,6 +123,16 @@ namespace campvis {
*/
void onBtnShowDataContainerInspectorClicked();
/**
* Slot to be called when _btnExecute was clicked.
*/
void onBtnLuaLoadClicked();
/**
* Slot to be called when _btnShowDataContainerInspector was clicked.
*/
void onBtnLuaSaveClicked();
/// Slot to be called when _btnPipelineFactory was clicked;
void onBtnPipelineFactoryClicked();
......@@ -191,6 +201,9 @@ namespace campvis {
LogViewerWidget* _logViewer; ///< Widget displaying log messages
ScriptingWidget* _scriptingConsoleWidget; ///< Widget showing the scripting console (if available)
QPushButton* _btnLuaLoad;
QPushButton* _btnLuaSave;
std::vector<QDockWidget*> _primaryDocks; ///< Docks located in top docking area of the main window
};
}
......
......@@ -189,19 +189,10 @@ namespace campvis {
{
tbb::mutex::scoped_lock lock(_localMutex);
// add a control point on CTRL+Click
std::vector<TFGeometry1D::KeyPoint>& kpts = g->getKeyPoints();
TFGeometry1D::KeyPoint kp(static_cast<float>(e->x()) / static_cast<float>(_canvas->width()), cgt::col4(255));
std::vector<TFGeometry1D::KeyPoint>::iterator lb = std::upper_bound(kpts.begin(), kpts.end(), kp);
if (lb != kpts.end()) {
kp._color = lb->_color;
}
else {
kp._color = kpts.back()._color;
}
float pos = static_cast<float>(e->x()) / static_cast<float>(_canvas->width());
float alpha = cgt::clamp(static_cast<float>(_canvas->height() - e->y()) / static_cast<float>(_canvas->height()), 0.f, 1.f);
kp._color.a = static_cast<uint8_t>(alpha * 255.f);
kpts.insert(lb, kp);
g->addKeyPoint(pos, alpha);
}
updateManipulators();
......
......@@ -33,8 +33,6 @@
#include <QPushButton>
namespace campvis {
PropertyCollectionWidget::PropertyCollectionWidget(QWidget* parent /*= 0*/)
: QWidget(parent)
, _propCollection(0)
......
......@@ -89,7 +89,13 @@ namespace campvis {
connect(_btnFitDomainToImage, SIGNAL(clicked(bool)), this, SLOT(onFitClicked(bool)));
connect(_cbAutoFitDomainToImage, SIGNAL(stateChanged(int)), this, SLOT(onAutoFitDomainToImageChanged(int)));
property->s_BeforeTFReplace.connect(this, &TransferFunctionPropertyWidget::onBeforeTFReplace);
property->s_AfterTFReplace.connect(this, &TransferFunctionPropertyWidget::onAfterTFReplace);
connect(this, SIGNAL(s_beforeTFReplace(AbstractTransferFunction*)), this, SLOT(execBeforeTFReplace(AbstractTransferFunction*)));
connect(this, SIGNAL(s_afterTFReplace(AbstractTransferFunction*)), this, SLOT(execAfterTFReplace(AbstractTransferFunction*)));
property->s_autoFitWindowToDataChanged.connect(this, &TransferFunctionPropertyWidget::onTransferFunctionAutoFitWindowToDataChanged);
wasVisible = false;
}
TransferFunctionPropertyWidget::~TransferFunctionPropertyWidget() {
......@@ -128,7 +134,7 @@ namespace campvis {
}
void TransferFunctionPropertyWidget::onEditClicked(bool checked) {
if (_editor == 0) {
if (_editor == nullptr) {
TransferFunctionProperty* prop = static_cast<TransferFunctionProperty*>(_property);
_editor = TransferFunctionEditorFactory::createEditor(prop);
......@@ -164,5 +170,41 @@ namespace campvis {
emit s_propertyChanged(_property);
}
void TransferFunctionPropertyWidget::execBeforeTFReplace(AbstractTransferFunction *tf ) {
if (!_dockWidget && !_editor)
return;
if (_dockWidget) {
wasVisible = _dockWidget->isVisible();
_dockWidget->setVisible(false);
}
if (_editor) {
delete _editor;
_editor = nullptr;
}
}
void TransferFunctionPropertyWidget::execAfterTFReplace(AbstractTransferFunction *tf ) {
if (!_dockWidget && !_editor)
return;
if (_editor == nullptr && _dockWidget != nullptr) {
TransferFunctionProperty* prop = static_cast<TransferFunctionProperty*>(_property);
_editor = TransferFunctionEditorFactory::createEditor(prop);
_dockWidget->setWidget(_editor);
_dockWidget->setVisible(wasVisible);
} else {
_dockWidget->setVisible(true);
}
}
void TransferFunctionPropertyWidget::onBeforeTFReplace( AbstractTransferFunction *tf ) {
emit s_beforeTFReplace(tf);
}
void TransferFunctionPropertyWidget::onAfterTFReplace( AbstractTransferFunction *tf ) {
emit s_afterTFReplace(tf);
}
}
\ No newline at end of file
......@@ -71,6 +71,11 @@ namespace campvis {
*/
void onTransferFunctionAutoFitWindowToDataChanged();
signals:
void s_beforeTFReplace(AbstractTransferFunction* tf);
void s_afterTFReplace(AbstractTransferFunction* tf);
private slots:
/// slot called when one of the intensity domain spin edits has changed
void onDomainChanged(double value);
......@@ -81,6 +86,18 @@ namespace campvis {
/// slot called when _cbAutoFitDomainToImage changed
void onAutoFitDomainToImageChanged(int state);
protected slots:
/// slot called when transfer function is about to be replaced
void execBeforeTFReplace(AbstractTransferFunction *tf);
/// slot called when transfer function just has replaced
void execAfterTFReplace(AbstractTransferFunction *tf);
private:
/// catch slot for tf replace action
void onBeforeTFReplace(AbstractTransferFunction *tf);
/// catch slot for tf replace action
void onAfterTFReplace(AbstractTransferFunction *tf);
private:
QWidget* _widget; ///< Widget grouping the widgets together
QGridLayout* _gridLayout; ///< Layout for _widget
......@@ -94,6 +111,8 @@ namespace campvis {
QDockWidget* _dockWidget; ///< DockWidget for transfer function editor
AbstractTransferFunctionEditor* _editor; ///< Transfer function editor
bool wasVisible; ///< remembers whether _docWidget was visible or not
};
// explicitly instantiate template, so that it gets registered also over DLL boundaries.
......
......@@ -17,7 +17,10 @@
#include "core/pipeline/autoevaluationpipeline.h"
#include "core/pipeline/visualizationprocessor.h"
#include "core/classification/tfgeometry1d.h"
#include "core/classification/tfgeometry2d.h"
#include "core/classification/geometry1dtransferfunction.h"
#include "core/classification/simpletransferfunction.h"
#include "core/classification/geometry2dtransferfunction.h"
%}
......@@ -117,6 +120,7 @@ namespace campvis {
virtual ~NumericProperty();
};
%template(IntGenericProperty) GenericProperty< int >;
%template(IntProperty) NumericProperty< int >;
typedef NumericProperty< int > IntProperty;
......@@ -181,6 +185,38 @@ namespace campvis {
%template(Vec4NumericProperty) NumericProperty< cgt::Vector4<float> >;
%template(Vec4Property) FloatingPointProperty< cgt::Vector4<float> >;
typedef FloatingPointProperty< cgt::Vector4<float> > Vec4Property;
/* OptionProperty */
class AbstractOptionProperty : public IntProperty {
public:
AbstractOptionProperty(const std::string& name, const std::string& title);
virtual ~AbstractOptionProperty();
virtual const std::string& getOptionId() = 0;
virtual void selectById(const std::string& id) = 0;
};
template<typename T>
class GenericOptionProperty : public AbstractOptionProperty {
public:
GenericOptionProperty(
const std::string& name,
const std::string& title,
const GenericOption<T>* options,
int count);
virtual ~GenericOptionProperty();
const std::string& getOptionId();
void selectById(const std::string& id);
};
/* Downcast the return value of selectById to appropriate subclass */
%factory(void campvis::AbstractOptionProperty::selectById,
campvis::GenericOptionProperty);
/* Downcast the return value of getOptionId to appropriate subclass */
%factory(void campvis::AbstractOptionProperty::getOptionId,
campvis::GenericOptionProperty);
/* TFGeometry1D */
%nodefaultctor TFGeometry1D;
......@@ -188,7 +224,20 @@ namespace campvis {
class TFGeometry1D {
public:
virtual ~TFGeometry1D();
static TFGeometry1D* createQuad(const cgt::vec2& interval, const cgt::col4& leftColor, const cgt::vec4& rightColor);
static TFGeometry1D* createQuad(const cgt::vec2& interval, const cgt::col4& leftColor, const cgt::col4& rightColor);
void addKeyPoint(float position, float alpha);
void addKeyPoint(float position, const cgt::col4& color);
};
/* TFGeometry2D */
%nodefaultctor TFGeometry2D;
class TFGeometry2D {
public:
virtual ~TFGeometry2D();
static TFGeometry2D* createQuad(const cgt::vec2& ll, const cgt::vec2& ur, const cgt::col4& color);
};
/* AbstractTransferFunction */
......@@ -201,6 +250,17 @@ namespace campvis {
virtual AbstractTransferFunction* clone() const = 0;
};
/* SimpleTransferFunction */
class SimpleTransferFunction : public AbstractTransferFunction {
public:
SimpleTransferFunction(size_t size, const cgt::vec2& intensityDomain = cgt::vec2(0.f, 1.f));
virtual ~SimpleTransferFunction();
virtual SimpleTransferFunction* clone() const;
void setLeftColor(const cgt::col4& color);
void setRightColor(const cgt::col4& color);
};
/* GenericGeometryTransferFunction */
template<class T>
......@@ -211,7 +271,7 @@ namespace campvis {
void addGeometry(T* geometry);
};
/* Geometry1DTransferFunction */
%template(GenericGeometryTransferFunction_TFGeometry1D) GenericGeometryTransferFunction<TFGeometry1D>;
......@@ -224,6 +284,18 @@ namespace campvis {
virtual Geometry1DTransferFunction* clone() const;
};
/* Geometry2DTransferFunction */
%template(GenericGeometryTransferFunction_TFGeometry2D) GenericGeometryTransferFunction<TFGeometry2D>;
class Geometry2DTransferFunction : public GenericGeometryTransferFunction<TFGeometry2D> {
public:
Geometry2DTransferFunction(const cgt::svec2& size, const cgt::vec2& intensityDomain = cgt::vec2(0.f, 1.f));
virtual ~Geometry2DTransferFunction();
virtual Geometry2DTransferFunction* clone() const;
};
/* TransferFunctionProperty */
class TransferFunctionProperty : public AbstractProperty {
......@@ -321,17 +393,22 @@ namespace campvis {
sigslot::signal0 s_changed;
%mutable;
};
/* Down casting or super classes.
* Down casting follows the order of declaration.
* Declare the classes as child first according to the class hierarchy.
*/
/* Downcast the return value of HasPropertyCollection::getProperty to appropriate subclass */
%factory(AbstractProperty* campvis::HasPropertyCollection::getProperty,
campvis::IntProperty, campvis::IVec2Property, campvis::IVec3Property, campvis::IVec4Property,
campvis::AbstractOptionProperty, campvis::IntProperty, campvis::IVec2Property, campvis::IVec3Property, campvis::IVec4Property,
campvis::FloatProperty, campvis::Vec2Property, campvis::Vec3Property, campvis::Vec4Property,
campvis::TransferFunctionProperty,
campvis::DataNameProperty, campvis::StringProperty, campvis::ButtonProperty, campvis::BoolProperty);
/* Downcast the return value of HasPropertyCollection::getNestedProperty to appropriate subclass */
%factory(AbstractProperty* campvis::HasPropertyCollection::getNestedProperty,
campvis::IntProperty, campvis::IVec2Property, campvis::IVec3Property, campvis::IVec4Property,
campvis::AbstractOptionProperty, campvis::IntProperty, campvis::IVec2Property, campvis::IVec3Property, campvis::IVec4Property,
campvis::FloatProperty, campvis::Vec2Property, campvis::Vec3Property, campvis::Vec4Property,
campvis::TransferFunctionProperty,
campvis::DataNameProperty, campvis::StringProperty, campvis::ButtonProperty, campvis::BoolProperty);
......@@ -383,10 +460,11 @@ namespace campvis {
const DataContainer& getDataContainer() const;
DataContainer& getDataContainer();
virtual void addProcessor(AbstractProcessor* processor);
virtual void executePipeline() = 0;
AbstractProcessor* getProcessor(const std::string& name) const;
AbstractProcessor* getProcessor(int index) const;
sigslot::signal0 s_init;
sigslot::signal0 s_deinit;
......
......@@ -116,5 +116,7 @@ namespace campvis {
}
return _texture;
}
const cgt::svec3& AbstractTransferFunction::getSize() {
return _size;
}
}
\ No newline at end of file
......@@ -124,6 +124,7 @@ namespace campvis {
/// Signal emitted when the intensity domain has changed
sigslot::signal0 s_intensityDomainChanged;
const cgt::svec3& getSize();
protected:
/**
* Computes the intensity histogram;
......
......@@ -80,3 +80,4 @@ namespace campvis {
}
#endif // SIMPLETRANSFERFUNCTION_H__
......@@ -137,4 +137,24 @@ namespace campvis {
return new TFGeometry1D(keyPoints);
}
void TFGeometry1D::addKeyPoint( float position, float alpha) {
TFGeometry1D::KeyPoint kp(position, cgt::col4(255));
cgt::col4 color(255);
std::vector<TFGeometry1D::KeyPoint>::iterator lb = std::upper_bound(_keyPoints.begin(), _keyPoints.end(), kp);
if (lb != _keyPoints.end()) {
color = lb->_color;
}
else {
color = _keyPoints.back()._color;
}
color.a = static_cast<uint8_t>(alpha * 255.f);
addKeyPoint(position, color);
}
void TFGeometry1D::addKeyPoint( float position, const cgt::col4& color ) {
TFGeometry1D::KeyPoint kp(position, color);
std::vector<TFGeometry1D::KeyPoint>::iterator lb = std::upper_bound(_keyPoints.begin(), _keyPoints.end(), kp);
_keyPoints.insert(lb, kp);
}
}
\ No newline at end of file
......@@ -95,6 +95,20 @@ namespace campvis {
/// Signal to be emitted when this TF geometry has changed.
sigslot::signal0 s_changed;
/**
* Adds a new KeyPoint
* \param position Position of new KeyPoint
* \param color Alpha of color of new KeyPoint. Color is interpolated from neighbors
*/
void addKeyPoint(float position, float alpha);
/**
* Adds a new KeyPoint
* \param position Position of new KeyPoint
* \param alpha Color for left KeyPoint
*/
void addKeyPoint(float position, const cgt::col4& color);
/**
* Creates a simple quad geometry for the given interval.
......
......@@ -270,6 +270,12 @@ namespace campvis {
return nullptr;
}
AbstractProcessor* AbstractPipeline::getProcessor(int index ) const {
if (index < 0 || (size_t) index >= _processors.size())
return nullptr;
return _processors[index];
}
}
......@@ -152,6 +152,13 @@ namespace campvis {
*/
AbstractProcessor* getProcessor(const std::string& name) const;
/**
* Returns the first processor of this pipeline whose name matches \a name.
* \param index The index of the processor to get
* \return The first processor whose name matches \a name, 0 if no such processor exists.
*/
AbstractProcessor* getProcessor(int index) const;
/**
* Gets the flag whether this pipeline is currently enabled.
* \return _enabled
......
......@@ -42,4 +42,8 @@ namespace campvis {
return _accessInfo;
}
void DataNameProperty::setAccessInfo(DataAccessInfo access) {
_accessInfo = access;
}
}
......@@ -67,6 +67,7 @@ namespace campvis {
* \return _accessInfo
*/
DataAccessInfo getAccessInfo() const;