<commit_before>/*=========================================================================
 *
 *  Copyright Leiden University Medical Center, Erasmus University Medical
 *  Center and contributors
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *        http://www.apache.org/licenses/LICENSE-2.0.txt
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 *=========================================================================*/

#include "selxComponentBase.h"

namespace selx
{
// TODO delete this constructor
ComponentBase::ComponentBase() : m_Name( "undefined" ), m_Logger( *( new LoggerImpl() ) )
{
}

ComponentBase::ComponentBase(const std::string & name, LoggerImpl & logger) : m_Logger(logger), m_Name( name )
{
}

//const std::map< std::string, std::string > ComponentBase::TemplateProperties()
// { return{}; }
} // end namespace selx

unsigned short Test_to_see_whether_warning_messages_are_displayed_at_CDash = 1.79769e+308;
void* Test_to_see_whether_error_messages_are_displayed_at_CDash = 42;
#error "Test to see whether error messages are displayed at http://my.cdash.org/index.php?project=SuperElastix"<commit_msg>Revert "COMP: Triggered two compiler errors and a warning, just to see how they get displayed by Jenkins + CDash."<commit_after>/*=========================================================================
 *
 *  Copyright Leiden University Medical Center, Erasmus University Medical
 *  Center and contributors
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *        http://www.apache.org/licenses/LICENSE-2.0.txt
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 *=========================================================================*/

#include "selxComponentBase.h"

namespace selx
{
// TODO delete this constructor
ComponentBase::ComponentBase() : m_Name( "undefined" ), m_Logger( *( new LoggerImpl() ) )
{
}

ComponentBase::ComponentBase(const std::string & name, LoggerImpl & logger) : m_Logger(logger), m_Name( name )
{
}

//const std::map< std::string, std::string > ComponentBase::TemplateProperties()
// { return{}; }
} // end namespace selx
<|endoftext|>


<commit_before>#include "rust_internal.h"
#include "rust_chan.h"

/**
 * Create a new rust channel and associate it with the specified port.
 */
rust_chan::rust_chan(rust_kernel *kernel, maybe_proxy<rust_port> *port,
                     size_t unit_sz)
    : ref_count(1),
      kernel(kernel),
      port(port),
      buffer(kernel, unit_sz) {
    if (port) {
        associate(port);
    }
    KLOG(kernel, comm, "new rust_chan(task=0x%" PRIxPTR
        ", port=0x%" PRIxPTR ") -> chan=0x%" PRIxPTR,
        (uintptr_t) task, (uintptr_t) port, (uintptr_t) this);
}

rust_chan::~rust_chan() {
    KLOG(kernel, comm, "del rust_chan(task=0x%" PRIxPTR ")",
         (uintptr_t) this);

    A(kernel, is_associated() == false,
      "Channel must be disassociated before being freed.");
}

/**
 * Link this channel with the specified port.
 */
void rust_chan::associate(maybe_proxy<rust_port> *port) {
    this->port = port;
    if (port->is_proxy() == false) {
        scoped_lock with(port->referent()->lock);
        KLOG(kernel, task,
            "associating chan: 0x%" PRIxPTR " with port: 0x%" PRIxPTR,
            this, port);
        ++this->ref_count;
        this->task = port->referent()->task;
        this->task->ref();
        this->port->referent()->chans.push(this);
    }
}

bool rust_chan::is_associated() {
    return port != NULL;
}

/**
 * Unlink this channel from its associated port.
 */
void rust_chan::disassociate() {
    A(kernel, is_associated(),
      "Channel must be associated with a port.");

    if (port->is_proxy() == false) {
        scoped_lock with(port->referent()->lock);
        KLOG(kernel, task,
             "disassociating chan: 0x%" PRIxPTR " from port: 0x%" PRIxPTR,
             this, port->referent());
        --this->ref_count;
        task->deref();
        this->task = NULL;
        port->referent()->chans.swap_delete(this);
    }

    // Delete reference to the port.
    port = NULL;
}

/**
 * Attempt to send data to the associated port.
 */
void rust_chan::send(void *sptr) {
    I(kernel, !port->is_proxy());

    rust_port *target_port = port->referent();
    // TODO: We can probably avoid this lock by using atomic operations in
    // circular_buffer.
    scoped_lock with(target_port->lock);

    buffer.enqueue(sptr);

    if (!is_associated()) {
        W(kernel, is_associated(),
          "rust_chan::transmit with no associated port.");
        return;
    }

    A(kernel, !buffer.is_empty(),
      "rust_chan::transmit with nothing to send.");

    if (port->is_proxy()) {
        data_message::send(buffer.peek(), buffer.unit_sz, "send data",
                           task->get_handle(), port->as_proxy()->handle());
        buffer.dequeue(NULL);
    } else {
        if (target_port->task->blocked_on(target_port)) {
            KLOG(kernel, comm, "dequeued in rendezvous_ptr");
            buffer.dequeue(target_port->task->rendezvous_ptr);
            target_port->task->rendezvous_ptr = 0;
            target_port->task->wakeup(target_port);
            return;
        }
    }

    return;
}

rust_chan *rust_chan::clone(rust_task *target) {
    size_t unit_sz = buffer.unit_sz;
    maybe_proxy<rust_port> *port = this->port;
    return new (target->kernel, "cloned chan")
        rust_chan(kernel, port, unit_sz);
}

/**
 * Cannot Yield: If the task were to unwind, the dropped ref would still
 * appear to be live, causing modify-after-free errors.
 */
void rust_chan::destroy() {
    A(kernel, ref_count == 0,
      "Channel's ref count should be zero.");

    if (is_associated()) {
        if (port->is_proxy()) {
            // Here is a good place to delete the port proxy we allocated
            // in upcall_clone_chan.
            rust_proxy<rust_port> *proxy = port->as_proxy();
            disassociate();
            delete proxy;
        } else {
            // We're trying to delete a channel that another task may be
            // reading from. We have two options:
            //
            // 1. We can flush the channel by blocking in upcall_flush_chan()
            //    and resuming only when the channel is flushed. The problem
            //    here is that we can get ourselves in a deadlock if the
            //    parent task tries to join us.
            //
            // 2. We can leave the channel in a "dormnat" state by not freeing
            //    it and letting the receiver task delete it for us instead.
            if (buffer.is_empty() == false) {
                return;
            }
            disassociate();
        }
    }
    delete this;
}

//
// Local Variables:
// mode: C++
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// compile-command: "make -k -C $RBUILD 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
// End:
//
<commit_msg>Fiddle with the locking around channel disassociation<commit_after>#include "rust_internal.h"
#include "rust_chan.h"

/**
 * Create a new rust channel and associate it with the specified port.
 */
rust_chan::rust_chan(rust_kernel *kernel, maybe_proxy<rust_port> *port,
                     size_t unit_sz)
    : ref_count(1),
      kernel(kernel),
      port(port),
      buffer(kernel, unit_sz) {
    if (port) {
        associate(port);
    }
    KLOG(kernel, comm, "new rust_chan(task=0x%" PRIxPTR
        ", port=0x%" PRIxPTR ") -> chan=0x%" PRIxPTR,
        (uintptr_t) task, (uintptr_t) port, (uintptr_t) this);
}

rust_chan::~rust_chan() {
    KLOG(kernel, comm, "del rust_chan(task=0x%" PRIxPTR ")",
         (uintptr_t) this);

    A(kernel, is_associated() == false,
      "Channel must be disassociated before being freed.");
}

/**
 * Link this channel with the specified port.
 */
void rust_chan::associate(maybe_proxy<rust_port> *port) {
    this->port = port;
    if (port->is_proxy() == false) {
        scoped_lock with(port->referent()->lock);
        KLOG(kernel, task,
            "associating chan: 0x%" PRIxPTR " with port: 0x%" PRIxPTR,
            this, port);
        ++this->ref_count;
        this->task = port->referent()->task;
        this->task->ref();
        this->port->referent()->chans.push(this);
    }
}

bool rust_chan::is_associated() {
    return port != NULL;
}

/**
 * Unlink this channel from its associated port.
 */
void rust_chan::disassociate() {
    A(kernel, is_associated(),
      "Channel must be associated with a port.");
    scoped_lock with(port->referent()->lock);
    if (port->is_proxy() == false) {
        KLOG(kernel, task,
             "disassociating chan: 0x%" PRIxPTR " from port: 0x%" PRIxPTR,
             this, port->referent());
        --this->ref_count;
        task->deref();
        this->task = NULL;
        port->referent()->chans.swap_delete(this);
    }

    // Delete reference to the port.
    port = NULL;
}

/**
 * Attempt to send data to the associated port.
 */
void rust_chan::send(void *sptr) {
    I(kernel, !port->is_proxy());

    rust_port *target_port = port->referent();
    // TODO: We can probably avoid this lock by using atomic operations in
    // circular_buffer.
    scoped_lock with(target_port->lock);

    buffer.enqueue(sptr);

    if (!is_associated()) {
        W(kernel, is_associated(),
          "rust_chan::transmit with no associated port.");
        return;
    }

    A(kernel, !buffer.is_empty(),
      "rust_chan::transmit with nothing to send.");

    if (port->is_proxy()) {
        data_message::send(buffer.peek(), buffer.unit_sz, "send data",
                           task->get_handle(), port->as_proxy()->handle());
        buffer.dequeue(NULL);
    } else {
        if (target_port->task->blocked_on(target_port)) {
            KLOG(kernel, comm, "dequeued in rendezvous_ptr");
            buffer.dequeue(target_port->task->rendezvous_ptr);
            target_port->task->rendezvous_ptr = 0;
            target_port->task->wakeup(target_port);
            return;
        }
    }

    return;
}

rust_chan *rust_chan::clone(rust_task *target) {
    size_t unit_sz = buffer.unit_sz;
    maybe_proxy<rust_port> *port = this->port;
    return new (target->kernel, "cloned chan")
        rust_chan(kernel, port, unit_sz);
}

/**
 * Cannot Yield: If the task were to unwind, the dropped ref would still
 * appear to be live, causing modify-after-free errors.
 */
void rust_chan::destroy() {
    A(kernel, ref_count == 0,
      "Channel's ref count should be zero.");

    if (is_associated()) {
        if (port->is_proxy()) {
            // Here is a good place to delete the port proxy we allocated
            // in upcall_clone_chan.
            rust_proxy<rust_port> *proxy = port->as_proxy();
            disassociate();
            delete proxy;
        } else {
            // We're trying to delete a channel that another task may be
            // reading from. We have two options:
            //
            // 1. We can flush the channel by blocking in upcall_flush_chan()
            //    and resuming only when the channel is flushed. The problem
            //    here is that we can get ourselves in a deadlock if the
            //    parent task tries to join us.
            //
            // 2. We can leave the channel in a "dormnat" state by not freeing
            //    it and letting the receiver task delete it for us instead.
            if (buffer.is_empty() == false) {
                return;
            }
            disassociate();
        }
    }
    delete this;
}

//
// Local Variables:
// mode: C++
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// compile-command: "make -k -C $RBUILD 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
// End:
//
<|endoftext|>


<commit_before>#include "saveasdialog.h"
#include "ui_saveasdialog.h"

#include <QFileDialog>
#include <QSettings>

#include "OgreMesh2.h"
#include "OgreSubMesh2.h"
#include "OgreMesh2Serializer.h"
#include "OgreHlmsJson.h"
#include "OgreItem.h"

#include "ogremanager.h"

struct QVariantMeshWrapper
{
    QVariantMeshWrapper() {}
    Ogre::Item* item;
};

Q_DECLARE_METATYPE(QVariantMeshWrapper);

SaveAsDialog::SaveAsDialog(QWidget* parent, OgreManager* ogre) : QDialog(parent)
{
    ui = new Ui::SaveAsDialog;
    ui->setupUi(this);

    mOgre = ogre;
    ui->progressBar->setVisible(false);

    connect(ui->browseButton, &QPushButton::clicked, this, &SaveAsDialog::browseButtonClicked);
    connect(ui->saveButton, &QPushButton::clicked, this, &SaveAsDialog::saveButtonClicked);
    connect(ui->cancelButton, &QPushButton::clicked, this, &SaveAsDialog::cancelButtonClicked);
}

SaveAsDialog::~SaveAsDialog()
{
    delete ui;
}

void SaveAsDialog::showEvent(QShowEvent*)
{
    if (!mInitialized)
    {
        ui->savePathText->setText(mOutputFolder);

        listAllMeshesFromScene();
        mInitialized = true;
    }
}

void SaveAsDialog::browseButtonClicked()
{
    QString initialPath = ui->savePathText->text();
    QString folder = QFileDialog::getExistingDirectory(this, "Output path", initialPath);

    if (!folder.isEmpty())
    {
        ui->savePathText->setText(folder);
        mOutputFolder = folder;
    }
}

void SaveAsDialog::saveButtonClicked()
{
    lockListWidget();

    std::vector<Ogre::Item*> ogreItems;

    QListWidget* listWidget = ui->listWidget;
    for (int i = 0; i < listWidget->count(); ++i)
    {
        QListWidgetItem* item = listWidget->item(i);
        bool checked = (item->checkState() == Qt::Checked);
        if (checked)
        {
            auto wrapper = item->data(Qt::UserRole).value<QVariantMeshWrapper>();
            ogreItems.push_back(wrapper.item);
        }
    }

    ui->progressBar->setVisible(true);
    ui->progressBar->setMaximum(ogreItems.size());
    QApplication::processEvents(QEventLoop::DialogExec);

    saveOgreMeshes(ogreItems);
    saveLuaScript(ogreItems);

    QSettings settings("OgreV2ModelViewer", "OgreV2ModelViewer");
    settings.setValue("actionSaveMesh", mOutputFolder);

    accept();
}

void SaveAsDialog::cancelButtonClicked()
{
    reject();
}

void SaveAsDialog::listAllMeshesFromScene()
{
    Ogre::SceneNode* node = mOgre->meshRootNode();

    std::vector<Ogre::Item*> items;
    collectMeshRecursively(node, items);

    for (const Ogre::Item* m : items)
    {
        qDebug() << m->getName().c_str();
    }

    createListItems(items);
}

void SaveAsDialog::collectMeshRecursively(Ogre::SceneNode* node, std::vector<Ogre::Item*>& ogreItems)
{
    size_t count = node->numAttachedObjects();
    for (size_t i = 0; i < count; ++i)
    {
        Ogre::Item* item = dynamic_cast<Ogre::Item*>(node->getAttachedObject(i));
        if (item)
        {
            ogreItems.push_back(item);
        }
    }

    for (int i = 0; i < node->numChildren(); ++i)
    {
        Ogre::SceneNode* child = static_cast<Ogre::SceneNode*>(node->getChild(i));
        collectMeshRecursively(child, ogreItems);
    }
}

void SaveAsDialog::createListItems(const std::vector<Ogre::Item*>& ogreItems)
{
    for (Ogre::Item* i : ogreItems)
    {
        QString meshName = QString::fromStdString(i->getName());

        QListWidgetItem* listItem = new QListWidgetItem(meshName, ui->listWidget);
        listItem->setFlags(listItem->flags() | Qt::ItemIsUserCheckable);
        listItem->setCheckState(Qt::Checked);

        QVariantMeshWrapper wrapper;
        wrapper.item = i;
        listItem->setData(Qt::UserRole, QVariant::fromValue(wrapper));

        ui->listWidget->addItem(listItem);
    }

    //QSignalBlocker b(ui->selectAllCheckbox);
    //ui->selectAllCheckbox->setChecked(true);
}

void SaveAsDialog::lockListWidget()
{
    QListWidget* listWidget = ui->listWidget;
    for (int i = 0; i < listWidget->count(); ++i)
    {
        QListWidgetItem* item = listWidget->item(i);
        item->setFlags(Qt::NoItemFlags);
    }
    QApplication::processEvents(QEventLoop::DialogExec);
}

void SaveAsDialog::saveOgreMeshes(const std::vector<Ogre::Item*>& ogreItems)
{
    for (int i = 0; i < ogreItems.size(); ++i)
    {
        applySubMeshMaterialNames(ogreItems[i]);

        QString meshName = validateFileName(QString::fromStdString(ogreItems[i]->getName()));

        QString fullPath = QDir(mOutputFolder).filePath(meshName);
        Ogre::Mesh* mesh = ogreItems[i]->getMesh().get();

        Ogre::Root* root = mOgre->ogreRoot();
        Ogre::MeshSerializer meshSerializer2(root->getRenderSystem()->getVaoManager());
        meshSerializer2.exportMesh(mesh, fullPath.toStdString());

        saveHlmsJson(ogreItems[i]);

        ui->progressBar->setValue(i + 1);
        QApplication::processEvents(QEventLoop::DialogExec);
    }
}

void SaveAsDialog::saveHlmsJson(const Ogre::Item* ogreItem)
{
    auto hlmsManager = Ogre::Root::getSingleton().getHlmsManager();

    size_t numSubItem = ogreItem->getNumSubItems();
    for (int i = 0; i < numSubItem; ++i)
    {
        Ogre::HlmsDatablock* datablock = ogreItem->getSubItem(i)->getDatablock();

        Ogre::HlmsJson hlmsJson(hlmsManager, nullptr);
        std::string outJson;
        hlmsJson.saveMaterial(datablock, outJson, "");

        QString outputPath = QDir(mOutputFolder).filePath(datablock->getNameStr()->c_str());
        if (!outputPath.endsWith(".material.json"))
        {
            outputPath.append(".material.json");
        }

        QFile f(outputPath);
        if (f.open(QFile::WriteOnly))
        {
            QTextStream fout(&f);
            fout.setCodec("UTF-8");
            fout << QString::fromStdString(outJson);
        }
        f.close();

        qDebug() << "Write Hlms Json: " << outputPath;
    }
}

QString SaveAsDialog::validateFileName(QString fileName)
{
    if (fileName.endsWith(" (v1)"))
    {
        fileName = fileName.mid(0, fileName.size() - 5); // remove the (v1) part
    }

    if (fileName.endsWith(".mesh.xml"))
    {
        fileName = fileName.mid(0, fileName.size() - 4); // remove the .xml part
    }

    if (!fileName.endsWith(".mesh"))
    {
        fileName.append(".mesh"); // make sure the file extension is .mesh
    }
    return fileName;
}

void SaveAsDialog::applySubMeshMaterialNames(Ogre::Item* ogreItem)
{
    // Otherwise the exported mesh won't contain the material name.
    // Check OgreMesh2SerializerImpl.cpp line 269 (in MeshSerializerImpl::writeSubMesh())

    size_t numSubItems = ogreItem->getNumSubItems();
    for (size_t i = 0; i < numSubItems; ++i)
    {
        std::string datablockName = *ogreItem->getSubItem(i)->getDatablock()->getNameStr();
        ogreItem->getSubItem(i)->getSubMesh()->setMaterialName(datablockName);
    }
}

void SaveAsDialog::saveLuaScript(const std::vector<Ogre::Item*>& ogreItems)
{
    // This function is just for my personal engine.
    QString fileName = "mesh_load.lua";
    QString fullPath = QDir(mOutputFolder).filePath(fileName);

    QFile f(fullPath);
    if (!f.open(QFile::WriteOnly))
        return;

    QTextStream fout(&f);
    fout << "local mesh_list = {}\n";

    for (size_t i = 0; i < ogreItems.size(); ++i)
    {
        Ogre::Item* item = ogreItems[i];
        Ogre::Vector3 pos = item->getParentSceneNode()->_getDerivedPosition();

        const Ogre::Quaternion quaternion = item->getParentSceneNode()->_getDerivedOrientation();
        Ogre::Matrix3 matrix3;
        quaternion.ToRotationMatrix(matrix3);

        Ogre::Radian rx, ry, rz;
        matrix3.ToEulerAnglesXYZ(rx, ry, rz);

        Ogre::Vector3 scale = item->getParentSceneNode()->_getDerivedScale();

        item->getParentSceneNode()->_getDerivedOrientation();
        QString line = QString("mesh_list[\"%1.mesh\"] = {pos={x=%2, y=%3, z=%4}, rot={x=%5, y=%6, z=%7}, scale={x=%8, y=%9, z=%10}}\n")
            .arg(item->getName().c_str())
            .arg(pos.x, 0, 'f', 4)
            .arg(pos.y, 0, 'f', 4)
            .arg(pos.z, 0, 'f', 4)
            .arg(rx.valueDegrees(), 0, 'f', 4)
            .arg(ry.valueDegrees(), 0, 'f', 4)
            .arg(rz.valueDegrees(), 0, 'f', 4)
            .arg(scale.x, 0, 'f', 4)
            .arg(scale.y, 0, 'f', 4)
            .arg(scale.z, 0, 'f', 4);
        fout << line;
    }
    fout << "\n";

    QString func = ""
        "function create_meshes() \n"
        "    local root_node = get_object_by_name('main_building') \n"
        "    for key, value in pairs(mesh_list) do \n"
        "        local path = 'script/' ..key \n"
        "        log_info(path) \n"
        "\n"
        "        local mesh = create_persistent_object('COgreMesh') \n"
        "        mesh:set_string('Path', path) \n"
        "\n"
        "        local node = create_persistent_object('CSceneNodeOgreMesh') \n"
        "        node:set_name(key) \n"
        "        node:set_ref('Ogre Mesh', mesh) \n"
        "        node:set_ref('Parent', root_node) \n"
        "        node:set_vec3('Position', { x = value.pos.x, y = value.pos.y, z = value.pos.z }) \n"
        "        node:set_vec3('Rotation', { x = value.rot.x, y = -value.rot.y, z = value.rot.z }) \n"
        "        node:set_vec3('Scale',    { x = value.scale.x, y = value.scale.y, z = value.scale.z }) \n"
        "        node:set_ref('Is Pickable', false) \n"
        "        node:signal_attribute('Parent') \n"
        "        node:signal_attribute('Name') \n"
        "        node:signal_attribute('Position') \n"
        "        node:signal_attribute('Rotation') \n"
        "        node:signal_attribute('Scale') \n"
        "    end \n"
        "end \n";

    fout << func;
    fout.flush();

    f.close();
}
<commit_msg>A wrong type in the generated Lua script<commit_after>#include "saveasdialog.h"
#include "ui_saveasdialog.h"

#include <QFileDialog>
#include <QSettings>

#include "OgreMesh2.h"
#include "OgreSubMesh2.h"
#include "OgreMesh2Serializer.h"
#include "OgreHlmsJson.h"
#include "OgreItem.h"

#include "ogremanager.h"

struct QVariantMeshWrapper
{
    QVariantMeshWrapper() {}
    Ogre::Item* item;
};

Q_DECLARE_METATYPE(QVariantMeshWrapper);

SaveAsDialog::SaveAsDialog(QWidget* parent, OgreManager* ogre) : QDialog(parent)
{
    ui = new Ui::SaveAsDialog;
    ui->setupUi(this);

    mOgre = ogre;
    ui->progressBar->setVisible(false);

    connect(ui->browseButton, &QPushButton::clicked, this, &SaveAsDialog::browseButtonClicked);
    connect(ui->saveButton, &QPushButton::clicked, this, &SaveAsDialog::saveButtonClicked);
    connect(ui->cancelButton, &QPushButton::clicked, this, &SaveAsDialog::cancelButtonClicked);
}

SaveAsDialog::~SaveAsDialog()
{
    delete ui;
}

void SaveAsDialog::showEvent(QShowEvent*)
{
    if (!mInitialized)
    {
        ui->savePathText->setText(mOutputFolder);

        listAllMeshesFromScene();
        mInitialized = true;
    }
}

void SaveAsDialog::browseButtonClicked()
{
    QString initialPath = ui->savePathText->text();
    QString folder = QFileDialog::getExistingDirectory(this, "Output path", initialPath);

    if (!folder.isEmpty())
    {
        ui->savePathText->setText(folder);
        mOutputFolder = folder;
    }
}

void SaveAsDialog::saveButtonClicked()
{
    lockListWidget();

    std::vector<Ogre::Item*> ogreItems;

    QListWidget* listWidget = ui->listWidget;
    for (int i = 0; i < listWidget->count(); ++i)
    {
        QListWidgetItem* item = listWidget->item(i);
        bool checked = (item->checkState() == Qt::Checked);
        if (checked)
        {
            auto wrapper = item->data(Qt::UserRole).value<QVariantMeshWrapper>();
            ogreItems.push_back(wrapper.item);
        }
    }

    ui->progressBar->setVisible(true);
    ui->progressBar->setMaximum(ogreItems.size());
    QApplication::processEvents(QEventLoop::DialogExec);

    saveOgreMeshes(ogreItems);
    saveLuaScript(ogreItems);

    QSettings settings("OgreV2ModelViewer", "OgreV2ModelViewer");
    settings.setValue("actionSaveMesh", mOutputFolder);

    accept();
}

void SaveAsDialog::cancelButtonClicked()
{
    reject();
}

void SaveAsDialog::listAllMeshesFromScene()
{
    Ogre::SceneNode* node = mOgre->meshRootNode();

    std::vector<Ogre::Item*> items;
    collectMeshRecursively(node, items);

    for (const Ogre::Item* m : items)
    {
        qDebug() << m->getName().c_str();
    }

    createListItems(items);
}

void SaveAsDialog::collectMeshRecursively(Ogre::SceneNode* node, std::vector<Ogre::Item*>& ogreItems)
{
    size_t count = node->numAttachedObjects();
    for (size_t i = 0; i < count; ++i)
    {
        Ogre::Item* item = dynamic_cast<Ogre::Item*>(node->getAttachedObject(i));
        if (item)
        {
            ogreItems.push_back(item);
        }
    }

    for (int i = 0; i < node->numChildren(); ++i)
    {
        Ogre::SceneNode* child = static_cast<Ogre::SceneNode*>(node->getChild(i));
        collectMeshRecursively(child, ogreItems);
    }
}

void SaveAsDialog::createListItems(const std::vector<Ogre::Item*>& ogreItems)
{
    for (Ogre::Item* i : ogreItems)
    {
        QString meshName = QString::fromStdString(i->getName());

        QListWidgetItem* listItem = new QListWidgetItem(meshName, ui->listWidget);
        listItem->setFlags(listItem->flags() | Qt::ItemIsUserCheckable);
        listItem->setCheckState(Qt::Checked);

        QVariantMeshWrapper wrapper;
        wrapper.item = i;
        listItem->setData(Qt::UserRole, QVariant::fromValue(wrapper));

        ui->listWidget->addItem(listItem);
    }

    //QSignalBlocker b(ui->selectAllCheckbox);
    //ui->selectAllCheckbox->setChecked(true);
}

void SaveAsDialog::lockListWidget()
{
    QListWidget* listWidget = ui->listWidget;
    for (int i = 0; i < listWidget->count(); ++i)
    {
        QListWidgetItem* item = listWidget->item(i);
        item->setFlags(Qt::NoItemFlags);
    }
    QApplication::processEvents(QEventLoop::DialogExec);
}

void SaveAsDialog::saveOgreMeshes(const std::vector<Ogre::Item*>& ogreItems)
{
    for (int i = 0; i < ogreItems.size(); ++i)
    {
        applySubMeshMaterialNames(ogreItems[i]);

        QString meshName = validateFileName(QString::fromStdString(ogreItems[i]->getName()));

        QString fullPath = QDir(mOutputFolder).filePath(meshName);
        Ogre::Mesh* mesh = ogreItems[i]->getMesh().get();

        Ogre::Root* root = mOgre->ogreRoot();
        Ogre::MeshSerializer meshSerializer2(root->getRenderSystem()->getVaoManager());
        meshSerializer2.exportMesh(mesh, fullPath.toStdString());

        saveHlmsJson(ogreItems[i]);

        ui->progressBar->setValue(i + 1);
        QApplication::processEvents(QEventLoop::DialogExec);
    }
}

void SaveAsDialog::saveHlmsJson(const Ogre::Item* ogreItem)
{
    auto hlmsManager = Ogre::Root::getSingleton().getHlmsManager();

    size_t numSubItem = ogreItem->getNumSubItems();
    for (int i = 0; i < numSubItem; ++i)
    {
        Ogre::HlmsDatablock* datablock = ogreItem->getSubItem(i)->getDatablock();

        Ogre::HlmsJson hlmsJson(hlmsManager, nullptr);
        std::string outJson;
        hlmsJson.saveMaterial(datablock, outJson, "");

        QString outputPath = QDir(mOutputFolder).filePath(datablock->getNameStr()->c_str());
        if (!outputPath.endsWith(".material.json"))
        {
            outputPath.append(".material.json");
        }

        QFile f(outputPath);
        if (f.open(QFile::WriteOnly))
        {
            QTextStream fout(&f);
            fout.setCodec("UTF-8");
            fout << QString::fromStdString(outJson);
        }
        f.close();

        qDebug() << "Write Hlms Json: " << outputPath;
    }
}

QString SaveAsDialog::validateFileName(QString fileName)
{
    if (fileName.endsWith(" (v1)"))
    {
        fileName = fileName.mid(0, fileName.size() - 5); // remove the (v1) part
    }

    if (fileName.endsWith(".mesh.xml"))
    {
        fileName = fileName.mid(0, fileName.size() - 4); // remove the .xml part
    }

    if (!fileName.endsWith(".mesh"))
    {
        fileName.append(".mesh"); // make sure the file extension is .mesh
    }
    return fileName;
}

void SaveAsDialog::applySubMeshMaterialNames(Ogre::Item* ogreItem)
{
    // Otherwise the exported mesh won't contain the material name.
    // Check OgreMesh2SerializerImpl.cpp line 269 (in MeshSerializerImpl::writeSubMesh())

    size_t numSubItems = ogreItem->getNumSubItems();
    for (size_t i = 0; i < numSubItems; ++i)
    {
        std::string datablockName = *ogreItem->getSubItem(i)->getDatablock()->getNameStr();
        ogreItem->getSubItem(i)->getSubMesh()->setMaterialName(datablockName);
    }
}

void SaveAsDialog::saveLuaScript(const std::vector<Ogre::Item*>& ogreItems)
{
    // This function is just for my personal engine.
    QString fileName = "mesh_load.lua";
    QString fullPath = QDir(mOutputFolder).filePath(fileName);

    QFile f(fullPath);
    if (!f.open(QFile::WriteOnly))
        return;

    QTextStream fout(&f);
    fout << "local mesh_list = {}\n";

    for (size_t i = 0; i < ogreItems.size(); ++i)
    {
        Ogre::Item* item = ogreItems[i];
        Ogre::Vector3 pos = item->getParentSceneNode()->_getDerivedPosition();

        const Ogre::Quaternion quaternion = item->getParentSceneNode()->_getDerivedOrientation();
        Ogre::Matrix3 matrix3;
        quaternion.ToRotationMatrix(matrix3);

        Ogre::Radian rx, ry, rz;
        matrix3.ToEulerAnglesXYZ(rx, ry, rz);

        Ogre::Vector3 scale = item->getParentSceneNode()->_getDerivedScale();

        item->getParentSceneNode()->_getDerivedOrientation();
        QString line = QString("mesh_list[\"%1.mesh\"] = {pos={x=%2, y=%3, z=%4}, rot={x=%5, y=%6, z=%7}, scale={x=%8, y=%9, z=%10}}\n")
            .arg(item->getName().c_str())
            .arg(pos.x, 0, 'f', 4)
            .arg(pos.y, 0, 'f', 4)
            .arg(pos.z, 0, 'f', 4)
            .arg(rx.valueDegrees(), 0, 'f', 4)
            .arg(ry.valueDegrees(), 0, 'f', 4)
            .arg(rz.valueDegrees(), 0, 'f', 4)
            .arg(scale.x, 0, 'f', 4)
            .arg(scale.y, 0, 'f', 4)
            .arg(scale.z, 0, 'f', 4);
        fout << line;
    }
    fout << "\n";

    QString func = ""
        "function create_meshes() \n"
        "    local root_node = get_object_by_name('main_building') \n"
        "    for key, value in pairs(mesh_list) do \n"
        "        local path = 'script/' ..key \n"
        "        log_info(path) \n"
        "\n"
        "        local mesh = create_persistent_object('COgreMesh') \n"
        "        mesh:set_string('Path', path) \n"
        "\n"
        "        local node = create_persistent_object('CSceneNodeOgreMesh') \n"
        "        node:set_name(key) \n"
        "        node:set_ref('Ogre Mesh', mesh) \n"
        "        node:set_ref('Parent', root_node) \n"
        "        node:set_vec3('Position', { x = value.pos.x, y = value.pos.y, z = value.pos.z }) \n"
        "        node:set_vec3('Rotation', { x = value.rot.x, y = -value.rot.y, z = value.rot.z }) \n"
        "        node:set_vec3('Scale',    { x = value.scale.x, y = value.scale.y, z = value.scale.z }) \n"
        "        node:set_bool('Is Pickable', false) \n"
        "        node:signal_attribute('Parent') \n"
        "        node:signal_attribute('Name') \n"
        "        node:signal_attribute('Position') \n"
        "        node:signal_attribute('Rotation') \n"
        "        node:signal_attribute('Scale') \n"
        "    end \n"
        "end \n";

    fout << func;
    fout.flush();

    f.close();
}
<|endoftext|>


<commit_before>/****************************************************************************
**
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtDeclarative module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this
** file. Please review the following information to ensure the GNU Lesser
** General Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU General
** Public License version 3.0 as published by the Free Software Foundation
** and appearing in the file LICENSE.GPL included in the packaging of this
** file. Please review the following information to ensure the GNU General
** Public License version 3.0 requirements will be met:
** http://www.gnu.org/copyleft/gpl.html.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "qdeclarativedebugtrace_p.h"

#include <QtCore/qdatastream.h>
#include <QtCore/qurl.h>
#include <QtCore/qtimer.h>

Q_GLOBAL_STATIC(QDeclarativeDebugTrace, traceInstance);

// convert to a QByteArray that can be sent to the debug client
// use of QDataStream can skew results if m_deferredSend == false
//     (see tst_qdeclarativedebugtrace::trace() benchmark)
QByteArray QDeclarativeDebugData::toByteArray() const
{
    QByteArray data;
    //### using QDataStream is relatively expensive
    QDataStream ds(&data, QIODevice::WriteOnly);
    ds << time << messageType << detailType;
    if (messageType == (int)QDeclarativeDebugTrace::RangeData)
        ds << detailData;
    if (messageType == (int)QDeclarativeDebugTrace::RangeLocation)
        ds << detailData << line;
    return data;
}

QDeclarativeDebugTrace::QDeclarativeDebugTrace()
    : QDeclarativeDebugService(QLatin1String("CanvasFrameRate")),
      m_enabled(false), m_deferredSend(true), m_messageReceived(false)
{
    m_timer.start();
    if (status() == Enabled) {
        // wait for first message indicating whether to trace or not
        while (!m_messageReceived)
            waitForMessage();
    }
}

void QDeclarativeDebugTrace::addEvent(EventType t)
{
    if (QDeclarativeDebugService::isDebuggingEnabled())
        traceInstance()->addEventImpl(t);
}

void QDeclarativeDebugTrace::startRange(RangeType t)
{
    if (QDeclarativeDebugService::isDebuggingEnabled())
        traceInstance()->startRangeImpl(t);
}

void QDeclarativeDebugTrace::rangeData(RangeType t, const QString &data)
{
    if (QDeclarativeDebugService::isDebuggingEnabled())
        traceInstance()->rangeDataImpl(t, data);
}

void QDeclarativeDebugTrace::rangeData(RangeType t, const QUrl &data)
{
    if (QDeclarativeDebugService::isDebuggingEnabled())
        traceInstance()->rangeDataImpl(t, data);
}

void QDeclarativeDebugTrace::rangeLocation(RangeType t, const QString &fileName, int line)
{
    if (QDeclarativeDebugService::isDebuggingEnabled())
        traceInstance()->rangeLocationImpl(t, fileName, line);
}

void QDeclarativeDebugTrace::rangeLocation(RangeType t, const QUrl &fileName, int line)
{
    if (QDeclarativeDebugService::isDebuggingEnabled())
        traceInstance()->rangeLocationImpl(t, fileName, line);
}

void QDeclarativeDebugTrace::endRange(RangeType t)
{
    if (QDeclarativeDebugService::isDebuggingEnabled())
        traceInstance()->endRangeImpl(t);
}

void QDeclarativeDebugTrace::addEventImpl(EventType event)
{
    if (status() != Enabled || !m_enabled)
        return;

    QDeclarativeDebugData ed = {m_timer.nsecsElapsed(), (int)Event, (int)event, QString(), -1};
    processMessage(ed);
}

void QDeclarativeDebugTrace::startRangeImpl(RangeType range)
{
    if (status() != Enabled || !m_enabled)
        return;

    QDeclarativeDebugData rd = {m_timer.nsecsElapsed(), (int)RangeStart, (int)range, QString(), -1};
    processMessage(rd);
}

void QDeclarativeDebugTrace::rangeDataImpl(RangeType range, const QString &rData)
{
    if (status() != Enabled || !m_enabled)
        return;

    QDeclarativeDebugData rd = {m_timer.nsecsElapsed(), (int)RangeData, (int)range, rData, -1};
    processMessage(rd);
}

void QDeclarativeDebugTrace::rangeDataImpl(RangeType range, const QUrl &rData)
{
    if (status() != Enabled || !m_enabled)
        return;

    QDeclarativeDebugData rd = {m_timer.nsecsElapsed(), (int)RangeData, (int)range, rData.toString(QUrl::FormattingOption(0x100)), -1};
    processMessage(rd);
}

void QDeclarativeDebugTrace::rangeLocationImpl(RangeType range, const QString &fileName, int line)
{
    if (status() != Enabled || !m_enabled)
        return;

    QDeclarativeDebugData rd = {m_timer.nsecsElapsed(), (int)RangeLocation, (int)range, fileName, line};
    processMessage(rd);
}

void QDeclarativeDebugTrace::rangeLocationImpl(RangeType range, const QUrl &fileName, int line)
{
    if (status() != Enabled || !m_enabled)
        return;

    QDeclarativeDebugData rd = {m_timer.nsecsElapsed(), (int)RangeLocation, (int)range, fileName.toString(QUrl::FormattingOption(0x100)), line};
    processMessage(rd);
}

void QDeclarativeDebugTrace::endRangeImpl(RangeType range)
{
    if (status() != Enabled || !m_enabled)
        return;

    QDeclarativeDebugData rd = {m_timer.nsecsElapsed(), (int)RangeEnd, (int)range, QString(), -1};
    processMessage(rd);
}

/*
    Either send the message directly, or queue up
    a list of messages to send later (via sendMessages)
*/
void QDeclarativeDebugTrace::processMessage(const QDeclarativeDebugData &message)
{
    if (m_deferredSend)
        m_data.append(message);
    else
        sendMessage(message.toByteArray());
}

/*
    Send the messages queued up by processMessage
*/
void QDeclarativeDebugTrace::sendMessages()
{
    if (m_deferredSend) {
        //### this is a suboptimal way to send batched messages
        for (int i = 0; i < m_data.count(); ++i)
            sendMessage(m_data.at(i).toByteArray());
        m_data.clear();

        //indicate completion
        QByteArray data;
        QDataStream ds(&data, QIODevice::WriteOnly);
        ds << (qint64)-1 << (int)Complete;
        sendMessage(data);
    }
}

void QDeclarativeDebugTrace::messageReceived(const QByteArray &message)
{
    QByteArray rwData = message;
    QDataStream stream(&rwData, QIODevice::ReadOnly);

    stream >> m_enabled;

    m_messageReceived = true;

    if (!m_enabled)
        sendMessages();
}
<commit_msg>Debugger: Add missing QT_BEGIN_NAMESPACE, QT_END_NAMESPACE<commit_after>/****************************************************************************
**
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtDeclarative module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this
** file. Please review the following information to ensure the GNU Lesser
** General Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU General
** Public License version 3.0 as published by the Free Software Foundation
** and appearing in the file LICENSE.GPL included in the packaging of this
** file. Please review the following information to ensure the GNU General
** Public License version 3.0 requirements will be met:
** http://www.gnu.org/copyleft/gpl.html.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "qdeclarativedebugtrace_p.h"

#include <QtCore/qdatastream.h>
#include <QtCore/qurl.h>
#include <QtCore/qtimer.h>

QT_BEGIN_NAMESPACE

Q_GLOBAL_STATIC(QDeclarativeDebugTrace, traceInstance);

// convert to a QByteArray that can be sent to the debug client
// use of QDataStream can skew results if m_deferredSend == false
//     (see tst_qdeclarativedebugtrace::trace() benchmark)
QByteArray QDeclarativeDebugData::toByteArray() const
{
    QByteArray data;
    //### using QDataStream is relatively expensive
    QDataStream ds(&data, QIODevice::WriteOnly);
    ds << time << messageType << detailType;
    if (messageType == (int)QDeclarativeDebugTrace::RangeData)
        ds << detailData;
    if (messageType == (int)QDeclarativeDebugTrace::RangeLocation)
        ds << detailData << line;
    return data;
}

QDeclarativeDebugTrace::QDeclarativeDebugTrace()
    : QDeclarativeDebugService(QLatin1String("CanvasFrameRate")),
      m_enabled(false), m_deferredSend(true), m_messageReceived(false)
{
    m_timer.start();
    if (status() == Enabled) {
        // wait for first message indicating whether to trace or not
        while (!m_messageReceived)
            waitForMessage();
    }
}

void QDeclarativeDebugTrace::addEvent(EventType t)
{
    if (QDeclarativeDebugService::isDebuggingEnabled())
        traceInstance()->addEventImpl(t);
}

void QDeclarativeDebugTrace::startRange(RangeType t)
{
    if (QDeclarativeDebugService::isDebuggingEnabled())
        traceInstance()->startRangeImpl(t);
}

void QDeclarativeDebugTrace::rangeData(RangeType t, const QString &data)
{
    if (QDeclarativeDebugService::isDebuggingEnabled())
        traceInstance()->rangeDataImpl(t, data);
}

void QDeclarativeDebugTrace::rangeData(RangeType t, const QUrl &data)
{
    if (QDeclarativeDebugService::isDebuggingEnabled())
        traceInstance()->rangeDataImpl(t, data);
}

void QDeclarativeDebugTrace::rangeLocation(RangeType t, const QString &fileName, int line)
{
    if (QDeclarativeDebugService::isDebuggingEnabled())
        traceInstance()->rangeLocationImpl(t, fileName, line);
}

void QDeclarativeDebugTrace::rangeLocation(RangeType t, const QUrl &fileName, int line)
{
    if (QDeclarativeDebugService::isDebuggingEnabled())
        traceInstance()->rangeLocationImpl(t, fileName, line);
}

void QDeclarativeDebugTrace::endRange(RangeType t)
{
    if (QDeclarativeDebugService::isDebuggingEnabled())
        traceInstance()->endRangeImpl(t);
}

void QDeclarativeDebugTrace::addEventImpl(EventType event)
{
    if (status() != Enabled || !m_enabled)
        return;

    QDeclarativeDebugData ed = {m_timer.nsecsElapsed(), (int)Event, (int)event, QString(), -1};
    processMessage(ed);
}

void QDeclarativeDebugTrace::startRangeImpl(RangeType range)
{
    if (status() != Enabled || !m_enabled)
        return;

    QDeclarativeDebugData rd = {m_timer.nsecsElapsed(), (int)RangeStart, (int)range, QString(), -1};
    processMessage(rd);
}

void QDeclarativeDebugTrace::rangeDataImpl(RangeType range, const QString &rData)
{
    if (status() != Enabled || !m_enabled)
        return;

    QDeclarativeDebugData rd = {m_timer.nsecsElapsed(), (int)RangeData, (int)range, rData, -1};
    processMessage(rd);
}

void QDeclarativeDebugTrace::rangeDataImpl(RangeType range, const QUrl &rData)
{
    if (status() != Enabled || !m_enabled)
        return;

    QDeclarativeDebugData rd = {m_timer.nsecsElapsed(), (int)RangeData, (int)range, rData.toString(QUrl::FormattingOption(0x100)), -1};
    processMessage(rd);
}

void QDeclarativeDebugTrace::rangeLocationImpl(RangeType range, const QString &fileName, int line)
{
    if (status() != Enabled || !m_enabled)
        return;

    QDeclarativeDebugData rd = {m_timer.nsecsElapsed(), (int)RangeLocation, (int)range, fileName, line};
    processMessage(rd);
}

void QDeclarativeDebugTrace::rangeLocationImpl(RangeType range, const QUrl &fileName, int line)
{
    if (status() != Enabled || !m_enabled)
        return;

    QDeclarativeDebugData rd = {m_timer.nsecsElapsed(), (int)RangeLocation, (int)range, fileName.toString(QUrl::FormattingOption(0x100)), line};
    processMessage(rd);
}

void QDeclarativeDebugTrace::endRangeImpl(RangeType range)
{
    if (status() != Enabled || !m_enabled)
        return;

    QDeclarativeDebugData rd = {m_timer.nsecsElapsed(), (int)RangeEnd, (int)range, QString(), -1};
    processMessage(rd);
}

/*
    Either send the message directly, or queue up
    a list of messages to send later (via sendMessages)
*/
void QDeclarativeDebugTrace::processMessage(const QDeclarativeDebugData &message)
{
    if (m_deferredSend)
        m_data.append(message);
    else
        sendMessage(message.toByteArray());
}

/*
    Send the messages queued up by processMessage
*/
void QDeclarativeDebugTrace::sendMessages()
{
    if (m_deferredSend) {
        //### this is a suboptimal way to send batched messages
        for (int i = 0; i < m_data.count(); ++i)
            sendMessage(m_data.at(i).toByteArray());
        m_data.clear();

        //indicate completion
        QByteArray data;
        QDataStream ds(&data, QIODevice::WriteOnly);
        ds << (qint64)-1 << (int)Complete;
        sendMessage(data);
    }
}

void QDeclarativeDebugTrace::messageReceived(const QByteArray &message)
{
    QByteArray rwData = message;
    QDataStream stream(&rwData, QIODevice::ReadOnly);

    stream >> m_enabled;

    m_messageReceived = true;

    if (!m_enabled)
        sendMessages();
}

QT_END_NAMESPACE
<|endoftext|>


<commit_before>/*
-----------------------------------------------------------------------------
This source file is part of OGRE
    (Object-oriented Graphics Rendering Engine)
For the latest info, see http://www.ogre3d.org/

Copyright (c) 2000-2012 Torus Knot Software Ltd

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 "OgreStableHeaders.h"
#include "OgreGpuProgramManager.h"
#include "OgreHighLevelGpuProgramManager.h"
#include "OgreRoot.h"
#include "OgreRenderSystem.h"

namespace Ogre {
    //-----------------------------------------------------------------------
    template<> GpuProgramManager* Singleton<GpuProgramManager>::msSingleton = 0;
    GpuProgramManager* GpuProgramManager::getSingletonPtr(void)
    {
        return msSingleton;
    }
    GpuProgramManager& GpuProgramManager::getSingleton(void)
    {
        assert( msSingleton );  return ( *msSingleton );
    }
	//---------------------------------------------------------------------------
	GpuProgramManager::GpuProgramManager()
	{
		// Loading order
		mLoadOrder = 50.0f;
		// Resource type
		mResourceType = "GpuProgram";
		mSaveMicrocodesToCache = false;

		// subclasses should register with resource group manager
	}
	//---------------------------------------------------------------------------
	GpuProgramManager::~GpuProgramManager()
	{
		// subclasses should unregister with resource group manager
	}
	//---------------------------------------------------------------------------
    GpuProgramPtr GpuProgramManager::load(const String& name,
		const String& groupName, const String& filename,
		GpuProgramType gptype, const String& syntaxCode)
    {
		GpuProgramPtr prg;
		{
			OGRE_LOCK_AUTO_MUTEX
			prg = getByName(name);
			if (prg.isNull())
			{
				prg = createProgram(name, groupName, filename, gptype, syntaxCode);
			}

		}
        prg->load();
        return prg;
    }
    //---------------------------------------------------------------------------
	GpuProgramPtr GpuProgramManager::loadFromString(const String& name,
		const String& groupName, const String& code,
        GpuProgramType gptype, const String& syntaxCode)
    {
		GpuProgramPtr prg;
		{
			OGRE_LOCK_AUTO_MUTEX
			prg = getByName(name);
			if (prg.isNull())
			{
				prg = createProgramFromString(name, groupName, code, gptype, syntaxCode);
			}

		}
        prg->load();
        return prg;
    }
    //---------------------------------------------------------------------------
    ResourcePtr GpuProgramManager::create(const String& name, const String& group,
        GpuProgramType gptype, const String& syntaxCode, bool isManual,
        ManualResourceLoader* loader)
    {
        // Call creation implementation
        ResourcePtr ret = ResourcePtr(
            createImpl(name, getNextHandle(), group, isManual, loader, gptype, syntaxCode));

        addImpl(ret);
        // Tell resource group manager
        ResourceGroupManager::getSingleton()._notifyResourceCreated(ret);
        return ret;
    }
    //---------------------------------------------------------------------------
	GpuProgramPtr GpuProgramManager::createProgram(const String& name,
		const String& groupName, const String& filename,
		GpuProgramType gptype, const String& syntaxCode)
    {
		GpuProgramPtr prg = create(name, groupName, gptype, syntaxCode);
        // Set all prarmeters (create does not set, just determines factory)
		prg->setType(gptype);
		prg->setSyntaxCode(syntaxCode);
		prg->setSourceFile(filename);
        return prg;
    }
    //---------------------------------------------------------------------------
	GpuProgramPtr GpuProgramManager::createProgramFromString(const String& name,
		const String& groupName, const String& code, GpuProgramType gptype,
		const String& syntaxCode)
    {
		GpuProgramPtr prg = create(name, groupName, gptype, syntaxCode);
        // Set all prarmeters (create does not set, just determines factory)
		prg->setType(gptype);
		prg->setSyntaxCode(syntaxCode);
		prg->setSource(code);
        return prg;
    }
    //---------------------------------------------------------------------------
		const GpuProgramManager::SyntaxCodes& GpuProgramManager::getSupportedSyntax(void) const
        {
				// Use the current render system
			  RenderSystem* rs = Root::getSingleton().getRenderSystem();

				// Get the supported syntaxed from RenderSystemCapabilities
				return rs->getCapabilities()->getSupportedShaderProfiles();
        }

    //---------------------------------------------------------------------------
    bool GpuProgramManager::isSyntaxSupported(const String& syntaxCode) const
        {
				// Use the current render system
			  RenderSystem* rs = Root::getSingleton().getRenderSystem();

				// Get the supported syntaxed from RenderSystemCapabilities
				return rs->getCapabilities()->isShaderProfileSupported(syntaxCode);

    }
    //---------------------------------------------------------------------------
    ResourcePtr GpuProgramManager::getByName(const String& name, bool preferHighLevelPrograms)
    {
        ResourcePtr ret;
        if (preferHighLevelPrograms)
        {
            ret = HighLevelGpuProgramManager::getSingleton().getByName(name);
            if (!ret.isNull())
                return ret;
        }
        return ResourceManager::getByName(name);
    }
	//-----------------------------------------------------------------------------
	GpuProgramParametersSharedPtr GpuProgramManager::createParameters(void)
	{
		return GpuProgramParametersSharedPtr(OGRE_NEW GpuProgramParameters());
	}
	//---------------------------------------------------------------------
	GpuSharedParametersPtr GpuProgramManager::createSharedParameters(const String& name)
	{
		if (mSharedParametersMap.find(name) != mSharedParametersMap.end())
		{
			OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS,
				"The shared parameter set '" + name + "' already exists!",
				"GpuProgramManager::createSharedParameters");
		}
		GpuSharedParametersPtr ret(OGRE_NEW GpuSharedParameters(name));
		mSharedParametersMap[name] = ret;
		return ret;
	}
	//---------------------------------------------------------------------
	GpuSharedParametersPtr GpuProgramManager::getSharedParameters(const String& name) const
	{
		SharedParametersMap::const_iterator i = mSharedParametersMap.find(name);
		if (i == mSharedParametersMap.end())
		{
			OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS,
				"No shared parameter set with name '" + name + "'!",
				"GpuProgramManager::createSharedParameters");
		}
		return i->second;
	}
	//---------------------------------------------------------------------
	const GpuProgramManager::SharedParametersMap&
	GpuProgramManager::getAvailableSharedParameters() const
	{
		return mSharedParametersMap;
	}
	//---------------------------------------------------------------------
	bool GpuProgramManager::getSaveMicrocodesToCache() const
	{
		return mSaveMicrocodesToCache;
	}
	//---------------------------------------------------------------------
	bool GpuProgramManager::canGetCompiledShaderBuffer() const
	{
		// Use the current render system
		RenderSystem* rs = Root::getSingleton().getRenderSystem();

		// Check if the supported
		return rs->getCapabilities()->hasCapability(RSC_CAN_GET_COMPILED_SHADER_BUFFER);
	}
	//---------------------------------------------------------------------
	void GpuProgramManager::setSaveMicrocodesToCache( const bool val )
	{
		mSaveMicrocodesToCache = val;
	}
	//---------------------------------------------------------------------
	String GpuProgramManager::addRenderSystemToName( const String & name )
	{
		// Use the current render system
		RenderSystem* rs = Root::getSingleton().getRenderSystem();

		return rs->getName() + "_" + name;
	}
	//---------------------------------------------------------------------
	bool GpuProgramManager::isMicrocodeAvailableInCache( const String & name ) const
	{
		return mMicrocodeCache.find(addRenderSystemToName(name)) != mMicrocodeCache.end();
	}
	//---------------------------------------------------------------------
	const GpuProgramManager::Microcode & GpuProgramManager::getMicrocodeFromCache( const String & name ) const
	{
		return mMicrocodeCache.find(addRenderSystemToName(name))->second;
	}
	//---------------------------------------------------------------------
    GpuProgramManager::Microcode GpuProgramManager::createMicrocode( const size_t size ) const
	{
		return Microcode(OGRE_NEW MemoryDataStream(size));
	}
	//---------------------------------------------------------------------
	void GpuProgramManager::addMicrocodeToCache( const String & name, const GpuProgramManager::Microcode & microcode )
	{
		String nameWithRenderSystem = addRenderSystemToName(name);
		MicrocodeMap::iterator foundIter = mMicrocodeCache.find(nameWithRenderSystem);
		if ( foundIter == mMicrocodeCache.end() )
		{
			mMicrocodeCache.insert(make_pair(nameWithRenderSystem, microcode));
		}
		else
		{
			foundIter->second = microcode;

		}
	}
	//---------------------------------------------------------------------
	void GpuProgramManager::saveMicrocodeCache( DataStreamPtr stream ) const
	{
		if (!stream->isWriteable())
		{
			OGRE_EXCEPT(Exception::ERR_CANNOT_WRITE_TO_FILE,
				"Unable to write to stream " + stream->getName(),
				"GpuProgramManager::saveMicrocodeCache");
		}

		// write the size of the array
		size_t sizeOfArray = mMicrocodeCache.size();
		stream->write(&sizeOfArray, sizeof(size_t));

		// loop the array and save it
		MicrocodeMap::const_iterator iter = mMicrocodeCache.begin();
		MicrocodeMap::const_iterator iterE = mMicrocodeCache.end();
		for ( ; iter != iterE ; iter++ )
		{
			// saves the name of the shader
			{
				const String & nameOfShader = iter->first;
				size_t stringLength = nameOfShader.size();
				stream->write(&stringLength, sizeof(size_t));
				stream->write(&nameOfShader[0], stringLength);
			}
			// saves the microcode
			{
				const Microcode & microcodeOfShader = iter->second;
				size_t microcodeLength = microcodeOfShader->size();
				stream->write(&microcodeLength, sizeof(size_t));
				stream->write(microcodeOfShader->getPtr(), microcodeLength);
			}
		}
	}
	//---------------------------------------------------------------------
	void GpuProgramManager::loadMicrocodeCache( DataStreamPtr stream )
	{
		mMicrocodeCache.clear();

		// write the size of the array
		size_t sizeOfArray = 0;
		stream->read(&sizeOfArray, sizeof(size_t));

		// loop the array and load it

		for ( size_t i = 0 ; i < sizeOfArray ; i++ )
		{
			String nameOfShader;
			// loads the name of the shader
			size_t stringLength  = 0;
			stream->read(&stringLength, sizeof(size_t));
			nameOfShader.resize(stringLength);
			stream->read(&nameOfShader[0], stringLength);

			// loads the microcode
			size_t microcodeLength = 0;
			stream->read(&microcodeLength, sizeof(size_t));

			Microcode microcodeOfShader(OGRE_NEW MemoryDataStream(nameOfShader, microcodeLength));
			microcodeOfShader->seek(0);
			stream->read(microcodeOfShader->getPtr(), microcodeLength);

			mMicrocodeCache.insert(make_pair(nameOfShader, microcodeOfShader));
		}
	}
	//---------------------------------------------------------------------

}
<commit_msg>Forgot the other half of this last bug fix.<commit_after>/*
-----------------------------------------------------------------------------
This source file is part of OGRE
    (Object-oriented Graphics Rendering Engine)
For the latest info, see http://www.ogre3d.org/

Copyright (c) 2000-2012 Torus Knot Software Ltd

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 "OgreStableHeaders.h"
#include "OgreGpuProgramManager.h"
#include "OgreHighLevelGpuProgramManager.h"
#include "OgreRoot.h"
#include "OgreRenderSystem.h"

namespace Ogre {
    //-----------------------------------------------------------------------
    template<> GpuProgramManager* Singleton<GpuProgramManager>::msSingleton = 0;
    GpuProgramManager* GpuProgramManager::getSingletonPtr(void)
    {
        return msSingleton;
    }
    GpuProgramManager& GpuProgramManager::getSingleton(void)
    {
        assert( msSingleton );  return ( *msSingleton );
    }
	//---------------------------------------------------------------------------
	GpuProgramManager::GpuProgramManager()
	{
		// Loading order
		mLoadOrder = 50.0f;
		// Resource type
		mResourceType = "GpuProgram";
		mSaveMicrocodesToCache = false;

		// subclasses should register with resource group manager
	}
	//---------------------------------------------------------------------------
	GpuProgramManager::~GpuProgramManager()
	{
		// subclasses should unregister with resource group manager
	}
	//---------------------------------------------------------------------------
    GpuProgramPtr GpuProgramManager::load(const String& name,
		const String& groupName, const String& filename,
		GpuProgramType gptype, const String& syntaxCode)
    {
		GpuProgramPtr prg;
		{
			OGRE_LOCK_AUTO_MUTEX
			prg = getByName(name);
			if (prg.isNull())
			{
				prg = createProgram(name, groupName, filename, gptype, syntaxCode);
			}

		}
        prg->load();
        return prg;
    }
    //---------------------------------------------------------------------------
	GpuProgramPtr GpuProgramManager::loadFromString(const String& name,
		const String& groupName, const String& code,
        GpuProgramType gptype, const String& syntaxCode)
    {
		GpuProgramPtr prg;
		{
			OGRE_LOCK_AUTO_MUTEX
			prg = getByName(name);
			if (prg.isNull())
			{
				prg = createProgramFromString(name, groupName, code, gptype, syntaxCode);
			}

		}
        prg->load();
        return prg;
    }
    //---------------------------------------------------------------------------
    ResourcePtr GpuProgramManager::create(const String& name, const String& group,
        GpuProgramType gptype, const String& syntaxCode, bool isManual,
        ManualResourceLoader* loader)
    {
        // Call creation implementation
        ResourcePtr ret = ResourcePtr(
            createImpl(name, getNextHandle(), group, isManual, loader, gptype, syntaxCode));

        addImpl(ret);
        // Tell resource group manager
        ResourceGroupManager::getSingleton()._notifyResourceCreated(ret);
        return ret;
    }
    //---------------------------------------------------------------------------
	GpuProgramPtr GpuProgramManager::createProgram(const String& name,
		const String& groupName, const String& filename,
		GpuProgramType gptype, const String& syntaxCode)
    {
		GpuProgramPtr prg = create(name, groupName, gptype, syntaxCode);
        // Set all prarmeters (create does not set, just determines factory)
		prg->setType(gptype);
		prg->setSyntaxCode(syntaxCode);
		prg->setSourceFile(filename);
        return prg;
    }
    //---------------------------------------------------------------------------
	GpuProgramPtr GpuProgramManager::createProgramFromString(const String& name,
		const String& groupName, const String& code, GpuProgramType gptype,
		const String& syntaxCode)
    {
		GpuProgramPtr prg = create(name, groupName, gptype, syntaxCode);
        // Set all prarmeters (create does not set, just determines factory)
		prg->setType(gptype);
		prg->setSyntaxCode(syntaxCode);
		prg->setSource(code);
        return prg;
    }
    //---------------------------------------------------------------------------
		const GpuProgramManager::SyntaxCodes& GpuProgramManager::getSupportedSyntax(void) const
        {
				// Use the current render system
			  RenderSystem* rs = Root::getSingleton().getRenderSystem();

				// Get the supported syntaxed from RenderSystemCapabilities
				return rs->getCapabilities()->getSupportedShaderProfiles();
        }

    //---------------------------------------------------------------------------
    bool GpuProgramManager::isSyntaxSupported(const String& syntaxCode) const
        {
				// Use the current render system
			  RenderSystem* rs = Root::getSingleton().getRenderSystem();

				// Get the supported syntaxed from RenderSystemCapabilities
				return rs->getCapabilities()->isShaderProfileSupported(syntaxCode);

    }
    //---------------------------------------------------------------------------
    ResourcePtr GpuProgramManager::getByName(const String& name, bool preferHighLevelPrograms)
    {
        ResourcePtr ret;
        if (preferHighLevelPrograms)
        {
            ret = HighLevelGpuProgramManager::getSingleton().getByName(name);
            if (!ret.isNull())
                return ret;
        }
        return ResourceManager::getByName(name);
    }
	//-----------------------------------------------------------------------------
	GpuProgramParametersSharedPtr GpuProgramManager::createParameters(void)
	{
		return GpuProgramParametersSharedPtr(OGRE_NEW GpuProgramParameters());
	}
	//---------------------------------------------------------------------
	GpuSharedParametersPtr GpuProgramManager::createSharedParameters(const String& name)
	{
		if (mSharedParametersMap.find(name) != mSharedParametersMap.end())
		{
			OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS,
				"The shared parameter set '" + name + "' already exists!",
				"GpuProgramManager::createSharedParameters");
		}
		GpuSharedParametersPtr ret(OGRE_NEW GpuSharedParameters(name));
		mSharedParametersMap[name] = ret;
		return ret;
	}
	//---------------------------------------------------------------------
	GpuSharedParametersPtr GpuProgramManager::getSharedParameters(const String& name) const
	{
		SharedParametersMap::const_iterator i = mSharedParametersMap.find(name);
		if (i == mSharedParametersMap.end())
		{
			OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS,
				"No shared parameter set with name '" + name + "'!",
				"GpuProgramManager::createSharedParameters");
		}
		return i->second;
	}
	//---------------------------------------------------------------------
	const GpuProgramManager::SharedParametersMap&
	GpuProgramManager::getAvailableSharedParameters() const
	{
		return mSharedParametersMap;
	}
	//---------------------------------------------------------------------
	bool GpuProgramManager::getSaveMicrocodesToCache()
	{
		return mSaveMicrocodesToCache;
	}
	//---------------------------------------------------------------------
	bool GpuProgramManager::canGetCompiledShaderBuffer()
	{
		// Use the current render system
		RenderSystem* rs = Root::getSingleton().getRenderSystem();

		// Check if the supported
		return rs->getCapabilities()->hasCapability(RSC_CAN_GET_COMPILED_SHADER_BUFFER);
	}
	//---------------------------------------------------------------------
	void GpuProgramManager::setSaveMicrocodesToCache( const bool val )
	{
		mSaveMicrocodesToCache = val;
	}
	//---------------------------------------------------------------------
	String GpuProgramManager::addRenderSystemToName( const String & name )
	{
		// Use the current render system
		RenderSystem* rs = Root::getSingleton().getRenderSystem();

		return rs->getName() + "_" + name;
	}
	//---------------------------------------------------------------------
	bool GpuProgramManager::isMicrocodeAvailableInCache( const String & name ) const
	{
		return mMicrocodeCache.find(addRenderSystemToName(name)) != mMicrocodeCache.end();
	}
	//---------------------------------------------------------------------
	const GpuProgramManager::Microcode & GpuProgramManager::getMicrocodeFromCache( const String & name ) const
	{
		return mMicrocodeCache.find(addRenderSystemToName(name))->second;
	}
	//---------------------------------------------------------------------
    GpuProgramManager::Microcode GpuProgramManager::createMicrocode( const size_t size ) const
	{
		return Microcode(OGRE_NEW MemoryDataStream(size));
	}
	//---------------------------------------------------------------------
	void GpuProgramManager::addMicrocodeToCache( const String & name, const GpuProgramManager::Microcode & microcode )
	{
		String nameWithRenderSystem = addRenderSystemToName(name);
		MicrocodeMap::iterator foundIter = mMicrocodeCache.find(nameWithRenderSystem);
		if ( foundIter == mMicrocodeCache.end() )
		{
			mMicrocodeCache.insert(make_pair(nameWithRenderSystem, microcode));
		}
		else
		{
			foundIter->second = microcode;

		}
	}
	//---------------------------------------------------------------------
	void GpuProgramManager::saveMicrocodeCache( DataStreamPtr stream ) const
	{
		if (!stream->isWriteable())
		{
			OGRE_EXCEPT(Exception::ERR_CANNOT_WRITE_TO_FILE,
				"Unable to write to stream " + stream->getName(),
				"GpuProgramManager::saveMicrocodeCache");
		}

		// write the size of the array
		size_t sizeOfArray = mMicrocodeCache.size();
		stream->write(&sizeOfArray, sizeof(size_t));

		// loop the array and save it
		MicrocodeMap::const_iterator iter = mMicrocodeCache.begin();
		MicrocodeMap::const_iterator iterE = mMicrocodeCache.end();
		for ( ; iter != iterE ; iter++ )
		{
			// saves the name of the shader
			{
				const String & nameOfShader = iter->first;
				size_t stringLength = nameOfShader.size();
				stream->write(&stringLength, sizeof(size_t));
				stream->write(&nameOfShader[0], stringLength);
			}
			// saves the microcode
			{
				const Microcode & microcodeOfShader = iter->second;
				size_t microcodeLength = microcodeOfShader->size();
				stream->write(&microcodeLength, sizeof(size_t));
				stream->write(microcodeOfShader->getPtr(), microcodeLength);
			}
		}
	}
	//---------------------------------------------------------------------
	void GpuProgramManager::loadMicrocodeCache( DataStreamPtr stream )
	{
		mMicrocodeCache.clear();

		// write the size of the array
		size_t sizeOfArray = 0;
		stream->read(&sizeOfArray, sizeof(size_t));

		// loop the array and load it

		for ( size_t i = 0 ; i < sizeOfArray ; i++ )
		{
			String nameOfShader;
			// loads the name of the shader
			size_t stringLength  = 0;
			stream->read(&stringLength, sizeof(size_t));
			nameOfShader.resize(stringLength);
			stream->read(&nameOfShader[0], stringLength);

			// loads the microcode
			size_t microcodeLength = 0;
			stream->read(&microcodeLength, sizeof(size_t));

			Microcode microcodeOfShader(OGRE_NEW MemoryDataStream(nameOfShader, microcodeLength));
			microcodeOfShader->seek(0);
			stream->read(microcodeOfShader->getPtr(), microcodeLength);

			mMicrocodeCache.insert(make_pair(nameOfShader, microcodeOfShader));
		}
	}
	//---------------------------------------------------------------------

}
<|endoftext|>


<commit_before>// testConstrollers.cpp
// Author:  Ajay Seth
/*
* Copyright (c)  2009, Stanford University. All rights reserved.
* Use of the OpenSim software in source form is permitted provided that the following
* conditions are met:
* 	1. The software is used only for non-commercial research and education. It may not
*     be used in relation to any commercial activity.
* 	2. The software is not distributed or redistributed.  Software distribution is allowed
*     only through https://simtk.org/home/opensim.
* 	3. Use of the OpenSim software or derivatives must be acknowledged in all publications,
*      presentations, or documents describing work in which OpenSim or derivatives are used.
* 	4. Credits to developers may not be removed from executables
*     created from modifications of the source.
* 	5. Modifications of source code must retain the above copyright notice, this list of
*     conditions and the following disclaimer.
*
*  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;
*  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
*  OR BUSINESS INTERRUPTION) 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.
*/

//==========================================================================================================
//	testControllers builds OpenSim models using the OpenSim API and verifies that controllers
//  behave as described.
//
//	Tests Include:
//		1. Test a control set controller on a block with an ideal actuator
//		2. Test a corrective controller on a block with an ideal actuator
//
//     Add tests here as new controller types are added to OpenSim
//
//==========================================================================================================
#include <iostream>
#include <OpenSim/Common/IO.h>
#include <OpenSim/Common/Exception.h>
#include <OpenSim/Simulation/Model/AnalysisSet.h>
#include <OpenSim/Simulation/Model/BodySet.h>
#include <OpenSim/Simulation/Manager/Manager.h>
#include <OpenSim/Analyses/Kinematics.h>
#include <OpenSim/Analyses/PointKinematics.h>
#include <OpenSim/Simulation/Model/Model.h>
#include <OpenSim/Simulation/SimbodyEngine/SliderJoint.h>
#include <OpenSim/Common/LoadOpenSimLibrary.h>
#include <OpenSim/Common/NaturalCubicSpline.h>
#include <OpenSim/Common/FunctionAdapter.h>
#include <OpenSim/Common/Constant.h>
#include <OpenSim/Tools/CorrectionController.h>
#include <OpenSim/Actuators/CoordinateActuator.h>
#include <OpenSim/Simulation/Control/ControlSetController.h>
#include <OpenSim/Simulation/Control/PrescribedController.h>
#include <OpenSim/Simulation/Control/ControlLinear.h>

using namespace OpenSim;
using namespace SimTK;
using namespace std;

//==========================================================================================================
bool testControlSetControllerOnBlock()
{
	bool status = true;

		// Create a new OpenSim model
	Model osimModel;
	osimModel.setName("osimModel");

	// Get the ground body
	OpenSim::Body& ground = osimModel.getGroundBody();

	// Create a 20 kg, 0.1 m^3 block body
	double blockMass = 20.0, blockSideLength = 0.1;
	Vec3 blockMassCenter(0), groundOrigin(0), blockInGround(0, blockSideLength/2, 0);
	Inertia blockIntertia = Inertia::brick(blockSideLength, blockSideLength, blockSideLength);

	OpenSim::Body block("block", blockMass, blockMassCenter, blockMass*blockIntertia);

	//Create a free joint with 6 degrees-of-freedom
	SimTK::Vec3 noRotation(0);
	SliderJoint blockToGround("",ground, blockInGround, noRotation, block, blockMassCenter, noRotation);
	// Create 6 coordinates (degrees-of-freedom) between the ground and block
	CoordinateSet& jointCoordinateSet = blockToGround.getCoordinateSet();
	double posRange[2] = {-1, 1};
	jointCoordinateSet[0].setName("xTranslation");
	jointCoordinateSet[0].setMotionType(Coordinate::Translational);
	jointCoordinateSet[0].setRange(posRange);

	// Add the block body to the model
	osimModel.addBody(&block);

	// Define a single coordinate actuator.
	CoordinateActuator actuator(jointCoordinateSet[0].getName());
	actuator.setName("actuator");

	// Add the actuator to the model
	osimModel.addForce(&actuator);

	double initialTime = 0;
	double finalTime = 1.0;

	// Define the initial and final control values
	double controlForce[1] = {100};
	// Create two control signals
	ControlLinear control;
	control.setName("actuator");
	// Create a control set and add the controls to the set
	ControlSet actuatorControls;
	actuatorControls.append(&control);
	actuatorControls.setMemoryOwner(false);
	actuatorControls.setControlValues(initialTime, controlForce);
	actuatorControls.setControlValues(finalTime, controlForce);
	// Create a control set controller that simply applies controls from a ControlSet
	ControlSetController actuatorController;
	actuatorController.setControlSet(&actuatorControls);

	// add the controller to the model
	osimModel.addController(&actuatorController);

	// Initialize the system and get the state representing the state system
	SimTK::State& si = osimModel.initSystem();

	// Specify zero slider joint kinematic states
	CoordinateSet &coordinates = osimModel.updCoordinateSet();
	coordinates[0].setValue(si, 0.0);    // x translation
	coordinates[0].setSpeedValue(si, 0.0);			 // x speed

	// Create the integrator and manager for the simulation.
	double accuracy = 1.0e-3;
	SimTK::RungeKuttaMersonIntegrator integrator(osimModel.getSystem());
	integrator.setMaximumStepSize(100);
	integrator.setMinimumStepSize(1.0e-6);
	integrator.setAccuracy(accuracy);
	integrator.setAbsoluteTolerance(1.0e-4);
	Manager manager(osimModel, integrator);

	// Integrate from initial time to final time
	manager.setInitialTime(initialTime);
	manager.setFinalTime(finalTime);
	std::cout<<"\n\nIntegrating from "<<initialTime<<" to "<<finalTime<<std::endl;
	manager.integrate(si);

	si.getQ().dump("Final position:");
	double x_err = fabs(coordinates[0].getValue(si) - 0.5*(controlForce[0]/blockMass)*finalTime*finalTime);
	if (x_err > accuracy){
		cout << "ControlSetControllerOnBlock failed to produce the expected motion." << endl;
		status = false;
	}

	// Save the simulation results
	Storage states(manager.getStateStorage());
	states.print("block_push.sto");

	osimModel.disownAllComponents();

	return status;
}// end of testControlSetControllerOnBlock()

//==========================================================================================================
bool testPrescribedControllerOnBlock()
{
	bool status = true;

		// Create a new OpenSim model
	Model osimModel;
	osimModel.setName("osimModel");

	// Get the ground body
	OpenSim::Body& ground = osimModel.getGroundBody();

	// Create a 20 kg, 0.1 m^3 block body
	double blockMass = 20.0, blockSideLength = 0.1;
	Vec3 blockMassCenter(0), groundOrigin(0), blockInGround(0, blockSideLength/2, 0);
	Inertia blockIntertia = Inertia::brick(blockSideLength, blockSideLength, blockSideLength);

	OpenSim::Body block("block", blockMass, blockMassCenter, blockMass*blockIntertia);

	//Create a free joint with 6 degrees-of-freedom
	SimTK::Vec3 noRotation(0);
	SliderJoint blockToGround("",ground, blockInGround, noRotation, block, blockMassCenter, noRotation);
	// Create 6 coordinates (degrees-of-freedom) between the ground and block
	CoordinateSet& jointCoordinateSet = blockToGround.getCoordinateSet();
	double posRange[2] = {-1, 1};
	jointCoordinateSet[0].setName("xTranslation");
	jointCoordinateSet[0].setMotionType(Coordinate::Translational);
	jointCoordinateSet[0].setRange(posRange);

	// Add the block body to the model
	osimModel.addBody(&block);

	// Define a single coordinate actuator.
	CoordinateActuator actuator(jointCoordinateSet[0].getName());
	actuator.setName("actuator");

	// Add the actuator to the model
	osimModel.addForce(&actuator);

	double initialTime = 0;
	double finalTime = 1.0;

	// Define the initial and final control values
	double controlForce = 100;

	// Create a prescribed controller that simply applies a function of the force
	PrescribedController actuatorController;
	actuatorController.prescribeControlForActuator(0, new Constant(controlForce));

	// add the controller to the model
	osimModel.addController(&actuatorController);

	// Initialize the system and get the state representing the state system
	SimTK::State& si = osimModel.initSystem();

	// Specify zero slider joint kinematic states
	CoordinateSet &coordinates = osimModel.updCoordinateSet();
	coordinates[0].setValue(si, 0.0);    // x translation
	coordinates[0].setSpeedValue(si, 0.0);			 // x speed

	// Create the integrator and manager for the simulation.
	double accuracy = 1.0e-3;
	SimTK::RungeKuttaMersonIntegrator integrator(osimModel.getSystem());
	integrator.setMaximumStepSize(100);
	integrator.setMinimumStepSize(1.0e-6);
	integrator.setAccuracy(accuracy);
	integrator.setAbsoluteTolerance(1.0e-4);
	Manager manager(osimModel, integrator);

	// Integrate from initial time to final time
	manager.setInitialTime(initialTime);
	manager.setFinalTime(finalTime);
	std::cout<<"\n\nIntegrating from "<<initialTime<<" to "<<finalTime<<std::endl;
	manager.integrate(si);

	si.getQ().dump("Final position:");
	double x_err = fabs(coordinates[0].getValue(si) - 0.5*(controlForce/blockMass)*finalTime*finalTime);
	if (x_err > accuracy){
		cout << "PrescribedController failed to produce the expected motion of block." << endl;
		status = false;
	}

	// Save the simulation results
	Storage states(manager.getStateStorage());
	states.print("block_push.sto");

	osimModel.disownAllComponents();

	return status;
}// end of testPrescribedControllerOnBlock()

//==========================================================================================================
bool testCorrectionControllerOnBlock()
{
	bool status = true;

		// Create a new OpenSim model
	Model osimModel;
	osimModel.setName("osimModel");

	// Get the ground body
	OpenSim::Body& ground = osimModel.getGroundBody();

	// Create a 20 kg, 0.1 m^3 block body
	double blockMass = 20.0, blockSideLength = 0.1;
	Vec3 blockMassCenter(0), groundOrigin(0), blockInGround(0, blockSideLength/2, 0);
	Inertia blockIntertia = Inertia::brick(blockSideLength, blockSideLength, blockSideLength);

	OpenSim::Body block("block", blockMass, blockMassCenter, blockMass*blockIntertia);

	//Create a free joint with 6 degrees-of-freedom
	SimTK::Vec3 noRotation(0);
	SliderJoint blockToGround("",ground, blockInGround, noRotation, block, blockMassCenter, noRotation);
	// Create 6 coordinates (degrees-of-freedom) between the ground and block
	CoordinateSet& jointCoordinateSet = blockToGround.getCoordinateSet();
	double posRange[2] = {-1, 1};
	jointCoordinateSet[0].setName("xTranslation");
	jointCoordinateSet[0].setMotionType(Coordinate::Translational);
	jointCoordinateSet[0].setRange(posRange);

	// Add the block body to the model
	osimModel.addBody(&block);

	// Generate tracking data
	Storage *desiredXTranslation = new Storage();

	CorrectionController tracker;

	// add the controller to the model
	osimModel.addController(&tracker);

	// Initialize the system and get the state representing the state system
	SimTK::State& si = osimModel.initSystem();

	// Create the integrator and manager for the simulation.
	SimTK::RungeKuttaMersonIntegrator integrator(osimModel.getSystem());
	integrator.setMaximumStepSize(1.0e-3);
	integrator.setMinimumStepSize(1.0e-6);
	integrator.setAccuracy(1.0e-3);
	integrator.setAbsoluteTolerance(1.0e-4);
	Manager manager(osimModel, integrator);

	osimModel.disownAllComponents();

	return status;
}// end of testCorrectionControllerOnBlock()

int main()
{
    int  status = 0;

	if(  !testControlSetControllerOnBlock()) {
        status = 1;
        cout << " testControlSetControllerOnBlock FAILED " << endl;
    }

	if(! testPrescribedControllerOnBlock()) {
        status = 1;
        cout << " testPrescribedControllerOnBlock FAILED " << endl;
    }

	if(  !testCorrectionControllerOnBlock()) {
        status = 1;
        cout << " testCorrectiveControllerOnBlock FAILED " << endl;
    }

	return status;
}
<commit_msg>Update testControllers.cpp to be consistent with change to PrescribedController<commit_after>// testConstrollers.cpp
// Author:  Ajay Seth
/*
* Copyright (c)  2009, Stanford University. All rights reserved.
* Use of the OpenSim software in source form is permitted provided that the following
* conditions are met:
* 	1. The software is used only for non-commercial research and education. It may not
*     be used in relation to any commercial activity.
* 	2. The software is not distributed or redistributed.  Software distribution is allowed
*     only through https://simtk.org/home/opensim.
* 	3. Use of the OpenSim software or derivatives must be acknowledged in all publications,
*      presentations, or documents describing work in which OpenSim or derivatives are used.
* 	4. Credits to developers may not be removed from executables
*     created from modifications of the source.
* 	5. Modifications of source code must retain the above copyright notice, this list of
*     conditions and the following disclaimer.
*
*  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;
*  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
*  OR BUSINESS INTERRUPTION) 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.
*/

//==========================================================================================================
//	testControllers builds OpenSim models using the OpenSim API and verifies that controllers
//  behave as described.
//
//	Tests Include:
//		1. Test a control set controller on a block with an ideal actuator
//		2. Test a corrective controller on a block with an ideal actuator
//
//     Add tests here as new controller types are added to OpenSim
//
//==========================================================================================================
#include <iostream>
#include <OpenSim/Common/IO.h>
#include <OpenSim/Common/Exception.h>
#include <OpenSim/Simulation/Model/AnalysisSet.h>
#include <OpenSim/Simulation/Model/BodySet.h>
#include <OpenSim/Simulation/Manager/Manager.h>
#include <OpenSim/Analyses/Kinematics.h>
#include <OpenSim/Analyses/PointKinematics.h>
#include <OpenSim/Simulation/Model/Model.h>
#include <OpenSim/Simulation/SimbodyEngine/SliderJoint.h>
#include <OpenSim/Common/LoadOpenSimLibrary.h>
#include <OpenSim/Common/NaturalCubicSpline.h>
#include <OpenSim/Common/FunctionAdapter.h>
#include <OpenSim/Common/Constant.h>
#include <OpenSim/Tools/CorrectionController.h>
#include <OpenSim/Actuators/CoordinateActuator.h>
#include <OpenSim/Simulation/Control/ControlSetController.h>
#include <OpenSim/Simulation/Control/PrescribedController.h>
#include <OpenSim/Simulation/Control/ControlLinear.h>

using namespace OpenSim;
using namespace SimTK;
using namespace std;

//==========================================================================================================
bool testControlSetControllerOnBlock()
{
	bool status = true;

		// Create a new OpenSim model
	Model osimModel;
	osimModel.setName("osimModel");

	// Get the ground body
	OpenSim::Body& ground = osimModel.getGroundBody();

	// Create a 20 kg, 0.1 m^3 block body
	double blockMass = 20.0, blockSideLength = 0.1;
	Vec3 blockMassCenter(0), groundOrigin(0), blockInGround(0, blockSideLength/2, 0);
	Inertia blockIntertia = Inertia::brick(blockSideLength, blockSideLength, blockSideLength);

	OpenSim::Body block("block", blockMass, blockMassCenter, blockMass*blockIntertia);

	//Create a free joint with 6 degrees-of-freedom
	SimTK::Vec3 noRotation(0);
	SliderJoint blockToGround("",ground, blockInGround, noRotation, block, blockMassCenter, noRotation);
	// Create 6 coordinates (degrees-of-freedom) between the ground and block
	CoordinateSet& jointCoordinateSet = blockToGround.getCoordinateSet();
	double posRange[2] = {-1, 1};
	jointCoordinateSet[0].setName("xTranslation");
	jointCoordinateSet[0].setMotionType(Coordinate::Translational);
	jointCoordinateSet[0].setRange(posRange);

	// Add the block body to the model
	osimModel.addBody(&block);

	// Define a single coordinate actuator.
	CoordinateActuator actuator(jointCoordinateSet[0].getName());
	actuator.setName("actuator");

	// Add the actuator to the model
	osimModel.addForce(&actuator);

	double initialTime = 0;
	double finalTime = 1.0;

	// Define the initial and final control values
	double controlForce[1] = {100};
	// Create two control signals
	ControlLinear control;
	control.setName("actuator");
	// Create a control set and add the controls to the set
	ControlSet actuatorControls;
	actuatorControls.append(&control);
	actuatorControls.setMemoryOwner(false);
	actuatorControls.setControlValues(initialTime, controlForce);
	actuatorControls.setControlValues(finalTime, controlForce);
	// Create a control set controller that simply applies controls from a ControlSet
	ControlSetController actuatorController;
	actuatorController.setControlSet(&actuatorControls);

	// add the controller to the model
	osimModel.addController(&actuatorController);

	// Initialize the system and get the state representing the state system
	SimTK::State& si = osimModel.initSystem();

	// Specify zero slider joint kinematic states
	CoordinateSet &coordinates = osimModel.updCoordinateSet();
	coordinates[0].setValue(si, 0.0);    // x translation
	coordinates[0].setSpeedValue(si, 0.0);			 // x speed

	// Create the integrator and manager for the simulation.
	double accuracy = 1.0e-3;
	SimTK::RungeKuttaMersonIntegrator integrator(osimModel.getSystem());
	integrator.setMaximumStepSize(100);
	integrator.setMinimumStepSize(1.0e-6);
	integrator.setAccuracy(accuracy);
	integrator.setAbsoluteTolerance(1.0e-4);
	Manager manager(osimModel, integrator);

	// Integrate from initial time to final time
	manager.setInitialTime(initialTime);
	manager.setFinalTime(finalTime);
	std::cout<<"\n\nIntegrating from "<<initialTime<<" to "<<finalTime<<std::endl;
	manager.integrate(si);

	si.getQ().dump("Final position:");
	double x_err = fabs(coordinates[0].getValue(si) - 0.5*(controlForce[0]/blockMass)*finalTime*finalTime);
	if (x_err > accuracy){
		cout << "ControlSetControllerOnBlock failed to produce the expected motion." << endl;
		status = false;
	}

	// Save the simulation results
	Storage states(manager.getStateStorage());
	states.print("block_push.sto");

	osimModel.disownAllComponents();

	return status;
}// end of testControlSetControllerOnBlock()

//==========================================================================================================
bool testPrescribedControllerOnBlock()
{
	bool status = true;

		// Create a new OpenSim model
	Model osimModel;
	osimModel.setName("osimModel");

	// Get the ground body
	OpenSim::Body& ground = osimModel.getGroundBody();

	// Create a 20 kg, 0.1 m^3 block body
	double blockMass = 20.0, blockSideLength = 0.1;
	Vec3 blockMassCenter(0), groundOrigin(0), blockInGround(0, blockSideLength/2, 0);
	Inertia blockIntertia = Inertia::brick(blockSideLength, blockSideLength, blockSideLength);

	OpenSim::Body block("block", blockMass, blockMassCenter, blockMass*blockIntertia);

	//Create a free joint with 6 degrees-of-freedom
	SimTK::Vec3 noRotation(0);
	SliderJoint blockToGround("",ground, blockInGround, noRotation, block, blockMassCenter, noRotation);
	// Create 6 coordinates (degrees-of-freedom) between the ground and block
	CoordinateSet& jointCoordinateSet = blockToGround.getCoordinateSet();
	double posRange[2] = {-1, 1};
	jointCoordinateSet[0].setName("xTranslation");
	jointCoordinateSet[0].setMotionType(Coordinate::Translational);
	jointCoordinateSet[0].setRange(posRange);

	// Add the block body to the model
	osimModel.addBody(&block);

	// Define a single coordinate actuator.
	CoordinateActuator actuator(jointCoordinateSet[0].getName());
	actuator.setName("actuator");

	// Add the actuator to the model
	osimModel.addForce(&actuator);

	double initialTime = 0;
	double finalTime = 1.0;

	// Define the initial and final control values
	double controlForce = 100;

	// Create a prescribed controller that simply applies a function of the force
	PrescribedController actuatorController;
	actuatorController.setActuators(osimModel.updActuators());
	actuatorController.prescribeControlForActuator(0, new Constant(controlForce));

	// add the controller to the model
	osimModel.addController(&actuatorController);

	// Initialize the system and get the state representing the state system
	SimTK::State& si = osimModel.initSystem();

	// Specify zero slider joint kinematic states
	CoordinateSet &coordinates = osimModel.updCoordinateSet();
	coordinates[0].setValue(si, 0.0);    // x translation
	coordinates[0].setSpeedValue(si, 0.0);			 // x speed

	// Create the integrator and manager for the simulation.
	double accuracy = 1.0e-3;
	SimTK::RungeKuttaMersonIntegrator integrator(osimModel.getSystem());
	integrator.setMaximumStepSize(100);
	integrator.setMinimumStepSize(1.0e-6);
	integrator.setAccuracy(accuracy);
	integrator.setAbsoluteTolerance(1.0e-4);
	Manager manager(osimModel, integrator);

	// Integrate from initial time to final time
	manager.setInitialTime(initialTime);
	manager.setFinalTime(finalTime);
	std::cout<<"\n\nIntegrating from "<<initialTime<<" to "<<finalTime<<std::endl;
	manager.integrate(si);

	si.getQ().dump("Final position:");
	double x_err = fabs(coordinates[0].getValue(si) - 0.5*(controlForce/blockMass)*finalTime*finalTime);
	if (x_err > accuracy){
		cout << "PrescribedController failed to produce the expected motion of block." << endl;
		status = false;
	}

	// Save the simulation results
	Storage states(manager.getStateStorage());
	states.print("block_push.sto");

	osimModel.disownAllComponents();

	return status;
}// end of testPrescribedControllerOnBlock()

//==========================================================================================================
bool testCorrectionControllerOnBlock()
{
	bool status = true;

		// Create a new OpenSim model
	Model osimModel;
	osimModel.setName("osimModel");

	// Get the ground body
	OpenSim::Body& ground = osimModel.getGroundBody();

	// Create a 20 kg, 0.1 m^3 block body
	double blockMass = 20.0, blockSideLength = 0.1;
	Vec3 blockMassCenter(0), groundOrigin(0), blockInGround(0, blockSideLength/2, 0);
	Inertia blockIntertia = Inertia::brick(blockSideLength, blockSideLength, blockSideLength);

	OpenSim::Body block("block", blockMass, blockMassCenter, blockMass*blockIntertia);

	//Create a free joint with 6 degrees-of-freedom
	SimTK::Vec3 noRotation(0);
	SliderJoint blockToGround("",ground, blockInGround, noRotation, block, blockMassCenter, noRotation);
	// Create 6 coordinates (degrees-of-freedom) between the ground and block
	CoordinateSet& jointCoordinateSet = blockToGround.getCoordinateSet();
	double posRange[2] = {-1, 1};
	jointCoordinateSet[0].setName("xTranslation");
	jointCoordinateSet[0].setMotionType(Coordinate::Translational);
	jointCoordinateSet[0].setRange(posRange);

	// Add the block body to the model
	osimModel.addBody(&block);

	// Generate tracking data
	Storage *desiredXTranslation = new Storage();

	CorrectionController tracker;

	// add the controller to the model
	osimModel.addController(&tracker);

	// Initialize the system and get the state representing the state system
	SimTK::State& si = osimModel.initSystem();

	// Create the integrator and manager for the simulation.
	SimTK::RungeKuttaMersonIntegrator integrator(osimModel.getSystem());
	integrator.setMaximumStepSize(1.0e-3);
	integrator.setMinimumStepSize(1.0e-6);
	integrator.setAccuracy(1.0e-3);
	integrator.setAbsoluteTolerance(1.0e-4);
	Manager manager(osimModel, integrator);

	osimModel.disownAllComponents();

	return status;
}// end of testCorrectionControllerOnBlock()

int main()
{
    int  status = 0;

	if(  !testControlSetControllerOnBlock()) {
        status = 1;
        cout << " testControlSetControllerOnBlock FAILED " << endl;
    }

	if(! testPrescribedControllerOnBlock()) {
        status = 1;
        cout << " testPrescribedControllerOnBlock FAILED " << endl;
    }

	if(  !testCorrectionControllerOnBlock()) {
        status = 1;
        cout << " testCorrectiveControllerOnBlock FAILED " << endl;
    }

	return status;
}
<|endoftext|>