diff --git a/CMakeLists.txt b/CMakeLists.txt index 98266c92f6834e769c39dd9945679dbbed3edc37..ef8d4907b8b6e4c707eab5e0a5a106bc7fe6e57b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -9,7 +9,7 @@ cmake_minimum_required( VERSION 3.1 FATAL_ERROR ) # visimpl project and version -project( visimpl VERSION 1.1.7 ) +project( visimpl VERSION 1.2.0 ) set( visimpl_VERSION_ABI 6 ) SET( VISIMPL_LICENSE "GPL") diff --git a/sumrice/TransferFunctionWidget.cpp b/sumrice/TransferFunctionWidget.cpp index 5b8b262e684e5747e97f2ac53537320468ccef1b..a6c13ba10a578315aeb0a9d7c793877825481fd5 100644 --- a/sumrice/TransferFunctionWidget.cpp +++ b/sumrice/TransferFunctionWidget.cpp @@ -62,6 +62,13 @@ QWidget( parent_ ) this->setLayout( mainLayout ); } +void TransferFunctionWidget::addPreset(const Preset &p) +{ + _presets.push_back(p); + _presetsComboBox->addItem(p.name()); + _presetsComboBox->setCurrentIndex(_presets.size()-1); +} + void TransferFunctionWidget::InitDialog( void ) { _dialog = new QWidget( ); diff --git a/sumrice/TransferFunctionWidget.h b/sumrice/TransferFunctionWidget.h index af9b890db0c1c049f8b77de1b22a4fdfc71749a5..818363ca12064a1be744ad0842938aa4971d0932 100644 --- a/sumrice/TransferFunctionWidget.h +++ b/sumrice/TransferFunctionWidget.h @@ -94,6 +94,12 @@ public: void setDialogIcon(const QIcon &icon) { if(_dialog) _dialog->setWindowIcon(icon); } + /** \brief Adds the given preset to the presets list and selects it. + * \param[in] p Preset class reference. + * + */ + void addPreset(const Preset &p); + protected slots: void gradientClicked( void ); void acceptClicked( void ); diff --git a/sumrice/types.h b/sumrice/types.h index fee58c13143a251a8f0d8233ee46fb34240dab28..11b2ec10316f0bd30e36fd66617a91836ec17069 100644 --- a/sumrice/types.h +++ b/sumrice/types.h @@ -161,9 +161,6 @@ namespace visimpl TNeuronCorrelationUMap values; }; - } - - #endif /* __VISIMPL_TYPES_H__ */ diff --git a/visimpl/DomainManager.cpp b/visimpl/DomainManager.cpp index 31bb59746f540c71654034293afc3c6117567e4c..97fa8de4cb0b4146496cff509c7df7f8b809265e 100644 --- a/visimpl/DomainManager.cpp +++ b/visimpl/DomainManager.cpp @@ -322,31 +322,11 @@ namespace visimpl auto colors = palette.colors( ); - constexpr float brightFactor = 0.4f; - constexpr float darkFactor = 1.0f - brightFactor; - _paletteColors.clear( ); for( auto color: colors ) { - glm::vec4 baseColor( color.red( ) * invRGBInt, - color.green( ) * invRGBInt, - color.blue( ) * invRGBInt, 0.6f ); - - color = QColor( baseColor.r * 255, - baseColor.g * 255, - baseColor.b * 255, - baseColor.a * 255 ); - - glm::vec4 darkColor = - ( baseColor * brightFactor ) + ( glm::vec4( 0.1f, 0.1f, 0.1f, 0.4f ) * darkFactor ); - - QColor darkqColor = QColor( darkColor.r * 255, - darkColor.g * 255, - darkColor.b * 255, - darkColor.a * 255 ); - - _paletteColors.emplace_back( std::make_pair( color, darkqColor )); + _paletteColors.emplace_back( generateColorPair(color) ); } } @@ -1015,7 +995,34 @@ namespace visimpl return _namesTypesFunction; } + std::pair<QColor, QColor> DomainManager::generateColorPair( + scoop::Color &color) + { + constexpr float brightFactor = 0.4f; + constexpr float darkFactor = 1.0f - brightFactor; + + const glm::vec4 baseColor( color.red( ) * invRGBInt, + color.green( ) * invRGBInt, + color.blue( ) * invRGBInt, 0.6f ); + + color = QColor( baseColor.r * 255, + baseColor.g * 255, + baseColor.b * 255, + baseColor.a * 255 ); + + const glm::vec4 darkColor = + ( baseColor * brightFactor ) + ( glm::vec4( 0.1f, 0.1f, 0.1f, 0.4f ) * darkFactor ); + + const QColor darkqColor = QColor( darkColor.r * 255, + darkColor.g * 255, + darkColor.b * 255, + darkColor.a * 255 ); + + return std::make_pair( color, darkqColor ); + } + #ifdef SIMIL_USE_BRION + tNeuronAttribs DomainManager::_loadNeuronTypes( const brion::BlueConfig& blueConfig ) { tNeuronAttribs result; diff --git a/visimpl/DomainManager.h b/visimpl/DomainManager.h index 0c1f17aa73a48576c8a6d0b0b2ccbae1720aef66..f1d3ea967948ac6817c4087331fa2341ef6c14fd 100644 --- a/visimpl/DomainManager.h +++ b/visimpl/DomainManager.h @@ -129,6 +129,12 @@ namespace visimpl void highlightElements( const std::unordered_set< unsigned int >& highlighted ); void clearHighlighting( void ); + /** \brief Helper method to generate que QColor pair from a given color. + * \param[inout] c scoop::Color object reference. + * + */ + static std::pair<QColor, QColor> generateColorPair(scoop::Color &c); + protected: typedef std::vector< std::tuple< uint32_t, float >> TModifiedNeurons; diff --git a/visimpl/MainWindow.cpp b/visimpl/MainWindow.cpp index ffacb147d91dd9ee6201682515bcda2aad451b24..2adc875837eafa6a04751dd34b430fe817afa45f 100644 --- a/visimpl/MainWindow.cpp +++ b/visimpl/MainWindow.cpp @@ -1624,42 +1624,98 @@ namespace visimpl #endif - void MainWindow::addGroupControls( const std::string& name, + void MainWindow::addGroupControls( VisualGroup *group, unsigned int currentIndex, unsigned int size ) { - auto icon = new QLabel; + QWidget* container = new QWidget( ); + auto itemLayout = new QHBoxLayout(container); + container->setLayout( itemLayout ); + const auto colors = _openGLWidget->colorPalette( ).colors( ); - QPixmap pixmap{20,20}; - pixmap.fill(colors[ currentIndex ].toRgb()); - icon->setPixmap(pixmap); + currentIndex = currentIndex % colors.size(); + auto color = colors[currentIndex].toRgb(); + const auto variations = DomainManager::generateColorPair(color); + + TTransferFunction colorVariation; + colorVariation.push_back( std::make_pair( 0.0f, variations.first )); + colorVariation.push_back( std::make_pair( 1.0f, variations.second )); + group->colorMapping(colorVariation); + + auto tfWidget = new TransferFunctionWidget(container); + tfWidget->setColorPoints(group->colorMapping()); + tfWidget->setSizeFunction(group->sizeFunction()); + tfWidget->setDialogIcon(QIcon(":/visimpl.png")); + tfWidget->setProperty("groupNum", static_cast<unsigned int>(currentIndex)); + + itemLayout->addWidget(tfWidget); + + const auto presetName = QString("Group selection %1").arg(currentIndex); + QGradientStops stops; + stops << qMakePair( 0.0, variations.first) + << qMakePair( 1.0, variations.second); + tfWidget->addPreset(TransferFunctionWidget::Preset(presetName, stops)); + + connect( tfWidget, SIGNAL(colorChanged()), + this, SLOT(onGroupColorChanged())); + connect( tfWidget, SIGNAL(previewColor()), + this, SLOT(onGroupPreview())); + + QCheckBox* visibilityCheckbox = new QCheckBox( "active" ); + visibilityCheckbox->setChecked( true ); + + connect( visibilityCheckbox, SIGNAL( clicked( ) ), this, + SLOT( checkGroupsVisibility( ) ) ); - QCheckBox* buttonVisibility = new QCheckBox( "active" ); - buttonVisibility->setChecked( true ); + QString numberText = QString( "# " ).append( QString::number( size ) ); - connect( buttonVisibility, SIGNAL( clicked( ) ), this, - SLOT( checkGroupsVisibility( ) ) ); + auto nameButton = new QPushButton(group->name().c_str()); + nameButton->setFlat(true); + nameButton->setProperty("groupNum", static_cast<unsigned int>(currentIndex)); - QWidget* container = new QWidget( ); - QGridLayout* layout = new QGridLayout( ); - container->setLayout( layout ); + connect(nameButton, SIGNAL(clicked()), this, SLOT(onGroupNameClicked())); - QString numberText = QString( "# " ).append( QString::number( size ) ); + auto layout = new QVBoxLayout(); + layout->setAlignment(Qt::AlignHCenter|Qt::AlignVCenter); + layout->addWidget( nameButton ); + layout->addWidget( visibilityCheckbox ); + layout->addWidget( new QLabel( numberText ) ); - layout->addWidget( icon, 0, 0, 1, 1 ); - layout->addWidget( new QLabel( name.c_str( ) ), 0, 1, 1, 1 ); - layout->addWidget( buttonVisibility, 0, 2, 1, 1 ); - layout->addWidget( new QLabel( numberText ), 0, 3, 1, 1 ); + itemLayout->insertLayout(1, layout, 0); + itemLayout->setSizeConstraint(QLayout::SizeConstraint::SetMinimumSize); _groupsVisButtons.push_back( - std::make_tuple( container, buttonVisibility ) ); + std::make_tuple( container, visibilityCheckbox ) ); _groupLayout->addWidget( container ); _buttonClearGroups->setEnabled( true ); } - void MainWindow::clearGroups( void ) + void MainWindow::Stop( bool notify ) + { + if ( !_openGLWidget || !_openGLWidget->player( ) ) + return; + + if ( _openGLWidget ) + { + _openGLWidget->Stop( ); + _playButton->setIcon( _playIcon ); + _startTimeLabel->setText( + QString::number( ( double )_openGLWidget->player( )->startTime( ) ) ); + + _openGLWidget->playbackMode( TPlaybackMode::CONTINUOUS ); + + if ( notify ) + { +#ifdef VISIMPL_USE_GMRVLEX + sendZeroEQPlaybackOperation( zeroeq::gmrv::STOP ); +#endif + } + } + } + +void MainWindow::clearGroups( void ) { for ( auto row : _groupsVisButtons ) { @@ -1696,10 +1752,10 @@ namespace visimpl }; std::for_each(subset.cbegin(), subset.cend(), filterGIDs); - addGroupControls( groupName, _domainManager->groups( ).size( ), - filteredGIDs.size( ) ); + const auto group = _domainManager->addVisualGroup( filteredGIDs, groupName ); - _domainManager->addVisualGroup( filteredGIDs, groupName ); + addGroupControls( group, _domainManager->groups( ).size( ) - 1, + filteredGIDs.size( ) ); }; std::for_each(groups.cbegin(), groups.cend(), addGroup); @@ -1713,10 +1769,9 @@ namespace visimpl void MainWindow::addGroupFromSelection( void ) { - unsigned int currentIndex = _domainManager->groups( ).size( ); - - QString groupName( "Group " + QString::number( currentIndex ) ); + const unsigned int currentIndex = _domainManager->groups( ).size( ); + QString groupName = QString( "Group " + QString::number( currentIndex ) ); if ( !_autoNameGroups ) { bool ok; @@ -1724,15 +1779,14 @@ namespace visimpl tr( "Please, introduce group name: " ), QLineEdit::Normal, groupName, &ok ); - if ( !ok ) - return; + if ( !ok ) return; } - addGroupControls( groupName.toStdString( ), - _domainManager->groups( ).size( ), - _domainManager->selection( ).size( ) ); + const auto group = _domainManager->addVisualGroupFromSelection( groupName.toStdString( ) ); - _domainManager->addVisualGroupFromSelection( groupName.toStdString( ) ); + addGroupControls( group, + _domainManager->groups( ).size( ) - 1, + _domainManager->selection( ).size( ) ); _openGLWidget->setUpdateGroups( ); _openGLWidget->update( ); @@ -1831,30 +1885,7 @@ namespace visimpl } } - void MainWindow::Stop( bool notify ) - { - if ( !_openGLWidget || !_openGLWidget->player( ) ) - return; - - if ( _openGLWidget ) - { - _openGLWidget->Stop( ); - _playButton->setIcon( _playIcon ); - _startTimeLabel->setText( - QString::number( ( double )_openGLWidget->player( )->startTime( ) ) ); - - _openGLWidget->playbackMode( TPlaybackMode::CONTINUOUS ); - - if ( notify ) - { -#ifdef VISIMPL_USE_GMRVLEX - sendZeroEQPlaybackOperation( zeroeq::gmrv::STOP ); -#endif - } - } - } - - void MainWindow::Repeat( bool notify ) + void MainWindow::Repeat( bool notify ) { if ( !_openGLWidget || !_openGLWidget->player( ) ) return; @@ -2007,6 +2038,41 @@ namespace visimpl } } + void MainWindow::onGroupColorChanged() + { + auto tfw = qobject_cast<TransferFunctionWidget *>(sender()); + if(tfw) + { + bool ok = false; + size_t groupNum = tfw->property("groupNum").toUInt(&ok); + + if(!ok) return; + updateGroupColors(groupNum, tfw->getColors(), tfw->getSizeFunction()); + } + } + + void MainWindow::onGroupPreview() + { + auto tfw = qobject_cast<TransferFunctionWidget *>(sender()); + if(tfw) + { + bool ok = false; + size_t groupNum = tfw->property("groupNum").toUInt(&ok); + + if(!ok) return; + updateGroupColors(groupNum, tfw->getPreviewColors(), tfw->getSizePreview()); + } + } + + void MainWindow::updateGroupColors(size_t idx, const TTransferFunction &t, + const TSizeFunction &s) + { + const auto groups = _domainManager->groups(); + const auto groupNum = std::min(idx, groups.size() - 1); + groups[groupNum]->colorMapping(t); + groups[groupNum]->sizeFunction(s); + } + void MainWindow::loadData(const simil::TDataType type, const std::string arg_1, const std::string arg_2, const simil::TSimulationType simType, const std::string &subsetEventFile) @@ -2049,6 +2115,28 @@ namespace visimpl QApplication::restoreOverrideCursor(); } + void MainWindow::onGroupNameClicked() + { + auto button = qobject_cast<QPushButton *>(sender()); + if(button) + { + bool ok = false; + size_t groupNum = button->property("groupNum").toUInt(&ok); + + if(!ok) return; + auto group = _domainManager->groups().at(groupNum); + + auto groupName = QString::fromStdString(group->name()); + groupName = QInputDialog::getText( this, tr( "Group Name" ), + tr( "Please, introduce group name: " ), + QLineEdit::Normal, groupName, &ok ); + + if (!ok) return; + group->name(groupName.toStdString()); + button->setText(groupName); + } + } + void MainWindow::sendZeroEQPlaybackOperation(const unsigned int op) { #ifdef SIMIL_USE_ZEROEQ diff --git a/visimpl/MainWindow.h b/visimpl/MainWindow.h index dcaf43d3e573df66c55361f2e7f70d221c2049b8..d5f6722f766a50348a2d7bc4d26f5a74c0305f43 100644 --- a/visimpl/MainWindow.h +++ b/visimpl/MainWindow.h @@ -152,7 +152,7 @@ namespace visimpl void configureComponents( void ); void importVisualGroups( void ); - void addGroupControls( const std::string& name, unsigned int index, + void addGroupControls( VisualGroup *group, unsigned int index, unsigned int size ); void clearGroups( void ); @@ -169,6 +169,21 @@ namespace visimpl void colorSelectionClicked( void ); + /** \brief Updates group selection color. + * + */ + void onGroupColorChanged(); + + /** \brief Updates group selection color. + * + */ + void onGroupPreview(); + + /** \brief Shows the dialog to change the group name. + * + */ + void onGroupNameClicked(); + void selectionManagerChanged( void ); void setSelection( const GIDUSet& selection_, TSelectionSource source_ = SRC_UNDEFINED ); void clearSelection( void ); @@ -191,6 +206,14 @@ namespace visimpl bool _showDialog( QColor& current, const QString& message = "" ); + /** \brief Helper to update a group representations colors. + * \param[in] idx Index of group in group list. + * \param[in] t Transfer function. + * \param[in] s Size function. + * + */ + void updateGroupColors(size_t idx, const TTransferFunction &t, const TSizeFunction &s); + #ifdef VISIMPL_USE_ZEROEQ #ifdef VISIMPL_USE_GMRVLEX diff --git a/visimpl/OpenGLWidget.cpp b/visimpl/OpenGLWidget.cpp index 74881da0b863342b7a8424b56b30e286f0db7233..91575376b6f82254798ea56f23fd25ee685a181d 100644 --- a/visimpl/OpenGLWidget.cpp +++ b/visimpl/OpenGLWidget.cpp @@ -1883,7 +1883,7 @@ namespace visimpl _eventsActivation.clear( ); const float totalTime = _player->endTime( ) - _player->startTime( ); - auto &colors = _colorPalette.colors( ); + const auto &colors = _colorPalette.colors( ); unsigned int row = 0; auto insertEvents = [&row, &totalTime, &colors, this](const std::string &eventName) @@ -1921,7 +1921,7 @@ namespace visimpl _eventLabelsLayout->addWidget( container, row, 10, 2, 1 ); - auto activity = _subsetEvents->eventActivity( eventName, _deltaEvents, totalTime ); + const auto activity = _subsetEvents->eventActivity( eventName, _deltaEvents, totalTime ); _eventsActivation.push_back(activity); ++row; @@ -1994,7 +1994,7 @@ namespace visimpl { if( _player ) { - bool playing = _player->isPlaying( ); + const bool playing = _player->isPlaying( ); _player->Stop( ); if( playing ) _player->Play( ); @@ -2038,12 +2038,12 @@ namespace visimpl prefr::vectortvec4 gcolors; - for( auto c : colors ) + for( const auto &c : colors ) { glm::vec4 gColor( c.second.red( ) * invRGBInt, - c.second.green( ) * invRGBInt, - c.second.blue( ) * invRGBInt, - c.second.alpha( ) * invRGBInt ); + c.second.green( ) * invRGBInt, + c.second.blue( ) * invRGBInt, + c.second.alpha( ) * invRGBInt ); gcolors.Insert( c.first, gColor ); } diff --git a/visimpl/VisualGroup.cpp b/visimpl/VisualGroup.cpp index 4e894c57ebea7e0137ddc323821f74901dcac303..b36793b98e7e765dfb0ec744b7df13dd55dae9a9 100644 --- a/visimpl/VisualGroup.cpp +++ b/visimpl/VisualGroup.cpp @@ -176,10 +176,9 @@ namespace visimpl void VisualGroup::colorMapping( const TTransferFunction& colors ) { - prefr::vectortvec4 gcolors; - for( auto c : colors ) + auto insertColor = [&gcolors](const TTFColor &c) { glm::vec4 gColor( c.second.red( ) * invRGBInt, c.second.green( ) * invRGBInt, @@ -187,53 +186,58 @@ namespace visimpl c.second.alpha( ) * invRGBInt ); gcolors.Insert( c.first, gColor ); - } + }; + std::for_each(colors.cbegin(), colors.cend(), insertColor); _color = colors[ 0 ].second; _model->color = gcolors; - } TTransferFunction VisualGroup::colorMapping( void ) const { TTransferFunction result; - prefr::vectortvec4 colors = _model->color; - auto timeValue = _model->color.times.begin( ); - for( auto c : _model->color.values ) + const auto values = _model->color.values; + + auto mapColor = [&timeValue, &result](const vec4 &c) { QColor color( c.r * 255, c.g * 255, c.b * 255, c.a * 255 ); result.push_back( std::make_pair( *timeValue, color )); ++timeValue; - } - + }; + std::for_each(values.cbegin(), values.cend(), mapColor); return result; } void VisualGroup::sizeFunction( const TSizeFunction& sizes ) { - utils::InterpolationSet< float > newSize; - for( auto s : sizes ) + + auto insertSize = [&newSize](const Event &e) { - newSize.Insert( s.first, s.second ); - } - _model->size = newSize; + newSize.Insert( e.first, e.second ); + }; + std::for_each(sizes.cbegin(), sizes.cend(), insertSize); + _model->size = newSize; } TSizeFunction VisualGroup::sizeFunction( void ) const { TSizeFunction result; + auto sizeValue = _model->size.values.begin( ); - for( auto s : _model->size.times) + const auto times = _model->size.times; + + auto insertTime = [&sizeValue, &result](const float f) { - result.push_back( std::make_pair( s, *sizeValue )); + result.push_back( std::make_pair( f, *sizeValue )); ++sizeValue; - } + }; + std::for_each(times.cbegin(), times.cend(), insertTime); return result; } diff --git a/visimpl/visimpl.cpp b/visimpl/visimpl.cpp index 040a27407f35faef21f6395feac9adb3f57e5068..f34f261e62edb174597e64720adec23bd5183a77 100644 --- a/visimpl/visimpl.cpp +++ b/visimpl/visimpl.cpp @@ -242,6 +242,12 @@ int main( int argc, char** argv ) path = QString::fromLocal8Bit(argv[i]); } + if(!QDir(path).exists() || !QDir(path).isReadable()) + { + std::cerr << "Invalid test file path: " << path.toStdString() << ". Using home directory instead." << std::endl; + path = QDir::homePath(); + } + if(!generateTestFiles(path, networkFile, activityFile)) usageMessage(argv[0]); else