<commit_before>/*
    Copyright © 2010, 2011, 2012 Vladimír Vondruš <mosra@centrum.cz>

    This file is part of Magnum.

    Magnum is free software: you can redistribute it and/or modify
    it under the terms of the GNU Lesser General Public License version 3
    only, as published by the Free Software Foundation.

    Magnum is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    GNU Lesser General Public License version 3 for more details.
*/

#include "PluginManager/PluginManager.h"
#include "Scene.h"
#include "Contexts/GlutContext.h"
#include "Trade/AbstractImporter.h"

#include "Billboard.h"
#include "ColorCorrectionCamera.h"

#include "configure.h"

using namespace Corrade::PluginManager;

namespace Magnum { namespace Examples {

class FramebufferExample: public Contexts::GlutContext {
    public:
        FramebufferExample(int& argc, char** argv): GlutContext(argc, argv, "Framebuffer example"), colorCorrectionBuffer(Buffer::Target::Texture) {
            if(argc != 2) {
                Debug() << "Usage:" << argv[0] << "image.tga";
                exit(0);
            }

            camera = new ColorCorrectionCamera(&scene);

            /* Load TGA importer plugin */
            PluginManager<Trade::AbstractImporter> manager(MAGNUM_PLUGINS_IMPORTER_DIR);
            Trade::AbstractImporter* importer;
            if(manager.load("TgaImporter") != AbstractPluginManager::LoadOk || !(importer = manager.instance("TgaImporter"))) {
                Error() << "Cannot load TgaImporter plugin from" << manager.pluginDirectory();
                exit(1);
            }

            /* Load the image */
            if(!importer->open(argv[1]) || !importer->image2DCount()) {
                Error() << "Cannot open image" << argv[1];
                exit(2);
            }

            /* Create color correction texture */
            GLfloat texture[1024];
            for(size_t i = 0; i != 1024; ++i) {
                GLfloat x = i*2/1023.0-1;
                texture[i] = (sin(x*Math::Constants<float>::pi())/3.7f+x+1)/2;
            }
            colorCorrectionBuffer.setData(sizeof(texture), texture, Buffer::Usage::StaticDraw);

            /* Add billboard to the scene */
            billboard = new Billboard(importer->image2D(0), &colorCorrectionBuffer, &scene);
            delete importer;
        }

    protected:
        inline void viewportEvent(const Math::Vector2<GLsizei>& size) {
            camera->setViewport(size);
        }

        inline void drawEvent() {
            camera->draw();
            swapBuffers();
        }

        void mouseEvent(MouseButton button, MouseState, const Math::Vector2<int>& position) {
            if(button == MouseButton::WheelUp)
                billboard->scale(Vector3(5.0f/4));
            else if(button == MouseButton::WheelDown)
                billboard->scale(Vector3(4.0f/5));

            previous = position;
            redraw();
        }

        void mouseMoveEvent(const Math::Vector2<int>& position) {
            Math::Vector2<int> delta = position-previous;
            billboard->translate({GLfloat(delta.x())/camera->viewport().x(),
                                 -GLfloat(delta.y())/camera->viewport().y(),
                                  0});
            previous = position;
            redraw();
        }

    private:
        Math::Vector2<int> previous;
        Scene scene;
        Camera* camera;
        Billboard* billboard;
        Buffer colorCorrectionBuffer;
};

}}

int main(int argc, char** argv) {
    Magnum::Examples::FramebufferExample e(argc, argv);
    return e.exec();
}
<commit_msg>Fixed float -> double promotion.<commit_after>/*
    Copyright © 2010, 2011, 2012 Vladimír Vondruš <mosra@centrum.cz>

    This file is part of Magnum.

    Magnum is free software: you can redistribute it and/or modify
    it under the terms of the GNU Lesser General Public License version 3
    only, as published by the Free Software Foundation.

    Magnum is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    GNU Lesser General Public License version 3 for more details.
*/

#include "PluginManager/PluginManager.h"
#include "Scene.h"
#include "Contexts/GlutContext.h"
#include "Trade/AbstractImporter.h"

#include "Billboard.h"
#include "ColorCorrectionCamera.h"

#include "configure.h"

using namespace Corrade::PluginManager;

namespace Magnum { namespace Examples {

class FramebufferExample: public Contexts::GlutContext {
    public:
        FramebufferExample(int& argc, char** argv): GlutContext(argc, argv, "Framebuffer example"), colorCorrectionBuffer(Buffer::Target::Texture) {
            if(argc != 2) {
                Debug() << "Usage:" << argv[0] << "image.tga";
                exit(0);
            }

            camera = new ColorCorrectionCamera(&scene);

            /* Load TGA importer plugin */
            PluginManager<Trade::AbstractImporter> manager(MAGNUM_PLUGINS_IMPORTER_DIR);
            Trade::AbstractImporter* importer;
            if(manager.load("TgaImporter") != AbstractPluginManager::LoadOk || !(importer = manager.instance("TgaImporter"))) {
                Error() << "Cannot load TgaImporter plugin from" << manager.pluginDirectory();
                exit(1);
            }

            /* Load the image */
            if(!importer->open(argv[1]) || !importer->image2DCount()) {
                Error() << "Cannot open image" << argv[1];
                exit(2);
            }

            /* Create color correction texture */
            GLfloat texture[1024];
            for(size_t i = 0; i != 1024; ++i) {
                GLfloat x = i*2/1023.0-1;
                texture[i] = (float(sin(x*Math::Constants<float>::pi()))/3.7f+x+1)/2;
            }
            colorCorrectionBuffer.setData(sizeof(texture), texture, Buffer::Usage::StaticDraw);

            /* Add billboard to the scene */
            billboard = new Billboard(importer->image2D(0), &colorCorrectionBuffer, &scene);
            delete importer;
        }

    protected:
        inline void viewportEvent(const Math::Vector2<GLsizei>& size) {
            camera->setViewport(size);
        }

        inline void drawEvent() {
            camera->draw();
            swapBuffers();
        }

        void mouseEvent(MouseButton button, MouseState, const Math::Vector2<int>& position) {
            if(button == MouseButton::WheelUp)
                billboard->scale(Vector3(5.0f/4));
            else if(button == MouseButton::WheelDown)
                billboard->scale(Vector3(4.0f/5));

            previous = position;
            redraw();
        }

        void mouseMoveEvent(const Math::Vector2<int>& position) {
            Math::Vector2<int> delta = position-previous;
            billboard->translate({GLfloat(delta.x())/camera->viewport().x(),
                                 -GLfloat(delta.y())/camera->viewport().y(),
                                  0});
            previous = position;
            redraw();
        }

    private:
        Math::Vector2<int> previous;
        Scene scene;
        Camera* camera;
        Billboard* billboard;
        Buffer colorCorrectionBuffer;
};

}}

int main(int argc, char** argv) {
    Magnum::Examples::FramebufferExample e(argc, argv);
    return e.exec();
}
<|endoftext|>


<commit_before>#ifndef _RICE_DECODED_DATA_H_
#define _RICE_DECODED_DATA_H_

#include <cstdint>
#include <vector>

namespace data {
class RiceDecodedData {
public:
    const std::vector<int32_t> decodedData;
    explicit RiceDecodedData(const std::vector<int32_t>&& decodedData) noexcept;
};

RiceDecodedData::RiceDecodedData(const std::vector<int32_t>&& decodedData) noexcept
    : decodedData(decodedData)
{
}
}

#endif<commit_msg>Chnages reverted<commit_after>#ifndef _RICE_DECODED_DATA_H_
#define _RICE_DECODED_DATA_H_

#include <cstdint>
#include <vector>

namespace data {
class RiceDecodedData {
public:
    const std::vector<int32_t> decodedData;
    explicit RiceDecodedData(const std::vector<int32_t>&& decodedData) noexcept
        : decodedData(decodedData)
    {
    }
};
}

#endif<|endoftext|>


<commit_before>/*=========================================================================

 medInria

 Copyright (c) INRIA 2013. All rights reserved.
 See LICENSE.txt for details.

  This software is distributed WITHOUT ANY WARRANTY; without even
  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  PURPOSE.

=========================================================================*/

#include <QtCore>
#include <QShortcut>

#include "medTabbedViewContainers.h"

#include "medViewContainer.h"
#include "medCustomViewContainer.h"
#include "medMultiViewContainer.h"
#include "medSingleViewContainer.h"

class medTabbedViewContainersPrivate
{
public:
    QHash<QString, medViewContainer*> containers;
    QString currentName;
    QShortcut *closeShortcut;

    QPushButton *addButton;
};

medTabbedViewContainers::medTabbedViewContainers(QWidget *parent) : QTabWidget(parent), d(new medTabbedViewContainersPrivate)
{
    this->setTabsClosable(true);
    this->setMovable(true);

    connect(this,SIGNAL(tabCloseRequested(int)),this,SLOT(deleteContainerClicked(int)));
    connect(this,SIGNAL(currentChanged(int)),this,SLOT(onCurrentContainerChanged(int)));

    d->addButton = new QPushButton(this);
    d->addButton->setStyleSheet("background-image: url(:medGui/pixmaps/plus_button.png);background-position: center;background-repeat: no-repeat;");
    d->addButton->setShortcut(Qt::ControlModifier + Qt::Key_T);
    this->setCornerWidget(d->addButton);

    connect(d->addButton,SIGNAL(clicked()),this,SIGNAL(addTabButtonClicked()));

    d->closeShortcut = new QShortcut(this);
    d->closeShortcut->setKey(Qt::ControlModifier + Qt::Key_W);
    connect(d->closeShortcut,SIGNAL(activated()),this,SLOT(deleteContainerShortcutActivated()));
}

medTabbedViewContainers::~medTabbedViewContainers(void)
{
    delete d;

    d = NULL;
}

void medTabbedViewContainers::lockTabs()
{
    this->setTabsClosable(false);
    this->setMovable(false);
    d->addButton->hide();
}

void medTabbedViewContainers::unlockTabs()
{
    this->setTabsClosable(true);
    this->setMovable(true);
    d->addButton->show();
}

/*
void medTabbedViewContainers::addNewTabContainer()
{
    // This slot should disappear, instead the creation signal should be sent to the parent who should call for the creation of a new tab
    QString name = "Tab ";
    name += QString::number(this->count());

    if (!this->container(name))
    {
        medViewContainer *new_container = new medMultiViewContainer();
        addContainer(name, new_container);
        this->setContainer(name);
    }
    else
        qDebug() << "Container" << name << "already exists in this workspaces";
}
*/

void medTabbedViewContainers::deleteContainerShortcutActivated()
{
    int index = this->currentIndex();
    this->deleteContainerClicked(index);
}

void medTabbedViewContainers::deleteContainerClicked(int index)
{
    if (this->count() == 1)
    {
        QString name = this->current()->identifier();

        medViewContainer *newTab = NULL;
        if (name == "Single")
            newTab = new medSingleViewContainer();
        else if (name == "Custom")
            newTab = new medCustomViewContainer();
        else if (name == "Multi")
            newTab = new medMultiViewContainer();

        if (newTab != NULL)
        {
            this->blockSignals(true);
            QString tabName = this->tabText(index);
            this->removeTab(index);
            this->insertContainer(index,tabName,newTab);
            this->setCurrentIndex(index);
            this->blockSignals(false);

            this->onCurrentContainerChanged(index);
        }
    }
    else
    {
        d->containers.remove(this->tabText(index));
        this->removeTab(index);
    }
}

void medTabbedViewContainers::addContainer(const QString &name, medViewContainer *container)
{
    if (!container)
        return;

    d->containers[name] = container;

    connect( container, SIGNAL( focused( dtkAbstractView * ) ),
             this,      SIGNAL( focused( dtkAbstractView * ) ) );
    connect( container, SIGNAL( imageSet( const medDataIndex & ) ),
             this,      SIGNAL( imageSet( const medDataIndex & ) ) );
    connect( container, SIGNAL( viewAdded( dtkAbstractView * ) ),
             this,      SIGNAL( viewAdded( dtkAbstractView * ) ) );
    connect( container, SIGNAL( viewRemoved( dtkAbstractView * ) ),
             this,      SIGNAL( viewRemoved( dtkAbstractView * ) ) );

    if (!this->count())
        d->currentName = name;

    this->addTab(container, name);
}

void medTabbedViewContainers::insertContainer(int index, const QString &name, medViewContainer *container)
{
    if (!container)
        return;

    d->containers[name] = container;

    connect( container, SIGNAL( focused( dtkAbstractView * ) ),
             this,      SIGNAL( focused( dtkAbstractView * ) ) );
    connect( container, SIGNAL( imageSet( const medDataIndex & ) ),
             this,      SIGNAL( imageSet( const medDataIndex & ) ) );

    connect( container, SIGNAL( viewAdded( dtkAbstractView * ) ),
             this,      SIGNAL( viewAdded( dtkAbstractView * ) ) );
    connect( container, SIGNAL( viewRemoved( dtkAbstractView * ) ),
             this,      SIGNAL( viewRemoved( dtkAbstractView * ) ) );

    if (!this->count())
        d->currentName = name;

    this->insertTab(index,container, name);
}

void medTabbedViewContainers::changeCurrentContainerName(const QString &name)
{
    unsigned int index = this->currentIndex();
    QString currentName = this->tabText(index);
    medViewContainer *currentContainer = d->containers[currentName];
    d->containers.remove(currentName);

    QString newName = name;
    if (this->container(newName))
    {
        unsigned int i = 1;
        newName = name + " ";
        newName += QString::number(i);
        while (this->container(newName))
        {
            ++i;
            newName = name + " ";
            newName += QString::number(i);
        }
    }

    this->setTabText(index,newName);
    d->containers[newName] = currentContainer;
}

void medTabbedViewContainers::changeCurrentContainerType(const QString &name)
{
    //qDebug() << "Changing container type to " << name << " from " << this->current()->identifier();
    //qDebug() << "Current index is " << this->currentIndex() << " and tab name " << this->tabText(this->currentIndex());

    if ((!this->current()->views().isEmpty()) && (name != this->current()->identifier()))
    {
        QMessageBox msgBox ( this );
        msgBox.setIcon ( QMessageBox::Warning );
        msgBox.setText(tr("Current tab is not empty. Changing tab type will delete current views."));
        msgBox.setInformativeText(tr("Are you sure you wish to change tab type?"));
        msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
        msgBox.setDefaultButton(QMessageBox::No);
        int reply = msgBox.exec();

        if( reply == QMessageBox::No )
        {
            this->onCurrentContainerChanged(this->currentIndex());
            return;
        }
    }

    if (name != this->current()->identifier())
    {
        medViewContainer *newTab = NULL;
        if (name == "Single")
            newTab = new medSingleViewContainer();
        else if (name == "Custom")
            newTab = new medCustomViewContainer();
        else if (name == "Multi")
            newTab = new medMultiViewContainer();

        if (newTab != NULL)
        {
            this->blockSignals(true);
            int index = this->currentIndex();
            QString tabName = this->tabText(index);
            this->removeTab(index);
            this->insertContainer(index,tabName,newTab);
            this->setCurrentIndex(index);
            this->blockSignals(false);

            this->onCurrentContainerChanged(index);
        }
    }
}

medViewContainer* medTabbedViewContainers::container(const QString &name) const
{
    if (!d->containers.contains(name))
        return NULL;

    return d->containers[name];
}

void medTabbedViewContainers::hideTabBar()
{
    QTabBar *tabBar = this->tabBar();
    tabBar->hide();
}

void medTabbedViewContainers::setContainer(const QString &name)
{
    if (!d->containers.contains(name))
    {
        qWarning()<<"container does not contain any container of name:" << name;
        return;
    }

    d->currentName = name;
    this->setCurrentWidget(d->containers[name]);
}

medViewContainer *medTabbedViewContainers::current(void) const
{
    return qobject_cast<medViewContainer*> (currentWidget());
}

QString medTabbedViewContainers::currentName(void) const
{
    return d->currentName;
}

QList<QString> medTabbedViewContainers::keys()
{
    return d->containers.keys();
}

void medTabbedViewContainers::removeContainer(const QString& name)
{
    if (d->containers.contains(name))
    {
        medViewContainer* container = d->containers[name];
        //removeWidget(container);
        container->deleteLater();
        d->containers.remove(name);

        this->blockSignals(true); // to prevent emission of currentChanged (int)
        this->removeTab( this->indexOf(container) );
        this->blockSignals(false);
    }
}

void medTabbedViewContainers::onCurrentContainerChanged(int index)
{
    QString name = this->tabText(index);

    emit currentChanged(name);
}
<commit_msg>Fix reset problems of view properties toolbox when changing tabs<commit_after>/*=========================================================================

 medInria

 Copyright (c) INRIA 2013. All rights reserved.
 See LICENSE.txt for details.

  This software is distributed WITHOUT ANY WARRANTY; without even
  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  PURPOSE.

=========================================================================*/

#include <QtCore>
#include <QShortcut>

#include "medTabbedViewContainers.h"

#include "medViewContainer.h"
#include "medCustomViewContainer.h"
#include "medMultiViewContainer.h"
#include "medSingleViewContainer.h"

class medTabbedViewContainersPrivate
{
public:
    QHash<QString, medViewContainer*> containers;
    QString currentName;
    QShortcut *closeShortcut;

    QPushButton *addButton;
};

medTabbedViewContainers::medTabbedViewContainers(QWidget *parent) : QTabWidget(parent), d(new medTabbedViewContainersPrivate)
{
    this->setTabsClosable(true);
    this->setMovable(true);

    connect(this,SIGNAL(tabCloseRequested(int)),this,SLOT(deleteContainerClicked(int)));
    connect(this,SIGNAL(currentChanged(int)),this,SLOT(onCurrentContainerChanged(int)));

    d->addButton = new QPushButton(this);
    d->addButton->setStyleSheet("background-image: url(:medGui/pixmaps/plus_button.png);background-position: center;background-repeat: no-repeat;");
    d->addButton->setShortcut(Qt::ControlModifier + Qt::Key_T);
    this->setCornerWidget(d->addButton);

    connect(d->addButton,SIGNAL(clicked()),this,SIGNAL(addTabButtonClicked()));

    d->closeShortcut = new QShortcut(this);
    d->closeShortcut->setKey(Qt::ControlModifier + Qt::Key_W);
    connect(d->closeShortcut,SIGNAL(activated()),this,SLOT(deleteContainerShortcutActivated()));
}

medTabbedViewContainers::~medTabbedViewContainers(void)
{
    delete d;

    d = NULL;
}

void medTabbedViewContainers::lockTabs()
{
    this->setTabsClosable(false);
    this->setMovable(false);
    d->addButton->hide();
}

void medTabbedViewContainers::unlockTabs()
{
    this->setTabsClosable(true);
    this->setMovable(true);
    d->addButton->show();
}

/*
void medTabbedViewContainers::addNewTabContainer()
{
    // This slot should disappear, instead the creation signal should be sent to the parent who should call for the creation of a new tab
    QString name = "Tab ";
    name += QString::number(this->count());

    if (!this->container(name))
    {
        medViewContainer *new_container = new medMultiViewContainer();
        addContainer(name, new_container);
        this->setContainer(name);
    }
    else
        qDebug() << "Container" << name << "already exists in this workspaces";
}
*/

void medTabbedViewContainers::deleteContainerShortcutActivated()
{
    int index = this->currentIndex();
    this->deleteContainerClicked(index);
}

void medTabbedViewContainers::deleteContainerClicked(int index)
{
    if (this->count() == 1)
    {
        QString name = this->current()->identifier();

        medViewContainer *newTab = NULL;
        if (name == "Single")
            newTab = new medSingleViewContainer();
        else if (name == "Custom")
            newTab = new medCustomViewContainer();
        else if (name == "Multi")
            newTab = new medMultiViewContainer();

        if (newTab != NULL)
        {
            this->blockSignals(true);
            QString tabName = this->tabText(index);
            this->removeTab(index);
            this->insertContainer(index,tabName,newTab);
            this->setCurrentIndex(index);
            this->blockSignals(false);

            this->onCurrentContainerChanged(index);
        }
    }
    else
    {
        d->containers.remove(this->tabText(index));
        this->removeTab(index);
    }
}

void medTabbedViewContainers::addContainer(const QString &name, medViewContainer *container)
{
    if (!container)
        return;

    d->containers[name] = container;

    connect( container, SIGNAL( focused( dtkAbstractView * ) ),
             this,      SIGNAL( focused( dtkAbstractView * ) ) );
    connect( container, SIGNAL( imageSet( const medDataIndex & ) ),
             this,      SIGNAL( imageSet( const medDataIndex & ) ) );
    connect( container, SIGNAL( viewAdded( dtkAbstractView * ) ),
             this,      SIGNAL( viewAdded( dtkAbstractView * ) ) );
    connect( container, SIGNAL( viewRemoved( dtkAbstractView * ) ),
             this,      SIGNAL( viewRemoved( dtkAbstractView * ) ) );

    if (!this->count())
        d->currentName = name;

    this->addTab(container, name);

    emit focused(NULL);
}

void medTabbedViewContainers::insertContainer(int index, const QString &name, medViewContainer *container)
{
    if (!container)
        return;

    d->containers[name] = container;

    connect( container, SIGNAL( focused( dtkAbstractView * ) ),
             this,      SIGNAL( focused( dtkAbstractView * ) ) );
    connect( container, SIGNAL( imageSet( const medDataIndex & ) ),
             this,      SIGNAL( imageSet( const medDataIndex & ) ) );

    connect( container, SIGNAL( viewAdded( dtkAbstractView * ) ),
             this,      SIGNAL( viewAdded( dtkAbstractView * ) ) );
    connect( container, SIGNAL( viewRemoved( dtkAbstractView * ) ),
             this,      SIGNAL( viewRemoved( dtkAbstractView * ) ) );

    if (!this->count())
        d->currentName = name;

    this->insertTab(index,container, name);
}

void medTabbedViewContainers::changeCurrentContainerName(const QString &name)
{
    unsigned int index = this->currentIndex();
    QString currentName = this->tabText(index);
    medViewContainer *currentContainer = d->containers[currentName];
    d->containers.remove(currentName);

    QString newName = name;
    if (this->container(newName))
    {
        unsigned int i = 1;
        newName = name + " ";
        newName += QString::number(i);
        while (this->container(newName))
        {
            ++i;
            newName = name + " ";
            newName += QString::number(i);
        }
    }

    this->setTabText(index,newName);
    d->containers[newName] = currentContainer;
}

void medTabbedViewContainers::changeCurrentContainerType(const QString &name)
{
    //qDebug() << "Changing container type to " << name << " from " << this->current()->identifier();
    //qDebug() << "Current index is " << this->currentIndex() << " and tab name " << this->tabText(this->currentIndex());

    if ((!this->current()->views().isEmpty()) && (name != this->current()->identifier()))
    {
        QMessageBox msgBox ( this );
        msgBox.setIcon ( QMessageBox::Warning );
        msgBox.setText(tr("Current tab is not empty. Changing tab type will delete current views."));
        msgBox.setInformativeText(tr("Are you sure you wish to change tab type?"));
        msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
        msgBox.setDefaultButton(QMessageBox::No);
        int reply = msgBox.exec();

        if( reply == QMessageBox::No )
        {
            this->onCurrentContainerChanged(this->currentIndex());
            return;
        }
    }

    if (name != this->current()->identifier())
    {
        medViewContainer *newTab = NULL;
        if (name == "Single")
            newTab = new medSingleViewContainer();
        else if (name == "Custom")
            newTab = new medCustomViewContainer();
        else if (name == "Multi")
            newTab = new medMultiViewContainer();

        if (newTab != NULL)
        {
            this->blockSignals(true);
            int index = this->currentIndex();
            QString tabName = this->tabText(index);
            this->removeTab(index);
            this->insertContainer(index,tabName,newTab);
            this->setCurrentIndex(index);
            this->blockSignals(false);

            this->onCurrentContainerChanged(index);
        }
    }
}

medViewContainer* medTabbedViewContainers::container(const QString &name) const
{
    if (!d->containers.contains(name))
        return NULL;

    return d->containers[name];
}

void medTabbedViewContainers::hideTabBar()
{
    QTabBar *tabBar = this->tabBar();
    tabBar->hide();
}

void medTabbedViewContainers::setContainer(const QString &name)
{
    if (!d->containers.contains(name))
    {
        qWarning()<<"container does not contain any container of name:" << name;
        return;
    }

    d->currentName = name;
    this->setCurrentWidget(d->containers[name]);
}

medViewContainer *medTabbedViewContainers::current(void) const
{
    return qobject_cast<medViewContainer*> (currentWidget());
}

QString medTabbedViewContainers::currentName(void) const
{
    return d->currentName;
}

QList<QString> medTabbedViewContainers::keys()
{
    return d->containers.keys();
}

void medTabbedViewContainers::removeContainer(const QString& name)
{
    if (d->containers.contains(name))
    {
        medViewContainer* container = d->containers[name];
        //removeWidget(container);
        container->deleteLater();
        d->containers.remove(name);

        this->blockSignals(true); // to prevent emission of currentChanged (int)
        this->removeTab( this->indexOf(container) );
        this->blockSignals(false);
    }
}

void medTabbedViewContainers::onCurrentContainerChanged(int index)
{
    QString name = this->tabText(index);

    emit focused(container(name)->current()->view());
    emit currentChanged(name);
}
<|endoftext|>


<commit_before>//////////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2004-2020 musikcube team
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
//    * Redistributions of source code must retain the above copyright notice,
//      this list of conditions and the following disclaimer.
//
//    * Redistributions in binary form must reproduce the above copyright
//      notice, this list of conditions and the following disclaimer in the
//      documentation and/or other materials provided with the distribution.
//
//    * Neither the name of the author nor the names of other contributors may
//      be used to endorse or promote products derived from this software
//      without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
//////////////////////////////////////////////////////////////////////////////

#include "pch.hpp"
#include "MessageQueue.h"

#include <algorithm>
#include <chrono>

using namespace std::chrono;
using namespace musik::core::runtime;

using LockT = std::unique_lock<std::mutex>;

MessageQueue::MessageQueue() {
    this->nextMessageTime.store(1);
}

void MessageQueue::WaitAndDispatch(int64_t timeoutMillis) {
    {
        LockT lock(this->queueMutex);

        if (this->queue.size()) {
            auto waitTime = duration_cast<milliseconds>(
                this->queue.front()->time -
                system_clock::now().time_since_epoch());

            if (timeoutMillis >= 0) {
                auto timeoutDuration = milliseconds(timeoutMillis);
                if (waitTime > timeoutDuration) {
                    waitTime = timeoutDuration;
                }
            }

            if (waitTime.count() > 0) {
                waitForDispatch.wait_for(lock, waitTime);
            }
       }
        else {
            if (timeoutMillis >= 0) {
                waitForDispatch.wait_for(lock, milliseconds(timeoutMillis));
            }
            else {
                waitForDispatch.wait(lock);
            }
        }
    }

    this->Dispatch();
}

MessageQueue::~MessageQueue() {

}

void MessageQueue::Dispatch() {
    milliseconds now = duration_cast<milliseconds>(
        system_clock::now().time_since_epoch());

    int64_t nextTime = nextMessageTime.load();

    if (nextTime > now.count() || nextTime < 0) {
        return; /* short circuit before any iteration. */
    }

    using Iterator = std::list<EnqueuedMessage*>::iterator;

    {
        LockT lock(this->queueMutex);

        this->nextMessageTime.store(-1);

        Iterator it = this->queue.begin();

        bool done = false;
        while (!done && it != this->queue.end()) {
            /* messages are time-ordered. pop and dispatch one at a time
            until we get to a message that should be delivered in the future,
            or the queue has been exhausted. */

            EnqueuedMessage *m = (*it);

            if (now >= m->time) {
                /* it's possible the target (receiver) has been unregistered;
                if that's the case, just discard it. otherwise, add it to the
                output set to be dispatched outside of the critical section */
                if (this->targets.find((*it)->message->Target()) != this->targets.end()) {
                    this->dispatch.push_back(m);
                }
                it = this->queue.erase(it);
            }
            else {
                done = true;
            }
        }
    }

    /* dispatch outside of the critical section */

    Iterator it = this->dispatch.begin();
    while (it != this->dispatch.end()) {
        this->Dispatch((*it)->message);
        delete *it;
        it++;
    }

    this->dispatch.clear();

    if (this->queue.size()) {
        this->nextMessageTime.store((*this->queue.begin())->time.count());
    }
}

void MessageQueue::Register(IMessageTarget* target) {
    LockT lock(this->queueMutex);
    this->targets.insert(target);
}

void MessageQueue::Unregister(IMessageTarget* target) {
    bool shouldRemove = false;
    {
        LockT lock(this->queueMutex);
        if (this->targets.find(target) != this->targets.end()) {
            this->targets.erase(target);
            shouldRemove = true;
        }
    }
    if (shouldRemove) {
        this->Remove(target);
    }
}

void MessageQueue::RegisterForBroadcasts(IMessageTargetPtr target) {
    LockT lock(this->queueMutex);
    this->receivers.insert(target);
}

void MessageQueue::UnregisterForBroadcasts(IMessageTarget *target) {
    LockT lock(this->queueMutex);
    for (auto it : this->receivers) {
        auto shared = it.lock();
        if (shared && shared.get() == target) {
            this->receivers.erase(it);
            return;
        }
    }
}

int MessageQueue::Remove(IMessageTarget *target, int type) {
    LockT lock(this->queueMutex);

    int count = 0;
    std::list<EnqueuedMessage*>::iterator it = this->queue.begin();
    while (it != this->queue.end()) {
        IMessagePtr current = (*it)->message;

        if (current->Target() == target) {
            if (type == -1 || type == current->Type()) {
                delete (*it);
                it = this->queue.erase(it);
                ++count;
                continue;
            }
        }

        ++it;
    }

    if (this->queue.size()) {
        this->nextMessageTime.store((*this->queue.begin())->time.count());
    }

    return count;
}

bool MessageQueue::Contains(IMessageTarget *target, int type) {
    LockT lock(this->queueMutex);

    std::list<EnqueuedMessage*>::iterator it = this->queue.begin();
    while (it != this->queue.end()) {
        IMessagePtr current = (*it)->message;

        if (current->Target() == target) {
            if (type == -1 || type == current->Type()) {
                return true;
            }
        }

        ++it;
    }
    return false;
}

void MessageQueue::Broadcast(IMessagePtr message, int64_t delayMs) {
    LockT lock(this->queueMutex);

    if (message->Target()) {
        throw new std::runtime_error("broadcasts cannot have a target!");
    }

    this->Enqueue(message, delayMs);
}

void MessageQueue::Post(IMessagePtr message, int64_t delayMs) {
    LockT lock(this->queueMutex);

    if (this->targets.find(message->Target()) == this->targets.end()) {
        return;
    }

    this->Enqueue(message, delayMs);
}

void MessageQueue::Enqueue(IMessagePtr message, int64_t delayMs) {
    delayMs = std::max((int64_t) 0, delayMs);

    milliseconds now = duration_cast<milliseconds>(
        system_clock::now().time_since_epoch());

    EnqueuedMessage *m = new EnqueuedMessage();
    m->message = message;
    m->time = now + milliseconds(delayMs);

    /* the queue is time ordered. start from the front of the queue, and
    work our way back until we find the correct place to insert the new one */

    typedef std::list<EnqueuedMessage*>::iterator Iterator;
    Iterator curr = this->queue.begin();

    while (curr != this->queue.end()) {
        if ((*curr)->time <= m->time) {
            curr++;
        }
        else {
            break;
        }
    }

    bool first = (curr == this->queue.begin());

    this->queue.insert(curr, m);

    if (this->queue.size()) {
        this->nextMessageTime.store((*this->queue.begin())->time.count());
    }

    if (first) {
        this->waitForDispatch.notify_all();
    }
}

void MessageQueue::Debounce(IMessagePtr message, int64_t delayMs) {
    Remove(message->Target(), message->Type());
    Post(message, delayMs);
}

void MessageQueue::Dispatch(IMessagePtr message) {
    if (message->Target()) {
        message->Target()->ProcessMessage(*message);
    }
    else {
        std::set<IWeakMessageTarget, WeakPtrLess> copy;

        /* copy to dispatch outside of a lock */
        {
            LockT lock(this->queueMutex);
            std::copy(
                receivers.begin(),
                receivers.end(),
                std::inserter(copy, copy.begin()));
        }

        /* dispatch */
        bool prune = false;
        for (auto receiver : copy) {
            auto shared = receiver.lock();
            if (shared) {
                shared->ProcessMessage(*message);
            }
            else {
                prune = true;
            }
        }

        if (prune) { /* at least one of our weak_ptrs is dead. */
            LockT lock(this->queueMutex);
            auto it = this->receivers.begin();
            while (it != this->receivers.end()) {
                if (it->expired()) {
                    it = this->receivers.erase(it);
                }
                else {
                    ++it;
                }
            }
        }
    }
}
<commit_msg>Fixed MessageQueue broadcast dispatching<commit_after>//////////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2004-2020 musikcube team
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
//    * Redistributions of source code must retain the above copyright notice,
//      this list of conditions and the following disclaimer.
//
//    * Redistributions in binary form must reproduce the above copyright
//      notice, this list of conditions and the following disclaimer in the
//      documentation and/or other materials provided with the distribution.
//
//    * Neither the name of the author nor the names of other contributors may
//      be used to endorse or promote products derived from this software
//      without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
//////////////////////////////////////////////////////////////////////////////

#include "pch.hpp"
#include "MessageQueue.h"

#include <algorithm>
#include <chrono>

using namespace std::chrono;
using namespace musik::core::runtime;

using LockT = std::unique_lock<std::mutex>;

MessageQueue::MessageQueue() {
    this->nextMessageTime.store(1);
}

void MessageQueue::WaitAndDispatch(int64_t timeoutMillis) {
    {
        LockT lock(this->queueMutex);

        if (this->queue.size()) {
            auto waitTime = duration_cast<milliseconds>(
                this->queue.front()->time -
                system_clock::now().time_since_epoch());

            if (timeoutMillis >= 0) {
                auto timeoutDuration = milliseconds(timeoutMillis);
                if (waitTime > timeoutDuration) {
                    waitTime = timeoutDuration;
                }
            }

            if (waitTime.count() > 0) {
                waitForDispatch.wait_for(lock, waitTime);
            }
       }
        else {
            if (timeoutMillis >= 0) {
                waitForDispatch.wait_for(lock, milliseconds(timeoutMillis));
            }
            else {
                waitForDispatch.wait(lock);
            }
        }
    }

    this->Dispatch();
}

MessageQueue::~MessageQueue() {

}

void MessageQueue::Dispatch() {
    milliseconds now = duration_cast<milliseconds>(
        system_clock::now().time_since_epoch());

    int64_t nextTime = nextMessageTime.load();

    if (nextTime > now.count() || nextTime < 0) {
        return; /* short circuit before any iteration. */
    }

    using Iterator = std::list<EnqueuedMessage*>::iterator;

    {
        LockT lock(this->queueMutex);

        this->nextMessageTime.store(-1);

        Iterator it = this->queue.begin();

        bool done = false;
        while (!done && it != this->queue.end()) {
            /* messages are time-ordered. pop and dispatch one at a time
            until we get to a message that should be delivered in the future,
            or the queue has been exhausted. */

            EnqueuedMessage *m = (*it);

            if (now >= m->time) {
                /* it's possible the target (receiver) has been unregistered;
                if that's the case, just discard it. otherwise, add it to the
                output set to be dispatched outside of the critical section */
                auto const target = (*it)->message->Target();
                if (target == nullptr || this->targets.find(target) != this->targets.end()) {
                    this->dispatch.push_back(m);
                }
                it = this->queue.erase(it);
            }
            else {
                done = true;
            }
        }
    }

    /* dispatch outside of the critical section */

    Iterator it = this->dispatch.begin();
    while (it != this->dispatch.end()) {
        this->Dispatch((*it)->message);
        delete *it;
        it++;
    }

    this->dispatch.clear();

    if (this->queue.size()) {
        this->nextMessageTime.store((*this->queue.begin())->time.count());
    }
}

void MessageQueue::Register(IMessageTarget* target) {
    LockT lock(this->queueMutex);
    this->targets.insert(target);
}

void MessageQueue::Unregister(IMessageTarget* target) {
    bool shouldRemove = false;
    {
        LockT lock(this->queueMutex);
        if (this->targets.find(target) != this->targets.end()) {
            this->targets.erase(target);
            shouldRemove = true;
        }
    }
    if (shouldRemove) {
        this->Remove(target);
    }
}

void MessageQueue::RegisterForBroadcasts(IMessageTargetPtr target) {
    LockT lock(this->queueMutex);
    this->receivers.insert(target);
}

void MessageQueue::UnregisterForBroadcasts(IMessageTarget *target) {
    LockT lock(this->queueMutex);
    for (auto it : this->receivers) {
        auto shared = it.lock();
        if (shared && shared.get() == target) {
            this->receivers.erase(it);
            return;
        }
    }
}

int MessageQueue::Remove(IMessageTarget *target, int type) {
    LockT lock(this->queueMutex);

    int count = 0;
    std::list<EnqueuedMessage*>::iterator it = this->queue.begin();
    while (it != this->queue.end()) {
        IMessagePtr current = (*it)->message;

        if (current->Target() == target) {
            if (type == -1 || type == current->Type()) {
                delete (*it);
                it = this->queue.erase(it);
                ++count;
                continue;
            }
        }

        ++it;
    }

    if (this->queue.size()) {
        this->nextMessageTime.store((*this->queue.begin())->time.count());
    }

    return count;
}

bool MessageQueue::Contains(IMessageTarget *target, int type) {
    LockT lock(this->queueMutex);

    std::list<EnqueuedMessage*>::iterator it = this->queue.begin();
    while (it != this->queue.end()) {
        IMessagePtr current = (*it)->message;

        if (current->Target() == target) {
            if (type == -1 || type == current->Type()) {
                return true;
            }
        }

        ++it;
    }
    return false;
}

void MessageQueue::Broadcast(IMessagePtr message, int64_t delayMs) {
    LockT lock(this->queueMutex);

    if (message->Target()) {
        throw new std::runtime_error("broadcasts cannot have a target!");
    }

    this->Enqueue(message, delayMs);
}

void MessageQueue::Post(IMessagePtr message, int64_t delayMs) {
    LockT lock(this->queueMutex);

    if (this->targets.find(message->Target()) == this->targets.end()) {
        return;
    }

    this->Enqueue(message, delayMs);
}

void MessageQueue::Enqueue(IMessagePtr message, int64_t delayMs) {
    delayMs = std::max((int64_t) 0, delayMs);

    milliseconds now = duration_cast<milliseconds>(
        system_clock::now().time_since_epoch());

    EnqueuedMessage *m = new EnqueuedMessage();
    m->message = message;
    m->time = now + milliseconds(delayMs);

    /* the queue is time ordered. start from the front of the queue, and
    work our way back until we find the correct place to insert the new one */

    typedef std::list<EnqueuedMessage*>::iterator Iterator;
    Iterator curr = this->queue.begin();

    while (curr != this->queue.end()) {
        if ((*curr)->time <= m->time) {
            curr++;
        }
        else {
            break;
        }
    }

    bool first = (curr == this->queue.begin());

    this->queue.insert(curr, m);

    if (this->queue.size()) {
        this->nextMessageTime.store((*this->queue.begin())->time.count());
    }

    if (first) {
        this->waitForDispatch.notify_all();
    }
}

void MessageQueue::Debounce(IMessagePtr message, int64_t delayMs) {
    Remove(message->Target(), message->Type());
    Post(message, delayMs);
}

void MessageQueue::Dispatch(IMessagePtr message) {
    if (message->Target()) {
        message->Target()->ProcessMessage(*message);
    }
    else {
        std::set<IWeakMessageTarget, WeakPtrLess> copy;

        /* copy to dispatch outside of a lock */
        {
            LockT lock(this->queueMutex);
            std::copy(
                receivers.begin(),
                receivers.end(),
                std::inserter(copy, copy.begin()));
        }

        /* dispatch */
        bool prune = false;
        for (auto receiver : copy) {
            auto shared = receiver.lock();
            if (shared) {
                shared->ProcessMessage(*message);
            }
            else {
                prune = true;
            }
        }

        if (prune) { /* at least one of our weak_ptrs is dead. */
            LockT lock(this->queueMutex);
            auto it = this->receivers.begin();
            while (it != this->receivers.end()) {
                if (it->expired()) {
                    it = this->receivers.erase(it);
                }
                else {
                    ++it;
                }
            }
        }
    }
}
<|endoftext|>


<commit_before>/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
 *
 * This application is open source and may be redistributed and/or modified
 * freely and without restriction, both in commercial and non commercial
 * applications, as long as this copyright notice is maintained.
 *
 * This application is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 *
*/

#include <sstream>
#include <memory>

#include <osg/Notify>
#include <osg/NodeVisitor>
#include <osgDB/ReaderWriter>
#include <osgDB/FileNameUtils>
#include <osgDB/Registry>
#include <osgDB/ConvertUTF>

#include <OpenThreads/ScopedLock>

#include "ReaderWriterDAE.h"
#include "daeReader.h"
#include "daeWriter.h"

#ifdef WIN32
#include "windows.h"
#endif

#define SERIALIZER() OpenThreads::ScopedLock<OpenThreads::ReentrantMutex> lock(_serializerMutex)

#if  __cplusplus > 199711L
    #define smart_ptr std::unique_ptr
#else
    #define smart_ptr std::auto_ptr
#endif

osgDB::ReaderWriter::ReadResult
ReaderWriterDAE::readNode(std::istream& fin,
        const osgDB::ReaderWriter::Options* options) const
{
    SERIALIZER();

    bool bOwnDAE = false;
    DAE* pDAE = NULL;

    // Process options
    osgDAE::daeReader::Options pluginOptions;
    if( options )
    {
        pDAE = (DAE*)options->getPluginData("DAE");

        pluginOptions.precisionHint = options->getPrecisionHint();

        std::istringstream iss( options->getOptionString() );
        std::string opt;
        while (iss >> opt)
        {
            if( opt == "StrictTransparency") pluginOptions.strictTransparency = true;
            else if (opt == "daeTessellateNone") pluginOptions.tessellateMode = osgDAE::daeReader::TESSELLATE_NONE;
            else if (opt == "daeTessellatePolygonsAsTriFans") pluginOptions.tessellateMode = osgDAE::daeReader::TESSELLATE_POLYGONS_AS_TRIFAN;
            else if (opt == "daeTessellatePolygons") pluginOptions.tessellateMode = osgDAE::daeReader::TESSELLATE_POLYGONS;
            else if (opt == "daeUsePredefinedTextureUnits") pluginOptions.usePredefinedTextureUnits = true;
            else if (opt == "daeUseSequencedTextureUnits") pluginOptions.usePredefinedTextureUnits = false;
        }
    }

    if (NULL == pDAE)
    {
        bOwnDAE = true;
#ifdef COLLADA_DOM_2_4_OR_LATER
        pDAE = new DAE(NULL,NULL,_specversion);
#else
        pDAE = new DAE;
#endif
    }

    smart_ptr<DAE> scopedDae(bOwnDAE ? pDAE : NULL);        // Deallocates locally created structure at scope exit

    osgDAE::daeReader daeReader(pDAE, &pluginOptions);

    if ( ! daeReader.convert( fin ) )
    {
        OSG_WARN << "Load failed in COLLADA DOM conversion" << std::endl;
        return ReadResult::ERROR_IN_READING_FILE;
    }

    if ( options )
    {
        // Return the document URI
        if (options->getPluginData("DAE-DocumentURI"))
            *(std::string*)options->getPluginData("DAE-DocumentURI") = std::string("/dev/null");
        // Return some additional information about the document
        if (options->getPluginData("DAE-AssetUnitName"))
             *(std::string*)options->getPluginData("DAE-AssetUnitName") = daeReader.getAssetUnitName();
        if (options->getPluginData("DAE-AssetUnitMeter"))
            *(float*)options->getPluginData("DAE-AssetUnitMeter") = daeReader.getAssetUnitMeter();
        if (options->getPluginData("DAE-AssetUp_axis"))
            *(domUpAxisType*)options->getPluginData("DAE-AssetUp_axis") = daeReader.getAssetUpAxis();
    }

    osg::Node* rootNode( daeReader.getRootNode() );
    return rootNode;
}

osgDB::ReaderWriter::ReadResult
ReaderWriterDAE::readNode(const std::string& fname,
        const osgDB::ReaderWriter::Options* options) const
{
    SERIALIZER();

    bool bOwnDAE = false;
    DAE* pDAE = NULL;

    // Process options
    osgDAE::daeReader::Options pluginOptions;
    if( options )
    {
        pDAE = (DAE*)options->getPluginData("DAE");

        pluginOptions.precisionHint = options->getPrecisionHint();

        std::istringstream iss( options->getOptionString() );
        std::string opt;
        while (iss >> opt)
        {
            if( opt == "StrictTransparency") pluginOptions.strictTransparency = true;
            else if (opt == "daeTessellateNone")              pluginOptions.tessellateMode = osgDAE::daeReader::TESSELLATE_NONE;
            else if (opt == "daeTessellatePolygonsAsTriFans") pluginOptions.tessellateMode = osgDAE::daeReader::TESSELLATE_POLYGONS_AS_TRIFAN;
            else if (opt == "daeTessellatePolygons")          pluginOptions.tessellateMode = osgDAE::daeReader::TESSELLATE_POLYGONS;
            else if (opt == "daeUsePredefinedTextureUnits") pluginOptions.usePredefinedTextureUnits = true;
            else if (opt == "daeUseSequencedTextureUnits")  pluginOptions.usePredefinedTextureUnits = false;
        }
    }

    std::string ext( osgDB::getLowerCaseFileExtension(fname) );
    if( ! acceptsExtension(ext) ) return ReadResult::FILE_NOT_HANDLED;

    std::string fileName( osgDB::findDataFile( fname, options ) );
    if( fileName.empty() ) return ReadResult::FILE_NOT_FOUND;

    OSG_INFO << "ReaderWriterDAE( \"" << fileName << "\" )" << std::endl;

    if (NULL == pDAE)
    {
        bOwnDAE = true;
#ifdef COLLADA_DOM_2_4_OR_LATER
        pDAE = new DAE(NULL,NULL,_specversion);
#else
        pDAE = new DAE;
#endif
    }

    smart_ptr<DAE> scopedDae(bOwnDAE ? pDAE : NULL);        // Deallocates locally created structure at scope exit

    osgDAE::daeReader daeReader(pDAE, &pluginOptions);

    // Convert file name to URI
    std::string fileURI = ConvertFilePathToColladaCompatibleURI(fileName);

    if ( ! daeReader.convert( fileURI ) )
    {
        OSG_WARN << "Load failed in COLLADA DOM conversion" << std::endl;
        return ReadResult::ERROR_IN_READING_FILE;
    }

    if ( options )
    {
        // Return the document URI
        if (options->getPluginData("DAE-DocumentURI"))
            *(std::string*)options->getPluginData("DAE-DocumentURI") = fileURI;
        // Return some additional information about the document
        if (options->getPluginData("DAE-AssetUnitName"))
             *(std::string*)options->getPluginData("DAE-AssetUnitName") = daeReader.getAssetUnitName();
        if (options->getPluginData("DAE-AssetUnitMeter"))
            *(float*)options->getPluginData("DAE-AssetUnitMeter") = daeReader.getAssetUnitMeter();
        if (options->getPluginData("DAE-AssetUp_axis"))
            *(domUpAxisType*)options->getPluginData("DAE-AssetUp_axis") = daeReader.getAssetUpAxis();
    }

    osg::Node* rootNode( daeReader.getRootNode() );
    return rootNode;
}

///////////////////////////////////////////////////////////////////////////

osgDB::ReaderWriter::WriteResult
ReaderWriterDAE::writeNode( const osg::Node& node,
        const std::string& fname, const osgDB::ReaderWriter::Options* options ) const
{
    SERIALIZER();

    bool bOwnDAE = false;
    DAE* pDAE = NULL;

    std::string ext( osgDB::getLowerCaseFileExtension(fname) );
    if( ! acceptsExtension(ext) ) return WriteResult::FILE_NOT_HANDLED;

    // Process options
    osgDAE::daeWriter::Options pluginOptions;
    std::string srcDirectory( osgDB::getFilePath(node.getName().empty() ? fname : node.getName()) );        // Base dir when relativising images paths
    if( options )
    {
        pDAE = (DAE*)options->getPluginData("DAE");

        const std::string & baseDir = options->getPluginStringData("baseImageDir");        // Rename "srcModelPath" (and call getFilePath() on it)?
        if (!baseDir.empty()) srcDirectory = baseDir;

        const std::string & relativiseImagesPathNbUpDirs = options->getPluginStringData("DAE-relativiseImagesPathNbUpDirs");
        if (!relativiseImagesPathNbUpDirs.empty()) {
            std::istringstream iss(relativiseImagesPathNbUpDirs);
            iss >> pluginOptions.relativiseImagesPathNbUpDirs;
        }

        // Sukender's note: I don't know why DAE seems to accept comma-sparated options instead of space-separated options as other ReaderWriters. However, to avoid breaking compatibility, here's a workaround:
        std::string optString( options->getOptionString() );
        for(std::string::iterator it=optString.begin(); it!=optString.end(); ++it) {
            if (*it == ' ') *it = ',';
        }
        std::istringstream iss( optString );
        std::string opt;

        //while (iss >> opt)
        while( std::getline( iss, opt, ',' ) )
        {
            if( opt == "polygon") pluginOptions.usePolygons = true;
            else if (opt == "GoogleMode") pluginOptions.googleMode = true;
            else if (opt == "NoExtras") pluginOptions.writeExtras = false;
            else if (opt == "daeEarthTex") pluginOptions.earthTex = true;
            else if (opt == "daeZUpAxis") {}    // Nothing (old option)
            else if (opt == "daeLinkOriginalTexturesNoForce") { pluginOptions.linkOrignialTextures = true; pluginOptions.forceTexture = false; }
            else if (opt == "daeLinkOriginalTexturesForce")   { pluginOptions.linkOrignialTextures = true; pluginOptions.forceTexture = true; }
            else if (opt == "daeNamesUseCodepage") pluginOptions.namesUseCodepage = true;
            else if (opt == "daeRenameIds") pluginOptions.renameIds = true;
            else if (!opt.empty())
            {
                OSG_NOTICE << std::endl << "COLLADA dae plugin: unrecognized option \"" << opt <<  std::endl;
            }
        }
    }

    if (NULL == pDAE)
    {
        bOwnDAE = true;
#ifdef COLLADA_DOM_2_4_OR_LATER
        pDAE = new DAE(NULL,NULL,_specversion);
#else
        pDAE = new DAE;
#endif
    }
    smart_ptr<DAE> scopedDae(bOwnDAE ? pDAE : NULL);        // Deallocates locally created structure at scope exit

    // Convert file name to URI
    std::string fileURI = ConvertFilePathToColladaCompatibleURI(fname);

    osg::NodeVisitor::TraversalMode traversalMode = pluginOptions.writeExtras ? osg::NodeVisitor::TRAVERSE_ALL_CHILDREN : osg::NodeVisitor::TRAVERSE_ACTIVE_CHILDREN;

    osgDAE::daeWriter daeWriter(pDAE, fileURI, osgDB::getFilePath(fname), srcDirectory, options, traversalMode, &pluginOptions);
    daeWriter.setRootNode( node );
    const_cast<osg::Node*>(&node)->accept( daeWriter );

    osgDB::ReaderWriter::WriteResult retVal( WriteResult::ERROR_IN_WRITING_FILE );
    if ( daeWriter.isSuccess() )
    {
        if (pDAE->write(fileURI))
            retVal = WriteResult::FILE_SAVED;
    }

    if ( options )
    {
        if (!bOwnDAE)
        {
            // Return the document URI used so that users of an external DAE object
            // can locate the correct database
            if (options->getPluginData("DAE-DocumentURI"))
                *(std::string*)options->getPluginData("DAE-DocumentURI") = fileURI;
        }
    }

    return retVal;
}

static void replace(std::string & str, const char from, const std::string & to)
{
    // Replace for all occurrences
    for(std::string::size_type pos=str.find(from); pos!=std::string::npos; pos=str.find(from))
    {
        str.replace(pos, 1, to);
    }
}

static void replace(std::string & str, const std::string & from, const std::string & to)
{
    // Replace for all occurrences
    std::size_t lenFrom = from.size();
    std::size_t lenTo = to.size();
    for(std::string::size_type pos=str.find(from); pos!=std::string::npos; pos = str.find(from, pos+lenTo))
    {
        str.replace(pos, lenFrom, to);
    }
}

std::string ReaderWriterDAE::ConvertFilePathToColladaCompatibleURI(const std::string& FilePath)
{
#ifdef OSG_USE_UTF8_FILENAME
    std::string path( cdom::nativePathToUri( FilePath ) );
#else
    std::string path( cdom::nativePathToUri( osgDB::convertStringFromCurrentCodePageToUTF8(FilePath) ) );
#endif

    // Unfortunately, cdom::nativePathToUri() does not convert '#' characters to "%23" as expected.
    // So having /a/#b/c will generate a wrong conversion, as '#' will be misinterpreted as an URI fragment.
    // Here are listed all special chars, but only # was found problematic. I (Sukender) tested #{}^~[]`;@=&$ under Windows.
    // Uncomment lines if you find issues with some other special characters.

    //replace(path, '%', "%25");        // % at first
    //replace(path, ' ', "%20");
    replace(path, '#', "%23");
    //replace(path, '<', "%3C");
    //replace(path, '>', "%3E");
    //replace(path, '{', "%7B");
    //replace(path, '}', "%7D");
    //replace(path, '|', "%7C");
    //replace(path, '^', "%5E");
    //replace(path, '~', "%7E");
    //replace(path, '[', "%5B");
    //replace(path, '}', "%5D");
    //replace(path, '`', "%60");
    //replace(path, ';', "%3B");
    //replace(path, '?', "%3F");
    //replace(path, '@', "%40");
    //replace(path, '=', "%3D");
    //replace(path, '&', "%26");
    //replace(path, '$', "%24");
    return path;
}

std::string ReaderWriterDAE::ConvertColladaCompatibleURIToFilePath(const std::string& uri)
{
    // Reciprocal of ConvertFilePathToColladaCompatibleURI()
#ifdef OSG_USE_UTF8_FILENAME
    std::string path( cdom::uriToNativePath( uri ) );
#else
    std::string path( osgDB::convertStringFromCurrentCodePageToUTF8( cdom::uriToNativePath(uri) ) );
#endif
    replace(path, "%23", "#");
    return path;
}

///////////////////////////////////////////////////////////////////////////
// Add ourself to the Registry to instantiate the reader/writer.

REGISTER_OSGPLUGIN(dae, ReaderWriterDAE)

// vim: set sw=4 ts=8 et ic ai:
<commit_msg>Update ReaderWriterDAE.cpp<commit_after>/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
 *
 * This application is open source and may be redistributed and/or modified
 * freely and without restriction, both in commercial and non commercial
 * applications, as long as this copyright notice is maintained.
 *
 * This application is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 *
*/

#include <sstream>
#include <memory>

#include <osg/Notify>
#include <osg/NodeVisitor>
#include <osgDB/ReaderWriter>
#include <osgDB/FileNameUtils>
#include <osgDB/Registry>
#include <osgDB/ConvertUTF>

#include <OpenThreads/ScopedLock>

#include "ReaderWriterDAE.h"
#include "daeReader.h"
#include "daeWriter.h"

#ifdef WIN32
#include "windows.h"
#endif

#define SERIALIZER() OpenThreads::ScopedLock<OpenThreads::ReentrantMutex> lock(_serializerMutex)

#if  __cplusplus > 199711L
    #define smart_ptr std::unique_ptr
#else
    #define smart_ptr std::auto_ptr
#endif

osgDB::ReaderWriter::ReadResult
ReaderWriterDAE::readNode(std::istream& fin,
        const osgDB::ReaderWriter::Options* options) const
{
    SERIALIZER();

    bool bOwnDAE = false;
    DAE* pDAE = NULL;

    // Process options
    osgDAE::daeReader::Options pluginOptions;
    if( options )
    {
        pDAE = (DAE*)options->getPluginData("DAE");

        pluginOptions.precisionHint = options->getPrecisionHint();

        std::istringstream iss( options->getOptionString() );
        std::string opt;
        while (iss >> opt)
        {
            if( opt == "StrictTransparency") pluginOptions.strictTransparency = true;
            else if (opt == "daeTessellateNone") pluginOptions.tessellateMode = osgDAE::daeReader::TESSELLATE_NONE;
            else if (opt == "daeTessellatePolygonsAsTriFans") pluginOptions.tessellateMode = osgDAE::daeReader::TESSELLATE_POLYGONS_AS_TRIFAN;
            else if (opt == "daeTessellatePolygons") pluginOptions.tessellateMode = osgDAE::daeReader::TESSELLATE_POLYGONS;
            else if (opt == "daeUsePredefinedTextureUnits") pluginOptions.usePredefinedTextureUnits = true;
            else if (opt == "daeUseSequencedTextureUnits") pluginOptions.usePredefinedTextureUnits = false;
        }
    }

    if (NULL == pDAE)
    {
        bOwnDAE = true;
#ifdef COLLADA_DOM_2_4_OR_LATER
        pDAE = new DAE(NULL,NULL,_specversion);
#else
        pDAE = new DAE;
#endif
    }

    smart_ptr<DAE> scopedDae(bOwnDAE ? pDAE : NULL);        // Deallocates locally created structure at scope exit

    osgDAE::daeReader daeReader(pDAE, &pluginOptions);

    if ( ! daeReader.convert( fin ) )
    {
        OSG_WARN << "Load failed in COLLADA DOM conversion" << std::endl;
        return ReadResult::ERROR_IN_READING_FILE;
    }

    if ( options )
    {
        // Return the document URI
        if (options->getPluginData("DAE-DocumentURI"))
            *(std::string*)options->getPluginData("DAE-DocumentURI") = std::string("/dev/null");
        // Return some additional information about the document
        if (options->getPluginData("DAE-AssetUnitName"))
             *(std::string*)options->getPluginData("DAE-AssetUnitName") = daeReader.getAssetUnitName();
        if (options->getPluginData("DAE-AssetUnitMeter"))
            *(float*)options->getPluginData("DAE-AssetUnitMeter") = daeReader.getAssetUnitMeter();
        if (options->getPluginData("DAE-AssetUp_axis"))
            *(domUpAxisType*)options->getPluginData("DAE-AssetUp_axis") = daeReader.getAssetUpAxis();
    }

    osg::Node* rootNode( daeReader.getRootNode() );
    return rootNode;
}

osgDB::ReaderWriter::ReadResult
ReaderWriterDAE::readNode(const std::string& fname,
        const osgDB::ReaderWriter::Options* options) const
{
    SERIALIZER();

    bool bOwnDAE = false;
    DAE* pDAE = NULL;

    // Process options
    osgDAE::daeReader::Options pluginOptions;
    if( options )
    {
        pDAE = (DAE*)options->getPluginData("DAE");

        pluginOptions.precisionHint = options->getPrecisionHint();

        std::istringstream iss( options->getOptionString() );
        std::string opt;
        while (iss >> opt)
        {
            if( opt == "StrictTransparency") pluginOptions.strictTransparency = true;
            else if (opt == "daeTessellateNone")              pluginOptions.tessellateMode = osgDAE::daeReader::TESSELLATE_NONE;
            else if (opt == "daeTessellatePolygonsAsTriFans") pluginOptions.tessellateMode = osgDAE::daeReader::TESSELLATE_POLYGONS_AS_TRIFAN;
            else if (opt == "daeTessellatePolygons")          pluginOptions.tessellateMode = osgDAE::daeReader::TESSELLATE_POLYGONS;
            else if (opt == "daeUsePredefinedTextureUnits") pluginOptions.usePredefinedTextureUnits = true;
            else if (opt == "daeUseSequencedTextureUnits")  pluginOptions.usePredefinedTextureUnits = false;
        }
    }

    std::string ext( osgDB::getLowerCaseFileExtension(fname) );
    if( ! acceptsExtension(ext) ) return ReadResult::FILE_NOT_HANDLED;

    std::string fileName( osgDB::findDataFile( fname, options ) );
    if( fileName.empty() ) return ReadResult::FILE_NOT_FOUND;

    pluginOptions.options = options ? static_cast<Options*>(options->clone(osg::CopyOp::SHALLOW_COPY)) : new Options;
    pluginOptions.options->getDatabasePathList().push_front(osgDB::getFilePath(fileName));

    OSG_INFO << "ReaderWriterDAE( \"" << fileName << "\" )" << std::endl;

    if (NULL == pDAE)
    {
        bOwnDAE = true;
#ifdef COLLADA_DOM_2_4_OR_LATER
        pDAE = new DAE(NULL,NULL,_specversion);
#else
        pDAE = new DAE;
#endif
    }

    smart_ptr<DAE> scopedDae(bOwnDAE ? pDAE : NULL);        // Deallocates locally created structure at scope exit

    osgDAE::daeReader daeReader(pDAE, &pluginOptions);

    // Convert file name to URI
    std::string fileURI = ConvertFilePathToColladaCompatibleURI(fileName);

    if ( ! daeReader.convert( fileURI ) )
    {
        OSG_WARN << "Load failed in COLLADA DOM conversion" << std::endl;
        return ReadResult::ERROR_IN_READING_FILE;
    }

    if ( options )
    {
        // Return the document URI
        if (options->getPluginData("DAE-DocumentURI"))
            *(std::string*)options->getPluginData("DAE-DocumentURI") = fileURI;
        // Return some additional information about the document
        if (options->getPluginData("DAE-AssetUnitName"))
             *(std::string*)options->getPluginData("DAE-AssetUnitName") = daeReader.getAssetUnitName();
        if (options->getPluginData("DAE-AssetUnitMeter"))
            *(float*)options->getPluginData("DAE-AssetUnitMeter") = daeReader.getAssetUnitMeter();
        if (options->getPluginData("DAE-AssetUp_axis"))
            *(domUpAxisType*)options->getPluginData("DAE-AssetUp_axis") = daeReader.getAssetUpAxis();
    }

    osg::Node* rootNode( daeReader.getRootNode() );
    return rootNode;
}

///////////////////////////////////////////////////////////////////////////

osgDB::ReaderWriter::WriteResult
ReaderWriterDAE::writeNode( const osg::Node& node,
        const std::string& fname, const osgDB::ReaderWriter::Options* options ) const
{
    SERIALIZER();

    bool bOwnDAE = false;
    DAE* pDAE = NULL;

    std::string ext( osgDB::getLowerCaseFileExtension(fname) );
    if( ! acceptsExtension(ext) ) return WriteResult::FILE_NOT_HANDLED;

    // Process options
    osgDAE::daeWriter::Options pluginOptions;
    std::string srcDirectory( osgDB::getFilePath(node.getName().empty() ? fname : node.getName()) );        // Base dir when relativising images paths
    if( options )
    {
        pDAE = (DAE*)options->getPluginData("DAE");

        const std::string & baseDir = options->getPluginStringData("baseImageDir");        // Rename "srcModelPath" (and call getFilePath() on it)?
        if (!baseDir.empty()) srcDirectory = baseDir;

        const std::string & relativiseImagesPathNbUpDirs = options->getPluginStringData("DAE-relativiseImagesPathNbUpDirs");
        if (!relativiseImagesPathNbUpDirs.empty()) {
            std::istringstream iss(relativiseImagesPathNbUpDirs);
            iss >> pluginOptions.relativiseImagesPathNbUpDirs;
        }

        // Sukender's note: I don't know why DAE seems to accept comma-sparated options instead of space-separated options as other ReaderWriters. However, to avoid breaking compatibility, here's a workaround:
        std::string optString( options->getOptionString() );
        for(std::string::iterator it=optString.begin(); it!=optString.end(); ++it) {
            if (*it == ' ') *it = ',';
        }
        std::istringstream iss( optString );
        std::string opt;

        //while (iss >> opt)
        while( std::getline( iss, opt, ',' ) )
        {
            if( opt == "polygon") pluginOptions.usePolygons = true;
            else if (opt == "GoogleMode") pluginOptions.googleMode = true;
            else if (opt == "NoExtras") pluginOptions.writeExtras = false;
            else if (opt == "daeEarthTex") pluginOptions.earthTex = true;
            else if (opt == "daeZUpAxis") {}    // Nothing (old option)
            else if (opt == "daeLinkOriginalTexturesNoForce") { pluginOptions.linkOrignialTextures = true; pluginOptions.forceTexture = false; }
            else if (opt == "daeLinkOriginalTexturesForce")   { pluginOptions.linkOrignialTextures = true; pluginOptions.forceTexture = true; }
            else if (opt == "daeNamesUseCodepage") pluginOptions.namesUseCodepage = true;
            else if (opt == "daeRenameIds") pluginOptions.renameIds = true;
            else if (!opt.empty())
            {
                OSG_NOTICE << std::endl << "COLLADA dae plugin: unrecognized option \"" << opt <<  std::endl;
            }
        }
    }

    if (NULL == pDAE)
    {
        bOwnDAE = true;
#ifdef COLLADA_DOM_2_4_OR_LATER
        pDAE = new DAE(NULL,NULL,_specversion);
#else
        pDAE = new DAE;
#endif
    }
    smart_ptr<DAE> scopedDae(bOwnDAE ? pDAE : NULL);        // Deallocates locally created structure at scope exit

    // Convert file name to URI
    std::string fileURI = ConvertFilePathToColladaCompatibleURI(fname);

    osg::NodeVisitor::TraversalMode traversalMode = pluginOptions.writeExtras ? osg::NodeVisitor::TRAVERSE_ALL_CHILDREN : osg::NodeVisitor::TRAVERSE_ACTIVE_CHILDREN;

    osgDAE::daeWriter daeWriter(pDAE, fileURI, osgDB::getFilePath(fname), srcDirectory, options, traversalMode, &pluginOptions);
    daeWriter.setRootNode( node );
    const_cast<osg::Node*>(&node)->accept( daeWriter );

    osgDB::ReaderWriter::WriteResult retVal( WriteResult::ERROR_IN_WRITING_FILE );
    if ( daeWriter.isSuccess() )
    {
        if (pDAE->write(fileURI))
            retVal = WriteResult::FILE_SAVED;
    }

    if ( options )
    {
        if (!bOwnDAE)
        {
            // Return the document URI used so that users of an external DAE object
            // can locate the correct database
            if (options->getPluginData("DAE-DocumentURI"))
                *(std::string*)options->getPluginData("DAE-DocumentURI") = fileURI;
        }
    }

    return retVal;
}

static void replace(std::string & str, const char from, const std::string & to)
{
    // Replace for all occurrences
    for(std::string::size_type pos=str.find(from); pos!=std::string::npos; pos=str.find(from))
    {
        str.replace(pos, 1, to);
    }
}

static void replace(std::string & str, const std::string & from, const std::string & to)
{
    // Replace for all occurrences
    std::size_t lenFrom = from.size();
    std::size_t lenTo = to.size();
    for(std::string::size_type pos=str.find(from); pos!=std::string::npos; pos = str.find(from, pos+lenTo))
    {
        str.replace(pos, lenFrom, to);
    }
}

std::string ReaderWriterDAE::ConvertFilePathToColladaCompatibleURI(const std::string& FilePath)
{
#ifdef OSG_USE_UTF8_FILENAME
    std::string path( cdom::nativePathToUri( FilePath ) );
#else
    std::string path( cdom::nativePathToUri( osgDB::convertStringFromCurrentCodePageToUTF8(FilePath) ) );
#endif

    // Unfortunately, cdom::nativePathToUri() does not convert '#' characters to "%23" as expected.
    // So having /a/#b/c will generate a wrong conversion, as '#' will be misinterpreted as an URI fragment.
    // Here are listed all special chars, but only # was found problematic. I (Sukender) tested #{}^~[]`;@=&$ under Windows.
    // Uncomment lines if you find issues with some other special characters.

    //replace(path, '%', "%25");        // % at first
    //replace(path, ' ', "%20");
    replace(path, '#', "%23");
    //replace(path, '<', "%3C");
    //replace(path, '>', "%3E");
    //replace(path, '{', "%7B");
    //replace(path, '}', "%7D");
    //replace(path, '|', "%7C");
    //replace(path, '^', "%5E");
    //replace(path, '~', "%7E");
    //replace(path, '[', "%5B");
    //replace(path, '}', "%5D");
    //replace(path, '`', "%60");
    //replace(path, ';', "%3B");
    //replace(path, '?', "%3F");
    //replace(path, '@', "%40");
    //replace(path, '=', "%3D");
    //replace(path, '&', "%26");
    //replace(path, '$', "%24");
    return path;
}

std::string ReaderWriterDAE::ConvertColladaCompatibleURIToFilePath(const std::string& uri)
{
    // Reciprocal of ConvertFilePathToColladaCompatibleURI()
#ifdef OSG_USE_UTF8_FILENAME
    std::string path( cdom::uriToNativePath( uri ) );
#else
    std::string path( osgDB::convertStringFromCurrentCodePageToUTF8( cdom::uriToNativePath(uri) ) );
#endif
    replace(path, "%23", "#");
    return path;
}

///////////////////////////////////////////////////////////////////////////
// Add ourself to the Registry to instantiate the reader/writer.

REGISTER_OSGPLUGIN(dae, ReaderWriterDAE)

// vim: set sw=4 ts=8 et ic ai:
<|endoftext|>


<commit_before>// ***************************************************************************
//
//   Generated automatically by genwrapper.
//   Please DO NOT EDIT this file!
//
// ***************************************************************************

#include <osgIntrospection/ReflectionMacros>
#include <osgIntrospection/TypedMethodInfo>
#include <osgIntrospection/Attributes>

#include <osg/GraphicsContext>
#include <osg/GraphicsThread>

// Must undefine IN and OUT macros defined in Windows headers
#ifdef IN
#undef IN
#endif
#ifdef OUT
#undef OUT
#endif

BEGIN_ENUM_REFLECTOR(osg::BarrierOperation::PreBlockOp)
	I_EnumLabel(osg::BarrierOperation::NO_OPERATION);
	I_EnumLabel(osg::BarrierOperation::GL_FLUSH);
	I_EnumLabel(osg::BarrierOperation::GL_FINISH);
END_REFLECTOR

BEGIN_OBJECT_REFLECTOR(osg::BarrierOperation)
	I_BaseType(osg::GraphicsThread::Operation);
	I_ConstructorWithDefaults2(IN, int, numThreads, , IN, osg::BarrierOperation::PreBlockOp, op, osg::BarrierOperation::NO_OPERATION);
END_REFLECTOR

BEGIN_OBJECT_REFLECTOR(osg::Block)
	I_VirtualBaseType(osg::Referenced);
	I_Constructor0();
	I_Method0(void, block);
	I_Method0(void, release);
	I_Method0(void, reset);
	I_Method1(void, set, IN, bool, doRelease);
	I_WriteOnlyProperty(bool, );
END_REFLECTOR

BEGIN_OBJECT_REFLECTOR(osg::GraphicsThread)
	I_BaseType(osg::Referenced);
	I_Constructor0();
	I_MethodWithDefaults2(void, add, IN, osg::GraphicsThread::Operation *, operation, , IN, bool, waitForCompletion, false);
	I_Method0(void, run);
	I_Method0(int, cancel);
END_REFLECTOR

BEGIN_OBJECT_REFLECTOR(osg::GraphicsThread::Operation)
	I_VirtualBaseType(osg::Referenced);
	I_Constructor2(IN, const std::string &, name, IN, bool, keep);
	I_Method1(void, setName, IN, const std::string &, name);
	I_Method0(const std::string &, getName);
	I_Method1(void, setKeep, IN, bool, keep);
	I_Method0(bool, getKeep);
	I_Property(bool, Keep);
	I_Property(const std::string &, Name);
END_REFLECTOR

BEGIN_OBJECT_REFLECTOR(osg::ReleaseContext_Block_MakeCurrentOperation)
	I_BaseType(osg::GraphicsThread::Operation);
	I_BaseType(osg::Block);
	I_Constructor0();
END_REFLECTOR

BEGIN_OBJECT_REFLECTOR(osg::SwapBuffersOperation)
	I_BaseType(osg::GraphicsThread::Operation);
	I_Constructor0();
END_REFLECTOR

<commit_msg>Updated wrappers<commit_after>// ***************************************************************************
//
//   Generated automatically by genwrapper.
//   Please DO NOT EDIT this file!
//
// ***************************************************************************

#include <osgIntrospection/ReflectionMacros>
#include <osgIntrospection/TypedMethodInfo>
#include <osgIntrospection/Attributes>

#include <osg/GraphicsContext>
#include <osg/GraphicsThread>

// Must undefine IN and OUT macros defined in Windows headers
#ifdef IN
#undef IN
#endif
#ifdef OUT
#undef OUT
#endif

BEGIN_ENUM_REFLECTOR(osg::BarrierOperation::PreBlockOp)
	I_EnumLabel(osg::BarrierOperation::NO_OPERATION);
	I_EnumLabel(osg::BarrierOperation::GL_FLUSH);
	I_EnumLabel(osg::BarrierOperation::GL_FINISH);
END_REFLECTOR

BEGIN_OBJECT_REFLECTOR(osg::BarrierOperation)
	I_BaseType(osg::GraphicsThread::Operation);
	I_ConstructorWithDefaults2(IN, int, numThreads, , IN, osg::BarrierOperation::PreBlockOp, op, osg::BarrierOperation::NO_OPERATION);
	I_Method0(void, release);
END_REFLECTOR

BEGIN_OBJECT_REFLECTOR(osg::Block)
	I_VirtualBaseType(osg::Referenced);
	I_Constructor0();
	I_Method0(void, block);
	I_Method0(void, release);
	I_Method0(void, reset);
	I_Method1(void, set, IN, bool, doRelease);
	I_WriteOnlyProperty(bool, );
END_REFLECTOR

BEGIN_OBJECT_REFLECTOR(osg::GraphicsThread)
	I_BaseType(osg::Referenced);
	I_Constructor0();
	I_MethodWithDefaults2(void, add, IN, osg::GraphicsThread::Operation *, operation, , IN, bool, waitForCompletion, false);
	I_Method1(void, remove, IN, osg::GraphicsThread::Operation *, operation);
	I_Method1(void, remove, IN, const std::string &, name);
	I_Method0(void, removeAllOperations);
	I_Method0(osg::ref_ptr< osg::GraphicsThread::Operation >, getCurrentOperation);
	I_Method0(void, run);
	I_Method1(void, setDone, IN, bool, done);
	I_Method0(bool, getDone);
	I_Method0(int, cancel);
	I_ReadOnlyProperty(osg::ref_ptr< osg::GraphicsThread::Operation >, CurrentOperation);
	I_Property(bool, Done);
END_REFLECTOR

BEGIN_OBJECT_REFLECTOR(osg::GraphicsThread::Operation)
	I_VirtualBaseType(osg::Referenced);
	I_Constructor2(IN, const std::string &, name, IN, bool, keep);
	I_Method1(void, setName, IN, const std::string &, name);
	I_Method0(const std::string &, getName);
	I_Method1(void, setKeep, IN, bool, keep);
	I_Method0(bool, getKeep);
	I_Method0(void, release);
	I_Property(bool, Keep);
	I_Property(const std::string &, Name);
END_REFLECTOR

BEGIN_OBJECT_REFLECTOR(osg::ReleaseContext_Block_MakeCurrentOperation)
	I_BaseType(osg::GraphicsThread::Operation);
	I_BaseType(osg::Block);
	I_Constructor0();
	I_Method0(void, release);
END_REFLECTOR

BEGIN_OBJECT_REFLECTOR(osg::SwapBuffersOperation)
	I_BaseType(osg::GraphicsThread::Operation);
	I_Constructor0();
END_REFLECTOR

BEGIN_VALUE_REFLECTOR(osg::ref_ptr< osg::GraphicsThread::Operation >)
	I_Constructor0();
	I_Constructor1(IN, osg::GraphicsThread::Operation *, t);
	I_Constructor1(IN, const osg::ref_ptr< osg::GraphicsThread::Operation > &, rp);
	I_Method0(bool, valid);
	I_Method0(osg::GraphicsThread::Operation *, get);
	I_Method0(const osg::GraphicsThread::Operation *, get);
	I_Method0(osg::GraphicsThread::Operation *, take);
	I_Method0(osg::GraphicsThread::Operation *, release);
	I_ReadOnlyProperty(osg::GraphicsThread::Operation *, );
END_REFLECTOR

<|endoftext|>