<commit_before>/*
 * datasetfibers.cpp
 *
 * Created on: Dec 12, 2012
 * @author Ralph Schurade
 */
#include "datasetfibers.h"

#include "fiberselector.h"
#include "../models.h"
#include "../../gui/gl/fiberrenderer.h"
#include "../../gui/gl/tuberenderer.h"

DatasetFibers::DatasetFibers( QDir filename, QVector< QVector< float > > fibs ) :
    Dataset( filename, Fn::DatasetType::FIBERS ),
    m_fibs( fibs ),
    m_renderer( 0 ),
    m_tubeRenderer( 0 ),
    m_selector( 0 )
{
    int numPoints = 0;
    for ( int i = 0; i < fibs.size(); ++i )
    {
        numPoints += fibs[i].size() / 3;
    }

    m_properties["maingl"]->set( Fn::Property::NUM_POINTS, numPoints );
    m_properties["maingl"]->set( Fn::Property::NUM_LINES, fibs.size() );
    m_properties["maingl"]->set( Fn::Property::FIBER_RENDERMODE, {"lines", "tubes"}, 0, true );
    m_properties["maingl"]->set( Fn::Property::COLORMODE, { "global", "local", "user defined", "mri" }, 0, true );
    m_properties["maingl"]->set( Fn::Property::COLOR, QColor( 255, 0, 0 ), true );
    m_properties["maingl"]->set( Fn::Property::ALPHA, 1.f, 0.f, 1.f, true );
    m_properties["maingl"]->set( Fn::Property::FIBER_THICKNESS, 1.0f, 0.1f, 5.0f, true );
    m_properties["maingl"]->set( Fn::Property::COLORMAP, 1 );
    m_properties["maingl"]->set( Fn::Property::MIN, 0.0f );
    m_properties["maingl"]->set( Fn::Property::MAX, 1.0f );
    m_properties["maingl"]->set( Fn::Property::SELECTED_MIN, 0.0f, 0.0f, 1.0f );
    m_properties["maingl"]->set( Fn::Property::SELECTED_MAX, 1.0f, 0.0f, 1.0f );
    m_properties["maingl"]->set( Fn::Property::LOWER_THRESHOLD, 0.0f, 0.0f, 1.0f );
    m_properties["maingl"]->set( Fn::Property::UPPER_THRESHOLD, 1.0f, 0.0f, 1.0f );
    m_properties["maingl"]->set( Fn::Property::DX, 100.0f, 0.0f, 100.0f, true );
    m_properties["maingl"]->set( Fn::Property::DY, 100.0f, 0.0f, 100.0f, true );
    m_properties["maingl"]->set( Fn::Property::DZ, 100.0f, 0.0f, 100.0f, true );
    m_properties["maingl"]->set( Fn::Property::NX, 800, 0, 1600, true );
    m_properties["maingl"]->set( Fn::Property::NY, 1000, 0, 2000, true );
    m_properties["maingl"]->set( Fn::Property::NZ, 800, 0, 1600, true );

    QVector<QVector<float> >data0;
    data0.reserve( fibs.size() );
    for ( int i = 0; i < fibs.size(); ++i )
    {
        data0.push_back( QVector<float>( fibs[i].size() / 3 ) );
    }
    m_data.push_back( data0 );
    m_dataNames.push_back( "no data" );
    connect( m_properties["maingl"]->getProperty( Fn::Property::COLOR ), SIGNAL( colorChanged( QColor ) ), this, SLOT( colorChanged() ) );
}

DatasetFibers::DatasetFibers( QDir filename,
                                 QVector< QVector< float > > fibs,
                                 QVector< QVector< QVector< float > > >data,
                                 QVector<QString>dataNames,
                                 QVector< float > mins,
                                 QVector<float> maxes ) :
    Dataset( filename, Fn::DatasetType::FIBERS ),
    m_fibs( fibs ),
    m_data( data ),
    m_dataNames( dataNames ),
    m_dataMins( mins ),
    m_dataMaxes( maxes ),
    m_renderer( 0 ),
    m_tubeRenderer( 0 ),
    m_selector( 0 )
{
    int numPoints = 0;
    for ( int i = 0; i < fibs.size(); ++i )
    {
        numPoints += fibs[i].size() / 3;
    }

    m_properties["maingl"]->set( Fn::Property::NUM_POINTS, numPoints );
    m_properties["maingl"]->set( Fn::Property::NUM_LINES, fibs.size() );
    m_properties["maingl"]->set( Fn::Property::FIBER_RENDERMODE, {"lines", "tubes"}, 0, true );
    m_properties["maingl"]->set( Fn::Property::COLORMODE, { "global", "local", "user defined", "mri", "data" }, 0, true );
    m_properties["maingl"]->set( Fn::Property::DATAMODE, dataNames, 0, true );
    m_properties["maingl"]->set( Fn::Property::COLOR, QColor( 255, 0, 0 ), true );
    m_properties["maingl"]->set( Fn::Property::ALPHA, 1.f, 0.f, 1.f, true );
    m_properties["maingl"]->set( Fn::Property::FIBER_THICKNESS, 1.0f, 0.1f, 5.0f, true );
    m_properties["maingl"]->set( Fn::Property::COLORMAP, 1, true );
    m_properties["maingl"]->set( Fn::Property::MIN, 0.0f );
    m_properties["maingl"]->set( Fn::Property::MAX, 1.0f );
    m_properties["maingl"]->set( Fn::Property::SELECTED_MIN, 0.0f, 0.0f, 1.0f, true );
    m_properties["maingl"]->set( Fn::Property::SELECTED_MAX, 1.0f, 0.0f, 1.0f, true );
    m_properties["maingl"]->set( Fn::Property::LOWER_THRESHOLD, 0.0f, 0.0f, 1.0f );
    m_properties["maingl"]->set( Fn::Property::UPPER_THRESHOLD, 1.0f, 0.0f, 1.0f );
    m_properties["maingl"]->set( Fn::Property::DX, 100.0f, 0.0f, 100.0f, true );
    m_properties["maingl"]->set( Fn::Property::DY, 100.0f, 0.0f, 100.0f, true );
    m_properties["maingl"]->set( Fn::Property::DZ, 100.0f, 0.0f, 100.0f, true );
    m_properties["maingl"]->set( Fn::Property::NX, 800, 0, 1600, true );
    m_properties["maingl"]->set( Fn::Property::NY, 1000, 0, 2000, true );
    m_properties["maingl"]->set( Fn::Property::NZ, 800, 0, 1600, true );

    connect( m_properties["maingl"]->getProperty( Fn::Property::SELECTED_MIN ), SIGNAL( valueChanged( float ) ),
              m_properties["maingl"]->getProperty( Fn::Property::LOWER_THRESHOLD ), SLOT( setMax( float ) ) );
    connect( m_properties["maingl"]->getProperty( Fn::Property::SELECTED_MAX ), SIGNAL( valueChanged( float ) ),
              m_properties["maingl"]->getProperty( Fn::Property::UPPER_THRESHOLD ), SLOT( setMin( float ) ) );

    connect( m_properties["maingl"]->getProperty( Fn::Property::SELECTED_MIN ), SIGNAL( valueChanged( float ) ),
              m_properties["maingl"]->getProperty( Fn::Property::SELECTED_MAX ), SLOT( setMin( float ) ) );
    connect( m_properties["maingl"]->getProperty( Fn::Property::SELECTED_MAX ), SIGNAL( valueChanged( float ) ),
              m_properties["maingl"]->getProperty( Fn::Property::SELECTED_MIN ), SLOT( setMax( float ) ) );
    connect( m_properties["maingl"]->getProperty( Fn::Property::COLOR ), SIGNAL( colorChanged( QColor ) ), this, SLOT( colorChanged() ) );
    connect( m_properties["maingl"]->getProperty( Fn::Property::DATAMODE ), SIGNAL( valueChanged( int ) ), this, SLOT( dataModeChanged() ) );
}

DatasetFibers::~DatasetFibers()
{
    m_fibs.clear();
}

QVector< QVector< float > > DatasetFibers::getFibs()
{
    return m_fibs;
}

QVector< QVector< QVector< float > > > DatasetFibers::getData()
{
    return m_data;
}

QVector< QVector< float > > DatasetFibers::getSelectedFibs()
{
    if ( m_renderer == 0 )
    {
        return m_fibs;
    }
    else
    {
        QVector<bool>*selected = m_selector->getSelection();
        QVector<QVector<float> >out;
        for ( int i = 0; i < selected->size(); ++i )
        {
            if ( selected->at( i ) )
            {
                out.push_back( m_fibs[i] );
            }
        }
        return out;
    }
}

void DatasetFibers::draw( QMatrix4x4 pMatrix, QMatrix4x4 mvMatrix, int width, int height, int renderMode, QString target )
{
    if ( !properties( target )->get( Fn::Property::ACTIVE ).toBool() )
    {
        return;
    }
    if ( m_selector == 0 )
    {
        m_selector = new FiberSelector();
        m_selector->init( m_fibs );
        connect( m_selector, SIGNAL( changed() ), Models::d(), SLOT( submit() ) );
    }

    if ( properties( target )->get( Fn::Property::FIBER_RENDERMODE).toInt() == 0 )
    {
        if ( m_renderer == 0 )
        {
            m_renderer = new FiberRenderer( m_selector, m_fibs, m_data[properties( target )->get( Fn::Property::DATAMODE).toInt()] );
            m_renderer->setModel( Models::g() );
            m_renderer->init();
            m_renderer->colorChanged( properties( target )->get( Fn::Property::COLOR ).value<QColor>() );
            connect( properties( target )->getProperty( Fn::Property::COLOR ), SIGNAL( colorChanged( QColor ) ), m_renderer, SLOT( colorChanged( QColor ) ) );
        }

        m_renderer->draw( pMatrix, mvMatrix, width, height, renderMode, properties( target ) );
    }
    else if ( properties( target )->get( Fn::Property::FIBER_RENDERMODE).toInt() == 1 )
    {
        if ( m_tubeRenderer == 0 )
        {
            m_tubeRenderer = new TubeRenderer( m_selector, m_fibs, m_data[properties( target )->get( Fn::Property::DATAMODE).toInt()] );
            m_tubeRenderer->setModel( Models::g() );
            m_tubeRenderer->init();
            m_tubeRenderer->colorChanged( properties( target )->get( Fn::Property::COLOR ).value<QColor>() );
            connect( properties( target )->getProperty( Fn::Property::COLOR ), SIGNAL( colorChanged( QColor ) ), m_tubeRenderer, SLOT( colorChanged( QColor ) ) );
        }

        m_tubeRenderer->draw( pMatrix, mvMatrix, width, height, renderMode, properties( target ) );
    }
}

QString DatasetFibers::getValueAsString( int x, int y, int z )
{
    return QString( "" );
}

void DatasetFibers::colorChanged()
{
    m_properties["maingl"]->set( Fn::Property::COLORMODE, 2 );
}

void DatasetFibers::dataModeChanged()
{
    if ( m_renderer != 0 )
    {
        delete m_renderer;
        m_renderer = 0;
    }
    if ( m_tubeRenderer != 0 )
    {
        delete m_tubeRenderer;
        m_tubeRenderer = 0;
    }
    float min = m_dataMins[ m_properties["maingl"]->get( Fn::Property::DATAMODE).toInt()];
    float max = m_dataMaxes[ m_properties["maingl"]->get( Fn::Property::DATAMODE).toInt()];

    m_properties["maingl"]->set( Fn::Property::MIN, min );
    m_properties["maingl"]->set( Fn::Property::MAX, max );
    static_cast<PropertyFloat*> ( m_properties["maingl"]->getProperty( Fn::Property::SELECTED_MIN ) )->setMin( min );
    static_cast<PropertyFloat*> ( m_properties["maingl"]->getProperty( Fn::Property::SELECTED_MIN ) )->setMax( max );
    static_cast<PropertyFloat*> ( m_properties["maingl"]->getProperty( Fn::Property::SELECTED_MAX ) )->setMin( min );
    static_cast<PropertyFloat*> ( m_properties["maingl"]->getProperty( Fn::Property::SELECTED_MAX ) )->setMax( max );
    static_cast<PropertyFloat*> ( m_properties["maingl"]->getProperty( Fn::Property::SELECTED_MIN ) )->setValue( min );
    static_cast<PropertyFloat*> ( m_properties["maingl"]->getProperty( Fn::Property::SELECTED_MAX ) )->setValue( max );
    static_cast<PropertyFloat*> ( m_properties["maingl"]->getProperty( Fn::Property::LOWER_THRESHOLD ) )->setValue( min );
    static_cast<PropertyFloat*> ( m_properties["maingl"]->getProperty( Fn::Property::UPPER_THRESHOLD ) )->setValue( max );
    Models::d()->submit();
}
<commit_msg>props for maingl2 for fiber datasets<commit_after>/*
 * datasetfibers.cpp
 *
 * Created on: Dec 12, 2012
 * @author Ralph Schurade
 */
#include "datasetfibers.h"

#include "fiberselector.h"
#include "../models.h"
#include "../../gui/gl/fiberrenderer.h"
#include "../../gui/gl/tuberenderer.h"

DatasetFibers::DatasetFibers( QDir filename, QVector< QVector< float > > fibs ) :
    Dataset( filename, Fn::DatasetType::FIBERS ),
    m_fibs( fibs ),
    m_renderer( 0 ),
    m_tubeRenderer( 0 ),
    m_selector( 0 )
{
    int numPoints = 0;
    for ( int i = 0; i < fibs.size(); ++i )
    {
        numPoints += fibs[i].size() / 3;
    }

    m_properties["maingl"]->set( Fn::Property::NUM_POINTS, numPoints );
    m_properties["maingl"]->set( Fn::Property::NUM_LINES, fibs.size() );
    m_properties["maingl"]->set( Fn::Property::FIBER_RENDERMODE, {"lines", "tubes"}, 0, true );
    m_properties["maingl"]->set( Fn::Property::COLORMODE, { "global", "local", "user defined", "mri" }, 0, true );
    m_properties["maingl"]->set( Fn::Property::COLOR, QColor( 255, 0, 0 ), true );
    m_properties["maingl"]->set( Fn::Property::ALPHA, 1.f, 0.f, 1.f, true );
    m_properties["maingl"]->set( Fn::Property::FIBER_THICKNESS, 1.0f, 0.1f, 5.0f, true );
    m_properties["maingl"]->set( Fn::Property::COLORMAP, 1 );
    m_properties["maingl"]->set( Fn::Property::MIN, 0.0f );
    m_properties["maingl"]->set( Fn::Property::MAX, 1.0f );
    m_properties["maingl"]->set( Fn::Property::SELECTED_MIN, 0.0f, 0.0f, 1.0f );
    m_properties["maingl"]->set( Fn::Property::SELECTED_MAX, 1.0f, 0.0f, 1.0f );
    m_properties["maingl"]->set( Fn::Property::LOWER_THRESHOLD, 0.0f, 0.0f, 1.0f );
    m_properties["maingl"]->set( Fn::Property::UPPER_THRESHOLD, 1.0f, 0.0f, 1.0f );
    m_properties["maingl"]->set( Fn::Property::DX, 100.0f, 0.0f, 100.0f, true );
    m_properties["maingl"]->set( Fn::Property::DY, 100.0f, 0.0f, 100.0f, true );
    m_properties["maingl"]->set( Fn::Property::DZ, 100.0f, 0.0f, 100.0f, true );
    m_properties["maingl"]->set( Fn::Property::NX, 800, 0, 1600, true );
    m_properties["maingl"]->set( Fn::Property::NY, 1000, 0, 2000, true );
    m_properties["maingl"]->set( Fn::Property::NZ, 800, 0, 1600, true );

    QVector<QVector<float> >data0;
    data0.reserve( fibs.size() );
    for ( int i = 0; i < fibs.size(); ++i )
    {
        data0.push_back( QVector<float>( fibs[i].size() / 3 ) );
    }
    m_data.push_back( data0 );
    m_dataNames.push_back( "no data" );
    connect( m_properties["maingl"]->getProperty( Fn::Property::COLOR ), SIGNAL( colorChanged( QColor ) ), this, SLOT( colorChanged() ) );

    PropertyGroup* props = new PropertyGroup();
    props->set( Fn::Property::ACTIVE, true, true );
    props->set( Fn::Property::RENDER_TARGET, "maingl2" );
    m_properties.insert( "maingl2", props );

    m_properties["maingl2"]->set( Fn::Property::NUM_POINTS, numPoints );
    m_properties["maingl2"]->set( Fn::Property::NUM_LINES, fibs.size() );
    m_properties["maingl2"]->set( Fn::Property::FIBER_RENDERMODE, {"lines", "tubes"}, 0, true );
    m_properties["maingl2"]->set( Fn::Property::COLORMODE, { "global", "local", "user defined", "mri" }, 0, true );
    //m_properties["maingl2"]->set( Fn::Property::COLOR, QColor( 255, 0, 0 ), true );
    m_properties["maingl2"]->set( Fn::Property::ALPHA, 1.f, 0.f, 1.f, true );
    m_properties["maingl2"]->set( Fn::Property::FIBER_THICKNESS, 1.0f, 0.1f, 5.0f, true );
    m_properties["maingl2"]->set( Fn::Property::COLORMAP, 1 );
    m_properties["maingl2"]->set( Fn::Property::MIN, 0.0f );
    m_properties["maingl2"]->set( Fn::Property::MAX, 1.0f );
    m_properties["maingl2"]->set( Fn::Property::SELECTED_MIN, 0.0f, 0.0f, 1.0f );
    m_properties["maingl2"]->set( Fn::Property::SELECTED_MAX, 1.0f, 0.0f, 1.0f );
    m_properties["maingl2"]->set( Fn::Property::LOWER_THRESHOLD, 0.0f, 0.0f, 1.0f );
    m_properties["maingl2"]->set( Fn::Property::UPPER_THRESHOLD, 1.0f, 0.0f, 1.0f );
    m_properties["maingl2"]->set( Fn::Property::DX, 100.0f, 0.0f, 100.0f, true );
    m_properties["maingl2"]->set( Fn::Property::DY, 100.0f, 0.0f, 100.0f, true );
    m_properties["maingl2"]->set( Fn::Property::DZ, 100.0f, 0.0f, 100.0f, true );
    m_properties["maingl2"]->set( Fn::Property::NX, 800, 0, 1600, true );
    m_properties["maingl2"]->set( Fn::Property::NY, 1000, 0, 2000, true );
    m_properties["maingl2"]->set( Fn::Property::NZ, 800, 0, 1600, true );
}

DatasetFibers::DatasetFibers( QDir filename,
                                 QVector< QVector< float > > fibs,
                                 QVector< QVector< QVector< float > > >data,
                                 QVector<QString>dataNames,
                                 QVector< float > mins,
                                 QVector<float> maxes ) :
    Dataset( filename, Fn::DatasetType::FIBERS ),
    m_fibs( fibs ),
    m_data( data ),
    m_dataNames( dataNames ),
    m_dataMins( mins ),
    m_dataMaxes( maxes ),
    m_renderer( 0 ),
    m_tubeRenderer( 0 ),
    m_selector( 0 )
{
    int numPoints = 0;
    for ( int i = 0; i < fibs.size(); ++i )
    {
        numPoints += fibs[i].size() / 3;
    }

    m_properties["maingl"]->set( Fn::Property::NUM_POINTS, numPoints );
    m_properties["maingl"]->set( Fn::Property::NUM_LINES, fibs.size() );
    m_properties["maingl"]->set( Fn::Property::FIBER_RENDERMODE, {"lines", "tubes"}, 0, true );
    m_properties["maingl"]->set( Fn::Property::COLORMODE, { "global", "local", "user defined", "mri", "data" }, 0, true );
    m_properties["maingl"]->set( Fn::Property::DATAMODE, dataNames, 0, true );
    m_properties["maingl"]->set( Fn::Property::COLOR, QColor( 255, 0, 0 ), true );
    m_properties["maingl"]->set( Fn::Property::ALPHA, 1.f, 0.f, 1.f, true );
    m_properties["maingl"]->set( Fn::Property::FIBER_THICKNESS, 1.0f, 0.1f, 5.0f, true );
    m_properties["maingl"]->set( Fn::Property::COLORMAP, 1, true );
    m_properties["maingl"]->set( Fn::Property::MIN, 0.0f );
    m_properties["maingl"]->set( Fn::Property::MAX, 1.0f );
    m_properties["maingl"]->set( Fn::Property::SELECTED_MIN, 0.0f, 0.0f, 1.0f, true );
    m_properties["maingl"]->set( Fn::Property::SELECTED_MAX, 1.0f, 0.0f, 1.0f, true );
    m_properties["maingl"]->set( Fn::Property::LOWER_THRESHOLD, 0.0f, 0.0f, 1.0f );
    m_properties["maingl"]->set( Fn::Property::UPPER_THRESHOLD, 1.0f, 0.0f, 1.0f );
    m_properties["maingl"]->set( Fn::Property::DX, 100.0f, 0.0f, 100.0f, true );
    m_properties["maingl"]->set( Fn::Property::DY, 100.0f, 0.0f, 100.0f, true );
    m_properties["maingl"]->set( Fn::Property::DZ, 100.0f, 0.0f, 100.0f, true );
    m_properties["maingl"]->set( Fn::Property::NX, 800, 0, 1600, true );
    m_properties["maingl"]->set( Fn::Property::NY, 1000, 0, 2000, true );
    m_properties["maingl"]->set( Fn::Property::NZ, 800, 0, 1600, true );

    connect( m_properties["maingl"]->getProperty( Fn::Property::SELECTED_MIN ), SIGNAL( valueChanged( float ) ),
              m_properties["maingl"]->getProperty( Fn::Property::LOWER_THRESHOLD ), SLOT( setMax( float ) ) );
    connect( m_properties["maingl"]->getProperty( Fn::Property::SELECTED_MAX ), SIGNAL( valueChanged( float ) ),
              m_properties["maingl"]->getProperty( Fn::Property::UPPER_THRESHOLD ), SLOT( setMin( float ) ) );

    connect( m_properties["maingl"]->getProperty( Fn::Property::SELECTED_MIN ), SIGNAL( valueChanged( float ) ),
              m_properties["maingl"]->getProperty( Fn::Property::SELECTED_MAX ), SLOT( setMin( float ) ) );
    connect( m_properties["maingl"]->getProperty( Fn::Property::SELECTED_MAX ), SIGNAL( valueChanged( float ) ),
              m_properties["maingl"]->getProperty( Fn::Property::SELECTED_MIN ), SLOT( setMax( float ) ) );
    connect( m_properties["maingl"]->getProperty( Fn::Property::COLOR ), SIGNAL( colorChanged( QColor ) ), this, SLOT( colorChanged() ) );
    connect( m_properties["maingl"]->getProperty( Fn::Property::DATAMODE ), SIGNAL( valueChanged( int ) ), this, SLOT( dataModeChanged() ) );
}

DatasetFibers::~DatasetFibers()
{
    m_fibs.clear();
}

QVector< QVector< float > > DatasetFibers::getFibs()
{
    return m_fibs;
}

QVector< QVector< QVector< float > > > DatasetFibers::getData()
{
    return m_data;
}

QVector< QVector< float > > DatasetFibers::getSelectedFibs()
{
    if ( m_renderer == 0 )
    {
        return m_fibs;
    }
    else
    {
        QVector<bool>*selected = m_selector->getSelection();
        QVector<QVector<float> >out;
        for ( int i = 0; i < selected->size(); ++i )
        {
            if ( selected->at( i ) )
            {
                out.push_back( m_fibs[i] );
            }
        }
        return out;
    }
}

void DatasetFibers::draw( QMatrix4x4 pMatrix, QMatrix4x4 mvMatrix, int width, int height, int renderMode, QString target )
{
    if ( !properties( target )->get( Fn::Property::ACTIVE ).toBool() )
    {
        return;
    }
    if ( m_selector == 0 )
    {
        m_selector = new FiberSelector();
        m_selector->init( m_fibs );
        connect( m_selector, SIGNAL( changed() ), Models::d(), SLOT( submit() ) );
    }

    if ( properties( target )->get( Fn::Property::FIBER_RENDERMODE).toInt() == 0 )
    {
        if ( m_renderer == 0 )
        {
            m_renderer = new FiberRenderer( m_selector, m_fibs, m_data[properties( target )->get( Fn::Property::DATAMODE).toInt()] );
            m_renderer->setModel( Models::g() );
            m_renderer->init();
            m_renderer->colorChanged( properties( target )->get( Fn::Property::COLOR ).value<QColor>() );
            connect( properties( target )->getProperty( Fn::Property::COLOR ), SIGNAL( colorChanged( QColor ) ), m_renderer, SLOT( colorChanged( QColor ) ) );
        }

        m_renderer->draw( pMatrix, mvMatrix, width, height, renderMode, properties( target ) );
    }
    else if ( properties( target )->get( Fn::Property::FIBER_RENDERMODE).toInt() == 1 )
    {
        if ( m_tubeRenderer == 0 )
        {
            m_tubeRenderer = new TubeRenderer( m_selector, m_fibs, m_data[properties( target )->get( Fn::Property::DATAMODE).toInt()] );
            m_tubeRenderer->setModel( Models::g() );
            m_tubeRenderer->init();
            m_tubeRenderer->colorChanged( properties( target )->get( Fn::Property::COLOR ).value<QColor>() );
            connect( properties( target )->getProperty( Fn::Property::COLOR ), SIGNAL( colorChanged( QColor ) ), m_tubeRenderer, SLOT( colorChanged( QColor ) ) );
        }

        m_tubeRenderer->draw( pMatrix, mvMatrix, width, height, renderMode, properties( target ) );
    }
}

QString DatasetFibers::getValueAsString( int x, int y, int z )
{
    return QString( "" );
}

void DatasetFibers::colorChanged()
{
    m_properties["maingl"]->set( Fn::Property::COLORMODE, 2 );
}

void DatasetFibers::dataModeChanged()
{
    if ( m_renderer != 0 )
    {
        delete m_renderer;
        m_renderer = 0;
    }
    if ( m_tubeRenderer != 0 )
    {
        delete m_tubeRenderer;
        m_tubeRenderer = 0;
    }
    float min = m_dataMins[ m_properties["maingl"]->get( Fn::Property::DATAMODE).toInt()];
    float max = m_dataMaxes[ m_properties["maingl"]->get( Fn::Property::DATAMODE).toInt()];

    m_properties["maingl"]->set( Fn::Property::MIN, min );
    m_properties["maingl"]->set( Fn::Property::MAX, max );
    static_cast<PropertyFloat*> ( m_properties["maingl"]->getProperty( Fn::Property::SELECTED_MIN ) )->setMin( min );
    static_cast<PropertyFloat*> ( m_properties["maingl"]->getProperty( Fn::Property::SELECTED_MIN ) )->setMax( max );
    static_cast<PropertyFloat*> ( m_properties["maingl"]->getProperty( Fn::Property::SELECTED_MAX ) )->setMin( min );
    static_cast<PropertyFloat*> ( m_properties["maingl"]->getProperty( Fn::Property::SELECTED_MAX ) )->setMax( max );
    static_cast<PropertyFloat*> ( m_properties["maingl"]->getProperty( Fn::Property::SELECTED_MIN ) )->setValue( min );
    static_cast<PropertyFloat*> ( m_properties["maingl"]->getProperty( Fn::Property::SELECTED_MAX ) )->setValue( max );
    static_cast<PropertyFloat*> ( m_properties["maingl"]->getProperty( Fn::Property::LOWER_THRESHOLD ) )->setValue( min );
    static_cast<PropertyFloat*> ( m_properties["maingl"]->getProperty( Fn::Property::UPPER_THRESHOLD ) )->setValue( max );
    Models::d()->submit();
}
<|endoftext|>


<commit_before>#include <cstdio>
#include <conio.h>
#include <iostream>
#include <stdlib.h>
#include <windows.h>

using namespace std;

void hanoi(int puzzle, char from, char help, char into) {
	HANDLE h = GetStdHandle(STD_OUTPUT_HANDLE);
	if(puzzle > 0) {
		hanoi (puzzle - 1, from, into, help);
		// system ("color B" );
		SetConsoleTextAttribute(h, FOREGROUND_BLUE | FOREGROUND_INTENSITY);
		printf("\t\t | Mueva la Pieza %d De %c a la Torre %c        |\n", puzzle, from, into);
		hanoi(puzzle - 1, help, from, into);
	}
}

int main() {
	HANDLE h = GetStdHandle(STD_OUTPUT_HANDLE);
	int puzzle;
	SetConsoleTextAttribute(h, FOREGROUND_GREEN | FOREGROUND_INTENSITY);
	printf("\t\t --------------------------------------------- \n");
	printf("\t\t               Torres De Hanoi                 \n");
	printf("\t\t --------------------------------------------- \n");
	SetConsoleTextAttribute(h, FOREGROUND_BLUE | FOREGROUND_INTENSITY);
	printf("\t\t Inserte El numero de piezas que desea :  ");
	SetConsoleTextAttribute(h, FOREGROUND_RED  | FOREGROUND_INTENSITY);
	scanf("%d", &puzzle);
	SetConsoleTextAttribute(h, FOREGROUND_BLUE | FOREGROUND_INTENSITY);
	printf("\t\t --------------------------------------------- \n");
	hanoi(puzzle, 'A', 'B', 'C');
	printf("\t\t --------------------------------------------- \n");
	int res = 1;

	for(int i = 0; i < puzzle; i++)
		res = res * 2;
	printf("\t\t\t      Cantidad De Pasos: %i", res -1);
	getch();
}
<commit_msg>small changes are added to file<commit_after>#include "stdafx.h"
#include <stdlib.h>
#include <iostream>
#include <windows.h>
#include <vector>

using namespace std;
using namespace System;

int puzzle;
int res = 1;

int cantidadTorres;

std::vector<int> a;
std::vector<int> b;
std::vector<int> c;

void iniciar(int n){
	a.clear();
	b.clear();
	c.clear();
	for(int i=n;i>0;i--){
		a.push_back(i);
	}
}

void hanoi(int puzzle, char from, char help, char into) {
	HANDLE h = GetStdHandle(STD_OUTPUT_HANDLE);
	if(puzzle > 0) {
		hanoi (puzzle - 1, from, into, help);
		// system ("color B" );
		SetConsoleTextAttribute(h, FOREGROUND_BLUE | FOREGROUND_INTENSITY);
		printf("\t\t | Mueva la Pieza %d De %c a la Torre %c        |\n", puzzle, from, into);
		hanoi(puzzle - 1, help, from, into);
	}
}

int main() {
	HANDLE h = GetStdHandle(STD_OUTPUT_HANDLE);
	int puzzle;
	SetConsoleTextAttribute(h, FOREGROUND_GREEN | FOREGROUND_INTENSITY);
	printf("\t\t --------------------------------------------- \n");
	printf("\t\t               Torres De Hanoi                 \n");
	printf("\t\t --------------------------------------------- \n");
	SetConsoleTextAttribute(h, FOREGROUND_BLUE | FOREGROUND_INTENSITY);
	printf("\t\t Inserte El numero de piezas que desea :  ");
	SetConsoleTextAttribute(h, FOREGROUND_RED  | FOREGROUND_INTENSITY);
	scanf("%d", &puzzle);
	SetConsoleTextAttribute(h, FOREGROUND_BLUE | FOREGROUND_INTENSITY);
	printf("\t\t --------------------------------------------- \n");
	hanoi(puzzle, 'A', 'B', 'C');
	printf("\t\t --------------------------------------------- \n");
	int res = 1;

	for(int i = 0; i < puzzle; i++)
		res = res * 2;
	printf("\t\t\t      Cantidad De Pasos: %i", res -1);
	getch();
}
<|endoftext|>


<commit_before>//
//  main.cpp
//  Hello-OpenCV
//
//  Created by nsp on 13/2/17.
//  Copyright © 2017 nspool. All rights reserved.
//

// Because the opencv framework headers don't play well with clang
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdocumentation"

#include <iostream>
#include "opencv2/opencv.hpp"

//cv::Vec small, fixed vectors
//cv::Matx small, fixed matrices
//cv::Point (x & y) can be cast to Vec but not derived from it. Dot & cross product.
//cv::Size (width & height), area computation
//cv::Rect (x & y & width & height), area, upper-left and bottom-right, intersections
//cv::RotatedRect
//cv::Scalar a four-dimensional point class, element-wise multiplication, quaternion conjection

void createSparse() {
    int size[] = {10,10};
    cv::SparseMat sm(2,size, CV_32F);

    for(int i=0; i<10; i++) {
        int idx[2];
        idx[0] = size[0] * rand();
        idx[1] = size[1] * rand();
        sm.ref<float>(idx) += 1.0f;
    }

    // cv::SparseMatConstIterator_<float> it = sm.begin<float>();
    // cv::SparseMatConstIterator_<float> it_end = sm.end<float>();
    auto it = sm.begin<float>();
    auto it_end = sm.end();
    for(;it != it_end; ++it) {
        const cv::SparseMat::Node* node = it.node();
        printf("(%3d,%3d) %f\n", node->idx[0],node->idx[1], *it);
    }
}

void createMat() {
    cv::Mat m;
    m.create(3, 10, CV_32FC3); // Create data area for 3 rows and 10 columns of 3-channel 32-bit floats
    m.setTo(cv::Scalar(1.0f, 0.0f, 1.0f)); // Set the value of 1st and 3rd channels to 1.0, 2nd channel to 0
    // Equivalent to:
    cv::Mat m2(3,10,CV_32FC3,cv::Scalar(1.0f, 0.0f, 1.0f));
}

void solve() {

}

int main(int argc, const char * argv[]) {

//    createSparse();

    cv::Mat imgBackground = cv::imread("a.jpg");
    cv::Mat imgSprite = cv::imread("b.jpg");

    if(imgBackground.empty() || imgSprite.empty()){
        return -1;
    }

    cv::Mat imgOutput;
    cv::transpose(imgSprite, imgOutput);

    cv::Mat roi1(imgBackground, cv::Rect(10,10,259,258));
    cv::Mat roi2(imgOutput, cv::Rect(0,0,259,258));

    cv::addWeighted(roi1, 0.5, roi2, 0.5, 0.0, roi1);

    cv::imshow("Example", imgBackground);
    cv::waitKey();
    cv::destroyWindow("Example");

    return 0;
}

<commit_msg>Text border examples<commit_after>//
//  main.cpp
//  Hello-OpenCV
//
//  Created by nsp on 13/2/17.
//  Copyright © 2017 nspool. All rights reserved.
//

// Because the opencv framework headers don't play well with clang
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdocumentation"

#include <iostream>
#include "opencv2/opencv.hpp"

//cv::Vec small, fixed vectors
//cv::Matx small, fixed matrices
//cv::Point (x & y) can be cast to Vec but not derived from it. Dot & cross product.
//cv::Size (width & height), area computation
//cv::Rect (x & y & width & height), area, upper-left and bottom-right, intersections
//cv::RotatedRect
//cv::Scalar a four-dimensional point class, element-wise multiplication, quaternion conjection

void createSparse() {
    int size[] = {10,10};
    cv::SparseMat sm(2,size, CV_32F);

    for(int i=0; i<10; i++) {
        int idx[2];
        idx[0] = size[0] * rand();
        idx[1] = size[1] * rand();
        sm.ref<float>(idx) += 1.0f;
    }

    // cv::SparseMatConstIterator_<float> it = sm.begin<float>();
    // cv::SparseMatConstIterator_<float> it_end = sm.end<float>();
    auto it = sm.begin<float>();
    auto it_end = sm.end();
    for(;it != it_end; ++it) {
        const cv::SparseMat::Node* node = it.node();
        printf("(%3d,%3d) %f\n", node->idx[0],node->idx[1], *it);
    }
}

void createMat() {
    cv::Mat m;
    m.create(3, 10, CV_32FC3); // Create data area for 3 rows and 10 columns of 3-channel 32-bit floats
    m.setTo(cv::Scalar(1.0f, 0.0f, 1.0f)); // Set the value of 1st and 3rd channels to 1.0, 2nd channel to 0
    // Equivalent to:
    cv::Mat m2(3,10,CV_32FC3,cv::Scalar(1.0f, 0.0f, 1.0f));
}

void solve() {

}

int main(int argc, const char * argv[]) {

//    createSparse();

    // Colours
    cv::Mat imgBackground = cv::imread("a.jpg");
    cv::Mat imgSprite = cv::imread("b.jpg");

    // For borders
    auto white = cv::Scalar(255,255,255,0);
    auto red = cv::Scalar(0,0,255,0);

    if(imgBackground.empty() || imgSprite.empty()){
        return -1;
    }

    cv::Mat imgOutput;
    cv::transpose(imgSprite, imgOutput);

    cv::Mat roi1(imgBackground, cv::Rect(10,10,259,258));
    cv::Mat roi2(imgOutput, cv::Rect(0,0,259,258));

    cv::addWeighted(roi1, 0.5, roi2, 0.5, 0.0, roi1);

    // Put a border around the transposed sprite
    cv::rectangle(imgBackground, cv::Point(10,10), cv::Point(269,268), white);

    // Draw the title text and place a red border around it

    auto titleText = std::string("Title Appears Here");
    cv::Point textPoint = cv::Point(300,30);
    cv::putText(imgBackground, titleText, textPoint, 0, 1, 0, 2, 4, false);
    int textBaseline = 0;
    cv::Size textSize = cv::getTextSize(titleText, 0, 1, 2, &textBaseline);
    textPoint.y = textPoint.y + textBaseline;
    cv::rectangle(imgBackground, textPoint, cv::Point(textPoint.x + textSize.width, textPoint.y - textBaseline - textSize.height - 2), red);

    cv::imshow("Example", imgBackground);
    cv::waitKey();
    cv::destroyWindow("Example");

    return 0;
}

<|endoftext|>


<commit_before>#include <QtGui>
#include <QMessageBox>
#include <QFileDialog>
#include <QGraphicsScene>
#include <iostream>
#include <algorithm>
#include "main_window.hpp"

#include <QDebug>

#include "geometry_msgs/Pose.h"

using namespace Qt;

namespace map_marker {

	const double map_min = -5;
	const double map_max = 5;
	const double map_pix = 992;

	const QColor red = QColor(180, 40, 0);
	const QColor blue = QColor(30, 30, 140);
	const QColor green = QColor(50, 140, 30);
	const QColor orange = QColor(230, 120, 0);

	MainWindow::MainWindow(int argc, char** argv, QWidget *parent) : QMainWindow(parent), qnode(argc,argv) {
		ui.setupUi(this);
		qnode.init();

		// Connect list update to draw function
		QObject::connect(ui.tableWidget->selectionModel(), SIGNAL(selectionChanged(const QItemSelection &, const QItemSelection &)), SLOT(UpdateWindow()));

		// Load map image
		QString url = "/home/lars/git/ESA-PROJ/maps/legomap3-cropped.pgm";
		map = new QPixmap(url);

		// Ttable editing
		ui.tableWidget->setEditTriggers(QAbstractItemView::NoEditTriggers);
		ui.tableWidget->setSelectionBehavior(QAbstractItemView::SelectRows);
		ui.tableWidget->setSelectionMode(QAbstractItemView::SingleSelection);

		// Create map image
		lblMapImage = new ClickableLabel(this);
		lblMapImage->setAlignment(Qt::AlignBottom | Qt::AlignRight);
		lblMapImage->setGeometry(QRect(0, 0, map_pix, map_pix));
		//lblMapImage->setPixmap(*map);
		QObject::connect(lblMapImage, SIGNAL(clicked(QPoint)), this, SLOT(lblMapImage_clicked(QPoint)));

		// Set validator for input fields
		ui.inpCustomX->setValidator(new QDoubleValidator(-100, 100, 5, ui.inpCustomX));
		ui.inpCustomY->setValidator(new QDoubleValidator(-100, 100, 5, ui.inpCustomY));
		ui.inpCustomAngle->setValidator(new QDoubleValidator(0, 360, 5, ui.inpCustomAngle));

		// Panic button color
		ui.btnPanic->setStyleSheet("color: rgb(192,0,0);");

		// Add marker for testing
		Marker m(1.0, 2.0, 40.0, Navigation);
		AddMarker(m);

		UpdateTable();
	}

	MainWindow::~MainWindow() {
		delete map;
		delete lblMapImage;

	}

	void MainWindow::paintEvent(QPaintEvent *e) {

      Q_UNUSED(e);

      ROS_INFO("Paintevent");

      QPainter qp(this);

      qp.drawPixmap(0,0,992,992, *map);
      drawMarkers(&qp);
    }

    void MainWindow::drawMarkers(QPainter *qp) {
		QPen pen(Qt::black, 2, Qt::SolidLine);
		geometry_msgs::Pose pos = qnode.GetRobotPosition();
		QPoint p1;

		pen.setWidth(10);

		for(int i = 0; i < markers.size(); i++) {

			if(i == GetSelectedMarker()) {
				pen.setColor(red);
			} else if(markers[i].GetType() == Workspace) {
				pen.setColor(green);
			} else {
				pen.setColor(orange);
			}

			p1.setX(ConvertRobotToPixel(markers[i].GetX()));
			p1.setY(ConvertRobotToPixel(markers[i].GetY()));

			qp->setPen(pen);
			qp->drawPoint(p1);
			ROS_INFO("Marker");
		}

		p1.setX(ConvertRobotToPixel(pos.position.x));
		p1.setY(ConvertRobotToPixel(pos.position.y));

		pen.setColor(blue);

		qp->setPen(pen);
		qp->drawPoint(p1);
    }

	void MainWindow::lblMapImage_clicked(QPoint a) {
		QString x = QString::number(ConvertPixelToRobot(a.x()));
		QString y = QString::number(ConvertPixelToRobot(a.y()));
		ui.inpCustomX->setText(x);
		ui.inpCustomY->setText(y);
	}

	void MainWindow::on_btnLoadYaml_clicked() {
		QFileDialog dialog(this);
		dialog.setFileMode(QFileDialog::AnyFile);
		dialog.setNameFilter(tr("Map image file (*.yaml)"));

		QStringList fileNames;
		if (dialog.exec())
		fileNames = dialog.selectedFiles();

		yaml.loadYaml(fileNames[0].toUtf8().constData());
		mapConfig.setFullConfigData(yaml.parsedYaml);

	}

	void MainWindow::on_btnLoadMap_clicked() {
		QFileDialog dialog(this);
		dialog.setFileMode(QFileDialog::AnyFile);
		dialog.setNameFilter(tr("Map image file (*.pbm *.pgm *.ppm)"));

		QStringList fileNames;
		if (dialog.exec())
		fileNames = dialog.selectedFiles();

		map = new QPixmap(fileNames[0]);
			lblMapImage->setPixmap(*map);
	}

	void MainWindow::on_btnWriteYaml_clicked() {
		ROS_ERROR("Not implemented yet :(");
	}

	void MainWindow::on_btnClearYaml_clicked() {
		ROS_ERROR("Not implemented yet :(");
	}

	void MainWindow::on_btnAddCurrentPose_clicked() {
		geometry_msgs::Pose pos = qnode.GetRobotPosition();

		MarkerType type;
		if(ui.radioNav->isChecked()) {
			type = Navigation;
		} else if (ui.radioWorkspace->isChecked()) {
			type = Workspace;
		}

		AddMarker(Marker(pos, type));
		UpdateTable();
	}

	void MainWindow::on_btnAddCustomPose_clicked() {
		double x = ui.inpCustomX->text().toDouble();
		double y = ui.inpCustomY->text().toDouble();
		double angle = ui.inpCustomAngle->text().toDouble();

		MarkerType type;
		if(ui.radioNav->isChecked()) {
			type = Navigation;
		} else if (ui.radioWorkspace->isChecked()) {
			type = Workspace;
		}

		AddMarker(Marker(x, y, angle, type));
		UpdateTable();
	}

	void MainWindow::on_btnMoveRobot_clicked() {
		int index = GetSelectedMarker();
		if(index == -1) {
			ROS_WARN("No marker selected");
			return;
		}
		Marker * m = &markers[index];
		qnode.MoveRobotToPose(m->GetPose());
	}

	void MainWindow::on_btnRemoveMarker_clicked() {
		int index = GetSelectedMarker();
		if(index == -1) {
			ROS_WARN("No marker selected");
			return;
		}
		markers.erase(markers.begin()+index);
		UpdateTable();
	}

	void MainWindow::on_btnPanic_clicked() {
		qnode.Panic();
		ROS_INFO("Panic button pressed, stopped robot...");
	}

	void MainWindow::on_btnMoveMarkerUp_clicked() {
		int selectedMarker = GetSelectedMarker();
		MoveMarkerUp(selectedMarker);
		UpdateTable();
	}

	void MainWindow::on_btnMoveMarkerDown_clicked() {
		int selectedMarker = GetSelectedMarker();
		MoveMarkerDown(selectedMarker);
		UpdateTable();
	}

	void MainWindow::on_btnClearAllMarkers_clicked() {
		markers.clear();
		UpdateTable();
	}

	int MainWindow::GetSelectedMarker() {
		int j = -1;
		QModelIndexList indexes = ui.tableWidget->selectionModel()->selectedRows();

		for (int i = 0; i < indexes.count(); ++i) {
			j = indexes.at(i).row();
		}

		return j;
	}

	void MainWindow::AddMarker(Marker marker) {
		markers.push_back(marker);
	}

	void MainWindow::MoveMarkerUp(int selectedMarker) {
		if(selectedMarker + 1 < markers.size() && selectedMarker >= 0) {
			std::swap(markers.at(selectedMarker), markers.at(selectedMarker + 1));
		} else {
			ROS_WARN("No marker selected");
		}
	}

	void MainWindow::MoveMarkerDown(int selectedMarker) {
		if(selectedMarker > 0) {
			std::swap(markers.at(selectedMarker), markers.at(selectedMarker - 1));
		} else {
			ROS_WARN("No marker selected");
		}
	}

	void MainWindow::UpdateTable() {
		ui.tableWidget->setRowCount(0);
		for(int i=0; i < markers.size(); i++) {
			ui.tableWidget->insertRow ( ui.tableWidget->rowCount() );
			ui.tableWidget->setItem(ui.tableWidget->rowCount()-1, 0, new QTableWidgetItem(QString::fromStdString(markers[i].GetTypeStr())));
			ui.tableWidget->setItem(ui.tableWidget->rowCount()-1, 1, new QTableWidgetItem(QString::number(markers[i].GetX())));
			ui.tableWidget->setItem(ui.tableWidget->rowCount()-1, 2, new QTableWidgetItem(QString::number(markers[i].GetY())));
			ui.tableWidget->setItem(ui.tableWidget->rowCount()-1, 3, new QTableWidgetItem(QString::number(markers[i].GetAngle())));
		}

		UpdateWindow();
	}

	void MainWindow::UpdateWindow() {
		// Update window - draw map and points again
		this->update();
	}

	int MainWindow::ConvertRobotToPixel(double a) {
		return (a - map_min) * (map_pix - 0) / (map_max - map_min);
	}

	double MainWindow::ConvertPixelToRobot(int a) {
		return (a) * (map_max - map_min) / (map_pix) + map_min;
	}
}
<commit_msg>Fixed load new image bug<commit_after>#include <QtGui>
#include <QMessageBox>
#include <QFileDialog>
#include <QGraphicsScene>
#include <iostream>
#include <algorithm>
#include "main_window.hpp"

#include <QDebug>

#include "geometry_msgs/Pose.h"

using namespace Qt;

namespace map_marker {

	const double map_min = -5;
	const double map_max = 5;
	const double map_pix = 992;

	const QColor red = QColor(180, 40, 0);
	const QColor blue = QColor(30, 30, 140);
	const QColor green = QColor(50, 140, 30);
	const QColor orange = QColor(230, 120, 0);

	MainWindow::MainWindow(int argc, char** argv, QWidget *parent) : QMainWindow(parent), qnode(argc,argv) {
		ui.setupUi(this);
		qnode.init();

		// Connect list update to draw function
		QObject::connect(ui.tableWidget->selectionModel(), SIGNAL(selectionChanged(const QItemSelection &, const QItemSelection &)), SLOT(UpdateWindow()));

		// Load map image
		QString url = "/home/lars/git/ESA-PROJ/maps/legomap3-cropped.pgm";
		map = new QPixmap(url);

		// Ttable editing
		ui.tableWidget->setEditTriggers(QAbstractItemView::NoEditTriggers);
		ui.tableWidget->setSelectionBehavior(QAbstractItemView::SelectRows);
		ui.tableWidget->setSelectionMode(QAbstractItemView::SingleSelection);

		// Create map image
		lblMapImage = new ClickableLabel(this);
		lblMapImage->setAlignment(Qt::AlignBottom | Qt::AlignRight);
		lblMapImage->setGeometry(QRect(0, 0, map_pix, map_pix));
		QObject::connect(lblMapImage, SIGNAL(clicked(QPoint)), this, SLOT(lblMapImage_clicked(QPoint)));

		// Set validator for input fields
		ui.inpCustomX->setValidator(new QDoubleValidator(-100, 100, 5, ui.inpCustomX));
		ui.inpCustomY->setValidator(new QDoubleValidator(-100, 100, 5, ui.inpCustomY));
		ui.inpCustomAngle->setValidator(new QDoubleValidator(0, 360, 5, ui.inpCustomAngle));

		// Panic button color
		ui.btnPanic->setStyleSheet("color: rgb(192,0,0);");

		// Add marker for testing
		Marker m(1.0, 2.0, 40.0, Navigation);
		AddMarker(m);

		UpdateTable();
	}

	MainWindow::~MainWindow() {
		delete map;
		delete lblMapImage;

	}

	void MainWindow::paintEvent(QPaintEvent *e) {

      Q_UNUSED(e);

      QPainter qp(this);

      qp.drawPixmap(0, 0, map_pix, map_pix, *map);
      drawMarkers(&qp);
    }

    void MainWindow::drawMarkers(QPainter *qp) {
		QPen pen(Qt::black, 2, Qt::SolidLine);
		geometry_msgs::Pose pos = qnode.GetRobotPosition();
		QPoint p1;

		pen.setWidth(10);

		for(int i = 0; i < markers.size(); i++) {

			if(i == GetSelectedMarker()) {
				pen.setColor(red);
			} else if(markers[i].GetType() == Workspace) {
				pen.setColor(green);
			} else {
				pen.setColor(orange);
			}

			p1.setX(ConvertRobotToPixel(markers[i].GetX()));
			p1.setY(ConvertRobotToPixel(markers[i].GetY()));

			qp->setPen(pen);
			qp->drawPoint(p1);
			ROS_INFO("Marker");
		}

		p1.setX(ConvertRobotToPixel(pos.position.x));
		p1.setY(ConvertRobotToPixel(pos.position.y));

		pen.setColor(blue);

		qp->setPen(pen);
		qp->drawPoint(p1);
    }

	void MainWindow::lblMapImage_clicked(QPoint a) {
		QString x = QString::number(ConvertPixelToRobot(a.x()));
		QString y = QString::number(ConvertPixelToRobot(a.y()));
		ui.inpCustomX->setText(x);
		ui.inpCustomY->setText(y);
	}

	void MainWindow::on_btnLoadYaml_clicked() {
		QFileDialog dialog(this);
		dialog.setFileMode(QFileDialog::AnyFile);
		dialog.setNameFilter(tr("Map image file (*.yaml)"));

		QStringList fileNames;
		if (dialog.exec())
		fileNames = dialog.selectedFiles();

		yaml.loadYaml(fileNames[0].toUtf8().constData());
		mapConfig.setFullConfigData(yaml.parsedYaml);

	}

	void MainWindow::on_btnLoadMap_clicked() {
		QFileDialog dialog(this);
		dialog.setFileMode(QFileDialog::AnyFile);
		dialog.setNameFilter(tr("Map image file (*.pbm *.pgm *.ppm)"));

		QStringList fileNames;
		if (dialog.exec())
		fileNames = dialog.selectedFiles();

		map = new QPixmap(fileNames[0]);
		UpdateWindow();
	}

	void MainWindow::on_btnWriteYaml_clicked() {
		ROS_ERROR("Not implemented yet :(");
	}

	void MainWindow::on_btnClearYaml_clicked() {
		ROS_ERROR("Not implemented yet :(");
	}

	void MainWindow::on_btnAddCurrentPose_clicked() {
		geometry_msgs::Pose pos = qnode.GetRobotPosition();

		MarkerType type;
		if(ui.radioNav->isChecked()) {
			type = Navigation;
		} else if (ui.radioWorkspace->isChecked()) {
			type = Workspace;
		}

		AddMarker(Marker(pos, type));
		UpdateTable();
	}

	void MainWindow::on_btnAddCustomPose_clicked() {
		double x = ui.inpCustomX->text().toDouble();
		double y = ui.inpCustomY->text().toDouble();
		double angle = ui.inpCustomAngle->text().toDouble();

		MarkerType type;
		if(ui.radioNav->isChecked()) {
			type = Navigation;
		} else if (ui.radioWorkspace->isChecked()) {
			type = Workspace;
		}

		AddMarker(Marker(x, y, angle, type));
		UpdateTable();
	}

	void MainWindow::on_btnMoveRobot_clicked() {
		int index = GetSelectedMarker();
		if(index == -1) {
			ROS_WARN("No marker selected");
			return;
		}
		Marker * m = &markers[index];
		qnode.MoveRobotToPose(m->GetPose());
	}

	void MainWindow::on_btnRemoveMarker_clicked() {
		int index = GetSelectedMarker();
		if(index == -1) {
			ROS_WARN("No marker selected");
			return;
		}
		markers.erase(markers.begin()+index);
		UpdateTable();
	}

	void MainWindow::on_btnPanic_clicked() {
		qnode.Panic();
		ROS_INFO("Panic button pressed, stopped robot...");
	}

	void MainWindow::on_btnMoveMarkerUp_clicked() {
		int selectedMarker = GetSelectedMarker();
		MoveMarkerUp(selectedMarker);
		UpdateTable();
	}

	void MainWindow::on_btnMoveMarkerDown_clicked() {
		int selectedMarker = GetSelectedMarker();
		MoveMarkerDown(selectedMarker);
		UpdateTable();
	}

	void MainWindow::on_btnClearAllMarkers_clicked() {
		markers.clear();
		UpdateTable();
	}

	int MainWindow::GetSelectedMarker() {
		int j = -1;
		QModelIndexList indexes = ui.tableWidget->selectionModel()->selectedRows();

		for (int i = 0; i < indexes.count(); ++i) {
			j = indexes.at(i).row();
		}

		return j;
	}

	void MainWindow::AddMarker(Marker marker) {
		markers.push_back(marker);
	}

	void MainWindow::MoveMarkerUp(int selectedMarker) {
		if(selectedMarker + 1 < markers.size() && selectedMarker >= 0) {
			std::swap(markers.at(selectedMarker), markers.at(selectedMarker + 1));
		} else {
			ROS_WARN("No marker selected");
		}
	}

	void MainWindow::MoveMarkerDown(int selectedMarker) {
		if(selectedMarker > 0) {
			std::swap(markers.at(selectedMarker), markers.at(selectedMarker - 1));
		} else {
			ROS_WARN("No marker selected");
		}
	}

	void MainWindow::UpdateTable() {
		ui.tableWidget->setRowCount(0);
		for(int i=0; i < markers.size(); i++) {
			ui.tableWidget->insertRow ( ui.tableWidget->rowCount() );
			ui.tableWidget->setItem(ui.tableWidget->rowCount()-1, 0, new QTableWidgetItem(QString::fromStdString(markers[i].GetTypeStr())));
			ui.tableWidget->setItem(ui.tableWidget->rowCount()-1, 1, new QTableWidgetItem(QString::number(markers[i].GetX())));
			ui.tableWidget->setItem(ui.tableWidget->rowCount()-1, 2, new QTableWidgetItem(QString::number(markers[i].GetY())));
			ui.tableWidget->setItem(ui.tableWidget->rowCount()-1, 3, new QTableWidgetItem(QString::number(markers[i].GetAngle())));
		}

		UpdateWindow();
	}

	void MainWindow::UpdateWindow() {
		// Update window - draw map and points again
		this->update();
	}

	int MainWindow::ConvertRobotToPixel(double a) {
		return (a - map_min) * (map_pix - 0) / (map_max - map_min);
	}

	double MainWindow::ConvertPixelToRobot(int a) {
		return (a) * (map_max - map_min) / (map_pix) + map_min;
	}
}
<|endoftext|>


<commit_before>/*************************************************************************/
/*  tiles_editor_plugin.cpp                                              */
/*************************************************************************/
/*                       This file is part of:                           */
/*                           GODOT ENGINE                                */
/*                      https://godotengine.org                          */
/*************************************************************************/
/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur.                 */
/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md).   */
/*                                                                       */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the       */
/* "Software"), to deal in the Software without restriction, including   */
/* without limitation the rights to use, copy, modify, merge, publish,   */
/* distribute, sublicense, and/or sell copies of the Software, and to    */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions:                                             */
/*                                                                       */
/* The above copyright notice and this permission notice shall be        */
/* included in all copies or substantial portions of the Software.       */
/*                                                                       */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
/*************************************************************************/

#include "tiles_editor_plugin.h"

#include "core/os/mutex.h"

#include "editor/editor_node.h"
#include "editor/editor_scale.h"
#include "editor/plugins/canvas_item_editor_plugin.h"

#include "scene/2d/tile_map.h"
#include "scene/gui/box_container.h"
#include "scene/gui/button.h"
#include "scene/gui/control.h"
#include "scene/gui/separator.h"
#include "scene/resources/tile_set.h"

#include "tile_set_editor.h"

TilesEditorPlugin *TilesEditorPlugin::singleton = nullptr;

void TilesEditorPlugin::_preview_frame_started() {
	RS::get_singleton()->request_frame_drawn_callback(callable_mp(const_cast<TilesEditorPlugin *>(this), &TilesEditorPlugin::_pattern_preview_done));
}

void TilesEditorPlugin::_pattern_preview_done() {
	pattern_preview_done.post();
}

void TilesEditorPlugin::_thread_func(void *ud) {
	TilesEditorPlugin *te = (TilesEditorPlugin *)ud;
	te->_thread();
}

void TilesEditorPlugin::_thread() {
	pattern_thread_exited.clear();
	while (!pattern_thread_exit.is_set()) {
		pattern_preview_sem.wait();

		pattern_preview_mutex.lock();
		if (pattern_preview_queue.size()) {
			QueueItem item = pattern_preview_queue.front()->get();
			pattern_preview_queue.pop_front();
			pattern_preview_mutex.unlock();

			int thumbnail_size = EditorSettings::get_singleton()->get("filesystem/file_dialog/thumbnail_size");
			thumbnail_size *= EDSCALE;
			Vector2 thumbnail_size2 = Vector2(thumbnail_size, thumbnail_size);

			if (item.pattern.is_valid() && !item.pattern->is_empty()) {
				// Generate the pattern preview
				SubViewport *viewport = memnew(SubViewport);
				viewport->set_size(thumbnail_size2);
				viewport->set_disable_input(true);
				viewport->set_transparent_background(true);
				viewport->set_update_mode(SubViewport::UPDATE_ONCE);

				TileMap *tile_map = memnew(TileMap);
				tile_map->set_tileset(item.tile_set);
				tile_map->set_pattern(0, Vector2(), item.pattern);
				viewport->add_child(tile_map);

				TypedArray<Vector2i> used_cells = tile_map->get_used_cells(0);

				Rect2 encompassing_rect = Rect2();
				encompassing_rect.set_position(tile_map->map_to_world(used_cells[0]));
				for (int i = 0; i < used_cells.size(); i++) {
					Vector2i cell = used_cells[i];
					Vector2 world_pos = tile_map->map_to_world(cell);
					encompassing_rect.expand_to(world_pos);

					// Texture.
					Ref<TileSetAtlasSource> atlas_source = tile_set->get_source(tile_map->get_cell_source_id(0, cell));
					if (atlas_source.is_valid()) {
						Vector2i coords = tile_map->get_cell_atlas_coords(0, cell);
						int alternative = tile_map->get_cell_alternative_tile(0, cell);

						Vector2 center = world_pos - atlas_source->get_tile_effective_texture_offset(coords, alternative);
						encompassing_rect.expand_to(center - atlas_source->get_tile_texture_region(coords).size / 2);
						encompassing_rect.expand_to(center + atlas_source->get_tile_texture_region(coords).size / 2);
					}
				}

				Vector2 scale = thumbnail_size2 / MAX(encompassing_rect.size.x, encompassing_rect.size.y);
				tile_map->set_scale(scale);
				tile_map->set_position(-(scale * encompassing_rect.get_center()) + thumbnail_size2 / 2);

				// Add the viewport at the lasst moment to avoid rendering too early.
				EditorNode::get_singleton()->add_child(viewport);

				RS::get_singleton()->connect(SNAME("frame_pre_draw"), callable_mp(const_cast<TilesEditorPlugin *>(this), &TilesEditorPlugin::_preview_frame_started), Vector<Variant>(), Object::CONNECT_ONESHOT);

				pattern_preview_done.wait();

				Ref<Image> image = viewport->get_texture()->get_image();
				Ref<ImageTexture> image_texture;
				image_texture.instantiate();
				image_texture->create_from_image(image);

				// Find the index for the given pattern. TODO: optimize.
				Variant args[] = { item.pattern, image_texture };
				const Variant *args_ptr[] = { &args[0], &args[1] };
				Variant r;
				Callable::CallError error;
				item.callback.call(args_ptr, 2, r, error);

				viewport->queue_delete();
			} else {
				pattern_preview_mutex.unlock();
			}
		}
	}
	pattern_thread_exited.set();
}

void TilesEditorPlugin::_tile_map_changed() {
	tile_map_changed_needs_update = true;
}

void TilesEditorPlugin::_update_editors() {
	// If tile_map is not edited, we change the edited only if we are not editing a tile_set.
	tileset_editor->edit(tile_set);
	TileMap *tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id));
	if (tile_map) {
		tilemap_editor->edit(tile_map);
	} else {
		tilemap_editor->edit(nullptr);
	}

	// Update the viewport.
	CanvasItemEditor::get_singleton()->update_viewport();
}

void TilesEditorPlugin::_notification(int p_what) {
	switch (p_what) {
		case NOTIFICATION_INTERNAL_PROCESS: {
			if (tile_map_changed_needs_update) {
				TileMap *tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id));
				if (tile_map) {
					tile_set = tile_map->get_tileset();
				}
				_update_editors();
				tile_map_changed_needs_update = false;
			}
		} break;
	}
}

void TilesEditorPlugin::make_visible(bool p_visible) {
	if (p_visible) {
		// Disable and hide invalid editors.
		TileMap *tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id));
		tileset_editor_button->set_visible(tile_set.is_valid());
		tilemap_editor_button->set_visible(tile_map);
		if (tile_map) {
			editor_node->make_bottom_panel_item_visible(tilemap_editor);
		} else {
			editor_node->make_bottom_panel_item_visible(tileset_editor);
		}

	} else {
		tileset_editor_button->hide();
		tilemap_editor_button->hide();
		editor_node->hide_bottom_panel();
	}
}

void TilesEditorPlugin::queue_pattern_preview(Ref<TileSet> p_tile_set, Ref<TileMapPattern> p_pattern, Callable p_callback) {
	ERR_FAIL_COND(!p_tile_set.is_valid());
	ERR_FAIL_COND(!p_pattern.is_valid());
	{
		MutexLock lock(pattern_preview_mutex);
		pattern_preview_queue.push_back({ p_tile_set, p_pattern, p_callback });
	}
	pattern_preview_sem.post();
}

void TilesEditorPlugin::set_sources_lists_current(int p_current) {
	atlas_sources_lists_current = p_current;
}

void TilesEditorPlugin::synchronize_sources_list(Object *p_current) {
	ItemList *item_list = Object::cast_to<ItemList>(p_current);
	ERR_FAIL_COND(!item_list);

	if (item_list->is_visible_in_tree()) {
		if (atlas_sources_lists_current < 0 || atlas_sources_lists_current >= item_list->get_item_count()) {
			item_list->deselect_all();
		} else {
			item_list->set_current(atlas_sources_lists_current);
			item_list->emit_signal(SNAME("item_selected"), atlas_sources_lists_current);
		}
	}
}

void TilesEditorPlugin::set_atlas_view_transform(float p_zoom, Vector2 p_scroll) {
	atlas_view_zoom = p_zoom;
	atlas_view_scroll = p_scroll;
}

void TilesEditorPlugin::synchronize_atlas_view(Object *p_current) {
	TileAtlasView *tile_atlas_view = Object::cast_to<TileAtlasView>(p_current);
	ERR_FAIL_COND(!tile_atlas_view);

	if (tile_atlas_view->is_visible_in_tree()) {
		tile_atlas_view->set_transform(atlas_view_zoom, atlas_view_scroll);
	}
}

void TilesEditorPlugin::edit(Object *p_object) {
	// Disconnect to changes.
	TileMap *tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id));
	if (tile_map) {
		tile_map->disconnect("changed", callable_mp(this, &TilesEditorPlugin::_tile_map_changed));
	}

	// Update edited objects.
	tile_set = Ref<TileSet>();
	if (p_object) {
		if (p_object->is_class("TileMap")) {
			tile_map_id = p_object->get_instance_id();
			tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id));
			tile_set = tile_map->get_tileset();
			editor_node->make_bottom_panel_item_visible(tilemap_editor);
		} else if (p_object->is_class("TileSet")) {
			tile_set = Ref<TileSet>(p_object);
			if (tile_map) {
				if (tile_map->get_tileset() != tile_set || !tile_map->is_inside_tree()) {
					tile_map = nullptr;
					tile_map_id = ObjectID();
				}
			}
			editor_node->make_bottom_panel_item_visible(tileset_editor);
		}
	}

	// Update the editors.
	_update_editors();

	// Add change listener.
	if (tile_map) {
		tile_map->connect("changed", callable_mp(this, &TilesEditorPlugin::_tile_map_changed));
	}
}

bool TilesEditorPlugin::handles(Object *p_object) const {
	return p_object->is_class("TileMap") || p_object->is_class("TileSet");
}

TilesEditorPlugin::TilesEditorPlugin(EditorNode *p_node) {
	set_process_internal(true);

	// Update the singleton.
	singleton = this;

	editor_node = p_node;

	// Tileset editor.
	tileset_editor = memnew(TileSetEditor);
	tileset_editor->set_h_size_flags(Control::SIZE_EXPAND_FILL);
	tileset_editor->set_v_size_flags(Control::SIZE_EXPAND_FILL);
	tileset_editor->set_custom_minimum_size(Size2(0, 200) * EDSCALE);
	tileset_editor->hide();

	// Tilemap editor.
	tilemap_editor = memnew(TileMapEditor);
	tilemap_editor->set_h_size_flags(Control::SIZE_EXPAND_FILL);
	tilemap_editor->set_v_size_flags(Control::SIZE_EXPAND_FILL);
	tilemap_editor->set_custom_minimum_size(Size2(0, 200) * EDSCALE);
	tilemap_editor->hide();

	// Pattern preview generation thread.
	pattern_preview_thread.start(_thread_func, this);

	// Bottom buttons.
	tileset_editor_button = p_node->add_bottom_panel_item(TTR("TileSet"), tileset_editor);
	tileset_editor_button->hide();
	tilemap_editor_button = p_node->add_bottom_panel_item(TTR("TileMap"), tilemap_editor);
	tilemap_editor_button->hide();

	// Initialization.
	_update_editors();
}

TilesEditorPlugin::~TilesEditorPlugin() {
	if (pattern_preview_thread.is_started()) {
		pattern_thread_exit.set();
		pattern_preview_sem.post();
		while (!pattern_thread_exited.is_set()) {
			OS::get_singleton()->delay_usec(10000);
			RenderingServer::get_singleton()->sync(); //sync pending stuff, as thread may be blocked on visual server
		}
		pattern_preview_thread.wait_to_finish();
	}
}
<commit_msg>Correctly show and hide tile set editor panel<commit_after>/*************************************************************************/
/*  tiles_editor_plugin.cpp                                              */
/*************************************************************************/
/*                       This file is part of:                           */
/*                           GODOT ENGINE                                */
/*                      https://godotengine.org                          */
/*************************************************************************/
/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur.                 */
/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md).   */
/*                                                                       */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the       */
/* "Software"), to deal in the Software without restriction, including   */
/* without limitation the rights to use, copy, modify, merge, publish,   */
/* distribute, sublicense, and/or sell copies of the Software, and to    */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions:                                             */
/*                                                                       */
/* The above copyright notice and this permission notice shall be        */
/* included in all copies or substantial portions of the Software.       */
/*                                                                       */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
/*************************************************************************/

#include "tiles_editor_plugin.h"

#include "core/os/mutex.h"

#include "editor/editor_node.h"
#include "editor/editor_scale.h"
#include "editor/plugins/canvas_item_editor_plugin.h"

#include "scene/2d/tile_map.h"
#include "scene/gui/box_container.h"
#include "scene/gui/button.h"
#include "scene/gui/control.h"
#include "scene/gui/separator.h"
#include "scene/resources/tile_set.h"

#include "tile_set_editor.h"

TilesEditorPlugin *TilesEditorPlugin::singleton = nullptr;

void TilesEditorPlugin::_preview_frame_started() {
	RS::get_singleton()->request_frame_drawn_callback(callable_mp(const_cast<TilesEditorPlugin *>(this), &TilesEditorPlugin::_pattern_preview_done));
}

void TilesEditorPlugin::_pattern_preview_done() {
	pattern_preview_done.post();
}

void TilesEditorPlugin::_thread_func(void *ud) {
	TilesEditorPlugin *te = (TilesEditorPlugin *)ud;
	te->_thread();
}

void TilesEditorPlugin::_thread() {
	pattern_thread_exited.clear();
	while (!pattern_thread_exit.is_set()) {
		pattern_preview_sem.wait();

		pattern_preview_mutex.lock();
		if (pattern_preview_queue.size()) {
			QueueItem item = pattern_preview_queue.front()->get();
			pattern_preview_queue.pop_front();
			pattern_preview_mutex.unlock();

			int thumbnail_size = EditorSettings::get_singleton()->get("filesystem/file_dialog/thumbnail_size");
			thumbnail_size *= EDSCALE;
			Vector2 thumbnail_size2 = Vector2(thumbnail_size, thumbnail_size);

			if (item.pattern.is_valid() && !item.pattern->is_empty()) {
				// Generate the pattern preview
				SubViewport *viewport = memnew(SubViewport);
				viewport->set_size(thumbnail_size2);
				viewport->set_disable_input(true);
				viewport->set_transparent_background(true);
				viewport->set_update_mode(SubViewport::UPDATE_ONCE);

				TileMap *tile_map = memnew(TileMap);
				tile_map->set_tileset(item.tile_set);
				tile_map->set_pattern(0, Vector2(), item.pattern);
				viewport->add_child(tile_map);

				TypedArray<Vector2i> used_cells = tile_map->get_used_cells(0);

				Rect2 encompassing_rect = Rect2();
				encompassing_rect.set_position(tile_map->map_to_world(used_cells[0]));
				for (int i = 0; i < used_cells.size(); i++) {
					Vector2i cell = used_cells[i];
					Vector2 world_pos = tile_map->map_to_world(cell);
					encompassing_rect.expand_to(world_pos);

					// Texture.
					Ref<TileSetAtlasSource> atlas_source = tile_set->get_source(tile_map->get_cell_source_id(0, cell));
					if (atlas_source.is_valid()) {
						Vector2i coords = tile_map->get_cell_atlas_coords(0, cell);
						int alternative = tile_map->get_cell_alternative_tile(0, cell);

						Vector2 center = world_pos - atlas_source->get_tile_effective_texture_offset(coords, alternative);
						encompassing_rect.expand_to(center - atlas_source->get_tile_texture_region(coords).size / 2);
						encompassing_rect.expand_to(center + atlas_source->get_tile_texture_region(coords).size / 2);
					}
				}

				Vector2 scale = thumbnail_size2 / MAX(encompassing_rect.size.x, encompassing_rect.size.y);
				tile_map->set_scale(scale);
				tile_map->set_position(-(scale * encompassing_rect.get_center()) + thumbnail_size2 / 2);

				// Add the viewport at the lasst moment to avoid rendering too early.
				EditorNode::get_singleton()->add_child(viewport);

				RS::get_singleton()->connect(SNAME("frame_pre_draw"), callable_mp(const_cast<TilesEditorPlugin *>(this), &TilesEditorPlugin::_preview_frame_started), Vector<Variant>(), Object::CONNECT_ONESHOT);

				pattern_preview_done.wait();

				Ref<Image> image = viewport->get_texture()->get_image();
				Ref<ImageTexture> image_texture;
				image_texture.instantiate();
				image_texture->create_from_image(image);

				// Find the index for the given pattern. TODO: optimize.
				Variant args[] = { item.pattern, image_texture };
				const Variant *args_ptr[] = { &args[0], &args[1] };
				Variant r;
				Callable::CallError error;
				item.callback.call(args_ptr, 2, r, error);

				viewport->queue_delete();
			} else {
				pattern_preview_mutex.unlock();
			}
		}
	}
	pattern_thread_exited.set();
}

void TilesEditorPlugin::_tile_map_changed() {
	tile_map_changed_needs_update = true;
}

void TilesEditorPlugin::_update_editors() {
	// If tile_map is not edited, we change the edited only if we are not editing a tile_set.
	tileset_editor->edit(tile_set);
	TileMap *tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id));
	if (tile_map) {
		tilemap_editor->edit(tile_map);
	} else {
		tilemap_editor->edit(nullptr);
	}

	// Update the viewport.
	CanvasItemEditor::get_singleton()->update_viewport();

	// Update visibility of bottom panel buttons.
	if (tileset_editor_button->is_pressed() && !tile_set.is_valid()) {
		if (tile_map) {
			editor_node->make_bottom_panel_item_visible(tilemap_editor);
		} else {
			editor_node->hide_bottom_panel();
		}
	}
	tileset_editor_button->set_visible(tile_set.is_valid());
	tilemap_editor_button->set_visible(tile_map);
}

void TilesEditorPlugin::_notification(int p_what) {
	switch (p_what) {
		case NOTIFICATION_INTERNAL_PROCESS: {
			if (tile_map_changed_needs_update) {
				TileMap *tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id));
				if (tile_map) {
					tile_set = tile_map->get_tileset();
				}
				_update_editors();
				tile_map_changed_needs_update = false;
			}
		} break;
	}
}

void TilesEditorPlugin::make_visible(bool p_visible) {
	if (p_visible) {
		// Disable and hide invalid editors.
		TileMap *tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id));
		tileset_editor_button->set_visible(tile_set.is_valid());
		tilemap_editor_button->set_visible(tile_map);
		if (tile_map) {
			editor_node->make_bottom_panel_item_visible(tilemap_editor);
		} else {
			editor_node->make_bottom_panel_item_visible(tileset_editor);
		}

	} else {
		tileset_editor_button->hide();
		tilemap_editor_button->hide();
		editor_node->hide_bottom_panel();
	}
}

void TilesEditorPlugin::queue_pattern_preview(Ref<TileSet> p_tile_set, Ref<TileMapPattern> p_pattern, Callable p_callback) {
	ERR_FAIL_COND(!p_tile_set.is_valid());
	ERR_FAIL_COND(!p_pattern.is_valid());
	{
		MutexLock lock(pattern_preview_mutex);
		pattern_preview_queue.push_back({ p_tile_set, p_pattern, p_callback });
	}
	pattern_preview_sem.post();
}

void TilesEditorPlugin::set_sources_lists_current(int p_current) {
	atlas_sources_lists_current = p_current;
}

void TilesEditorPlugin::synchronize_sources_list(Object *p_current) {
	ItemList *item_list = Object::cast_to<ItemList>(p_current);
	ERR_FAIL_COND(!item_list);

	if (item_list->is_visible_in_tree()) {
		if (atlas_sources_lists_current < 0 || atlas_sources_lists_current >= item_list->get_item_count()) {
			item_list->deselect_all();
		} else {
			item_list->set_current(atlas_sources_lists_current);
			item_list->emit_signal(SNAME("item_selected"), atlas_sources_lists_current);
		}
	}
}

void TilesEditorPlugin::set_atlas_view_transform(float p_zoom, Vector2 p_scroll) {
	atlas_view_zoom = p_zoom;
	atlas_view_scroll = p_scroll;
}

void TilesEditorPlugin::synchronize_atlas_view(Object *p_current) {
	TileAtlasView *tile_atlas_view = Object::cast_to<TileAtlasView>(p_current);
	ERR_FAIL_COND(!tile_atlas_view);

	if (tile_atlas_view->is_visible_in_tree()) {
		tile_atlas_view->set_transform(atlas_view_zoom, atlas_view_scroll);
	}
}

void TilesEditorPlugin::edit(Object *p_object) {
	// Disconnect to changes.
	TileMap *tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id));
	if (tile_map) {
		tile_map->disconnect("changed", callable_mp(this, &TilesEditorPlugin::_tile_map_changed));
	}

	// Update edited objects.
	tile_set = Ref<TileSet>();
	if (p_object) {
		if (p_object->is_class("TileMap")) {
			tile_map_id = p_object->get_instance_id();
			tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id));
			tile_set = tile_map->get_tileset();
			editor_node->make_bottom_panel_item_visible(tilemap_editor);
		} else if (p_object->is_class("TileSet")) {
			tile_set = Ref<TileSet>(p_object);
			if (tile_map) {
				if (tile_map->get_tileset() != tile_set || !tile_map->is_inside_tree()) {
					tile_map = nullptr;
					tile_map_id = ObjectID();
				}
			}
			editor_node->make_bottom_panel_item_visible(tileset_editor);
		}
	}

	// Update the editors.
	_update_editors();

	// Add change listener.
	if (tile_map) {
		tile_map->connect("changed", callable_mp(this, &TilesEditorPlugin::_tile_map_changed));
	}
}

bool TilesEditorPlugin::handles(Object *p_object) const {
	return p_object->is_class("TileMap") || p_object->is_class("TileSet");
}

TilesEditorPlugin::TilesEditorPlugin(EditorNode *p_node) {
	set_process_internal(true);

	// Update the singleton.
	singleton = this;

	editor_node = p_node;

	// Tileset editor.
	tileset_editor = memnew(TileSetEditor);
	tileset_editor->set_h_size_flags(Control::SIZE_EXPAND_FILL);
	tileset_editor->set_v_size_flags(Control::SIZE_EXPAND_FILL);
	tileset_editor->set_custom_minimum_size(Size2(0, 200) * EDSCALE);
	tileset_editor->hide();

	// Tilemap editor.
	tilemap_editor = memnew(TileMapEditor);
	tilemap_editor->set_h_size_flags(Control::SIZE_EXPAND_FILL);
	tilemap_editor->set_v_size_flags(Control::SIZE_EXPAND_FILL);
	tilemap_editor->set_custom_minimum_size(Size2(0, 200) * EDSCALE);
	tilemap_editor->hide();

	// Pattern preview generation thread.
	pattern_preview_thread.start(_thread_func, this);

	// Bottom buttons.
	tileset_editor_button = p_node->add_bottom_panel_item(TTR("TileSet"), tileset_editor);
	tileset_editor_button->hide();
	tilemap_editor_button = p_node->add_bottom_panel_item(TTR("TileMap"), tilemap_editor);
	tilemap_editor_button->hide();

	// Initialization.
	_update_editors();
}

TilesEditorPlugin::~TilesEditorPlugin() {
	if (pattern_preview_thread.is_started()) {
		pattern_thread_exit.set();
		pattern_preview_sem.post();
		while (!pattern_thread_exited.is_set()) {
			OS::get_singleton()->delay_usec(10000);
			RenderingServer::get_singleton()->sync(); //sync pending stuff, as thread may be blocked on visual server
		}
		pattern_preview_thread.wait_to_finish();
	}
}
<|endoftext|>


<commit_before>#include <ctime>
#include <iostream>
#include <cassert>

// Interface of this cpp file is used by C code, we need to declare
// extern "C" to prevent linking errors.
extern "C" {
#include "policy/policy_resalt_cmd.h"
#include "policy/policy_resalt_task.h"
#include "shared/duration.h"
#include "shared/file.h"
#include "daemon/engine.h"
}

static const char *policy_resalt_cmd_str = "policy_resalt_cmd";

void help_policy_resalt_cmd(int sockfd)
{
    char buf[ODS_SE_MAXLINE];
    (void) snprintf(buf, ODS_SE_MAXLINE,
                    "policy resalt   resalt policies\n"
                    );
    ods_writen(sockfd, buf, strlen(buf));
}

int handled_policy_resalt_cmd(int sockfd, engine_type* engine, const char *cmd,
                                ssize_t n)
{
    char buf[ODS_SE_MAXLINE];
    task_type *task;
    ods_status status;
    const char *scmd =  "policy resalt";
    ssize_t ncmd = strlen(scmd);

    if (n < ncmd || strncmp(cmd,scmd, ncmd) != 0) return 0;
    ods_log_debug("[%s] %s command", policy_resalt_cmd_str, scmd);
    if (cmd[ncmd] == '\0') {
        cmd = "";
    } else if (cmd[ncmd] != ' ') {
        return 0;
    } else {
        cmd = &cmd[ncmd+1];
    }

    if (strncmp(cmd, "--task", 7) == 0) {
        /* schedule task */
        task = policy_resalt_task(engine->config);
        if (!task) {
            ods_log_crit("[%s] failed to create %s task",
                         policy_resalt_cmd_str,scmd);
        } else {
            status = schedule_task_from_thread(engine->taskq, task, 0);
            if (status != ODS_STATUS_OK) {
                ods_log_crit("[%s] failed to create %s task",
                             policy_resalt_cmd_str,scmd);

                (void)snprintf(buf, ODS_SE_MAXLINE,
                               "Unable to schedule %s task.\n",scmd);
                ods_writen(sockfd, buf, strlen(buf));
            } else  {
                (void)snprintf(buf, ODS_SE_MAXLINE,
                               "Scheduled %s task.\n",scmd);
                ods_writen(sockfd, buf, strlen(buf));
            }
        }
    } else {
        /* Do the update directly, giving the update process the chance to
         * report back any problems directly via sockfd.
         */
        perform_policy_resalt(sockfd, engine->config);
        (void)snprintf(buf, ODS_SE_MAXLINE, "%s complete.\n",scmd);
        ods_writen(sockfd, buf, strlen(buf));
    }
    return 1;
}
<commit_msg>Improve help message for 'policy resalt' command<commit_after>#include <ctime>
#include <iostream>
#include <cassert>

// Interface of this cpp file is used by C code, we need to declare
// extern "C" to prevent linking errors.
extern "C" {
#include "policy/policy_resalt_cmd.h"
#include "policy/policy_resalt_task.h"
#include "shared/duration.h"
#include "shared/file.h"
#include "daemon/engine.h"
}

static const char *policy_resalt_cmd_str = "policy_resalt_cmd";

void help_policy_resalt_cmd(int sockfd)
{
    char buf[ODS_SE_MAXLINE];
    (void)
    snprintf(buf, ODS_SE_MAXLINE,
             "policy resalt   generate new NSEC3 salts for policies that have\n"
             "                salts older than the resalt duration.\n"
                   );
    ods_writen(sockfd, buf, strlen(buf));
}

int handled_policy_resalt_cmd(int sockfd, engine_type* engine, const char *cmd,
                                ssize_t n)
{
    char buf[ODS_SE_MAXLINE];
    task_type *task;
    ods_status status;
    const char *scmd =  "policy resalt";
    ssize_t ncmd = strlen(scmd);

    if (n < ncmd || strncmp(cmd,scmd, ncmd) != 0) return 0;
    ods_log_debug("[%s] %s command", policy_resalt_cmd_str, scmd);
    if (cmd[ncmd] == '\0') {
        cmd = "";
    } else if (cmd[ncmd] != ' ') {
        return 0;
    } else {
        cmd = &cmd[ncmd+1];
    }

    if (strncmp(cmd, "--task", 7) == 0) {
        /* schedule task */
        task = policy_resalt_task(engine->config);
        if (!task) {
            ods_log_crit("[%s] failed to create %s task",
                         policy_resalt_cmd_str,scmd);
        } else {
            status = schedule_task_from_thread(engine->taskq, task, 0);
            if (status != ODS_STATUS_OK) {
                ods_log_crit("[%s] failed to create %s task",
                             policy_resalt_cmd_str,scmd);

                (void)snprintf(buf, ODS_SE_MAXLINE,
                               "Unable to schedule %s task.\n",scmd);
                ods_writen(sockfd, buf, strlen(buf));
            } else  {
                (void)snprintf(buf, ODS_SE_MAXLINE,
                               "Scheduled %s task.\n",scmd);
                ods_writen(sockfd, buf, strlen(buf));
            }
        }
    } else {
        /* Do the update directly, giving the update process the chance to
         * report back any problems directly via sockfd.
         */
        perform_policy_resalt(sockfd, engine->config);
        (void)snprintf(buf, ODS_SE_MAXLINE, "%s complete.\n",scmd);
        ods_writen(sockfd, buf, strlen(buf));
    }
    return 1;
}
<|endoftext|>


<commit_before>/**
 * \file
 * \brief       MD5 model demonstration
 * \author      Alexey Vasilyev <alexa.infra@gmail.com>
 * \copyright   MIT License
 **/
#include "app/app.h"
#include "renderer/md5mesh.h"
#include "renderer/md5anim.h"
#include "renderer/md5renderer.h"
#include "renderer/camera.h"
#include "renderer/gltexture.h"
#include "renderer/glprogram.h"
#include "renderer/wirebox.h"
#include <assert.h>

using namespace base;
using namespace base::math;
using namespace base::opengl;
using namespace base::resource;

class Demo : public Application
{
    Program        program_;
    Program        program_wirebox_;
    Camera          camera_;
    TextureLoader   texure_loader_;
    Matrix4         projection_;
    Matrix4         modelview_;
    Matrix4         cameraTransform_;
    Matrix4         modelTransform_;
    WireBox*        wire_box_;
    WireBox*        camera_wirebox_;
    Md5Renderer*    md5_renderer_;
    Entity*         entity;
    Texture*        texture_;
    Texture*        texture_bump_;
public:
    Demo() {
        camera_.set_position( Vector3( 0.f, 0.f, 500.f ) );
        camera_.set_pitch( 0 );
        camera_.set_head( 180 * deg_to_rad );
        camera_.set_aspect( width_ / ( f32 )height_ );
        camera_.set_fov( 45.0f );
        camera_.set_zNear( 1 );
        camera_.set_zFar( 1000 );
        camera_.Update();
        cameraTransform_ = camera_.GetModelView();
        projection_ = camera_.GetProjection();
        modelTransform_ = Matrix4::Identity();
        modelTransform_ *= Matrix4::Translation( Vector3( 0, 0, 450 ) );
        modelTransform_ *= Matrix4::RotationX( -90 * deg_to_rad );
        modelTransform_ *= Matrix4::RotationZ( 180 * deg_to_rad );
        program_.CreateFromFileWithAssert( "bump.shader" );
        texture_ = texure_loader_.Load( "hellknight.png" );
        texture_bump_ = texure_loader_.Load( "hellknight_local.png" );
        entity = Entity::Load( "hellknight.md5mesh" );
        entity->object.md5Anim = new Md5Anim;
        entity->object.md5Anim->Load( "hellknight_idle2.md5anim" );
        md5_renderer_ = new Md5Renderer( &entity->object.md5Model );
        program_wirebox_.CreateFromFileWithAssert( "wirebox.shader" );
        wire_box_ = new WireBox( md5_renderer_->boundingBox.min,
                                 md5_renderer_->boundingBox.max );
        f32 box_radius  = 600.0f;
        camera_wirebox_ = new WireBox ( Vector3( -1 * box_radius, -1 * box_radius, -1 * box_radius ),
                                        Vector3( box_radius, box_radius, box_radius ) );
    }
    virtual ~Demo() {
        program_.Destroy();
        program_wirebox_.Destroy();

        delete entity->object.md5Anim;
        delete entity;
        delete wire_box_;
        delete camera_wirebox_;
        delete md5_renderer_;
    }
protected:
    void OnFrame() {
        glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
        glClearColor( 1.0f, 1.0f, 1.0f, 1.0f );
        glEnable( GL_DEPTH_TEST );
        program_.Bind();
        program_.set_uniform( base::opengl::UniformVars::Diffuse, texture_ );
        program_.set_uniform( base::opengl::UniformVars::Bump, texture_bump_ );
        modelTransform_ *= Matrix4::RotationZ( 20 / 60.f * deg_to_rad );
        program_.set_uniform( base::opengl::UniformVars::Projection, projection_ );
        program_.set_uniform( base::opengl::UniformVars::Modelview, cameraTransform_ * modelTransform_ );
        program_.set_uniform( base::opengl::UniformVars::CameraPos, camera_.position() );
        program_.set_uniform( base::opengl::UniformVars::LightPos, Vector3( 40, 110, -200 ) );
        static u32 counter = 0;
        counter++;
        u32 frame  = counter / 2;
        f32 interp = ( counter % 2 ) / 2.f;
        entity->object.md5Anim->Update( &entity->object.md5Model, frame, interp );
        md5_renderer_->Commit();
        AttributeBinding binding = program_.binding();
        md5_renderer_->Draw( binding );
        program_.Unbind();
        program_wirebox_.Bind();
        program_wirebox_.set_uniform( base::opengl::UniformVars::Projection, projection_ );
        program_wirebox_.set_uniform( base::opengl::UniformVars::Modelview, cameraTransform_ * modelTransform_ );
        wire_box_->setMinPoint( md5_renderer_->boundingBox.min );
        wire_box_->setMaxPoint( md5_renderer_->boundingBox.max );
        wire_box_->Draw( &program_wirebox_ );
        program_wirebox_.set_uniform( base::opengl::UniformVars::Modelview, cameraTransform_ );
        camera_wirebox_->Draw( &program_wirebox_ );
        program_wirebox_.Unbind();
        assert( glGetError() == GL_NO_ERROR );
        Application::OnFrame();
    }

    void OnMotion( i32 x, i32 y, i32 dx, i32 dy ) {
        camera_.set_head( camera_.head()  + deg_to_rad * dx );

        if ( fabs ( camera_.pitch() + deg_to_rad * dy ) < base::math::pi / 4.0f ) {
            camera_.set_pitch( camera_.pitch() + deg_to_rad * dy );
        }

        camera_.Update();
        cameraTransform_ = camera_.GetModelView();
    }

    void OnKeyboardDown( u8 key ) {
        const f32 speed = 5.0f;

        if ( key == 'w' ) {
            camera_.set_position( camera_.position() + camera_.forward() * speed );
        } else if ( key == 's' ) {
            camera_.set_position( camera_.position() - camera_.forward() * speed );
        } else if ( key == 'a' ) {
            camera_.set_position( camera_.position() - camera_.right()   * speed );
        } else if ( key == 'd' ) {
            camera_.set_position( camera_.position() + camera_.right()   * speed );
        }

        camera_.Update();
        cameraTransform_ = camera_.GetModelView();
    }

};

int main()
{
    Demo app;
    app.Run();
    return 0;
}
<commit_msg>minor refactoring<commit_after>/**
 * \file
 * \brief       MD5 model demonstration
 * \author      Alexey Vasilyev <alexa.infra@gmail.com>
 * \copyright   MIT License
 **/
#include "app/app.h"
#include "renderer/md5mesh.h"
#include "renderer/md5anim.h"
#include "renderer/md5renderer.h"
#include "renderer/camera.h"
#include "renderer/gltexture.h"
#include "renderer/glprogram.h"
#include "renderer/wirebox.h"
#include <assert.h>

using namespace base;
using namespace base::math;
using namespace base::opengl;
using namespace base::resource;

class Demo : public Application
{
    Program        program_;
    Program        program_wirebox_;
    Camera          camera_;
    TextureLoader   texure_loader_;
    Matrix4         modelTransform_;
    WireBox*        wire_box_;
    WireBox*        camera_wirebox_;
    Md5Renderer*    md5_renderer_;
    Entity*         entity;
    Texture*        texture_;
    Texture*        texture_bump_;
public:
    Demo() {
        camera_.set_position( Vector3( 0.f, 0.f, 500.f ) );
        camera_.set_pitch( 0 );
        camera_.set_head( 180 * deg_to_rad );
        camera_.set_aspect( width_ / ( f32 )height_ );
        camera_.set_fov( 45.0f );
        camera_.set_zNear( 1 );
        camera_.set_zFar( 1000 );
        camera_.Update();
        modelTransform_ = Matrix4::Identity();
        modelTransform_ *= Matrix4::Translation( Vector3( 0, 0, 450 ) );
        modelTransform_ *= Matrix4::RotationX( -90 * deg_to_rad );
        modelTransform_ *= Matrix4::RotationZ( 180 * deg_to_rad );
        program_.CreateFromFileWithAssert( "bump.shader" );
        texture_ = texure_loader_.Load( "hellknight.png" );
        texture_bump_ = texure_loader_.Load( "hellknight_local.png" );
        entity = Entity::Load( "hellknight.md5mesh" );
        entity->object.md5Anim = new Md5Anim;
        entity->object.md5Anim->Load( "hellknight_idle2.md5anim" );
        md5_renderer_ = new Md5Renderer( &entity->object.md5Model );
        program_wirebox_.CreateFromFileWithAssert( "wirebox.shader" );
        wire_box_ = new WireBox( md5_renderer_->boundingBox.min,
                                 md5_renderer_->boundingBox.max );
        f32 box_radius  = 600.0f;
        camera_wirebox_ = new WireBox ( Vector3( -1 * box_radius, -1 * box_radius, -1 * box_radius ),
                                        Vector3( box_radius, box_radius, box_radius ) );
    }
    virtual ~Demo() {
        program_.Destroy();
        program_wirebox_.Destroy();

        delete entity->object.md5Anim;
        delete entity;
        delete wire_box_;
        delete camera_wirebox_;
        delete md5_renderer_;
    }
protected:
    void OnFrame() {
        glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
        glClearColor( 1.0f, 1.0f, 1.0f, 1.0f );
        glEnable( GL_DEPTH_TEST );
        program_.Bind();
        program_.set_uniform( base::opengl::UniformVars::Diffuse, texture_ );
        program_.set_uniform( base::opengl::UniformVars::Bump, texture_bump_ );
        modelTransform_ *= Matrix4::RotationZ( 20 / 60.f * deg_to_rad );
        program_.set_uniform( base::opengl::UniformVars::Projection, camera_.GetProjection() );
        program_.set_uniform( base::opengl::UniformVars::Modelview, camera_.GetModelView() * modelTransform_ );
        program_.set_uniform( base::opengl::UniformVars::CameraPos, camera_.position() );
        program_.set_uniform( base::opengl::UniformVars::LightPos, Vector3( 40, 110, -200 ) );
        static u32 counter = 0;
        counter++;
        u32 frame  = counter / 2;
        f32 interp = ( counter % 2 ) / 2.f;
        entity->object.md5Anim->Update( &entity->object.md5Model, frame, interp );
        md5_renderer_->Commit();
        AttributeBinding binding = program_.binding();
        md5_renderer_->Draw( binding );
        program_.Unbind();
        program_wirebox_.Bind();
        program_wirebox_.set_uniform( base::opengl::UniformVars::Projection, camera_.GetProjection() );
        program_wirebox_.set_uniform( base::opengl::UniformVars::Modelview, camera_.GetModelView() * modelTransform_ );
        wire_box_->setMinPoint( md5_renderer_->boundingBox.min );
        wire_box_->setMaxPoint( md5_renderer_->boundingBox.max );
        wire_box_->Draw( &program_wirebox_ );
        program_wirebox_.set_uniform( base::opengl::UniformVars::Modelview, camera_.GetModelView() );
        camera_wirebox_->Draw( &program_wirebox_ );
        program_wirebox_.Unbind();
        assert( glGetError() == GL_NO_ERROR );
        Application::OnFrame();
    }

    void OnMotion( i32 x, i32 y, i32 dx, i32 dy ) {
        camera_.set_head( camera_.head()  + deg_to_rad * dx );

        if ( fabs ( camera_.pitch() + deg_to_rad * dy ) < base::math::pi / 4.0f ) {
            camera_.set_pitch( camera_.pitch() + deg_to_rad * dy );
        }

        camera_.Update();
    }

    void OnKeyboardDown( u8 key ) {
        const f32 speed = 5.0f;

        if ( key == 'w' ) {
            camera_.set_position( camera_.position() + camera_.forward() * speed );
        } else if ( key == 's' ) {
            camera_.set_position( camera_.position() - camera_.forward() * speed );
        } else if ( key == 'a' ) {
            camera_.set_position( camera_.position() - camera_.right()   * speed );
        } else if ( key == 'd' ) {
            camera_.set_position( camera_.position() + camera_.right()   * speed );
        }

        camera_.Update();
    }

};

int main()
{
    Demo app;
    app.Run();
    return 0;
}
<|endoftext|>


<commit_before>//----------------------------------------------------------------------------
// Author:		Martin Klemsa
//----------------------------------------------------------------------------
#ifndef _ctoolhu_event_aggregator_included_
#define _ctoolhu_event_aggregator_included_

#include <boost/signals2.hpp>
#include <loki/Singleton.h>

namespace Ctoolhu {

	namespace Event {

		typedef boost::signals2::connection connection_type;

		namespace Private {

			//facilitates event handling between unrelated publishers and subscribers
			template <class Event>
			class Aggregator {

			  public:

				Aggregator(const Aggregator &) = delete;
				Aggregator &operator =(const Aggregator &) = delete;

				typedef boost::signals2::signal<void (Event *)> signal_type;
				typedef typename signal_type::slot_type slot_type;

				connection_type Subscribe(const slot_type &handler)
				{
					return _signal.connect(handler);
				}

				void Fire(Event &e)
				{
					_signal(&e);
				}

			  private:

				friend struct Loki::CreateUsingNew<Aggregator>;
				Aggregator() = default;

				signal_type _signal;
			};

			template <class Event>
			using SingleAggregator = Loki::SingletonHolder<Private::Aggregator<Event>>;

		} //ns Private

	} //ns Event

} //ns Ctoolhu

#endif
<commit_msg>marked event aggregator's firing method as const<commit_after>//----------------------------------------------------------------------------
// Author:		Martin Klemsa
//----------------------------------------------------------------------------
#ifndef _ctoolhu_event_aggregator_included_
#define _ctoolhu_event_aggregator_included_

#include <boost/signals2.hpp>
#include <loki/Singleton.h>

namespace Ctoolhu {

	namespace Event {

		typedef boost::signals2::connection connection_type;

		namespace Private {

			//facilitates event handling between unrelated publishers and subscribers
			template <class Event>
			class Aggregator {

			  public:

				Aggregator(const Aggregator &) = delete;
				Aggregator &operator =(const Aggregator &) = delete;

				typedef boost::signals2::signal<void (Event *)> signal_type;
				typedef typename signal_type::slot_type slot_type;

				connection_type Subscribe(const slot_type &handler)
				{
					return _signal.connect(handler);
				}

				void Fire(Event &e) const
				{
					_signal(&e);
				}

			  private:

				friend struct Loki::CreateUsingNew<Aggregator>;
				Aggregator() = default;

				signal_type _signal;
			};

			template <class Event>
			using SingleAggregator = Loki::SingletonHolder<Private::Aggregator<Event>>;

		} //ns Private

	} //ns Event

} //ns Ctoolhu

#endif
<|endoftext|>