<commit_before>/*

openfx-arena - https://github.com/olear/openfx-arena

Copyright (c) 2015, Ole-André Rodlie <olear@fxarena.net>
Copyright (c) 2015, FxArena DA <mail@fxarena.net>
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

* Redistributions of source code must retain the above copyright notice, this
  list of conditions and the following disclaimer.

* Neither the name of FxArena DA nor the names of its
  contributors may be used to endorse or promote products derived from
  this software without specific prior written permission.

* Redistributions in binary form must reproduce the above copyright notice,
  this list of conditions and the following disclaimer in the documentation
  and/or other materials provided with the distribution.

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 HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

*/

#include "Mirror.h"
#include "ofxsMacros.h"
#include <Magick++.h>

#define kPluginName "Mirror"
#define kPluginGrouping "Filter"
#define kPluginDescription  "Mirrors image in various ways."

#define kPluginIdentifier "net.fxarena.openfx.Mirror"
#define kPluginVersionMajor 3
#define kPluginVersionMinor 1

#define kParamMirror "mirrorType"
#define kParamMirrorLabel "Type"
#define kParamMirrorHint "Select mirror type"
#define kParamMirrorDefault 1

#define kSupportsTiles 0
#define kSupportsMultiResolution 0
#define kSupportsRenderScale 1
#define kRenderThreadSafety eRenderInstanceSafe

using namespace OFX;

class MirrorPlugin : public OFX::ImageEffect
{
public:
    MirrorPlugin(OfxImageEffectHandle handle);
    virtual ~MirrorPlugin();
    virtual void render(const OFX::RenderArguments &args) OVERRIDE FINAL;
    virtual bool getRegionOfDefinition(const OFX::RegionOfDefinitionArguments &args, OfxRectD &rod) OVERRIDE FINAL;
private:
    OFX::Clip *dstClip_;
    OFX::Clip *srcClip_;
    OFX::ChoiceParam *mirror_;
};

MirrorPlugin::MirrorPlugin(OfxImageEffectHandle handle)
: OFX::ImageEffect(handle)
, dstClip_(0)
, srcClip_(0)
{
    Magick::InitializeMagick(NULL);
    dstClip_ = fetchClip(kOfxImageEffectOutputClipName);
    assert(dstClip_ && dstClip_->getPixelComponents() == OFX::ePixelComponentRGBA);
    srcClip_ = fetchClip(kOfxImageEffectSimpleSourceClipName);
    assert(srcClip_ && srcClip_->getPixelComponents() == OFX::ePixelComponentRGBA);
    mirror_ = fetchChoiceParam(kParamMirror);
    assert(mirror_);
}

MirrorPlugin::~MirrorPlugin()
{
}

void MirrorPlugin::render(const OFX::RenderArguments &args)
{
    // render scale
    if (!kSupportsRenderScale && (args.renderScale.x != 1. || args.renderScale.y != 1.)) {
        OFX::throwSuiteStatusException(kOfxStatFailed);
        return;
    }

    // get src clip
    if (!srcClip_) {
        OFX::throwSuiteStatusException(kOfxStatFailed);
        return;
    }
    assert(srcClip_);
    std::auto_ptr<const OFX::Image> srcImg(srcClip_->fetchImage(args.time));
    OfxRectI srcRod,srcBounds;
    if (srcImg.get()) {
        srcRod = srcImg->getRegionOfDefinition();
        srcBounds = srcImg->getBounds();
        if (srcImg->getRenderScale().x != args.renderScale.x ||
            srcImg->getRenderScale().y != args.renderScale.y ||
            srcImg->getField() != args.fieldToRender) {
            setPersistentMessage(OFX::Message::eMessageError, "", "OFX Host gave image with wrong scale or field properties");
            OFX::throwSuiteStatusException(kOfxStatFailed);
            return;
        }
    }

    // get dest clip
    if (!dstClip_) {
        OFX::throwSuiteStatusException(kOfxStatFailed);
        return;
    }
    assert(dstClip_);
    std::auto_ptr<OFX::Image> dstImg(dstClip_->fetchImage(args.time));
    if (!dstImg.get()) {
        OFX::throwSuiteStatusException(kOfxStatFailed);
        return;
    }
    if (dstImg->getRenderScale().x != args.renderScale.x ||
        dstImg->getRenderScale().y != args.renderScale.y ||
        dstImg->getField() != args.fieldToRender) {
        setPersistentMessage(OFX::Message::eMessageError, "", "OFX Host gave image with wrong scale or field properties");
        OFX::throwSuiteStatusException(kOfxStatFailed);
        return;
    }

    // get bit depth
    OFX::BitDepthEnum dstBitDepth = dstImg->getPixelDepth();
    if (dstBitDepth != OFX::eBitDepthFloat || (srcImg.get() && (dstBitDepth != srcImg->getPixelDepth()))) {
        OFX::throwSuiteStatusException(kOfxStatErrFormat);
        return;
    }

    // get pixel component
    OFX::PixelComponentEnum dstComponents  = dstImg->getPixelComponents();
    if (dstComponents != OFX::ePixelComponentRGBA || (srcImg.get() && (dstComponents != srcImg->getPixelComponents()))) {
        OFX::throwSuiteStatusException(kOfxStatErrFormat);
        return;
    }

    // are we in the image bounds?
    OfxRectI dstBounds = dstImg->getBounds();
    if(args.renderWindow.x1 < dstBounds.x1 || args.renderWindow.x1 >= dstBounds.x2 || args.renderWindow.y1 < dstBounds.y1 || args.renderWindow.y1 >= dstBounds.y2 ||
       args.renderWindow.x2 <= dstBounds.x1 || args.renderWindow.x2 > dstBounds.x2 || args.renderWindow.y2 <= dstBounds.y1 || args.renderWindow.y2 > dstBounds.y2) {
        OFX::throwSuiteStatusException(kOfxStatErrValue);
        return;
    }

    // get params
    int mirror = 0;
    mirror_->getValueAtTime(args.time, mirror);

    // setup
    int srcWidth = srcRod.x2-srcRod.x1;
    int srcHeight = srcRod.y2-srcRod.y1;
    int mirrorWidth = srcWidth/2;
    int mirrorHeight = srcHeight/2;
    Magick::Image image;
    Magick::Image image1;
    Magick::Image image2;
    Magick::Image image3;
    Magick::Image image4;

    // read source image
    Magick::Image container(Magick::Geometry(srcWidth,srcHeight),Magick::Color("rgba(0,0,0,0)"));
    if (srcClip_ && srcClip_->isConnected())
        image.read(srcWidth,srcHeight,"RGBA",Magick::FloatPixel,(float*)srcImg->getPixelData());

    // proc image(s)
    switch(mirror) {
    case 1: // North
        image1 = image;
        image1.flip();
        image.crop(Magick::Geometry(srcWidth,mirrorHeight,0,mirrorHeight));
        image1.crop(Magick::Geometry(srcWidth,mirrorHeight,0,0));
        container.composite(image,0,mirrorHeight,Magick::OverCompositeOp);
        container.composite(image1,0,0,Magick::OverCompositeOp);
        break;
    case 2: // South
        image1 = image;
        image.flip();
        image.crop(Magick::Geometry(srcWidth,mirrorHeight,0,mirrorHeight));
        image1.crop(Magick::Geometry(srcWidth,mirrorHeight,0,0));
        container.composite(image,0,mirrorHeight,Magick::OverCompositeOp);
        container.composite(image1,0,0,Magick::OverCompositeOp);
        break;
    case 3: // East
        image1 = image;
        image1.flop();
        image.crop(Magick::Geometry(mirrorWidth,srcHeight,mirrorWidth,0));
        image1.crop(Magick::Geometry(mirrorWidth,srcHeight,0,0));
        container.composite(image,mirrorWidth,0,Magick::OverCompositeOp);
        container.composite(image1,0,0,Magick::OverCompositeOp);
        break;
    case 4: // West
        image1 = image;
        image.flop();
        image.crop(Magick::Geometry(mirrorWidth,srcHeight,mirrorWidth,0));
        image1.crop(Magick::Geometry(mirrorWidth,srcHeight,0,0));
        container.composite(image,mirrorWidth,0,Magick::OverCompositeOp);
        container.composite(image1,0,0,Magick::OverCompositeOp);
        break;
    case 5: // NorthWest
        image1 = image;
        image1.crop(Magick::Geometry(mirrorWidth,mirrorHeight,0,mirrorHeight));
        image2 = image1;
        image2.flop();
        image3 = image2;
        image3.flip();
        image4 = image3;
        image4.flop();
        break;
    case 6: // NorthEast
        image1 = image;
        image1.crop(Magick::Geometry(mirrorWidth,mirrorHeight,mirrorWidth,mirrorHeight));
        image1.flop();
        image2 = image1;
        image2.flop();
        image3 = image2;
        image3.flip();
        image4 = image3;
        image4.flop();
        break;
    case 7: // SouthWest
        image1 = image;
        image1.crop(Magick::Geometry(mirrorWidth,mirrorHeight,0,0));
        image1.flip();
        image2 = image1;
        image2.flop();
        image3 = image2;
        image3.flip();
        image4 = image3;
        image4.flop();
        break;
    case 8: // SouthEast
        image1 = image;
        image1.crop(Magick::Geometry(mirrorWidth,mirrorHeight,mirrorWidth,0));
        image1.flop();
        image1.flip();
        image2 = image1;
        image2.flop();
        image3 = image2;
        image3.flip();
        image4 = image3;
        image4.flop();
        break;
    default: // None
        container = image;
        break;
    }
    if (mirror==5|mirror==6||mirror==7||mirror==8) {
        container.composite(image1,0,mirrorHeight,Magick::OverCompositeOp);
        container.composite(image2,mirrorWidth,mirrorHeight,Magick::OverCompositeOp);
        container.composite(image3,mirrorWidth,0,Magick::OverCompositeOp);
        container.composite(image4,0,0,Magick::OverCompositeOp);
    }

    // return image
    if (dstClip_ && dstClip_->isConnected() && srcClip_ && srcClip_->isConnected()) {
        switch (dstBitDepth) {
        case eBitDepthUByte: // 8bit
            if (image.depth()>8)
                image.depth(8);
            container.write(0,0,srcWidth,srcHeight,"RGBA",Magick::CharPixel,(float*)dstImg->getPixelData());
            break;
        case eBitDepthUShort: // 16bit
            if (image.depth()>16)
                image.depth(16);
            container.write(0,0,srcWidth,srcHeight,"RGBA",Magick::ShortPixel,(float*)dstImg->getPixelData());
            break;
        case eBitDepthFloat: // 32bit
            container.write(0,0,srcWidth,srcHeight,"RGBA",Magick::FloatPixel,(float*)dstImg->getPixelData());
            break;
        }
    }
}

bool MirrorPlugin::getRegionOfDefinition(const OFX::RegionOfDefinitionArguments &args, OfxRectD &rod)
{
    if (!kSupportsRenderScale && (args.renderScale.x != 1. || args.renderScale.y != 1.)) {
        OFX::throwSuiteStatusException(kOfxStatFailed);
        return false;
    }
    if (srcClip_ && srcClip_->isConnected()) {
        rod = srcClip_->getRegionOfDefinition(args.time);
    } else {
        rod.x1 = rod.y1 = kOfxFlagInfiniteMin;
        rod.x2 = rod.y2 = kOfxFlagInfiniteMax;
    }
    return true;
}

mDeclarePluginFactory(MirrorPluginFactory, {}, {});

/** @brief The basic describe function, passed a plugin descriptor */
void MirrorPluginFactory::describe(OFX::ImageEffectDescriptor &desc)
{
    // basic labels
    desc.setLabel(kPluginName);
    desc.setPluginGrouping(kPluginGrouping);
    desc.setPluginDescription(kPluginDescription);

    // add the supported contexts
    desc.addSupportedContext(eContextGeneral);
    desc.addSupportedContext(eContextFilter);

    // add supported pixel depths
    //desc.addSupportedBitDepth(eBitDepthUByte);
    //desc.addSupportedBitDepth(eBitDepthUShort);
    desc.addSupportedBitDepth(eBitDepthFloat);

    // other
    desc.setSupportsTiles(kSupportsTiles);
    desc.setSupportsMultiResolution(kSupportsMultiResolution);
    desc.setRenderThreadSafety(kRenderThreadSafety);
}

/** @brief The describe in context function, passed a plugin descriptor and a context */
void MirrorPluginFactory::describeInContext(OFX::ImageEffectDescriptor &desc, ContextEnum /*context*/)
{
    // create the mandated source clip
    ClipDescriptor *srcClip = desc.defineClip(kOfxImageEffectSimpleSourceClipName);
    srcClip->addSupportedComponent(ePixelComponentRGBA);
    srcClip->setTemporalClipAccess(false);
    srcClip->setSupportsTiles(kSupportsTiles);
    srcClip->setIsMask(false);

    // create the mandated output clip
    ClipDescriptor *dstClip = desc.defineClip(kOfxImageEffectOutputClipName);
    dstClip->addSupportedComponent(ePixelComponentRGBA);
    dstClip->setSupportsTiles(kSupportsTiles);

    // make pages and params
    PageParamDescriptor *page = desc.definePageParam(kPluginName);
    {
        ChoiceParamDescriptor *param = desc.defineChoiceParam(kParamMirror);
        param->setLabel(kParamMirrorLabel);
        param->setHint(kParamMirrorHint);
        param->appendOption("Undefined");
        param->appendOption("North");
        param->appendOption("South");
        param->appendOption("East");
        param->appendOption("West");
        param->appendOption("NorthWest");
        param->appendOption("NorthEast");
        param->appendOption("SouthWest");
        param->appendOption("SouthEast");
        param->setDefault(kParamMirrorDefault);
        param->setAnimates(true);
        page->addChild(*param);
    }
}

/** @brief The create instance function, the plugin must return an object derived from the \ref OFX::ImageEffect class */
ImageEffect* MirrorPluginFactory::createInstance(OfxImageEffectHandle handle, ContextEnum /*context*/)
{
    return new MirrorPlugin(handle);
}

void getMirrorPluginID(OFX::PluginFactoryArray &ids)
{
    static MirrorPluginFactory p(kPluginIdentifier, kPluginVersionMajor, kPluginVersionMinor);
    ids.push_back(&p);
}
<commit_msg>Mirror: fix typo<commit_after>/*

openfx-arena - https://github.com/olear/openfx-arena

Copyright (c) 2015, Ole-André Rodlie <olear@fxarena.net>
Copyright (c) 2015, FxArena DA <mail@fxarena.net>
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

* Redistributions of source code must retain the above copyright notice, this
  list of conditions and the following disclaimer.

* Neither the name of FxArena DA nor the names of its
  contributors may be used to endorse or promote products derived from
  this software without specific prior written permission.

* Redistributions in binary form must reproduce the above copyright notice,
  this list of conditions and the following disclaimer in the documentation
  and/or other materials provided with the distribution.

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 HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

*/

#include "Mirror.h"
#include "ofxsMacros.h"
#include <Magick++.h>

#define kPluginName "Mirror"
#define kPluginGrouping "Filter"
#define kPluginDescription  "Mirrors image in various ways."

#define kPluginIdentifier "net.fxarena.openfx.Mirror"
#define kPluginVersionMajor 3
#define kPluginVersionMinor 1

#define kParamMirror "mirrorType"
#define kParamMirrorLabel "Type"
#define kParamMirrorHint "Select mirror type"
#define kParamMirrorDefault 1

#define kSupportsTiles 0
#define kSupportsMultiResolution 0
#define kSupportsRenderScale 1
#define kRenderThreadSafety eRenderInstanceSafe

using namespace OFX;

class MirrorPlugin : public OFX::ImageEffect
{
public:
    MirrorPlugin(OfxImageEffectHandle handle);
    virtual ~MirrorPlugin();
    virtual void render(const OFX::RenderArguments &args) OVERRIDE FINAL;
    virtual bool getRegionOfDefinition(const OFX::RegionOfDefinitionArguments &args, OfxRectD &rod) OVERRIDE FINAL;
private:
    OFX::Clip *dstClip_;
    OFX::Clip *srcClip_;
    OFX::ChoiceParam *mirror_;
};

MirrorPlugin::MirrorPlugin(OfxImageEffectHandle handle)
: OFX::ImageEffect(handle)
, dstClip_(0)
, srcClip_(0)
{
    Magick::InitializeMagick(NULL);
    dstClip_ = fetchClip(kOfxImageEffectOutputClipName);
    assert(dstClip_ && dstClip_->getPixelComponents() == OFX::ePixelComponentRGBA);
    srcClip_ = fetchClip(kOfxImageEffectSimpleSourceClipName);
    assert(srcClip_ && srcClip_->getPixelComponents() == OFX::ePixelComponentRGBA);
    mirror_ = fetchChoiceParam(kParamMirror);
    assert(mirror_);
}

MirrorPlugin::~MirrorPlugin()
{
}

void MirrorPlugin::render(const OFX::RenderArguments &args)
{
    // render scale
    if (!kSupportsRenderScale && (args.renderScale.x != 1. || args.renderScale.y != 1.)) {
        OFX::throwSuiteStatusException(kOfxStatFailed);
        return;
    }

    // get src clip
    if (!srcClip_) {
        OFX::throwSuiteStatusException(kOfxStatFailed);
        return;
    }
    assert(srcClip_);
    std::auto_ptr<const OFX::Image> srcImg(srcClip_->fetchImage(args.time));
    OfxRectI srcRod,srcBounds;
    if (srcImg.get()) {
        srcRod = srcImg->getRegionOfDefinition();
        srcBounds = srcImg->getBounds();
        if (srcImg->getRenderScale().x != args.renderScale.x ||
            srcImg->getRenderScale().y != args.renderScale.y ||
            srcImg->getField() != args.fieldToRender) {
            setPersistentMessage(OFX::Message::eMessageError, "", "OFX Host gave image with wrong scale or field properties");
            OFX::throwSuiteStatusException(kOfxStatFailed);
            return;
        }
    }

    // get dest clip
    if (!dstClip_) {
        OFX::throwSuiteStatusException(kOfxStatFailed);
        return;
    }
    assert(dstClip_);
    std::auto_ptr<OFX::Image> dstImg(dstClip_->fetchImage(args.time));
    if (!dstImg.get()) {
        OFX::throwSuiteStatusException(kOfxStatFailed);
        return;
    }
    if (dstImg->getRenderScale().x != args.renderScale.x ||
        dstImg->getRenderScale().y != args.renderScale.y ||
        dstImg->getField() != args.fieldToRender) {
        setPersistentMessage(OFX::Message::eMessageError, "", "OFX Host gave image with wrong scale or field properties");
        OFX::throwSuiteStatusException(kOfxStatFailed);
        return;
    }

    // get bit depth
    OFX::BitDepthEnum dstBitDepth = dstImg->getPixelDepth();
    if (dstBitDepth != OFX::eBitDepthFloat || (srcImg.get() && (dstBitDepth != srcImg->getPixelDepth()))) {
        OFX::throwSuiteStatusException(kOfxStatErrFormat);
        return;
    }

    // get pixel component
    OFX::PixelComponentEnum dstComponents  = dstImg->getPixelComponents();
    if (dstComponents != OFX::ePixelComponentRGBA || (srcImg.get() && (dstComponents != srcImg->getPixelComponents()))) {
        OFX::throwSuiteStatusException(kOfxStatErrFormat);
        return;
    }

    // are we in the image bounds?
    OfxRectI dstBounds = dstImg->getBounds();
    if(args.renderWindow.x1 < dstBounds.x1 || args.renderWindow.x1 >= dstBounds.x2 || args.renderWindow.y1 < dstBounds.y1 || args.renderWindow.y1 >= dstBounds.y2 ||
       args.renderWindow.x2 <= dstBounds.x1 || args.renderWindow.x2 > dstBounds.x2 || args.renderWindow.y2 <= dstBounds.y1 || args.renderWindow.y2 > dstBounds.y2) {
        OFX::throwSuiteStatusException(kOfxStatErrValue);
        return;
    }

    // get params
    int mirror = 0;
    mirror_->getValueAtTime(args.time, mirror);

    // setup
    int srcWidth = srcRod.x2-srcRod.x1;
    int srcHeight = srcRod.y2-srcRod.y1;
    int mirrorWidth = srcWidth/2;
    int mirrorHeight = srcHeight/2;
    Magick::Image image;
    Magick::Image image1;
    Magick::Image image2;
    Magick::Image image3;
    Magick::Image image4;

    // read source image
    Magick::Image container(Magick::Geometry(srcWidth,srcHeight),Magick::Color("rgba(0,0,0,0)"));
    if (srcClip_ && srcClip_->isConnected())
        image.read(srcWidth,srcHeight,"RGBA",Magick::FloatPixel,(float*)srcImg->getPixelData());

    // proc image(s)
    switch(mirror) {
    case 1: // North
        image1 = image;
        image1.flip();
        image.crop(Magick::Geometry(srcWidth,mirrorHeight,0,mirrorHeight));
        image1.crop(Magick::Geometry(srcWidth,mirrorHeight,0,0));
        container.composite(image,0,mirrorHeight,Magick::OverCompositeOp);
        container.composite(image1,0,0,Magick::OverCompositeOp);
        break;
    case 2: // South
        image1 = image;
        image.flip();
        image.crop(Magick::Geometry(srcWidth,mirrorHeight,0,mirrorHeight));
        image1.crop(Magick::Geometry(srcWidth,mirrorHeight,0,0));
        container.composite(image,0,mirrorHeight,Magick::OverCompositeOp);
        container.composite(image1,0,0,Magick::OverCompositeOp);
        break;
    case 3: // East
        image1 = image;
        image1.flop();
        image.crop(Magick::Geometry(mirrorWidth,srcHeight,mirrorWidth,0));
        image1.crop(Magick::Geometry(mirrorWidth,srcHeight,0,0));
        container.composite(image,mirrorWidth,0,Magick::OverCompositeOp);
        container.composite(image1,0,0,Magick::OverCompositeOp);
        break;
    case 4: // West
        image1 = image;
        image.flop();
        image.crop(Magick::Geometry(mirrorWidth,srcHeight,mirrorWidth,0));
        image1.crop(Magick::Geometry(mirrorWidth,srcHeight,0,0));
        container.composite(image,mirrorWidth,0,Magick::OverCompositeOp);
        container.composite(image1,0,0,Magick::OverCompositeOp);
        break;
    case 5: // NorthWest
        image1 = image;
        image1.crop(Magick::Geometry(mirrorWidth,mirrorHeight,0,mirrorHeight));
        image2 = image1;
        image2.flop();
        image3 = image2;
        image3.flip();
        image4 = image3;
        image4.flop();
        break;
    case 6: // NorthEast
        image1 = image;
        image1.crop(Magick::Geometry(mirrorWidth,mirrorHeight,mirrorWidth,mirrorHeight));
        image1.flop();
        image2 = image1;
        image2.flop();
        image3 = image2;
        image3.flip();
        image4 = image3;
        image4.flop();
        break;
    case 7: // SouthWest
        image1 = image;
        image1.crop(Magick::Geometry(mirrorWidth,mirrorHeight,0,0));
        image1.flip();
        image2 = image1;
        image2.flop();
        image3 = image2;
        image3.flip();
        image4 = image3;
        image4.flop();
        break;
    case 8: // SouthEast
        image1 = image;
        image1.crop(Magick::Geometry(mirrorWidth,mirrorHeight,mirrorWidth,0));
        image1.flop();
        image1.flip();
        image2 = image1;
        image2.flop();
        image3 = image2;
        image3.flip();
        image4 = image3;
        image4.flop();
        break;
    default: // None
        container = image;
        break;
    }
    if (mirror==5|mirror==6||mirror==7||mirror==8) {
        container.composite(image1,0,mirrorHeight,Magick::OverCompositeOp);
        container.composite(image2,mirrorWidth,mirrorHeight,Magick::OverCompositeOp);
        container.composite(image3,mirrorWidth,0,Magick::OverCompositeOp);
        container.composite(image4,0,0,Magick::OverCompositeOp);
    }

    // return image
    if (dstClip_ && dstClip_->isConnected() && srcClip_ && srcClip_->isConnected()) {
        switch (dstBitDepth) {
        case eBitDepthUByte: // 8bit
            if (container.depth()>8)
                container.depth(8);
            container.write(0,0,srcWidth,srcHeight,"RGBA",Magick::CharPixel,(float*)dstImg->getPixelData());
            break;
        case eBitDepthUShort: // 16bit
            if (container.depth()>16)
                container.depth(16);
            container.write(0,0,srcWidth,srcHeight,"RGBA",Magick::ShortPixel,(float*)dstImg->getPixelData());
            break;
        case eBitDepthFloat: // 32bit
            container.write(0,0,srcWidth,srcHeight,"RGBA",Magick::FloatPixel,(float*)dstImg->getPixelData());
            break;
        }
    }
}

bool MirrorPlugin::getRegionOfDefinition(const OFX::RegionOfDefinitionArguments &args, OfxRectD &rod)
{
    if (!kSupportsRenderScale && (args.renderScale.x != 1. || args.renderScale.y != 1.)) {
        OFX::throwSuiteStatusException(kOfxStatFailed);
        return false;
    }
    if (srcClip_ && srcClip_->isConnected()) {
        rod = srcClip_->getRegionOfDefinition(args.time);
    } else {
        rod.x1 = rod.y1 = kOfxFlagInfiniteMin;
        rod.x2 = rod.y2 = kOfxFlagInfiniteMax;
    }
    return true;
}

mDeclarePluginFactory(MirrorPluginFactory, {}, {});

/** @brief The basic describe function, passed a plugin descriptor */
void MirrorPluginFactory::describe(OFX::ImageEffectDescriptor &desc)
{
    // basic labels
    desc.setLabel(kPluginName);
    desc.setPluginGrouping(kPluginGrouping);
    desc.setPluginDescription(kPluginDescription);

    // add the supported contexts
    desc.addSupportedContext(eContextGeneral);
    desc.addSupportedContext(eContextFilter);

    // add supported pixel depths
    //desc.addSupportedBitDepth(eBitDepthUByte);
    //desc.addSupportedBitDepth(eBitDepthUShort);
    desc.addSupportedBitDepth(eBitDepthFloat);

    // other
    desc.setSupportsTiles(kSupportsTiles);
    desc.setSupportsMultiResolution(kSupportsMultiResolution);
    desc.setRenderThreadSafety(kRenderThreadSafety);
}

/** @brief The describe in context function, passed a plugin descriptor and a context */
void MirrorPluginFactory::describeInContext(OFX::ImageEffectDescriptor &desc, ContextEnum /*context*/)
{
    // create the mandated source clip
    ClipDescriptor *srcClip = desc.defineClip(kOfxImageEffectSimpleSourceClipName);
    srcClip->addSupportedComponent(ePixelComponentRGBA);
    srcClip->setTemporalClipAccess(false);
    srcClip->setSupportsTiles(kSupportsTiles);
    srcClip->setIsMask(false);

    // create the mandated output clip
    ClipDescriptor *dstClip = desc.defineClip(kOfxImageEffectOutputClipName);
    dstClip->addSupportedComponent(ePixelComponentRGBA);
    dstClip->setSupportsTiles(kSupportsTiles);

    // make pages and params
    PageParamDescriptor *page = desc.definePageParam(kPluginName);
    {
        ChoiceParamDescriptor *param = desc.defineChoiceParam(kParamMirror);
        param->setLabel(kParamMirrorLabel);
        param->setHint(kParamMirrorHint);
        param->appendOption("Undefined");
        param->appendOption("North");
        param->appendOption("South");
        param->appendOption("East");
        param->appendOption("West");
        param->appendOption("NorthWest");
        param->appendOption("NorthEast");
        param->appendOption("SouthWest");
        param->appendOption("SouthEast");
        param->setDefault(kParamMirrorDefault);
        param->setAnimates(true);
        page->addChild(*param);
    }
}

/** @brief The create instance function, the plugin must return an object derived from the \ref OFX::ImageEffect class */
ImageEffect* MirrorPluginFactory::createInstance(OfxImageEffectHandle handle, ContextEnum /*context*/)
{
    return new MirrorPlugin(handle);
}

void getMirrorPluginID(OFX::PluginFactoryArray &ids)
{
    static MirrorPluginFactory p(kPluginIdentifier, kPluginVersionMajor, kPluginVersionMinor);
    ids.push_back(&p);
}
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2009, Gostai S.A.S.
 *
 * This software is provided "as is" without warranty of any kind,
 * either expressed or implied, including but not limited to the
 * implied warranties of fitness for a particular purpose.
 *
 * See the LICENSE file for more information.
 */
#ifndef CXX_OBJECT_HXX
# define CXX_OBJECT_HXX

# include <libport/bind.hh>

# include <urbi/object/cxx-primitive.hh>
# include <urbi/object/primitive.hh>
# include <urbi/object/string.hh>
# include <runner/raise.hh>

namespace urbi
{
  namespace object
  {
    inline void
    check_arg_count (unsigned effective, unsigned formal)
    {
      if (formal != effective)
        runner::raise_arity_error(effective, formal);
    }

    inline void
    check_arg_count (unsigned effective, unsigned min, unsigned max)
    {
      if (min == max)
        check_arg_count(effective, min);
      else
        if (effective < min || effective > max)
          runner::raise_arity_error(effective, min, max);
    }

    template <typename T>
    bool CxxObject::add()
    {
      initializers_get().push_back(new TypeInitializer<T>());
      return true;
    }

    template <typename T>
    CxxObject::TypeInitializer<T>::TypeInitializer()
      : Initializer(T::proto)
    {}

    namespace
    {
      template <typename T>
      rObject cxx_object_clone(objects_type args)
      {
        check_arg_count(args.size() - 1, 0);
        rObject tgt = args[0];
        assert(tgt->as<T>());
        libport::intrusive_ptr<T> res = new T(tgt->as<T>());
        // If the user didn't specify a prototype, use the model.
        if (res->protos_get().empty())
          res->proto_add(tgt);
        return res;
      }

      template <typename T>
      rObject cxx_object_id(objects_type args)
      {
        check_arg_count(args.size() - 1, 0);
        return args[0];
      }
    }

    template <typename T>
    void
    CxxObject::TypeInitializer<T>::create()
    {
      res_ = new T(FirstPrototypeFlag());
      // If the user didn't specify a prototype, use Object.
      if (res_->protos_get().empty())
        res_->proto_add(Object::proto);
      assert(res_);
    }

    template <typename T>
    rObject
    CxxObject::TypeInitializer<T>::make_class()
    {
      using boost::bind;

      static libport::Symbol type("type");
      static libport::Symbol clone("clone");
      res_->slot_set(type, new String(T::type_name()), true);
      res_->slot_set(clone, new Primitive(bind(cxx_object_clone<T>, _1)), true);
      Binder<T> b(res_);
      T::initialize(b);

      libport::Symbol name = libport::Symbol(std::string("as") + T::type_name());
      if (!res_->slot_locate(name, false).first)
        res_->slot_set(name, new Primitive(bind(cxx_object_id<T>, _1)), true);
      return res_;
    }

    template <typename T>
    libport::Symbol
    CxxObject::TypeInitializer<T>::name()
    {
      return libport::Symbol(T::type_name());
    }

    // BINDER
    template <typename T>
    CxxObject::Binder<T>::Binder(rObject tgt)
      : tgt_(tgt)
    {}

    template <typename T>
    template <typename M>
    void
    CxxObject::Binder<T>::operator()(const libport::Symbol& name,
                                     M method)
    {
      tgt_->slot_set(name, make_primitive(method), true);
    }

    template <typename C, typename T>
    static rObject
    getter(libport::intrusive_ptr<C> self, T (C::* value))
    {
      return to_urbi(self.get()->*value);
    }

    template <typename C, typename T>
    static rObject
    setter(T (C::* attr), libport::intrusive_ptr<C> self,
           const std::string&, const T& value)
    {
      self.get()->*attr = value;
      return 0;
    }

    template <typename T>
    template <typename A>
    void
    CxxObject::Binder<T>::var(const libport::Symbol& name,
                              A (T::*attr))
    {
      using libport::intrusive_ptr;

      typedef boost::function1<rObject, intrusive_ptr<T> > urbi_getter_type;
      typedef boost::function3<rObject, intrusive_ptr<T>, const std::string&, const A&> urbi_setter_type;

      urbi_getter_type get(boost::bind(&getter<T, A>, _1, attr));
      tgt_->slot_set(name, make_primitive(get), true);

      urbi_setter_type set(boost::bind(&setter<T, A>, attr, _1, _2, _3));
#define S(Name) Symbol(#Name)
      tgt_->property_set(name, libport::S(updateHook), make_primitive(set));
#undef S
    }

    template<typename T>
    inline libport::intrusive_ptr<T>
    type_check(const rObject& o,
  	     boost::optional<unsigned> idx)
    {
      // If we do not have the right type, bounce onto the slower version
      // which will take care of throwing the appropriate exception. The
      // check will be done again, but this is harmless and only happens
      // when there is actually a mismatch.
      if (!is_a<T>(o))
        type_check(o, T::proto, idx);
      return o->as<T>();
    }

    template<typename T>
    void
    CxxObject::push_initializer_to_back()
    {
      CxxObject::initializers_type &l = CxxObject::initializers_get();
      for (CxxObject::initializers_type::iterator i = l.begin(); i!=l.end(); i++)
      {
        if (CxxObject::TypeInitializer<T>* v =
            dynamic_cast<CxxObject::TypeInitializer<T> *>(*i))
        {
          l.erase(i);
          l.push_back(v);
          break;
        }
      }
    }
  }
}

#endif
<commit_msg>Formatting changes.<commit_after>/*
 * Copyright (C) 2009, Gostai S.A.S.
 *
 * This software is provided "as is" without warranty of any kind,
 * either expressed or implied, including but not limited to the
 * implied warranties of fitness for a particular purpose.
 *
 * See the LICENSE file for more information.
 */
#ifndef CXX_OBJECT_HXX
# define CXX_OBJECT_HXX

# include <libport/bind.hh>

# include <urbi/object/cxx-primitive.hh>
# include <urbi/object/primitive.hh>
# include <urbi/object/string.hh>
# include <runner/raise.hh>

namespace urbi
{
  namespace object
  {
    inline void
    check_arg_count (unsigned effective, unsigned formal)
    {
      if (formal != effective)
        runner::raise_arity_error(effective, formal);
    }

    inline void
    check_arg_count (unsigned effective, unsigned min, unsigned max)
    {
      if (min == max)
        check_arg_count(effective, min);
      else
        if (effective < min || effective > max)
          runner::raise_arity_error(effective, min, max);
    }

    template <typename T>
    bool CxxObject::add()
    {
      initializers_get().push_back(new TypeInitializer<T>());
      return true;
    }

    template <typename T>
    CxxObject::TypeInitializer<T>::TypeInitializer()
      : Initializer(T::proto)
    {}

    namespace
    {
      template <typename T>
      rObject cxx_object_clone(objects_type args)
      {
        check_arg_count(args.size() - 1, 0);
        rObject tgt = args[0];
        assert(tgt->as<T>());
        libport::intrusive_ptr<T> res = new T(tgt->as<T>());
        // If the user didn't specify a prototype, use the model.
        if (res->protos_get().empty())
          res->proto_add(tgt);
        return res;
      }

      template <typename T>
      rObject cxx_object_id(objects_type args)
      {
        check_arg_count(args.size() - 1, 0);
        return args[0];
      }
    }

    template <typename T>
    void
    CxxObject::TypeInitializer<T>::create()
    {
      res_ = new T(FirstPrototypeFlag());
      // If the user didn't specify a prototype, use Object.
      if (res_->protos_get().empty())
        res_->proto_add(Object::proto);
      assert(res_);
    }

    template <typename T>
    rObject
    CxxObject::TypeInitializer<T>::make_class()
    {
      using boost::bind;

      static libport::Symbol type("type");
      static libport::Symbol clone("clone");
      res_->slot_set(type, new String(T::type_name()), true);
      res_->slot_set(clone, new Primitive(bind(cxx_object_clone<T>, _1)), true);
      Binder<T> b(res_);
      T::initialize(b);

      libport::Symbol name = libport::Symbol(std::string("as") + T::type_name());
      if (!res_->slot_locate(name, false).first)
        res_->slot_set(name, new Primitive(bind(cxx_object_id<T>, _1)), true);
      return res_;
    }

    template <typename T>
    libport::Symbol
    CxxObject::TypeInitializer<T>::name()
    {
      return libport::Symbol(T::type_name());
    }

    // BINDER
    template <typename T>
    CxxObject::Binder<T>::Binder(rObject tgt)
      : tgt_(tgt)
    {}

    template <typename T>
    template <typename M>
    void
    CxxObject::Binder<T>::operator()(const libport::Symbol& name,
                                     M method)
    {
      tgt_->slot_set(name, make_primitive(method), true);
    }

    template <typename C, typename T>
    static rObject
    getter(libport::intrusive_ptr<C> self, T (C::* value))
    {
      return to_urbi(self.get()->*value);
    }

    template <typename C, typename T>
    static rObject
    setter(T (C::* attr), libport::intrusive_ptr<C> self,
           const std::string&, const T& value)
    {
      self.get()->*attr = value;
      return 0;
    }

    template <typename T>
    template <typename A>
    void
    CxxObject::Binder<T>::var(const libport::Symbol& name,
                              A (T::*attr))
    {
      using libport::intrusive_ptr;

      typedef boost::function1<rObject, intrusive_ptr<T> > urbi_getter_type;
      typedef boost::function3<rObject, intrusive_ptr<T>, const std::string&, const A&> urbi_setter_type;

      urbi_getter_type get(boost::bind(&getter<T, A>, _1, attr));
      tgt_->slot_set(name, make_primitive(get), true);

      urbi_setter_type set(boost::bind(&setter<T, A>, attr, _1, _2, _3));
#define S(Name) Symbol(#Name)
      tgt_->property_set(name, libport::S(updateHook), make_primitive(set));
#undef S
    }

    template<typename T>
    inline libport::intrusive_ptr<T>
    type_check(const rObject& o,
  	     boost::optional<unsigned> idx)
    {
      // If we do not have the right type, bounce onto the slower version
      // which will take care of throwing the appropriate exception. The
      // check will be done again, but this is harmless and only happens
      // when there is actually a mismatch.
      if (!is_a<T>(o))
        type_check(o, T::proto, idx);
      return o->as<T>();
    }

    template<typename T>
    void
    CxxObject::push_initializer_to_back()
    {
      CxxObject::initializers_type &l = CxxObject::initializers_get();
      for (CxxObject::initializers_type::iterator i = l.begin();
           i != l.end(); ++i)
        if (CxxObject::TypeInitializer<T>* v =
            dynamic_cast<CxxObject::TypeInitializer<T> *>(*i))
        {
          l.erase(i);
          l.push_back(v);
          break;
        }
    }
  }
}

#endif
<|endoftext|>


<commit_before>#ifndef STAN_MATH_PRIM_FUN_EIGEN_COMPARISONS_HPP
#define STAN_MATH_PRIM_FUN_EIGEN_COMPARISONS_HPP

#include <stan/math/prim/meta.hpp>
#include <stan/math/prim/fun/Eigen.hpp>
#include <stan/math/prim/fun/value_of.hpp>

namespace stan {
namespace math {

/**
 * Add support for comparisons involving Eigen types with different scalars,
 * where one of the scalars is an autodiff type. This includes comparisons of
 * an Eigen type and a scalar.
 * @param OP operator to add support for
 **/
#define ADD_MIXED_AUTODIFF_SCALAR_COMPARISON(OPERATOR, OP) \
  template <typename T_a, typename T_b,                           \
            require_any_eigen_t<T_a, T_b>* = nullptr,             \
            require_any_st_autodiff<T_a, T_b>* = nullptr,         \
            require_not_st_same<T_a, T_b>* = nullptr>             \
  auto OPERATOR(const T_a& a, const T_b& b) {                     \
    return value_of(a) OP value_of(b);                            \
  }

ADD_MIXED_AUTODIFF_SCALAR_COMPARISON(operator<, <);
ADD_MIXED_AUTODIFF_SCALAR_COMPARISON(operator<=, <=);
ADD_MIXED_AUTODIFF_SCALAR_COMPARISON(operator>, >);
ADD_MIXED_AUTODIFF_SCALAR_COMPARISON(operator>=, >=);
ADD_MIXED_AUTODIFF_SCALAR_COMPARISON(operator==, ==);
ADD_MIXED_AUTODIFF_SCALAR_COMPARISON(operator!=, !=);

#undef ADD_MIXED_AUTODIFF_SCALAR_COMPARISON

}  // namespace math
}  // namespace stan

#endif
<commit_msg>fixed doxygen<commit_after>#ifndef STAN_MATH_PRIM_FUN_EIGEN_COMPARISONS_HPP
#define STAN_MATH_PRIM_FUN_EIGEN_COMPARISONS_HPP

#include <stan/math/prim/meta.hpp>
#include <stan/math/prim/fun/Eigen.hpp>
#include <stan/math/prim/fun/value_of.hpp>

namespace stan {
namespace math {

/**
 * Add support for comparisons involving Eigen types with different scalars,
 * where one of the scalars is an autodiff type. This includes comparisons of
 * an Eigen type and a scalar.
 * @param OPERATOR name of the operator function to implement
 * @param OP operator to use for comparison of values
 **/
#define ADD_MIXED_AUTODIFF_SCALAR_COMPARISON(OPERATOR, OP) \
  template <typename T_a, typename T_b,                           \
            require_any_eigen_t<T_a, T_b>* = nullptr,             \
            require_any_st_autodiff<T_a, T_b>* = nullptr,         \
            require_not_st_same<T_a, T_b>* = nullptr>             \
  auto OPERATOR(const T_a& a, const T_b& b) {                     \
    return value_of(a) OP value_of(b);                            \
  }

ADD_MIXED_AUTODIFF_SCALAR_COMPARISON(operator<, <);
ADD_MIXED_AUTODIFF_SCALAR_COMPARISON(operator<=, <=);
ADD_MIXED_AUTODIFF_SCALAR_COMPARISON(operator>, >);
ADD_MIXED_AUTODIFF_SCALAR_COMPARISON(operator>=, >=);
ADD_MIXED_AUTODIFF_SCALAR_COMPARISON(operator==, ==);
ADD_MIXED_AUTODIFF_SCALAR_COMPARISON(operator!=, !=);

#undef ADD_MIXED_AUTODIFF_SCALAR_COMPARISON

}  // namespace math
}  // namespace stan

#endif
<|endoftext|>


<commit_before>#ifndef STAN_MATH_REV_MAT_FUNCTOR_ODE_SYSTEM_HPP
#define STAN_MATH_REV_MAT_FUNCTOR_ODE_SYSTEM_HPP

#include <stan/math/rev/core.hpp>
#include <stan/math/prim/arr/fun/value_of.hpp>
#include <iostream>
#include <sstream>
#include <vector>

namespace stan {
  namespace math {

    /**
     * Internal representation of an ODE model object which provides
     * convenient Jacobian functions to obtain gradients wrt to states
     * and parameters. Can be used to provide analytic Jacobians via
     * partial template specialisation.
     *
     * @tparam F type of functor for the base ode system.
     */
    template <typename F>
    class ode_system {
    private:
      const F& f_;
      const std::vector<double> theta_;
      const std::vector<double>& x_;
      const std::vector<int>& x_int_;
      std::ostream* msgs_;

      std::string error_msg(size_t y_size, size_t dy_dt_size) const {
        std::stringstream msg;
        msg << "ode_system: size of state vector y (" << y_size << ")"
            << " and derivative vector dy_dt (" << dy_dt_size << ")"
            << " in the ODE functor do not match in size.";
        return msg.str();
      }

    public:
      /**
       * Construct an ODE model with the specified base ODE system,
       * parameters, data, and a message stream.
       *
       * @param[in] f the base ODE system functor.
       * @param[in] theta parameters of the ode.
       * @param[in] x real data.
       * @param[in] x_int integer data.
       * @param[in] msgs stream to which messages are printed.
       */
      ode_system(const F& f, const std::vector<double> theta,
                 const std::vector<double>& x, const std::vector<int>& x_int,
                 std::ostream* msgs)
        : f_(f), theta_(theta), x_(x), x_int_(x_int), msgs_(msgs) { }

      /**
       * Calculate the RHS of the ODE
       *
       * @param[in] t time.
       * @param[in] y state of the ode system at time t.
       * @param[out] dy_dt ODE RHS
       */
      template <typename Derived1>
      inline void operator()(double t, const std::vector<double>& y,
                             Eigen::MatrixBase<Derived1>& dy_dt) const {
        const std::vector<double> dy_dt_vec = f_(t, y, theta_, x_, x_int_,
                                                 msgs_);
        if (unlikely(y.size() != dy_dt_vec.size()))
          throw std::runtime_error(error_msg(y.size(), dy_dt_vec.size()));
        dy_dt = Eigen::Map<const Eigen::VectorXd>(&dy_dt_vec[0], y.size());
      }

      /**
       * Calculate the Jacobian of the ODE RHS wrt to states y. The
       * function expects the output objects to have correct sizes,
       * i.e. dy_dt must be length N and Jy a NxN matrix (N states).
       *
       * @param[in] t time.
       * @param[in] y state of the ode system at time t.
       * @param[out] dy_dt ODE RHS
       * @param[out] Jy Jacobian of ODE RHS wrt to y.
       */
      template <typename Derived1, typename Derived2>
      inline void jacobian(double t, const std::vector<double>& y,
                           Eigen::MatrixBase<Derived1>& dy_dt,
                           Eigen::MatrixBase<Derived2>& Jy) const {
        using Eigen::Matrix;
        using Eigen::Map;
        using Eigen::RowVectorXd;
        using std::vector;
        vector<double> grad(y.size());
        Map<RowVectorXd> grad_eig(&grad[0], y.size());
        try {
          start_nested();
          vector<var> y_var(y.begin(), y.end());
          vector<var> dy_dt_var = f_(t, y_var, theta_, x_, x_int_, msgs_);
          if (unlikely(y.size() != dy_dt_var.size())) {
            recover_memory_nested();
            throw std::runtime_error(error_msg(y.size(), dy_dt_var.size()));
          }
          for (size_t i = 0; i < dy_dt_var.size(); ++i) {
            dy_dt(i) = dy_dt_var[i].val();
            set_zero_all_adjoints_nested();
            dy_dt_var[i].grad(y_var, grad);
            Jy.row(i) = grad_eig;
          }
        } catch (const std::exception& e) {
          recover_memory_nested();
          throw;
        }
        recover_memory_nested();
      }

      /**
       * Calculate the Jacobian of the ODE RHS wrt to states y and
       * parameters theta. The function expects the output objects to
       * have correct sizes, i.e. dy_dt must be length N, Jy a NxN
       * matrix and Jtheta a NxM matrix (N states, M parameters).
       *
       * @param[in] t time.
       * @param[in] y state of the ode system at time t.
       * @param[out] dy_dt ODE RHS
       * @param[out] Jy Jacobian of ODE RHS wrt to y.
       * @param[out] Jtheta Jacobian of ODE RHS wrt to theta.
       */
      template <typename Derived1, typename Derived2>
      inline void jacobian(double t, const std::vector<double>& y,
                           Eigen::MatrixBase<Derived1>& dy_dt,
                           Eigen::MatrixBase<Derived2>& Jy,
                           Eigen::MatrixBase<Derived2>& Jtheta) const {
        using Eigen::Dynamic;
        using Eigen::Map;
        using Eigen::Matrix;
        using Eigen::RowVectorXd;
        using std::vector;
        vector<double> grad(y.size() + theta_.size());
        Map<RowVectorXd> grad_eig(&grad[0], y.size() + theta_.size());
        try {
          start_nested();
          vector<var> y_var(y.begin(), y.end());
          vector<var> theta_var(theta_.begin(), theta_.end());
          vector<var> z_var;
          z_var.reserve(y.size() + theta_.size());
          z_var.insert(z_var.end(), y_var.begin(), y_var.end());
          z_var.insert(z_var.end(), theta_var.begin(), theta_var.end());
          vector<var> dy_dt_var = f_(t, y_var, theta_var, x_, x_int_, msgs_);
          if (unlikely(y.size() != dy_dt_var.size())) {
            recover_memory_nested();
            throw std::runtime_error(error_msg(y.size(), dy_dt_var.size()));
          }
          for (size_t i = 0; i < dy_dt_var.size(); ++i) {
            dy_dt(i) = dy_dt_var[i].val();
            set_zero_all_adjoints_nested();
            dy_dt_var[i].grad(z_var, grad);
            Jy.row(i) = grad_eig.leftCols(y.size());
            Jtheta.row(i) = grad_eig.rightCols(theta_.size());
          }
        } catch (const std::exception& e) {
          recover_memory_nested();
          throw;
        }
        recover_memory_nested();
      }
    };

  }
}
#endif
<commit_msg>cpplint<commit_after>#ifndef STAN_MATH_REV_MAT_FUNCTOR_ODE_SYSTEM_HPP
#define STAN_MATH_REV_MAT_FUNCTOR_ODE_SYSTEM_HPP

#include <stan/math/rev/core.hpp>
#include <stan/math/prim/arr/fun/value_of.hpp>
#include <iostream>
#include <sstream>
#include <string>
#include <vector>

namespace stan {
  namespace math {

    /**
     * Internal representation of an ODE model object which provides
     * convenient Jacobian functions to obtain gradients wrt to states
     * and parameters. Can be used to provide analytic Jacobians via
     * partial template specialisation.
     *
     * @tparam F type of functor for the base ode system.
     */
    template <typename F>
    class ode_system {
    private:
      const F& f_;
      const std::vector<double> theta_;
      const std::vector<double>& x_;
      const std::vector<int>& x_int_;
      std::ostream* msgs_;

      std::string error_msg(size_t y_size, size_t dy_dt_size) const {
        std::stringstream msg;
        msg << "ode_system: size of state vector y (" << y_size << ")"
            << " and derivative vector dy_dt (" << dy_dt_size << ")"
            << " in the ODE functor do not match in size.";
        return msg.str();
      }

    public:
      /**
       * Construct an ODE model with the specified base ODE system,
       * parameters, data, and a message stream.
       *
       * @param[in] f the base ODE system functor.
       * @param[in] theta parameters of the ode.
       * @param[in] x real data.
       * @param[in] x_int integer data.
       * @param[in] msgs stream to which messages are printed.
       */
      ode_system(const F& f, const std::vector<double> theta,
                 const std::vector<double>& x, const std::vector<int>& x_int,
                 std::ostream* msgs)
        : f_(f), theta_(theta), x_(x), x_int_(x_int), msgs_(msgs) { }

      /**
       * Calculate the RHS of the ODE
       *
       * @param[in] t time.
       * @param[in] y state of the ode system at time t.
       * @param[out] dy_dt ODE RHS
       */
      template <typename Derived1>
      inline void operator()(double t, const std::vector<double>& y,
                             Eigen::MatrixBase<Derived1>& dy_dt) const {
        const std::vector<double> dy_dt_vec = f_(t, y, theta_, x_, x_int_,
                                                 msgs_);
        if (unlikely(y.size() != dy_dt_vec.size()))
          throw std::runtime_error(error_msg(y.size(), dy_dt_vec.size()));
        dy_dt = Eigen::Map<const Eigen::VectorXd>(&dy_dt_vec[0], y.size());
      }

      /**
       * Calculate the Jacobian of the ODE RHS wrt to states y. The
       * function expects the output objects to have correct sizes,
       * i.e. dy_dt must be length N and Jy a NxN matrix (N states).
       *
       * @param[in] t time.
       * @param[in] y state of the ode system at time t.
       * @param[out] dy_dt ODE RHS
       * @param[out] Jy Jacobian of ODE RHS wrt to y.
       */
      template <typename Derived1, typename Derived2>
      inline void jacobian(double t, const std::vector<double>& y,
                           Eigen::MatrixBase<Derived1>& dy_dt,
                           Eigen::MatrixBase<Derived2>& Jy) const {
        using Eigen::Matrix;
        using Eigen::Map;
        using Eigen::RowVectorXd;
        using std::vector;
        vector<double> grad(y.size());
        Map<RowVectorXd> grad_eig(&grad[0], y.size());
        try {
          start_nested();
          vector<var> y_var(y.begin(), y.end());
          vector<var> dy_dt_var = f_(t, y_var, theta_, x_, x_int_, msgs_);
          if (unlikely(y.size() != dy_dt_var.size())) {
            recover_memory_nested();
            throw std::runtime_error(error_msg(y.size(), dy_dt_var.size()));
          }
          for (size_t i = 0; i < dy_dt_var.size(); ++i) {
            dy_dt(i) = dy_dt_var[i].val();
            set_zero_all_adjoints_nested();
            dy_dt_var[i].grad(y_var, grad);
            Jy.row(i) = grad_eig;
          }
        } catch (const std::exception& e) {
          recover_memory_nested();
          throw;
        }
        recover_memory_nested();
      }

      /**
       * Calculate the Jacobian of the ODE RHS wrt to states y and
       * parameters theta. The function expects the output objects to
       * have correct sizes, i.e. dy_dt must be length N, Jy a NxN
       * matrix and Jtheta a NxM matrix (N states, M parameters).
       *
       * @param[in] t time.
       * @param[in] y state of the ode system at time t.
       * @param[out] dy_dt ODE RHS
       * @param[out] Jy Jacobian of ODE RHS wrt to y.
       * @param[out] Jtheta Jacobian of ODE RHS wrt to theta.
       */
      template <typename Derived1, typename Derived2>
      inline void jacobian(double t, const std::vector<double>& y,
                           Eigen::MatrixBase<Derived1>& dy_dt,
                           Eigen::MatrixBase<Derived2>& Jy,
                           Eigen::MatrixBase<Derived2>& Jtheta) const {
        using Eigen::Dynamic;
        using Eigen::Map;
        using Eigen::Matrix;
        using Eigen::RowVectorXd;
        using std::vector;
        vector<double> grad(y.size() + theta_.size());
        Map<RowVectorXd> grad_eig(&grad[0], y.size() + theta_.size());
        try {
          start_nested();
          vector<var> y_var(y.begin(), y.end());
          vector<var> theta_var(theta_.begin(), theta_.end());
          vector<var> z_var;
          z_var.reserve(y.size() + theta_.size());
          z_var.insert(z_var.end(), y_var.begin(), y_var.end());
          z_var.insert(z_var.end(), theta_var.begin(), theta_var.end());
          vector<var> dy_dt_var = f_(t, y_var, theta_var, x_, x_int_, msgs_);
          if (unlikely(y.size() != dy_dt_var.size())) {
            recover_memory_nested();
            throw std::runtime_error(error_msg(y.size(), dy_dt_var.size()));
          }
          for (size_t i = 0; i < dy_dt_var.size(); ++i) {
            dy_dt(i) = dy_dt_var[i].val();
            set_zero_all_adjoints_nested();
            dy_dt_var[i].grad(z_var, grad);
            Jy.row(i) = grad_eig.leftCols(y.size());
            Jtheta.row(i) = grad_eig.rightCols(theta_.size());
          }
        } catch (const std::exception& e) {
          recover_memory_nested();
          throw;
        }
        recover_memory_nested();
      }
    };

  }
}
#endif
<|endoftext|>


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

  Program:   Visualization Library
  Module:    PolyMap.cc
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

This file is part of the Visualization Library. No part of this file or its
contents may be copied, reproduced or altered in any way without the express
written consent of the authors.

Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen 1993, 1994

=========================================================================*/
//
// Methods for polygon mapper
//
#include "PolyMap.hh"

vlPolyMapper::vlPolyMapper()
{
  this->Input = NULL;
  this->Verts = NULL;
  this->Lines = NULL;
  this->Polys = NULL;
  this->Strips = NULL;
  this->VertsVisibility = 1;
  this->LinesVisibility = 1;
  this->PolysVisibility = 1;
  this->StripsVisibility = 1;
}

vlPolyMapper::~vlPolyMapper()
{
  if ( this->Input != NULL )
    {
    this->Input->UnRegister(this);
    }
}

void vlPolyMapper::SetInput(vlPolyData *in)
{
  if (in != this->Input )
    {
    this->Input = in;
    this->Input->Register(this);
    this->Modified();
    }
}
vlPolyData* vlPolyMapper::GetInput()
{
  return this->Input;
}
//
// Return bounding box of data
//
float *vlPolyMapper::GetBounds()
{
  static float bounds[] = {-1.0,1.0, -1.0,1.0, -1.0,1.0};

  if ( ! this->Input )
    return bounds;
  else
    {
    this->Input->Update();
    return this->Input->GetBounds();
    }
}

//
// Receives from Actor -> maps data to primitives
//
void vlPolyMapper::Render(vlRenderer *ren)
{
  vlPointData *pd;
  vlRGBArray *colors;
  vlScalars *scalars;
  int i;
  char forceBuild = 0;
//
// make sure that we've been properly initialized
//
  if ( this->Input != NULL )
    {
    vlErrorMacro(<< "No input!\n");
    return;
    }
  else
    this->Input->Update();

  if ( ! this->LookupTable ) this->LookupTable = new vlLookupTable;
  this->LookupTable->Build();

//
// Now send data down to primitives and draw it
//
  if ( forceBuild || this->Input->GetMTime() > this->BuildTime ||
  this->LookupTable->GetMTime() > this->BuildTime )
    {
//
// create colors
//
    if ( this->ScalarsVisible && (pd=this->Input->GetPointData()) &&
    (scalars=pd->GetScalars()) )
      {
      colors = new vlRGBArray;
      colors->Allocate (this->Input->GetNumberOfPoints());

      this->LookupTable->SetTableRange(this->ScalarRange);
      for (i=0; i<this->Input->GetNumberOfPoints(); i++)
        {
        colors->SetColor(i,this->LookupTable->MapValue(scalars->GetScalar(i)));
        }
      }
    else
      {
      colors = NULL;
      }

    if (this->VertsVisibility && this->Input->GetNumberOfVerts())
      {
      if (!this->Verts) this->Verts = ren->GetPrimitive("points");
      this->Verts->Build(this->Input,colors);
      }
    if ( this->LinesVisibility && this->Input->GetNumberOfLines())
      {
      if (!this->Lines) this->Lines = ren->GetPrimitive("lines");
      this->Lines->Build(this->Input,colors);
      }
    if ( this->PolysVisibility && this->Input->GetNumberOfPolys())
      {
      if (!this->Polys) this->Polys = ren->GetPrimitive("polygons");
      this->Polys->Build(this->Input,colors);
      }
    if ( this->StripsVisibility && this->Input->GetNumberOfStrips())
      {
      if (!this->Strips) this->Strips = ren->GetPrimitive("triangle_strips");
      this->Strips->Build(this->Input,colors);
      }

    this->BuildTime.Modified();
    }

  // draw the primitives
  if (this->VertsVisibility && this->Input->GetNumberOfVerts())
    {
    this->Verts->Draw(ren);
    }
  if ( this->LinesVisibility && this->Input->GetNumberOfLines())
    {
    this->Lines->Draw(ren);
    }
  if ( this->PolysVisibility && this->Input->GetNumberOfPolys())
    {
    this->Polys->Draw(ren);
    }
  if ( this->StripsVisibility && this->Input->GetNumberOfStrips())
    {
    this->Strips->Draw(ren);
    }

}

void vlPolyMapper::PrintSelf(ostream& os, vlIndent indent)
{
  if (this->ShouldIPrint(vlPolyMapper::GetClassName()))
    {
    vlMapper::PrintSelf(os,indent);

    if ( this->Input )
      {
      os << indent << "Input: (" << this->Input << ")\n";
      }
    else
      {
      os << indent << "Input: (none)\n";
      }

    os << indent << "Vertex Visibility: " << (this->VertsVisibility ? "On\n" : "Off\n");
    os << indent << "Line Visibility: " << (this->LinesVisibility ? "On\n" : "Off\n");
    os << indent << "Polygon Visibility: " << (this->PolysVisibility ? "On\n" : "Off\n");
    os << indent << "Triangle Strip Visibility: " << (this->StripsVisibility ? "On\n" : "Off\n");

   }
}
<commit_msg>*** empty log message ***<commit_after>/*=========================================================================

  Program:   Visualization Library
  Module:    PolyMap.cc
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

This file is part of the Visualization Library. No part of this file or its
contents may be copied, reproduced or altered in any way without the express
written consent of the authors.

Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen 1993, 1994

=========================================================================*/
//
// Methods for polygon mapper
//
#include "PolyMap.hh"

vlPolyMapper::vlPolyMapper()
{
  this->Input = NULL;
  this->Verts = NULL;
  this->Lines = NULL;
  this->Polys = NULL;
  this->Strips = NULL;
  this->VertsVisibility = 1;
  this->LinesVisibility = 1;
  this->PolysVisibility = 1;
  this->StripsVisibility = 1;
}

vlPolyMapper::~vlPolyMapper()
{
  if ( this->Input != NULL )
    {
    this->Input->UnRegister(this);
    }
}

void vlPolyMapper::SetInput(vlPolyData *in)
{
  if (in != this->Input )
    {
    this->Input = in;
    this->Input->Register(this);
    this->Modified();
    }
}
vlPolyData* vlPolyMapper::GetInput()
{
  return this->Input;
}
//
// Return bounding box of data
//
float *vlPolyMapper::GetBounds()
{
  static float bounds[] = {-1.0,1.0, -1.0,1.0, -1.0,1.0};

  if ( ! this->Input )
    return bounds;
  else
    {
    this->Input->Update();
    return this->Input->GetBounds();
    }
}

//
// Receives from Actor -> maps data to primitives
//
void vlPolyMapper::Render(vlRenderer *ren)
{
  vlPointData *pd;
  vlRGBArray *colors;
  vlScalars *scalars;
  int i;
  char forceBuild = 0;
//
// make sure that we've been properly initialized
//
  if ( this->Input == NULL )
    {
    vlErrorMacro(<< "No input!\n");
    return;
    }
  else
    this->Input->Update();

  if ( ! this->LookupTable ) this->LookupTable = new vlLookupTable;
  this->LookupTable->Build();

//
// Now send data down to primitives and draw it
//
  if ( forceBuild || this->Input->GetMTime() > this->BuildTime ||
  this->LookupTable->GetMTime() > this->BuildTime )
    {
//
// create colors
//
    if ( this->ScalarsVisible && (pd=this->Input->GetPointData()) &&
    (scalars=pd->GetScalars()) )
      {
      colors = new vlRGBArray;
      colors->Allocate (this->Input->GetNumberOfPoints());

      this->LookupTable->SetTableRange(this->ScalarRange);
      for (i=0; i<this->Input->GetNumberOfPoints(); i++)
        {
        colors->SetColor(i,this->LookupTable->MapValue(scalars->GetScalar(i)));
        }
      }
    else
      {
      colors = NULL;
      }

    if (this->VertsVisibility && this->Input->GetNumberOfVerts())
      {
      if (!this->Verts) this->Verts = ren->GetPrimitive("points");
      this->Verts->Build(this->Input,colors);
      }
    if ( this->LinesVisibility && this->Input->GetNumberOfLines())
      {
      if (!this->Lines) this->Lines = ren->GetPrimitive("lines");
      this->Lines->Build(this->Input,colors);
      }
    if ( this->PolysVisibility && this->Input->GetNumberOfPolys())
      {
      if (!this->Polys) this->Polys = ren->GetPrimitive("polygons");
      this->Polys->Build(this->Input,colors);
      }
    if ( this->StripsVisibility && this->Input->GetNumberOfStrips())
      {
      if (!this->Strips) this->Strips = ren->GetPrimitive("triangle_strips");
      this->Strips->Build(this->Input,colors);
      }

    this->BuildTime.Modified();
    }

  // draw the primitives
  if (this->VertsVisibility && this->Input->GetNumberOfVerts())
    {
    this->Verts->Draw(ren);
    }
  if ( this->LinesVisibility && this->Input->GetNumberOfLines())
    {
    this->Lines->Draw(ren);
    }
  if ( this->PolysVisibility && this->Input->GetNumberOfPolys())
    {
    this->Polys->Draw(ren);
    }
  if ( this->StripsVisibility && this->Input->GetNumberOfStrips())
    {
    this->Strips->Draw(ren);
    }

}

void vlPolyMapper::PrintSelf(ostream& os, vlIndent indent)
{
  if (this->ShouldIPrint(vlPolyMapper::GetClassName()))
    {
    vlMapper::PrintSelf(os,indent);

    if ( this->Input )
      {
      os << indent << "Input: (" << this->Input << ")\n";
      }
    else
      {
      os << indent << "Input: (none)\n";
      }

    os << indent << "Vertex Visibility: " << (this->VertsVisibility ? "On\n" : "Off\n");
    os << indent << "Line Visibility: " << (this->LinesVisibility ? "On\n" : "Off\n");
    os << indent << "Polygon Visibility: " << (this->PolysVisibility ? "On\n" : "Off\n");
    os << indent << "Triangle Strip Visibility: " << (this->StripsVisibility ? "On\n" : "Off\n");

   }
}
<|endoftext|>


<commit_before>/**
 * @file lldynamictexture.cpp
 * @brief Implementation of LLViewerDynamicTexture class
 *
 * $LicenseInfo:firstyear=2001&license=viewerlgpl$
 * Second Life Viewer Source Code
 * Copyright (C) 2010, Linden Research, Inc.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation;
 * version 2.1 of the License only.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 *
 * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
 * $/LicenseInfo$
 */

#include "llviewerprecompiledheaders.h"

#include "lldynamictexture.h"

// Linden library includes
#include "llglheaders.h"
#include "llwindow.h"			// getPosition()

// Viewer includes
#include "llviewerwindow.h"
#include "llviewercamera.h"
#include "llviewercontrol.h"
#include "llviewertexture.h"
#include "llvertexbuffer.h"
#include "llviewerdisplay.h"
#include "llrender.h"
#include "llglslshader.h"

// static
LLViewerDynamicTexture::instance_list_t LLViewerDynamicTexture::sInstances[ LLViewerDynamicTexture::ORDER_COUNT ];
S32 LLViewerDynamicTexture::sNumRenders = 0;

//-----------------------------------------------------------------------------
// LLViewerDynamicTexture()
//-----------------------------------------------------------------------------
LLViewerDynamicTexture::LLViewerDynamicTexture(S32 width, S32 height, S32 components, EOrder order, BOOL clamp) :
	LLViewerTexture(width, height, components, FALSE),
	mClamp(clamp)
{
	llassert((1 <= components) && (components <= 4));

	if(gGLManager.mDebugGPU)
	{
		if(components == 3)
		{
			mComponents = 4 ; //convert to 32bits.
		}
	}
	generateGLTexture();

	llassert( 0 <= order && order < ORDER_COUNT );
	LLViewerDynamicTexture::sInstances[ order ].insert(this);
}

//-----------------------------------------------------------------------------
// LLViewerDynamicTexture()
//-----------------------------------------------------------------------------
LLViewerDynamicTexture::~LLViewerDynamicTexture()
{
	for( S32 order = 0; order < ORDER_COUNT; order++ )
	{
		LLViewerDynamicTexture::sInstances[order].erase(this);  // will fail in all but one case.
	}
}

//virtual
S8 LLViewerDynamicTexture::getType() const
{
	return LLViewerTexture::DYNAMIC_TEXTURE ;
}

//-----------------------------------------------------------------------------
// generateGLTexture()
//-----------------------------------------------------------------------------
void LLViewerDynamicTexture::generateGLTexture()
{
	LLViewerTexture::generateGLTexture() ;
	generateGLTexture(-1, 0, 0, FALSE);
}

void LLViewerDynamicTexture::generateGLTexture(LLGLint internal_format, LLGLenum primary_format, LLGLenum type_format, BOOL swap_bytes)
{
	if (mComponents < 1 || mComponents > 4)
	{
		llerrs << "Bad number of components in dynamic texture: " << mComponents << llendl;
	}

	LLPointer<LLImageRaw> raw_image = new LLImageRaw(mFullWidth, mFullHeight, mComponents);
	if (internal_format >= 0)
	{
		setExplicitFormat(internal_format, primary_format, type_format, swap_bytes);
	}
	createGLTexture(0, raw_image, 0, TRUE, LLViewerTexture::DYNAMIC_TEX);
	setAddressMode((mClamp) ? LLTexUnit::TAM_CLAMP : LLTexUnit::TAM_WRAP);
	mGLTexturep->setGLTextureCreated(false);
}

//-----------------------------------------------------------------------------
// render()
//-----------------------------------------------------------------------------
BOOL LLViewerDynamicTexture::render()
{
	return FALSE;
}

//-----------------------------------------------------------------------------
// preRender()
//-----------------------------------------------------------------------------
void LLViewerDynamicTexture::preRender(BOOL clear_depth)
{
	{
		// force rendering to on-screen portion of frame buffer
		LLCoordScreen window_pos;
		gViewerWindow->getWindow()->getPosition( &window_pos );
		mOrigin.set(0, gViewerWindow->getWindowHeightRaw() - mFullHeight);  // top left corner

		if (window_pos.mX < 0)
		{
			mOrigin.mX = -window_pos.mX;
		}
		if (window_pos.mY < 0)
		{
			mOrigin.mY += window_pos.mY;
			mOrigin.mY = llmax(mOrigin.mY, 0) ;
		}

		gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
	}
	// Set up camera
	LLViewerCamera* camera = LLViewerCamera::getInstance();
	mCamera.setOrigin(*camera);
	mCamera.setAxes(*camera);
	mCamera.setAspect(camera->getAspect());
	mCamera.setView(camera->getView());
	mCamera.setNear(camera->getNear());

	glViewport(mOrigin.mX, mOrigin.mY, mFullWidth, mFullHeight);
	if (clear_depth)
	{
		glClear(GL_DEPTH_BUFFER_BIT);
	}
}

//-----------------------------------------------------------------------------
// postRender()
//-----------------------------------------------------------------------------
void LLViewerDynamicTexture::postRender(BOOL success)
{
	{
		if (success)
		{
			if(mGLTexturep.isNull())
			{
				generateGLTexture() ;
			}
			else if(!mGLTexturep->getHasGLTexture())
			{
				generateGLTexture() ;
			}
			else if(mGLTexturep->getDiscardLevel() != 0)//do not know how it happens, but regenerate one if it does.
			{
				generateGLTexture() ;
			}

			success = mGLTexturep->setSubImageFromFrameBuffer(0, 0, mOrigin.mX, mOrigin.mY, mFullWidth, mFullHeight);
		}
	}

	// restore viewport
	gViewerWindow->setup2DViewport();

	// restore camera
	LLViewerCamera* camera = LLViewerCamera::getInstance();
	camera->setOrigin(mCamera);
	camera->setAxes(mCamera);
	camera->setAspect(mCamera.getAspect());
	camera->setView(mCamera.getView());
	camera->setNear(mCamera.getNear());
}

//-----------------------------------------------------------------------------
// static
// updateDynamicTextures()
// Calls update on each dynamic texture.  Calls each group in order: "first," then "middle," then "last."
//-----------------------------------------------------------------------------
BOOL LLViewerDynamicTexture::updateAllInstances()
{
	sNumRenders = 0;
	if (gGLManager.mIsDisabled)
	{
		return TRUE;
	}

	LLGLSLShader::bindNoShader();
	LLVertexBuffer::unbind();

	BOOL result = FALSE;
	BOOL ret = FALSE ;
	for( S32 order = 0; order < ORDER_COUNT; order++ )
	{
		for (instance_list_t::iterator iter = LLViewerDynamicTexture::sInstances[order].begin();
			 iter != LLViewerDynamicTexture::sInstances[order].end(); ++iter)
		{
			LLViewerDynamicTexture *dynamicTexture = *iter;
			if (dynamicTexture->needsRender())
			{
				glClear(GL_DEPTH_BUFFER_BIT);
				gDepthDirty = TRUE;

				gGL.color4f(1,1,1,1);
				dynamicTexture->preRender();	// Must be called outside of startRender()
				result = FALSE;
				if (dynamicTexture->render())
				{
					ret = TRUE ;
					result = TRUE;
					sNumRenders++;
				}
				gGL.flush();
				LLVertexBuffer::unbind();

				dynamicTexture->postRender(result);
			}
		}
	}

	return ret;
}

//-----------------------------------------------------------------------------
// static
// destroyGL()
//-----------------------------------------------------------------------------
void LLViewerDynamicTexture::destroyGL()
{
	for( S32 order = 0; order < ORDER_COUNT; order++ )
	{
		for (instance_list_t::iterator iter = LLViewerDynamicTexture::sInstances[order].begin();
			 iter != LLViewerDynamicTexture::sInstances[order].end(); ++iter)
		{
			LLViewerDynamicTexture *dynamicTexture = *iter;
			dynamicTexture->destroyGLTexture() ;
		}
	}
}

//-----------------------------------------------------------------------------
// static
// restoreGL()
//-----------------------------------------------------------------------------
void LLViewerDynamicTexture::restoreGL()
{
	if (gGLManager.mIsDisabled)
	{
		return ;
	}

	for( S32 order = 0; order < ORDER_COUNT; order++ )
	{
		for (instance_list_t::iterator iter = LLViewerDynamicTexture::sInstances[order].begin();
			 iter != LLViewerDynamicTexture::sInstances[order].end(); ++iter)
		{
			LLViewerDynamicTexture *dynamicTexture = *iter;
			dynamicTexture->restoreGLTexture() ;
		}
	}
}
<commit_msg>SH-2242 Don't make LLDynamicTexture targets use shaders all the time (revisit later).<commit_after>/**
 * @file lldynamictexture.cpp
 * @brief Implementation of LLViewerDynamicTexture class
 *
 * $LicenseInfo:firstyear=2001&license=viewerlgpl$
 * Second Life Viewer Source Code
 * Copyright (C) 2010, Linden Research, Inc.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation;
 * version 2.1 of the License only.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 *
 * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
 * $/LicenseInfo$
 */

#include "llviewerprecompiledheaders.h"

#include "lldynamictexture.h"

// Linden library includes
#include "llglheaders.h"
#include "llwindow.h"			// getPosition()

// Viewer includes
#include "llviewerwindow.h"
#include "llviewercamera.h"
#include "llviewercontrol.h"
#include "llviewertexture.h"
#include "llvertexbuffer.h"
#include "llviewerdisplay.h"
#include "llrender.h"
#include "llglslshader.h"

// static
LLViewerDynamicTexture::instance_list_t LLViewerDynamicTexture::sInstances[ LLViewerDynamicTexture::ORDER_COUNT ];
S32 LLViewerDynamicTexture::sNumRenders = 0;

//-----------------------------------------------------------------------------
// LLViewerDynamicTexture()
//-----------------------------------------------------------------------------
LLViewerDynamicTexture::LLViewerDynamicTexture(S32 width, S32 height, S32 components, EOrder order, BOOL clamp) :
	LLViewerTexture(width, height, components, FALSE),
	mClamp(clamp)
{
	llassert((1 <= components) && (components <= 4));

	if(gGLManager.mDebugGPU)
	{
		if(components == 3)
		{
			mComponents = 4 ; //convert to 32bits.
		}
	}
	generateGLTexture();

	llassert( 0 <= order && order < ORDER_COUNT );
	LLViewerDynamicTexture::sInstances[ order ].insert(this);
}

//-----------------------------------------------------------------------------
// LLViewerDynamicTexture()
//-----------------------------------------------------------------------------
LLViewerDynamicTexture::~LLViewerDynamicTexture()
{
	for( S32 order = 0; order < ORDER_COUNT; order++ )
	{
		LLViewerDynamicTexture::sInstances[order].erase(this);  // will fail in all but one case.
	}
}

//virtual
S8 LLViewerDynamicTexture::getType() const
{
	return LLViewerTexture::DYNAMIC_TEXTURE ;
}

//-----------------------------------------------------------------------------
// generateGLTexture()
//-----------------------------------------------------------------------------
void LLViewerDynamicTexture::generateGLTexture()
{
	LLViewerTexture::generateGLTexture() ;
	generateGLTexture(-1, 0, 0, FALSE);
}

void LLViewerDynamicTexture::generateGLTexture(LLGLint internal_format, LLGLenum primary_format, LLGLenum type_format, BOOL swap_bytes)
{
	if (mComponents < 1 || mComponents > 4)
	{
		llerrs << "Bad number of components in dynamic texture: " << mComponents << llendl;
	}

	LLPointer<LLImageRaw> raw_image = new LLImageRaw(mFullWidth, mFullHeight, mComponents);
	if (internal_format >= 0)
	{
		setExplicitFormat(internal_format, primary_format, type_format, swap_bytes);
	}
	createGLTexture(0, raw_image, 0, TRUE, LLViewerTexture::DYNAMIC_TEX);
	setAddressMode((mClamp) ? LLTexUnit::TAM_CLAMP : LLTexUnit::TAM_WRAP);
	mGLTexturep->setGLTextureCreated(false);
}

//-----------------------------------------------------------------------------
// render()
//-----------------------------------------------------------------------------
BOOL LLViewerDynamicTexture::render()
{
	return FALSE;
}

//-----------------------------------------------------------------------------
// preRender()
//-----------------------------------------------------------------------------
void LLViewerDynamicTexture::preRender(BOOL clear_depth)
{
	{
		// force rendering to on-screen portion of frame buffer
		LLCoordScreen window_pos;
		gViewerWindow->getWindow()->getPosition( &window_pos );
		mOrigin.set(0, gViewerWindow->getWindowHeightRaw() - mFullHeight);  // top left corner

		if (window_pos.mX < 0)
		{
			mOrigin.mX = -window_pos.mX;
		}
		if (window_pos.mY < 0)
		{
			mOrigin.mY += window_pos.mY;
			mOrigin.mY = llmax(mOrigin.mY, 0) ;
		}

		gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
	}
	// Set up camera
	LLViewerCamera* camera = LLViewerCamera::getInstance();
	mCamera.setOrigin(*camera);
	mCamera.setAxes(*camera);
	mCamera.setAspect(camera->getAspect());
	mCamera.setView(camera->getView());
	mCamera.setNear(camera->getNear());

	glViewport(mOrigin.mX, mOrigin.mY, mFullWidth, mFullHeight);
	if (clear_depth)
	{
		glClear(GL_DEPTH_BUFFER_BIT);
	}
}

//-----------------------------------------------------------------------------
// postRender()
//-----------------------------------------------------------------------------
void LLViewerDynamicTexture::postRender(BOOL success)
{
	{
		if (success)
		{
			if(mGLTexturep.isNull())
			{
				generateGLTexture() ;
			}
			else if(!mGLTexturep->getHasGLTexture())
			{
				generateGLTexture() ;
			}
			else if(mGLTexturep->getDiscardLevel() != 0)//do not know how it happens, but regenerate one if it does.
			{
				generateGLTexture() ;
			}

			success = mGLTexturep->setSubImageFromFrameBuffer(0, 0, mOrigin.mX, mOrigin.mY, mFullWidth, mFullHeight);
		}
	}

	// restore viewport
	gViewerWindow->setup2DViewport();

	// restore camera
	LLViewerCamera* camera = LLViewerCamera::getInstance();
	camera->setOrigin(mCamera);
	camera->setAxes(mCamera);
	camera->setAspect(mCamera.getAspect());
	camera->setView(mCamera.getView());
	camera->setNear(mCamera.getNear());
}

//-----------------------------------------------------------------------------
// static
// updateDynamicTextures()
// Calls update on each dynamic texture.  Calls each group in order: "first," then "middle," then "last."
//-----------------------------------------------------------------------------
BOOL LLViewerDynamicTexture::updateAllInstances()
{
	sNumRenders = 0;
	if (gGLManager.mIsDisabled)
	{
		return TRUE;
	}

	LLGLSLShader::bindNoShader();
	LLVertexBuffer::unbind();

	bool no_ff = LLGLSLShader::sNoFixedFunction;
	LLGLSLShader::sNoFixedFunction = false;

	BOOL result = FALSE;
	BOOL ret = FALSE ;
	for( S32 order = 0; order < ORDER_COUNT; order++ )
	{
		for (instance_list_t::iterator iter = LLViewerDynamicTexture::sInstances[order].begin();
			 iter != LLViewerDynamicTexture::sInstances[order].end(); ++iter)
		{
			LLViewerDynamicTexture *dynamicTexture = *iter;
			if (dynamicTexture->needsRender())
			{
				glClear(GL_DEPTH_BUFFER_BIT);
				gDepthDirty = TRUE;

				gGL.color4f(1,1,1,1);
				dynamicTexture->preRender();	// Must be called outside of startRender()
				result = FALSE;
				if (dynamicTexture->render())
				{
					ret = TRUE ;
					result = TRUE;
					sNumRenders++;
				}
				gGL.flush();
				LLVertexBuffer::unbind();

				dynamicTexture->postRender(result);
			}
		}
	}

	LLGLSLShader::sNoFixedFunction = no_ff;

	return ret;
}

//-----------------------------------------------------------------------------
// static
// destroyGL()
//-----------------------------------------------------------------------------
void LLViewerDynamicTexture::destroyGL()
{
	for( S32 order = 0; order < ORDER_COUNT; order++ )
	{
		for (instance_list_t::iterator iter = LLViewerDynamicTexture::sInstances[order].begin();
			 iter != LLViewerDynamicTexture::sInstances[order].end(); ++iter)
		{
			LLViewerDynamicTexture *dynamicTexture = *iter;
			dynamicTexture->destroyGLTexture() ;
		}
	}
}

//-----------------------------------------------------------------------------
// static
// restoreGL()
//-----------------------------------------------------------------------------
void LLViewerDynamicTexture::restoreGL()
{
	if (gGLManager.mIsDisabled)
	{
		return ;
	}

	for( S32 order = 0; order < ORDER_COUNT; order++ )
	{
		for (instance_list_t::iterator iter = LLViewerDynamicTexture::sInstances[order].begin();
			 iter != LLViewerDynamicTexture::sInstances[order].end(); ++iter)
		{
			LLViewerDynamicTexture *dynamicTexture = *iter;
			dynamicTexture->restoreGLTexture() ;
		}
	}
}
<|endoftext|>


<commit_before>// PythonStuff.cpp
// Copyright (c) 2009, Dan Heeks
// This program is released under the BSD license. See the file COPYING for details.

#include "stdafx.h"
#include <wx/file.h>
#include <wx/mimetype.h>
#include <wx/process.h>
#include <wx/stdpaths.h>
#include <wx/filename.h>
#include <wx/txtstrm.h>
#include <wx/log.h>
#include "PythonStuff.h"
#include "ProgramCanvas.h"
#include "OutputCanvas.h"
#include "Program.h"

class CPyProcess : public wxProcess
{
protected:
  int m_pid;

public:
  CPyProcess(void);

  void Execute(const wxChar* cmd);
  void Cancel(void);
  void OnTerminate(int pid, int status);
  void OnTimer(wxTimerEvent& event);

  virtual void ThenDo(void) { }

private:
  wxTimer m_timer;
  void HandleInput(void);

};

CPyProcess::CPyProcess(void)
{
  m_pid = 0;
  wxProcess(heeksCAD->GetMainFrame());
  Connect(wxEVT_TIMER, wxTimerEventHandler(CPyProcess::OnTimer));
  m_timer.SetOwner(this);

}

void CPyProcess::OnTimer(wxTimerEvent& event)
{
  HandleInput();
}

void CPyProcess::HandleInput(void)
{
  wxString s;
  int l;
  wxInputStream *m_in,*m_err;

  m_in = GetInputStream();
  m_err = GetErrorStream();

  if (m_in)
    {
      while (m_in->CanRead()) {
	char buffer[4096];
	m_in->Read(buffer, WXSIZEOF(buffer) - 1);
	l = m_in->LastRead();
	s += wxString::From8BitData(buffer, l);
      }
      if (s.Length() > 0) {
	wxLogMessage(_T("> %s"),s.c_str());
      }
    }
  if (m_err)
    {
      while (m_err->CanRead()) {
	char buffer[4096];
	m_err->Read(buffer, WXSIZEOF(buffer) - 1);
	l = m_err->LastRead();
	s += wxString::From8BitData(buffer, l);
      }
      if (s.Length() > 0) {
	wxLogMessage(_T("! %s"),s.c_str());
      }
    }
}

void CPyProcess::Execute(const wxChar* cmd)
{
	Redirect();
	m_pid = wxExecute(cmd, wxEXEC_ASYNC, this);
        wxLogMessage(_T("starting '%s' (%d)"),cmd,m_pid);
	m_timer.Start(100);   //msec

}

void CPyProcess::Cancel(void)
{
	if (m_pid)
	{
		wxProcess::Kill(m_pid);
		m_pid = 0;
	}
}

void CPyProcess::OnTerminate(int pid, int status)
{
	if (pid == m_pid)
	{
	  m_timer.Stop();
	  HandleInput();
	  if (status) {
	    wxLogMessage(_T("process %d exit(%d)"),pid, status);
	  } else {
	    wxLogDebug(_T("process %d exit(0)"),pid);
	  }
	  m_pid = 0;
	  ThenDo();
	}
}

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

class CPyBackPlot : public CPyProcess
{
protected:
	const CProgram* m_program;
	HeeksObj* m_into;
	wxString m_filename;
	wxBusyCursor *m_busy_cursor;

	static CPyBackPlot* m_object;

public:
	CPyBackPlot(const CProgram* program, HeeksObj* into, const wxChar* filename): m_program(program), m_into(into),m_filename(filename),m_busy_cursor(NULL) { m_object = this; }
	~CPyBackPlot(void) { m_object = NULL; }

	static void StaticCancel(void) { if (m_object) m_object->Cancel(); }

	void Do(void)
	{
		if(m_busy_cursor == NULL)m_busy_cursor = new wxBusyCursor();

		if (m_program->m_machine.file_name == _T("not found"))
		{
			wxMessageBox(_T("Machine name (defined in Program Properties) not found"));
		} // End if - then
		else
		{
#ifdef WIN32
			Execute(wxString(_T("\"")) + theApp.GetDllFolder() + _T("\\nc_read.bat\" ") + m_program->m_machine.file_name + _T(" \"") + m_filename + _T("\""));
#else
#ifdef RUNINPLACE
            wxString path(_T("/nc/"));
#else
            wxString path(_T("/../heekscnc/nc/"));
#endif

			Execute(wxString(_T("python \"")) + theApp.GetDllFolder() + path + m_program->m_machine.file_name + wxString(_T("_read.py\" \"")) + m_filename + wxString(_T("\"")) );
#endif
		} // End if - else
	}
	void ThenDo(void)
	{
		// there should now be a .nc.xml written
		wxString xml_file_str = m_filename + wxString(_T(".nc.xml"));
		wxFile ofs(xml_file_str.c_str());
		if(!ofs.IsOpened())
		{
			wxMessageBox(wxString(_("Couldn't open file")) + _T(" - ") + xml_file_str);
			return;
		}

		// read the xml file, just like paste, into the program
		heeksCAD->OpenXMLFile(xml_file_str, m_into);
		heeksCAD->Repaint();

		// in Windows, at least, executing the bat file was making HeeksCAD change it's Z order
		heeksCAD->GetMainFrame()->Raise();

		delete m_busy_cursor;
		m_busy_cursor = NULL;
	}
};

CPyBackPlot* CPyBackPlot::m_object = NULL;

class CPyPostProcess : public CPyProcess
{
protected:
	const CProgram* m_program;
	wxString m_filename;
	bool m_include_backplot_processing;

	static CPyPostProcess* m_object;

public:
	CPyPostProcess(const CProgram* program,
			const wxChar* filename,
			const bool include_backplot_processing = true ) :
		m_program(program), m_filename(filename), m_include_backplot_processing(include_backplot_processing)
	{
		m_object = this;
	}

	~CPyPostProcess(void) { m_object = NULL; }

	static void StaticCancel(void) { if (m_object) m_object->Cancel(); }

	void Do(void)
	{
		wxBusyCursor wait; // show an hour glass until the end of this function
		wxStandardPaths standard_paths;
		wxFileName path( standard_paths.GetTempDir().c_str(), _T("post.py"));

#ifdef WIN32
        Execute(wxString(_T("\"")) + theApp.GetDllFolder() + wxString(_T("\\post.bat\" \"")) + path.GetFullPath() + wxString(_T("\"")));
#else

        wxString post_path = wxString(_T("python ")) + path.GetFullPath();
		Execute(post_path);
#endif
	}
	void ThenDo(void)
	{
		if (m_include_backplot_processing)
		{
			(new CPyBackPlot(m_program, (HeeksObj*)m_program, m_filename))->Do();
		}
	}
};

CPyPostProcess* CPyPostProcess::m_object = NULL;

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

static bool write_python_file(const wxString& python_file_path)
{
	wxFile ofs(python_file_path.c_str(), wxFile::write);
	if(!ofs.IsOpened())return false;

	ofs.Write(theApp.m_program->m_python_program.c_str());

	return true;
}

bool HeeksPyPostProcess(const CProgram* program, const wxString &filepath, const bool include_backplot_processing)
{
	try{
		theApp.m_output_canvas->m_textCtrl->Clear(); // clear the output window

		// write the python file
		wxStandardPaths standard_paths;
		wxFileName file_str( standard_paths.GetTempDir().c_str(), _T("post.py"));

		if(!write_python_file(file_str.GetFullPath()))
		{
		    wxString error;
		    error << _T("couldn't write ") << file_str.GetFullPath();
		    wxMessageBox(error.c_str());
		}
		else
		{
#ifdef WIN32
			// Set the working directory to the area that contains the DLL so that
			// the system can find the post.bat file correctly.
			::wxSetWorkingDirectory(theApp.GetDllFolder());
#else
			::wxSetWorkingDirectory(standard_paths.GetTempDir());
#endif

			// call the python file
			(new CPyPostProcess(program, filepath, include_backplot_processing))->Do();

			return true;
		}
	}
	catch(...)
	{
		wxMessageBox(_T("Error while post-processing the program!"));
	}
	return false;
}

bool HeeksPyBackplot(const CProgram* program, HeeksObj* into, const wxString &filepath)
{
	try{
		theApp.m_output_canvas->m_textCtrl->Clear(); // clear the output window

		::wxSetWorkingDirectory(theApp.GetDllFolder());

		// call the python file
		(new CPyBackPlot(program, into, filepath))->Do();

		// in Windows, at least, executing the bat file was making HeeksCAD change it's Z order
		heeksCAD->GetMainFrame()->Raise();

		return true;
	}
	catch(...)
	{
		wxMessageBox(_T("Error while backplotting the program!"));
	}
	return false;
}

void HeeksPyCancel(void)
{
	CPyBackPlot::StaticCancel();
	CPyPostProcess::StaticCancel();
}

<commit_msg>py stdout/stderr logging touchups<commit_after>// PythonStuff.cpp
// Copyright (c) 2009, Dan Heeks
// This program is released under the BSD license. See the file COPYING for details.

#include "stdafx.h"
#include <wx/file.h>
#include <wx/mimetype.h>
#include <wx/process.h>
#include <wx/stdpaths.h>
#include <wx/filename.h>
#include <wx/txtstrm.h>
#include <wx/log.h>
#include "PythonStuff.h"
#include "ProgramCanvas.h"
#include "OutputCanvas.h"
#include "Program.h"

class CPyProcess : public wxProcess
{
protected:
  int m_pid;

public:
  CPyProcess(void);

  void Execute(const wxChar* cmd);
  void Cancel(void);
  void OnTerminate(int pid, int status);
  void OnTimer(wxTimerEvent& WXUNUSED(event));

  virtual void ThenDo(void) { }

private:
  wxTimer m_timer;
  void HandleInput(void);

};

CPyProcess::CPyProcess(void)
{
  m_pid = 0;
  wxProcess(heeksCAD->GetMainFrame());
  Connect(wxEVT_TIMER, wxTimerEventHandler(CPyProcess::OnTimer));
  m_timer.SetOwner(this);

}

void CPyProcess::OnTimer(wxTimerEvent& event)
{
  HandleInput();
}

void CPyProcess::HandleInput(void)
{
  wxString s;
  wxInputStream *m_in,*m_err;

  m_in = GetInputStream();
  m_err = GetErrorStream();

  if (m_in)
    {
      while (m_in->CanRead()) {
	char buffer[4096];
	m_in->Read(buffer, sizeof(buffer));
	s += wxString::From8BitData(buffer, m_in->LastRead());
      }
      if (s.Length() > 0) {
	wxLogMessage(_T("> %s"),s.c_str());
      }
    }
  if (m_err)
    {
      while (m_err->CanRead()) {
	char buffer[4096];
	m_err->Read(buffer, sizeof(buffer));
	s += wxString::From8BitData(buffer, m_err->LastRead());
      }
      if (s.Length() > 0) {
	wxLogMessage(_T("! %s"),s.c_str());
      }
    }
}

void CPyProcess::Execute(const wxChar* cmd)
{
	Redirect();
	m_pid = wxExecute(cmd, wxEXEC_ASYNC, this);
	if (!m_pid) {
	  wxLogMessage(_T("could not execute '%s'"),cmd);
	} else {
	  wxLogMessage(_T("starting '%s' (%d)"),cmd,m_pid);
	}
	m_timer.Start(100);   //msec

}

void CPyProcess::Cancel(void)
{
	if (m_pid)
	{
		wxProcess::Kill(m_pid);
		m_pid = 0;
	}
}

void CPyProcess::OnTerminate(int pid, int status)
{
	if (pid == m_pid)
	{
	  m_timer.Stop();
	  HandleInput();   // anything left?
	  if (status) {
	    wxLogMessage(_T("process %d exit(%d)"),pid, status);
	  } else {
	    wxLogDebug(_T("process %d exit(0)"),pid);
	  }
	  m_pid = 0;
	  ThenDo();
	}
}

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

class CPyBackPlot : public CPyProcess
{
protected:
	const CProgram* m_program;
	HeeksObj* m_into;
	wxString m_filename;
	wxBusyCursor *m_busy_cursor;

	static CPyBackPlot* m_object;

public:
	CPyBackPlot(const CProgram* program, HeeksObj* into, const wxChar* filename): m_program(program), m_into(into),m_filename(filename),m_busy_cursor(NULL) { m_object = this; }
	~CPyBackPlot(void) { m_object = NULL; }

	static void StaticCancel(void) { if (m_object) m_object->Cancel(); }

	void Do(void)
	{
		if(m_busy_cursor == NULL)m_busy_cursor = new wxBusyCursor();

		if (m_program->m_machine.file_name == _T("not found"))
		{
			wxMessageBox(_T("Machine name (defined in Program Properties) not found"));
		} // End if - then
		else
		{
#ifdef WIN32
			Execute(wxString(_T("\"")) + theApp.GetDllFolder() + _T("\\nc_read.bat\" ") + m_program->m_machine.file_name + _T(" \"") + m_filename + _T("\""));
#else
#ifdef RUNINPLACE
            wxString path(_T("/nc/"));
#else
            wxString path(_T("/../heekscnc/nc/"));
#endif

			Execute(wxString(_T("python \"")) + theApp.GetDllFolder() + path + m_program->m_machine.file_name + wxString(_T("_read.py\" \"")) + m_filename + wxString(_T("\"")) );
#endif
		} // End if - else
	}
	void ThenDo(void)
	{
		// there should now be a .nc.xml written
		wxString xml_file_str = m_filename + wxString(_T(".nc.xml"));
		wxFile ofs(xml_file_str.c_str());
		if(!ofs.IsOpened())
		{
			wxMessageBox(wxString(_("Couldn't open file")) + _T(" - ") + xml_file_str);
			return;
		}

		// read the xml file, just like paste, into the program
		heeksCAD->OpenXMLFile(xml_file_str, m_into);
		heeksCAD->Repaint();

		// in Windows, at least, executing the bat file was making HeeksCAD change it's Z order
		heeksCAD->GetMainFrame()->Raise();

		delete m_busy_cursor;
		m_busy_cursor = NULL;
	}
};

CPyBackPlot* CPyBackPlot::m_object = NULL;

class CPyPostProcess : public CPyProcess
{
protected:
	const CProgram* m_program;
	wxString m_filename;
	bool m_include_backplot_processing;

	static CPyPostProcess* m_object;

public:
	CPyPostProcess(const CProgram* program,
			const wxChar* filename,
			const bool include_backplot_processing = true ) :
		m_program(program), m_filename(filename), m_include_backplot_processing(include_backplot_processing)
	{
		m_object = this;
	}

	~CPyPostProcess(void) { m_object = NULL; }

	static void StaticCancel(void) { if (m_object) m_object->Cancel(); }

	void Do(void)
	{
		wxBusyCursor wait; // show an hour glass until the end of this function
		wxStandardPaths standard_paths;
		wxFileName path( standard_paths.GetTempDir().c_str(), _T("post.py"));

#ifdef WIN32
        Execute(wxString(_T("\"")) + theApp.GetDllFolder() + wxString(_T("\\post.bat\" \"")) + path.GetFullPath() + wxString(_T("\"")));
#else

        wxString post_path = wxString(_T("python ")) + path.GetFullPath();
		Execute(post_path);
#endif
	}
	void ThenDo(void)
	{
		if (m_include_backplot_processing)
		{
			(new CPyBackPlot(m_program, (HeeksObj*)m_program, m_filename))->Do();
		}
	}
};

CPyPostProcess* CPyPostProcess::m_object = NULL;

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

static bool write_python_file(const wxString& python_file_path)
{
	wxFile ofs(python_file_path.c_str(), wxFile::write);
	if(!ofs.IsOpened())return false;

	ofs.Write(theApp.m_program->m_python_program.c_str());

	return true;
}

bool HeeksPyPostProcess(const CProgram* program, const wxString &filepath, const bool include_backplot_processing)
{
	try{
		theApp.m_output_canvas->m_textCtrl->Clear(); // clear the output window

		// write the python file
		wxStandardPaths standard_paths;
		wxFileName file_str( standard_paths.GetTempDir().c_str(), _T("post.py"));

		if(!write_python_file(file_str.GetFullPath()))
		{
		    wxString error;
		    error << _T("couldn't write ") << file_str.GetFullPath();
		    wxMessageBox(error.c_str());
		}
		else
		{
#ifdef WIN32
			// Set the working directory to the area that contains the DLL so that
			// the system can find the post.bat file correctly.
			::wxSetWorkingDirectory(theApp.GetDllFolder());
#else
			::wxSetWorkingDirectory(standard_paths.GetTempDir());
#endif

			// call the python file
			(new CPyPostProcess(program, filepath, include_backplot_processing))->Do();

			return true;
		}
	}
	catch(...)
	{
		wxMessageBox(_T("Error while post-processing the program!"));
	}
	return false;
}

bool HeeksPyBackplot(const CProgram* program, HeeksObj* into, const wxString &filepath)
{
	try{
		theApp.m_output_canvas->m_textCtrl->Clear(); // clear the output window

		::wxSetWorkingDirectory(theApp.GetDllFolder());

		// call the python file
		(new CPyBackPlot(program, into, filepath))->Do();

		// in Windows, at least, executing the bat file was making HeeksCAD change it's Z order
		heeksCAD->GetMainFrame()->Raise();

		return true;
	}
	catch(...)
	{
		wxMessageBox(_T("Error while backplotting the program!"));
	}
	return false;
}

void HeeksPyCancel(void)
{
	CPyBackPlot::StaticCancel();
	CPyPostProcess::StaticCancel();
}

<|endoftext|>