<commit_before>/*
 OFX NoOp plugin.
 Does nothing.

 Copyright (C) 2014 INRIA
 Author: Frederic Devernay <frederic.devernay@inria.fr>

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

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

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

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

 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 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.

 INRIA
 Domaine de Voluceau
 Rocquencourt - B.P. 105
 78153 Le Chesnay Cedex - France

 */

#include "NoOp.h"

#ifdef _WINDOWS
#include <windows.h>
#endif

#include "ofxsProcessing.H"

#define kPluginName "NoOpOFX"
#define kPluginGrouping "Other"
#define kPluginDescription "Copies the input to the ouput."
#define kPluginIdentifier "net.sf.openfx:NoOpPlugin"
#define kPluginVersionMajor 1 // Incrementing this number means that you have broken backwards compatibility of the plug-in.
#define kPluginVersionMinor 0 // Increment this when you have fixed a bug or made it faster.

#define kForceCopyParamName "forceCopy"
#define kForceCopyParamLabel "Force Copy"
#define kForceCopyParamHint "Force copy from input to output"

// Base class for the RGBA and the Alpha processor
class CopierBase : public OFX::ImageProcessor
{
protected:
    OFX::Image *_srcImg;

public:
    /** @brief no arg ctor */
    CopierBase(OFX::ImageEffect &instance)
    : OFX::ImageProcessor(instance)
    , _srcImg(0)
    {
    }

    /** @brief set the src image */
    void setSrcImg(OFX::Image *v) {_srcImg = v;}
};

// template to do the RGBA processing
template <class PIX, int nComponents>
class ImageCopier : public CopierBase
{
public:
    // ctor
    ImageCopier(OFX::ImageEffect &instance)
    : CopierBase(instance)
    {}

private:
    // and do some processing
    void multiThreadProcessImages(OfxRectI procWindow)
    {
        for (int y = procWindow.y1; y < procWindow.y2; y++) {
            if (_effect.abort()) break;

            PIX *dstPix = (PIX *) _dstImg->getPixelAddress(procWindow.x1, y);

            for (int x = procWindow.x1; x < procWindow.x2; x++) {

                PIX *srcPix = (PIX *)  (_srcImg ? _srcImg->getPixelAddress(x, y) : 0);

                // do we have a source image to scale up
                if (srcPix) {
                    for (int c = 0; c < nComponents; c++) {
                        dstPix[c] = srcPix[c];
                    }
                }
                else {
                    // no src pixel here, be black and transparent
                    for (int c = 0; c < nComponents; c++) {
                        dstPix[c] = 0;
                    }
                }

                // increment the dst pixel
                dstPix += nComponents;
            }
        }
    }
};

using namespace OFX;

////////////////////////////////////////////////////////////////////////////////
/** @brief The plugin that does our work */
class NoOpPlugin : public OFX::ImageEffect
{
public:
    /** @brief ctor */
    NoOpPlugin(OfxImageEffectHandle handle)
    : ImageEffect(handle)
    , dstClip_(0)
    , srcClip_(0)
    , forceCopy_(0)
    {
        dstClip_ = fetchClip(kOfxImageEffectOutputClipName);
        assert(dstClip_ && (dstClip_->getPixelComponents() == ePixelComponentAlpha || dstClip_->getPixelComponents() == ePixelComponentRGB || dstClip_->getPixelComponents() == ePixelComponentRGBA));
        srcClip_ = fetchClip(kOfxImageEffectSimpleSourceClipName);
        assert(srcClip_ && (srcClip_->getPixelComponents() == ePixelComponentAlpha || srcClip_->getPixelComponents() == ePixelComponentRGB || srcClip_->getPixelComponents() == ePixelComponentRGBA));
        forceCopy_ = fetchBooleanParam(kForceCopyParamName);
        assert(forceCopy_);
    }

private:
    /* Override the render */
    virtual void render(const OFX::RenderArguments &args);

    /* set up and run a processor */
    void setupAndProcess(CopierBase &, const OFX::RenderArguments &args);

    virtual bool isIdentity(const RenderArguments &args, Clip * &identityClip, double &identityTime) /*OVERRIDE FINAL*/;

private:
    // do not need to delete these, the ImageEffect is managing them for us
    OFX::Clip *dstClip_;
    OFX::Clip *srcClip_;

    OFX::BooleanParam *forceCopy_;
};

////////////////////////////////////////////////////////////////////////////////
/** @brief render for the filter */

////////////////////////////////////////////////////////////////////////////////
// basic plugin render function, just a skelington to instantiate templates from

/* set up and run a processor */
void
NoOpPlugin::setupAndProcess(CopierBase &processor, const OFX::RenderArguments &args)
{
    // get a dst image
    std::auto_ptr<OFX::Image> dst(dstClip_->fetchImage(args.time));
    if (!dst.get()) {
        OFX::throwSuiteStatusException(kOfxStatFailed);
    }
    if (dst->getRenderScale().x != args.renderScale.x ||
        dst->getRenderScale().y != args.renderScale.y ||
        dst->getField() != args.fieldToRender) {
        setPersistentMessage(OFX::Message::eMessageError, "", "OFX Host gave image with wrong scale or field properties");
        OFX::throwSuiteStatusException(kOfxStatFailed);
    }
    OFX::BitDepthEnum dstBitDepth       = dst->getPixelDepth();
    OFX::PixelComponentEnum dstComponents  = dst->getPixelComponents();

    // fetch main input image
    std::auto_ptr<OFX::Image> src(srcClip_->fetchImage(args.time));

    // make sure bit depths are sane
    if (src.get()) {
        OFX::BitDepthEnum    srcBitDepth      = src->getPixelDepth();
        OFX::PixelComponentEnum srcComponents = src->getPixelComponents();

        // see if they have the same depths and bytes and all
        if (srcBitDepth != dstBitDepth || srcComponents != dstComponents)
            OFX::throwSuiteStatusException(kOfxStatErrImageFormat);
    }

    // set the images
    processor.setDstImg(dst.get());
    processor.setSrcImg(src.get());

    // set the render window
    processor.setRenderWindow(args.renderWindow);

    // Call the base class process member, this will call the derived templated process code
    processor.process();
}

// the overridden render function
void
NoOpPlugin::render(const OFX::RenderArguments &args)
{
    bool forceCopy;
    forceCopy_->getValue(forceCopy);

    if (!forceCopy) {
        setPersistentMessage(OFX::Message::eMessageError, "", "OFX Host should not render");
        throwSuiteStatusException(kOfxStatFailed);
    }

    // instantiate the render code based on the pixel depth of the dst clip
    OFX::BitDepthEnum       dstBitDepth    = dstClip_->getPixelDepth();
    OFX::PixelComponentEnum dstComponents  = dstClip_->getPixelComponents();

    // do the rendering
    if (dstComponents == OFX::ePixelComponentRGBA) {
        switch(dstBitDepth) {
            case OFX::eBitDepthUByte : {
                ImageCopier<unsigned char, 4> fred(*this);
                setupAndProcess(fred, args);
            }
                break;

            case OFX::eBitDepthUShort : {
                ImageCopier<unsigned short, 4> fred(*this);
                setupAndProcess(fred, args);
            }
                break;

            case OFX::eBitDepthFloat : {
                ImageCopier<float, 4> fred(*this);
                setupAndProcess(fred, args);
            }
                break;
            default :
                OFX::throwSuiteStatusException(kOfxStatErrUnsupported);
        }
    } else if (dstComponents == OFX::ePixelComponentRGB) {
        switch(dstBitDepth) {
            case OFX::eBitDepthUByte : {
                ImageCopier<unsigned char, 3> fred(*this);
                setupAndProcess(fred, args);
            }
                break;

            case OFX::eBitDepthUShort : {
                ImageCopier<unsigned short, 3> fred(*this);
                setupAndProcess(fred, args);
            }
                break;

            case OFX::eBitDepthFloat : {
                ImageCopier<float, 3> fred(*this);
                setupAndProcess(fred, args);
            }
                break;
            default :
                OFX::throwSuiteStatusException(kOfxStatErrUnsupported);
        }
    } else {
        assert(dstComponents == OFX::ePixelComponentAlpha);
        switch(dstBitDepth) {
            case OFX::eBitDepthUByte : {
                ImageCopier<unsigned char, 1> fred(*this);
                setupAndProcess(fred, args);
            }
                break;

            case OFX::eBitDepthUShort : {
                ImageCopier<unsigned short, 1> fred(*this);
                setupAndProcess(fred, args);
            }
                break;

            case OFX::eBitDepthFloat : {
                ImageCopier<float, 1> fred(*this);
                setupAndProcess(fred, args);
            }
                break;
            default :
                OFX::throwSuiteStatusException(kOfxStatErrUnsupported);
        }
    }
}

bool
NoOpPlugin::isIdentity(const RenderArguments &args, Clip * &identityClip, double &identityTime)
{
    bool forceCopy;
    forceCopy_->getValue(forceCopy);

    return !forceCopy;
}

using namespace OFX;

mDeclarePluginFactory(NoOpPluginFactory, {}, {});

void NoOpPluginFactory::describe(OFX::ImageEffectDescriptor &desc)
{
    // basic labels
    desc.setLabels(kPluginName, kPluginName, kPluginName);
    desc.setPluginGrouping(kPluginGrouping);
    desc.setPluginDescription(kPluginDescription);

    // add the supported contexts, only filter at the moment
    desc.addSupportedContext(eContextFilter);

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

    // set a few flags
    desc.setSingleInstance(false);
    desc.setHostFrameThreading(false);
    desc.setSupportsMultiResolution(true);
    desc.setSupportsTiles(true);
    desc.setTemporalClipAccess(false);
    desc.setRenderTwiceAlways(false);
    desc.setSupportsMultipleClipPARs(false);
}

void NoOpPluginFactory::describeInContext(OFX::ImageEffectDescriptor &desc, OFX::ContextEnum context)
{
    if (!OFX::fetchSuite(kOfxVegasStereoscopicImageEffectSuite, 1, true)) {
        throwHostMissingSuiteException(kOfxVegasStereoscopicImageEffectSuite);
    }

    // Source clip only in the filter context
    // create the mandated source clip
    ClipDescriptor *srcClip = desc.defineClip(kOfxImageEffectSimpleSourceClipName);
    srcClip->addSupportedComponent(ePixelComponentRGB);
    srcClip->addSupportedComponent(ePixelComponentRGBA);
    srcClip->addSupportedComponent(ePixelComponentAlpha);
    srcClip->setTemporalClipAccess(false);
    srcClip->setSupportsTiles(true);
    srcClip->setIsMask(false);

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

    // make some pages and to things in
    PageParamDescriptor *page = desc.definePageParam("Controls");

    BooleanParamDescriptor *forceCopy = desc.defineBooleanParam(kForceCopyParamName);
    forceCopy->setLabels(kForceCopyParamLabel, kForceCopyParamLabel, kForceCopyParamLabel);
    forceCopy->setHint(kForceCopyParamHint);
    forceCopy->setDefault(false);
    forceCopy->setAnimates(false);

    page->addChild(*forceCopy);
}

OFX::ImageEffect* NoOpPluginFactory::createInstance(OfxImageEffectHandle handle, OFX::ContextEnum context)
{
    return new NoOpPlugin(handle);
}

void getNoOpPluginID(OFX::PluginFactoryArray &ids)
{
    static NoOpPluginFactory p(kPluginIdentifier, kPluginVersionMajor, kPluginVersionMinor);
    ids.push_back(&p);
}
<commit_msg>NoOp: add Clip Info button<commit_after>/*
 OFX NoOp plugin.
 Does nothing.

 Copyright (C) 2014 INRIA
 Author: Frederic Devernay <frederic.devernay@inria.fr>

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

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

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

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

 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 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.

 INRIA
 Domaine de Voluceau
 Rocquencourt - B.P. 105
 78153 Le Chesnay Cedex - France

 */

#include "NoOp.h"

#ifdef _WINDOWS
#include <windows.h>
#endif

#include "ofxsProcessing.H"

#define kPluginName "NoOpOFX"
#define kPluginGrouping "Other"
#define kPluginDescription "Copies the input to the ouput."
#define kPluginIdentifier "net.sf.openfx:NoOpPlugin"
#define kPluginVersionMajor 1 // Incrementing this number means that you have broken backwards compatibility of the plug-in.
#define kPluginVersionMinor 0 // Increment this when you have fixed a bug or made it faster.

#define kClipInfoParamName "clipInfo"
#define kClipInfoParamLabel "Clip Info..."
#define kClipInfoParamHint "Display information about the inputs"

#define kForceCopyParamName "forceCopy"
#define kForceCopyParamLabel "Force Copy"
#define kForceCopyParamHint "Force copy from input to output"

// Base class for the RGBA and the Alpha processor
class CopierBase : public OFX::ImageProcessor
{
protected:
    OFX::Image *_srcImg;

public:
    /** @brief no arg ctor */
    CopierBase(OFX::ImageEffect &instance)
    : OFX::ImageProcessor(instance)
    , _srcImg(0)
    {
    }

    /** @brief set the src image */
    void setSrcImg(OFX::Image *v) {_srcImg = v;}
};

// template to do the RGBA processing
template <class PIX, int nComponents>
class ImageCopier : public CopierBase
{
public:
    // ctor
    ImageCopier(OFX::ImageEffect &instance)
    : CopierBase(instance)
    {}

private:
    // and do some processing
    void multiThreadProcessImages(OfxRectI procWindow)
    {
        for (int y = procWindow.y1; y < procWindow.y2; y++) {
            if (_effect.abort()) break;

            PIX *dstPix = (PIX *) _dstImg->getPixelAddress(procWindow.x1, y);

            for (int x = procWindow.x1; x < procWindow.x2; x++) {

                PIX *srcPix = (PIX *)  (_srcImg ? _srcImg->getPixelAddress(x, y) : 0);

                // do we have a source image to scale up
                if (srcPix) {
                    for (int c = 0; c < nComponents; c++) {
                        dstPix[c] = srcPix[c];
                    }
                }
                else {
                    // no src pixel here, be black and transparent
                    for (int c = 0; c < nComponents; c++) {
                        dstPix[c] = 0;
                    }
                }

                // increment the dst pixel
                dstPix += nComponents;
            }
        }
    }
};

using namespace OFX;

////////////////////////////////////////////////////////////////////////////////
/** @brief The plugin that does our work */
class NoOpPlugin : public OFX::ImageEffect
{
public:
    /** @brief ctor */
    NoOpPlugin(OfxImageEffectHandle handle)
    : ImageEffect(handle)
    , dstClip_(0)
    , srcClip_(0)
    , forceCopy_(0)
    {
        dstClip_ = fetchClip(kOfxImageEffectOutputClipName);
        assert(dstClip_ && (dstClip_->getPixelComponents() == ePixelComponentAlpha || dstClip_->getPixelComponents() == ePixelComponentRGB || dstClip_->getPixelComponents() == ePixelComponentRGBA));
        srcClip_ = fetchClip(kOfxImageEffectSimpleSourceClipName);
        assert(srcClip_ && (srcClip_->getPixelComponents() == ePixelComponentAlpha || srcClip_->getPixelComponents() == ePixelComponentRGB || srcClip_->getPixelComponents() == ePixelComponentRGBA));
        forceCopy_ = fetchBooleanParam(kForceCopyParamName);
        assert(forceCopy_);
    }

private:
    /* Override the render */
    virtual void render(const OFX::RenderArguments &args);

    /* set up and run a processor */
    void setupAndProcess(CopierBase &, const OFX::RenderArguments &args);

    virtual bool isIdentity(const RenderArguments &args, Clip * &identityClip, double &identityTime) /*OVERRIDE FINAL*/;

    virtual void changedParam(const OFX::InstanceChangedArgs &args, const std::string &paramName);

private:
    // do not need to delete these, the ImageEffect is managing them for us
    OFX::Clip *dstClip_;
    OFX::Clip *srcClip_;

    OFX::BooleanParam *forceCopy_;
};

////////////////////////////////////////////////////////////////////////////////
/** @brief render for the filter */

////////////////////////////////////////////////////////////////////////////////
// basic plugin render function, just a skelington to instantiate templates from

/* set up and run a processor */
void
NoOpPlugin::setupAndProcess(CopierBase &processor, const OFX::RenderArguments &args)
{
    // get a dst image
    std::auto_ptr<OFX::Image> dst(dstClip_->fetchImage(args.time));
    if (!dst.get()) {
        OFX::throwSuiteStatusException(kOfxStatFailed);
    }
    if (dst->getRenderScale().x != args.renderScale.x ||
        dst->getRenderScale().y != args.renderScale.y ||
        dst->getField() != args.fieldToRender) {
        setPersistentMessage(OFX::Message::eMessageError, "", "OFX Host gave image with wrong scale or field properties");
        OFX::throwSuiteStatusException(kOfxStatFailed);
    }
    OFX::BitDepthEnum dstBitDepth       = dst->getPixelDepth();
    OFX::PixelComponentEnum dstComponents  = dst->getPixelComponents();

    // fetch main input image
    std::auto_ptr<OFX::Image> src(srcClip_->fetchImage(args.time));

    // make sure bit depths are sane
    if (src.get()) {
        OFX::BitDepthEnum    srcBitDepth      = src->getPixelDepth();
        OFX::PixelComponentEnum srcComponents = src->getPixelComponents();

        // see if they have the same depths and bytes and all
        if (srcBitDepth != dstBitDepth || srcComponents != dstComponents)
            OFX::throwSuiteStatusException(kOfxStatErrImageFormat);
    }

    // set the images
    processor.setDstImg(dst.get());
    processor.setSrcImg(src.get());

    // set the render window
    processor.setRenderWindow(args.renderWindow);

    // Call the base class process member, this will call the derived templated process code
    processor.process();
}

// the overridden render function
void
NoOpPlugin::render(const OFX::RenderArguments &args)
{
    bool forceCopy;
    forceCopy_->getValue(forceCopy);

    if (!forceCopy) {
        setPersistentMessage(OFX::Message::eMessageError, "", "OFX Host should not render");
        throwSuiteStatusException(kOfxStatFailed);
    }

    // instantiate the render code based on the pixel depth of the dst clip
    OFX::BitDepthEnum       dstBitDepth    = dstClip_->getPixelDepth();
    OFX::PixelComponentEnum dstComponents  = dstClip_->getPixelComponents();

    // do the rendering
    if (dstComponents == OFX::ePixelComponentRGBA) {
        switch(dstBitDepth) {
            case OFX::eBitDepthUByte : {
                ImageCopier<unsigned char, 4> fred(*this);
                setupAndProcess(fred, args);
            }
                break;

            case OFX::eBitDepthUShort : {
                ImageCopier<unsigned short, 4> fred(*this);
                setupAndProcess(fred, args);
            }
                break;

            case OFX::eBitDepthFloat : {
                ImageCopier<float, 4> fred(*this);
                setupAndProcess(fred, args);
            }
                break;
            default :
                OFX::throwSuiteStatusException(kOfxStatErrUnsupported);
        }
    } else if (dstComponents == OFX::ePixelComponentRGB) {
        switch(dstBitDepth) {
            case OFX::eBitDepthUByte : {
                ImageCopier<unsigned char, 3> fred(*this);
                setupAndProcess(fred, args);
            }
                break;

            case OFX::eBitDepthUShort : {
                ImageCopier<unsigned short, 3> fred(*this);
                setupAndProcess(fred, args);
            }
                break;

            case OFX::eBitDepthFloat : {
                ImageCopier<float, 3> fred(*this);
                setupAndProcess(fred, args);
            }
                break;
            default :
                OFX::throwSuiteStatusException(kOfxStatErrUnsupported);
        }
    } else if (dstComponents == OFX::ePixelComponentAlpha) {
        switch(dstBitDepth) {
            case OFX::eBitDepthUByte : {
                ImageCopier<unsigned char, 1> fred(*this);
                setupAndProcess(fred, args);
            }
                break;

            case OFX::eBitDepthUShort : {
                ImageCopier<unsigned short, 1> fred(*this);
                setupAndProcess(fred, args);
            }
                break;

            case OFX::eBitDepthFloat : {
                ImageCopier<float, 1> fred(*this);
                setupAndProcess(fred, args);
            }
                break;
            default :
                OFX::throwSuiteStatusException(kOfxStatErrUnsupported);
        }
    } else {
        OFX::throwSuiteStatusException(kOfxStatErrUnsupported);
    }
}

bool
NoOpPlugin::isIdentity(const RenderArguments &args, Clip * &identityClip, double &identityTime)
{
    bool forceCopy;
    forceCopy_->getValue(forceCopy);

    return !forceCopy;
}

static const char*
bitDepthString(BitDepthEnum bitDepth)
{
    switch (bitDepth) {
        case OFX::eBitDepthUByte:
            return "8u";
        case OFX::eBitDepthUShort:
            return "16u";
        case OFX::eBitDepthHalf:
            return "16f";
        case OFX::eBitDepthFloat:
            return "32f";
        case OFX::eBitDepthCustom:
            return "x";
        case OFX::eBitDepthNone:
            return "0";
#ifdef OFX_EXTENSIONS_VEGAS
        case eBitDepthUByteBGRA:
            return "8uBGRA";
        case eBitDepthUShortBGRA:
            return "16uBGRA";
        case eBitDepthFloatBGRA:
            return "32fBGRA";
#endif
        default:
            return "[unknown bit depth]";
    }
}

static std::string
pixelComponentString(const std::string& p)
{
    const std::string prefix = "OfxImageComponent";
    std::string s = p;
    return s.replace(s.find(prefix),prefix.length(),"");
}

static const char* premultString(PreMultiplicationEnum e)
{
    switch (e) {
        case eImageOpaque:
            return "Opaque";
        case eImagePreMultiplied:
            return "PreMultiplied";
        case eImageUnPreMultiplied:
            return "UnPreMultiplied";
        default:
            return "[unknown premult]";
    }
}

static const char* fieldOrderString(FieldEnum e)
{
    switch (e) {
        case eFieldBoth:
            return "Both";
        case eFieldLower:
            return "Lower";
        case eFieldUpper:
            return "Upper";
        case eFieldSingle:
            return "Single";
        case eFieldDoubled:
            return "Doubled";
        default:
            return "[unknown field order]";
    }
}

void
NoOpPlugin::changedParam(const OFX::InstanceChangedArgs &args, const std::string &paramName)
{
    if (paramName == kClipInfoParamName) {
        std::ostringstream oss;
        oss << "Clip Info:\n\n";
        oss << "Input: ";
        if (!srcClip_) {
            oss << "N/A";
        } else {
            OFX::Clip &c = *srcClip_;
            oss << pixelComponentString(c.getPixelComponentsProperty());
            oss << bitDepthString(c.getPixelDepth());
            oss << "(unmapped: ";
            oss << pixelComponentString(c.getUnmappedPixelComponentsProperty());
            oss << bitDepthString(c.getUnmappedPixelDepth());
            oss << ")\npremultiplication: ";
            oss << premultString(c.getPreMultiplication());
            oss << "\nfield order: ";
            oss << fieldOrderString(c.getFieldOrder());
            oss << "\n";
            oss << (c.isConnected() ? "connected" : "not connected");
            oss << "\n";
            oss << (c.hasContinuousSamples() ? "continuous samples" : "discontinuous samples");
            oss << "\npixel aspect ratio: ";
            oss << c.getPixelAspectRatio();
            oss << "\nframe rate: ";
            oss << c.getFrameRate();
            oss << " (unmapped: ";
            oss << c.getUnmappedFrameRate();
            oss << ")";
            OfxRangeD range = c.getFrameRange();
            oss << "\nframe range: ";
            oss << range.min << "..." << range.max;
            oss << " (unmapped: ";
            range = c.getUnmappedFrameRange();
            oss << range.min << "..." << range.max;
            oss << ")";
            oss << "\nregion of definition: ";
            OfxRectD rod = c.getRegionOfDefinition(args.time);
            oss << rod.x1 << ' ' << rod.y1 << ' ' << rod.x2 << ' ' << rod.y2;
        }
        oss << "\n\n";
        oss << "Output: ";
        if (!dstClip_) {
            oss << "N/A";
        } else {
            OFX::Clip &c = *dstClip_;
            oss << pixelComponentString(c.getPixelComponentsProperty());
            oss << bitDepthString(c.getPixelDepth());
            oss << "(unmapped: ";
            oss << pixelComponentString(c.getUnmappedPixelComponentsProperty());
            oss << bitDepthString(c.getUnmappedPixelDepth());
            oss << ")\npremultiplication: ";
            oss << premultString(c.getPreMultiplication());
            oss << "\nfield order: ";
            oss << fieldOrderString(c.getFieldOrder());
            oss << "\n";
            oss << (c.isConnected() ? "connected" : "not connected");
            oss << "\n";
            oss << (c.hasContinuousSamples() ? "continuous samples" : "discontinuous samples");
            oss << "\npixel aspect ratio: ";
            oss << c.getPixelAspectRatio();
            oss << "\nframe rate: ";
            oss << c.getFrameRate();
            oss << " (unmapped: ";
            oss << c.getUnmappedFrameRate();
            oss << ")";
            OfxRangeD range = c.getFrameRange();
            oss << "\nframe range: ";
            oss << range.min << "..." << range.max;
            oss << " (unmapped: ";
            range = c.getUnmappedFrameRange();
            oss << range.min << "..." << range.max;
            oss << ")";
            oss << "\nregion of definition: ";
            OfxRectD rod = c.getRegionOfDefinition(args.time);
            oss << rod.x1 << ' ' << rod.y1 << ' ' << rod.x2 << ' ' << rod.y2;
        }
        oss << "\n\n";
        oss << "time: " << args.time << ", renderscale: " << args.renderScale.x << 'x' << args.renderScale.y << '\n';

        sendMessage(OFX::Message::eMessageMessage, "", oss.str());
    }
}

using namespace OFX;

mDeclarePluginFactory(NoOpPluginFactory, {}, {});

void NoOpPluginFactory::describe(OFX::ImageEffectDescriptor &desc)
{
    // basic labels
    desc.setLabels(kPluginName, kPluginName, kPluginName);
    desc.setPluginGrouping(kPluginGrouping);
    desc.setPluginDescription(kPluginDescription);

    // add the supported contexts, only filter at the moment
    desc.addSupportedContext(eContextFilter);

    // add supported pixel depths
    desc.addSupportedBitDepth(eBitDepthNone);
    desc.addSupportedBitDepth(eBitDepthUByte);
    desc.addSupportedBitDepth(eBitDepthUShort);
    desc.addSupportedBitDepth(eBitDepthHalf);
    desc.addSupportedBitDepth(eBitDepthFloat);
    desc.addSupportedBitDepth(eBitDepthCustom);
#ifdef OFX_EXTENSIONS_VEGAS
    desc.addSupportedBitDepth(eBitDepthUByteBGRA);
    desc.addSupportedBitDepth(eBitDepthUShortBGRA);
    desc.addSupportedBitDepth(eBitDepthFloatBGRA);
#endif

    // set a few flags
    desc.setSingleInstance(false);
    desc.setHostFrameThreading(false);
    desc.setSupportsMultiResolution(true);
    desc.setSupportsTiles(true);
    desc.setTemporalClipAccess(false);
    desc.setRenderTwiceAlways(false);
    desc.setSupportsMultipleClipPARs(false);
}

void NoOpPluginFactory::describeInContext(OFX::ImageEffectDescriptor &desc, OFX::ContextEnum context)
{
    // Source clip only in the filter context
    // create the mandated source clip
    ClipDescriptor *srcClip = desc.defineClip(kOfxImageEffectSimpleSourceClipName);
    srcClip->addSupportedComponent(ePixelComponentNone);
    srcClip->addSupportedComponent(ePixelComponentRGBA);
    srcClip->addSupportedComponent(ePixelComponentRGB);
    srcClip->addSupportedComponent(ePixelComponentAlpha);
#ifdef OFX_EXTENSIONS_NUKE
    srcClip->addSupportedComponent(ePixelComponentMotionVectors);
    srcClip->addSupportedComponent(ePixelComponentStereoDisparity);
#endif
    srcClip->addSupportedComponent(ePixelComponentCustom);
    srcClip->setTemporalClipAccess(false);
    srcClip->setSupportsTiles(true);
    srcClip->setIsMask(false);

    // create the mandated output clip
    ClipDescriptor *dstClip = desc.defineClip(kOfxImageEffectOutputClipName);
    dstClip->addSupportedComponent(ePixelComponentNone);
    dstClip->addSupportedComponent(ePixelComponentRGBA);
    dstClip->addSupportedComponent(ePixelComponentRGB);
    dstClip->addSupportedComponent(ePixelComponentAlpha);
#ifdef OFX_EXTENSIONS_NUKE
    dstClip->addSupportedComponent(ePixelComponentMotionVectors);
    dstClip->addSupportedComponent(ePixelComponentStereoDisparity);
#endif
    dstClip->addSupportedComponent(ePixelComponentCustom);
    dstClip->setSupportsTiles(true);

    // make some pages and to things in
    PageParamDescriptor *page = desc.definePageParam("Controls");

    BooleanParamDescriptor *forceCopy = desc.defineBooleanParam(kForceCopyParamName);
    forceCopy->setLabels(kForceCopyParamLabel, kForceCopyParamLabel, kForceCopyParamLabel);
    forceCopy->setHint(kForceCopyParamHint);
    forceCopy->setDefault(false);
    forceCopy->setAnimates(false);
    page->addChild(*forceCopy);

    PushButtonParamDescriptor *clipInfo = desc.definePushButtonParam(kClipInfoParamName);
    clipInfo->setLabels(kClipInfoParamLabel, kClipInfoParamLabel, kClipInfoParamLabel);
    clipInfo->setHint(kClipInfoParamHint);
    page->addChild(*clipInfo);
}

OFX::ImageEffect* NoOpPluginFactory::createInstance(OfxImageEffectHandle handle, OFX::ContextEnum context)
{
    return new NoOpPlugin(handle);
}

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


<commit_before>#ifndef GENERIC_FORWARDER_HPP
# define GENERIC_FORWARDER_HPP
# pragma once

#include <cassert>

// ::std::size_t
#include <cstddef>

#include <type_traits>

#include <utility>

namespace generic
{

namespace detail
{

namespace forwarder
{

template <typename ...A>
struct argument_types
{
};

template <typename A>
struct argument_types
{
  using argument_type = A;
};

template <typename A, typename B>
struct argument_types
{
  using first_argument_type = A;
  using second_argument_type = B;
};

}

}

template<typename F, ::std::size_t N = 4 * sizeof(void*)>
class forwarder;

template<typename R, typename ...A, ::std::size_t N>
class forwarder<R (A...), N> : public detail::forwarder::argument_types
{
  R (*stub_)(void const*, A&&...){};

  typename ::std::aligned_storage<N>::type store_;

  template<typename T, typename ...U, ::std::size_t M>
  friend bool operator==(forwarder<T (U...), M> const&,
    ::std::nullptr_t) noexcept;
  template<typename T, typename ...U, ::std::size_t M>
  friend bool operator==(::std::nullptr_t,
    forwarder<T (U...), M> const&) noexcept;

  template<typename T, typename ...U, ::std::size_t M>
  friend bool operator!=(forwarder<T (U...), M> const&,
    ::std::nullptr_t) noexcept;
  template<typename T, typename ...U, ::std::size_t M>
  friend bool operator!=(::std::nullptr_t,
    forwarder<T (U...), M> const&) noexcept;

public:
  using result_type	= R;

public:
  forwarder() = default;

  forwarder(forwarder const&) = default;

  template<typename T,
    typename = typename ::std::enable_if<
      !::std::is_same<forwarder, typename ::std::decay<T>::type>{}
    >::type
  >
  forwarder(T&& f) noexcept
  {
    assign(::std::forward<T>(f));
  }

  forwarder& operator=(forwarder const&) = default;

  forwarder& operator=(forwarder&&) = default;

  template <
    typename T,
    typename = typename ::std::enable_if<
      !::std::is_same<forwarder, typename ::std::decay<T>::type>{}
    >::type
  >
  forwarder& operator=(T&& f) noexcept
  {
    assign(::std::forward<T>(f));

    return *this;
  }

  explicit operator bool() const noexcept { return stub_; }

  R operator()(A... args) const
    noexcept(noexcept(stub_(&store_, ::std::forward(args)...)))
  {
    //assert(stub_);
    return stub_(&store_, ::std::forward(args)...);
  }

  template <typename T>
  void assign(T&& f) noexcept
  {
    using functor_type = typename ::std::decay<T>::type;

    static_assert(sizeof(functor_type) <= sizeof(store_),
      "functor too large");
    static_assert(::std::is_trivially_copyable<T>{},
      "functor not trivially copyable");

    ::new (static_cast<void*>(&store_)) functor_type(::std::forward<T>(f));

    stub_ = [](void const* const ptr, A&&... args) noexcept(noexcept(
        (*static_cast<functor_type const*>(ptr))(::std::forward(args)...))
      ) -> R
      {
        return (*static_cast<functor_type const*>(ptr))(
          ::std::forward(args)...
        );
      };
  }

  void reset() noexcept { stub_ = nullptr; }

  void swap(forwarder& other) noexcept { ::std::swap(*this, other); }

  template <typename T>
  T* target() noexcept
  {
    return reinterpret_cast<T*>(&store_);
  }

  template <typename T>
  T const* target() const noexcept
  {
    return reinterpret_cast<T const*>(&store_);
  }
};

template<typename R, typename ...A, ::std::size_t N>
bool operator==(forwarder<R (A...), N> const& f,
  ::std::nullptr_t const) noexcept
{
  return f.stub_ == nullptr;
}

template<typename R, typename ...A, ::std::size_t N>
bool operator==(::std::nullptr_t const,
  forwarder<R (A...), N> const& f) noexcept
{
  return f.stub_ == nullptr;
}

template<typename R, typename ...A, ::std::size_t N>
bool operator!=(forwarder<R (A...), N> const& f,
  ::std::nullptr_t const) noexcept
{
  return !operator==(f, nullptr);
}

template<typename R, typename ...A, ::std::size_t N>
bool operator!=(::std::nullptr_t const,
  forwarder<R (A...), N> const& f) noexcept
{
  return !operator==(f, nullptr);
}

}

#endif // GENERIC_FORWARDER_HPP
<commit_msg>some fixes<commit_after>#ifndef GENERIC_FORWARDER_HPP
# define GENERIC_FORWARDER_HPP
# pragma once

#include <cassert>

// ::std::size_t
#include <cstddef>

#include <type_traits>

#include <utility>

namespace generic
{

namespace detail
{

namespace forwarder
{

template <typename ...A>
struct argument_types
{
};

template <typename A>
struct argument_types
{
  using argument_type = A;
};

template <typename A, typename B>
struct argument_types
{
  using first_argument_type = A;
  using second_argument_type = B;
};

}

}

template<typename F, ::std::size_t N = 4 * sizeof(void*)>
class forwarder;

template<typename R, typename ...A, ::std::size_t N>
class forwarder<R (A...), N> : public detail::forwarder::argument_types
{
  R (*stub_)(void const*, A&&...){};

  typename ::std::aligned_storage<N>::type store_;

  template<typename T, typename ...U, ::std::size_t M>
  friend bool operator==(forwarder<T (U...), M> const&,
    ::std::nullptr_t) noexcept;
  template<typename T, typename ...U, ::std::size_t M>
  friend bool operator==(::std::nullptr_t,
    forwarder<T (U...), M> const&) noexcept;

  template<typename T, typename ...U, ::std::size_t M>
  friend bool operator!=(forwarder<T (U...), M> const&,
    ::std::nullptr_t) noexcept;
  template<typename T, typename ...U, ::std::size_t M>
  friend bool operator!=(::std::nullptr_t,
    forwarder<T (U...), M> const&) noexcept;

public:
  using result_type	= R;

public:
  forwarder() = default;

  forwarder(forwarder const&) = default;

  template<typename T, typename ...U,
    typename = typename ::std::enable_if<
      !::std::is_same<forwarder, typename ::std::decay<T>::type>{}
    >::type
  >
  forwarder(T&& t, U&& ...u) noexcept
  {
    assign(::std::forward<T>(t), ::std::forward(u)...);
  }

  forwarder& operator=(forwarder const&) = default;

  forwarder& operator=(forwarder&&) = default;

  template <
    typename T,
    typename = typename ::std::enable_if<
      !::std::is_same<forwarder, typename ::std::decay<T>::type>{}
    >::type
  >
  forwarder& operator=(T&& f) noexcept
  {
    assign(::std::forward<T>(f));

    return *this;
  }

  explicit operator bool() const noexcept { return stub_; }

  R operator()(A... args) const
    noexcept(noexcept(stub_(&store_, ::std::forward(args)...)))
  {
    //assert(stub_);
    return stub_(&store_, ::std::forward(args)...);
  }

  template <typename T>
  void assign(T&& f) noexcept
  {
    using functor_type = typename ::std::decay<T>::type;

    static_assert(sizeof(functor_type) <= sizeof(store_),
      "functor too large");
    static_assert(::std::is_trivially_copyable<T>{},
      "functor not trivially copyable");

    ::new (static_cast<void*>(&store_)) functor_type(::std::forward<T>(f));

    stub_ = [](void const* const ptr, A&&... args) noexcept(noexcept(
        (*static_cast<functor_type const*>(ptr))(::std::forward(args)...))
      ) -> R
      {
        return (*static_cast<functor_type const*>(ptr))(
          ::std::forward(args)...
        );
      };
  }

  template <class C>
  void assign(C* const object_ptr,
    R (C::* const method_ptr)(A...)) noexcept
  {
    assign([object_ptr, method_ptr](A&&... args) noexcept(
      (object_ptr->*method_ptr)(::std::declval()...)) {
        return (object_ptr->*method_ptr)(::std::forward(args)...);
      }
    );
  }

  template <class C>
  void assign(C* const object_ptr,
    R (C::* const method_ptr)(A...) const) noexcept
  {
    assign([object_ptr, method_ptr](A&&... args) noexcept(
      (object_ptr->*method_ptr)(::std::declval()...)) {
        return (object_ptr->*method_ptr)(::std::forward(args)...);
      }
    );
  }

  template <class C>
  void assign(C& object,
    R (C::* const method_ptr)(A...)) noexcept
  {
    assign([&object, method_ptr](A&&... args) noexcept(
      (object.*method_ptr)(::std::declval()...)) {
        return (object.*method_ptr)(::std::forward(args)...);
      }
    );
  }

  template <class C>
  void assign(C const& object,
    R (C::* const method_ptr)(A...) const) noexcept
  {
    assign([&object, method_ptr](A&&... args) noexcept(
      (object.*method_ptr)(::std::declval()...)) {
        return (object.*method_ptr)(::std::forward(args)...);
      }
    );
  }

  void reset() noexcept { stub_ = nullptr; }

  void swap(forwarder& other) noexcept { ::std::swap(*this, other); }

  template <typename T>
  T* target() noexcept
  {
    return reinterpret_cast<T*>(&store_);
  }

  template <typename T>
  T const* target() const noexcept
  {
    return reinterpret_cast<T const*>(&store_);
  }
};

template<typename R, typename ...A, ::std::size_t N>
bool operator==(forwarder<R (A...), N> const& f,
  ::std::nullptr_t const) noexcept
{
  return f.stub_ == nullptr;
}

template<typename R, typename ...A, ::std::size_t N>
bool operator==(::std::nullptr_t const,
  forwarder<R (A...), N> const& f) noexcept
{
  return f.stub_ == nullptr;
}

template<typename R, typename ...A, ::std::size_t N>
bool operator!=(forwarder<R (A...), N> const& f,
  ::std::nullptr_t const) noexcept
{
  return !operator==(f, nullptr);
}

template<typename R, typename ...A, ::std::size_t N>
bool operator!=(::std::nullptr_t const,
  forwarder<R (A...), N> const& f) noexcept
{
  return !operator==(f, nullptr);
}

}

#endif // GENERIC_FORWARDER_HPP
<|endoftext|>


<commit_before>#ifndef GENERIC_FORWARDER_HPP
# define GENERIC_FORWARDER_HPP
# pragma once

#include <cassert>

// ::std::size_t
#include <cstddef>

#include <type_traits>

#include <utility>

namespace generic
{

template<typename F, ::std::size_t N = 4 * sizeof(void*)>
class forwarder;

template<typename R, typename ...A, ::std::size_t N>
class forwarder<R (A...), N>
{
  R (*stub_)(void const*, A&&...){};

  typename ::std::aligned_storage<N>::type store_;

  template<typename T, typename ...U, ::std::size_t M>
  friend bool operator==(forwarder<T (U...), M> const&,
    ::std::nullptr_t) noexcept;
  template<typename T, typename ...U, ::std::size_t M>
  friend bool operator==(::std::nullptr_t,
    forwarder<T (U...), M> const&) noexcept;

  template<typename T, typename ...U, ::std::size_t M>
  friend bool operator!=(forwarder<T (U...), M> const&,
    ::std::nullptr_t) noexcept;
  template<typename T, typename ...U, ::std::size_t M>
  friend bool operator!=(::std::nullptr_t,
    forwarder<T (U...), M> const&) noexcept;

public:
  using result_type	= R;

public:
  forwarder() = default;

  forwarder(forwarder const&) = default;

  template<typename T>
  forwarder(T&& f) noexcept
  {
    operator=(::std::forward<T>(f));
  }

  forwarder& operator=(forwarder const&) = default;

  forwarder& operator=(forwarder&&) = default;

  template <
    typename T,
    typename = typename ::std::enable_if<
      !::std::is_same<forwarder, typename ::std::decay<T>::type>{}
    >::type
  >
  forwarder& operator=(T&& f) noexcept
  {
    using functor_type = typename ::std::decay<T>::type;

    static_assert(sizeof(functor_type) <= sizeof(store_),
      "functor too large");
    static_assert(::std::is_trivially_copyable<T>{},
      "functor not trivially copyable");

    ::new (static_cast<void*>(&store_)) functor_type(::std::forward<T>(f));

    stub_ = [](void const* const ptr, A&&... args) noexcept(noexcept(
        (*static_cast<functor_type const*>(ptr))(::std::forward<A>(args)...))
      ) -> R
      {
        return (*static_cast<functor_type const*>(ptr))(
          ::std::forward<A>(args)...
        );
      };

    return *this;
  }

  explicit operator bool() const noexcept { return stub_; }

  R operator()(A... args) const
    noexcept(noexcept(stub_(&store_, ::std::forward<A>(args)...)))
  {
    //assert(stub_);
    return stub_(&store_, ::std::forward<A>(args)...);
  }

  template <typename T>
  void assign(T&& f) noexcept(noexcept(operator=(::std::forward<T>(f))))
  {
    operator=(::std::forward<T>(f));
  }

  void reset() noexcept { stub_ = nullptr; }

  void swap(forwarder& other) noexcept { ::std::swap(*this, other); }

  template <typename T>
  T* target() noexcept
  {
    return reinterpret_cast<T*>(&store_);
  }

  template <typename T>
  T const* target() const noexcept
  {
    return reinterpret_cast<T const*>(&store_);
  }
};

template<typename R, typename ...A, ::std::size_t N>
bool operator==(forwarder<R (A...), N> const& f,
  ::std::nullptr_t const) noexcept
{
  return f.stub_ == nullptr;
}

template<typename R, typename ...A, ::std::size_t N>
bool operator==(::std::nullptr_t const,
  forwarder<R (A...), N> const& f) noexcept
{
  return f.stub_ == nullptr;
}

template<typename R, typename ...A, ::std::size_t N>
bool operator!=(forwarder<R (A...), N> const& f,
  ::std::nullptr_t const) noexcept
{
  return !operator==(f, nullptr);
}

template<typename R, typename ...A, ::std::size_t N>
bool operator!=(::std::nullptr_t const,
  forwarder<R (A...), N> const& f) noexcept
{
  return !operator==(f, nullptr);
}

}

#endif // GENERIC_FORWARDER_HPP
<commit_msg>some fixes<commit_after>#ifndef GENERIC_FORWARDER_HPP
# define GENERIC_FORWARDER_HPP
# pragma once

#include <cassert>

// ::std::size_t
#include <cstddef>

#include <type_traits>

#include <utility>

namespace generic
{

template <typename ...A>
struct forwarder_argument_types
{
};

template <typename A>
struct forwarder_argument_types<A>
{
  using argument_type = A;
};

template <typename A, typename B>
struct forwarder_argument_types<A, B>
{
  using first_argument_type = A;
  using second_argument_type = B;
};

template<typename F, ::std::size_t N = 4 * sizeof(void*)>
class forwarder;

template<typename R, typename ...A, ::std::size_t N>
class forwarder<R (A...), N> : public forwarder_argument_types<A...>
{
  R (*stub_)(void const*, A&&...){};

  typename ::std::aligned_storage<N>::type store_;

  template<typename T, typename ...U, ::std::size_t M>
  friend bool operator==(forwarder<T (U...), M> const&,
    ::std::nullptr_t) noexcept;
  template<typename T, typename ...U, ::std::size_t M>
  friend bool operator==(::std::nullptr_t,
    forwarder<T (U...), M> const&) noexcept;

  template<typename T, typename ...U, ::std::size_t M>
  friend bool operator!=(forwarder<T (U...), M> const&,
    ::std::nullptr_t) noexcept;
  template<typename T, typename ...U, ::std::size_t M>
  friend bool operator!=(::std::nullptr_t,
    forwarder<T (U...), M> const&) noexcept;

public:
  using result_type	= R;

public:
  forwarder() = default;

  forwarder(forwarder const&) = default;

  template<typename T>
  forwarder(T&& f) noexcept
  {
    operator=(::std::forward<T>(f));
  }

  forwarder& operator=(forwarder const&) = default;

  forwarder& operator=(forwarder&&) = default;

  template <
    typename T,
    typename = typename ::std::enable_if<
      !::std::is_same<forwarder, typename ::std::decay<T>::type>{}
    >::type
  >
  forwarder& operator=(T&& f) noexcept
  {
    using functor_type = typename ::std::decay<T>::type;

    static_assert(sizeof(functor_type) <= sizeof(store_),
      "functor too large");
    static_assert(::std::is_trivially_copyable<T>{},
      "functor not trivially copyable");

    ::new (static_cast<void*>(&store_)) functor_type(::std::forward<T>(f));

    stub_ = [](void const* const ptr, A&&... args) noexcept(noexcept(
        (*static_cast<functor_type const*>(ptr))(::std::forward<A>(args)...))
      ) -> R
      {
        return (*static_cast<functor_type const*>(ptr))(
          ::std::forward<A>(args)...
        );
      };

    return *this;
  }

  explicit operator bool() const noexcept { return stub_; }

  R operator()(A... args) const
    noexcept(noexcept(stub_(&store_, ::std::forward<A>(args)...)))
  {
    //assert(stub_);
    return stub_(&store_, ::std::forward<A>(args)...);
  }

  template <typename T>
  void assign(T&& f) noexcept(noexcept(operator=(::std::forward<T>(f))))
  {
    operator=(::std::forward<T>(f));
  }

  void reset() noexcept { stub_ = nullptr; }

  void swap(forwarder& other) noexcept { ::std::swap(*this, other); }

  template <typename T>
  T* target() noexcept
  {
    return reinterpret_cast<T*>(&store_);
  }

  template <typename T>
  T const* target() const noexcept
  {
    return reinterpret_cast<T const*>(&store_);
  }
};

template<typename R, typename ...A, ::std::size_t N>
bool operator==(forwarder<R (A...), N> const& f,
  ::std::nullptr_t const) noexcept
{
  return f.stub_ == nullptr;
}

template<typename R, typename ...A, ::std::size_t N>
bool operator==(::std::nullptr_t const,
  forwarder<R (A...), N> const& f) noexcept
{
  return f.stub_ == nullptr;
}

template<typename R, typename ...A, ::std::size_t N>
bool operator!=(forwarder<R (A...), N> const& f,
  ::std::nullptr_t const) noexcept
{
  return !operator==(f, nullptr);
}

template<typename R, typename ...A, ::std::size_t N>
bool operator!=(::std::nullptr_t const,
  forwarder<R (A...), N> const& f) noexcept
{
  return !operator==(f, nullptr);
}

}

#endif // GENERIC_FORWARDER_HPP
<|endoftext|>


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

  Program:   OpenIGTLink Library
  Language:  C++
  Date:      $Date: 2016/01/25 19:53:38 $

  Copyright (c) Insight Software Consortium. All rights reserved.

  This software is distributed WITHOUT ANY WARRANTY; without even
  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  PURPOSE.  See the above copyright notices for more information.

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

#include <igtlMessageBase.h>
#include <igtlMessageHeader.h>
#include "gtest/gtest.h"
#include "igtlutil/igtl_test_data_image.h"
#include "igtl_util.h"

TEST(MessageBaseTest, InitializationTest)
{
  igtl::MessageBase::Pointer messageBaseTest = igtl::MessageBase::New();
  messageBaseTest->SetDeviceName("DeviceTest");
  EXPECT_STREQ(messageBaseTest->GetDeviceName(), "DeviceTest");
  messageBaseTest->InitPack();
  EXPECT_STREQ(messageBaseTest->GetDeviceName(),"");
}

TEST(MessageBaseTest, SetDeviceNameTest)
{
  igtl::MessageBase::Pointer messageBaseTest = igtl::MessageBase::New();
  messageBaseTest->InitPack();
  EXPECT_STREQ(messageBaseTest->GetDeviceName(), "");
  messageBaseTest->SetDeviceName("DeviceTest");
  EXPECT_STREQ(messageBaseTest->GetDeviceName(), "DeviceTest");
}

TEST(MessageBaseTest, GetDeviceNameTest)
{
  igtl::MessageBase::Pointer messageBaseTest = igtl::MessageBase::New();
  messageBaseTest->SetDeviceName("DeviceTest");
  EXPECT_STREQ(messageBaseTest->GetDeviceName(), "DeviceTest");
}

TEST(MessageBaseTest, TimeStampTest)
{
  igtl::MessageBase::Pointer messageBaseTest = igtl::MessageBase::New();
  messageBaseTest->SetTimeStamp(1,2);
  unsigned int sec=0, nanosec=0;
  messageBaseTest->GetTimeStamp(&sec,&nanosec);
  EXPECT_EQ(sec, 1);
  EXPECT_EQ(nanosec, 2);
  igtl::TimeStamp::Pointer ts_input = igtl::TimeStamp::New();
  ts_input->SetTime(123,500000000); //nanosecond can not be larger or equal to 1e9.
  //5e8 nanosecond equals 2147483647 frac second.
  messageBaseTest->SetTimeStamp(ts_input);
  messageBaseTest->GetTimeStamp(&sec,&nanosec);
  EXPECT_EQ(sec, 123);
  EXPECT_EQ(nanosec, 2147483647);
}

TEST(MessageBaseTest, UNPACKTEST)
{
  igtl::MessageBase::Pointer messageBaseTest = igtl::MessageBase::New();
  int status = messageBaseTest->Unpack(); // The m_packSize cannot be set, so the unpack cannot be tested
  EXPECT_EQ(status, messageBaseTest->UNPACK_UNDEF);
}

int main(int argc, char **argv)
{
  testing::InitGoogleTest(&argc, argv);
  return RUN_ALL_TESTS();
}

<commit_msg>resolve the warning from EXPECT_EQ(int, enum)<commit_after>/*=========================================================================

  Program:   OpenIGTLink Library
  Language:  C++
  Date:      $Date: 2016/01/25 19:53:38 $

  Copyright (c) Insight Software Consortium. All rights reserved.

  This software is distributed WITHOUT ANY WARRANTY; without even
  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  PURPOSE.  See the above copyright notices for more information.

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

#include <igtlMessageBase.h>
#include <igtlMessageHeader.h>
#include "gtest/gtest.h"
#include "igtlutil/igtl_test_data_image.h"
#include "igtl_util.h"

TEST(MessageBaseTest, InitializationTest)
{
  igtl::MessageBase::Pointer messageBaseTest = igtl::MessageBase::New();
  messageBaseTest->SetDeviceName("DeviceTest");
  EXPECT_STREQ(messageBaseTest->GetDeviceName(), "DeviceTest");
  messageBaseTest->InitPack();
  EXPECT_STREQ(messageBaseTest->GetDeviceName(),"");
}

TEST(MessageBaseTest, SetDeviceNameTest)
{
  igtl::MessageBase::Pointer messageBaseTest = igtl::MessageBase::New();
  messageBaseTest->InitPack();
  EXPECT_STREQ(messageBaseTest->GetDeviceName(), "");
  messageBaseTest->SetDeviceName("DeviceTest");
  EXPECT_STREQ(messageBaseTest->GetDeviceName(), "DeviceTest");
}

TEST(MessageBaseTest, GetDeviceNameTest)
{
  igtl::MessageBase::Pointer messageBaseTest = igtl::MessageBase::New();
  messageBaseTest->SetDeviceName("DeviceTest");
  EXPECT_STREQ(messageBaseTest->GetDeviceName(), "DeviceTest");
}

TEST(MessageBaseTest, TimeStampTest)
{
  igtl::MessageBase::Pointer messageBaseTest = igtl::MessageBase::New();
  messageBaseTest->SetTimeStamp(1,2);
  unsigned int sec=0, nanosec=0;
  messageBaseTest->GetTimeStamp(&sec,&nanosec);
  EXPECT_EQ(sec, 1);
  EXPECT_EQ(nanosec, 2);
  igtl::TimeStamp::Pointer ts_input = igtl::TimeStamp::New();
  ts_input->SetTime(123,500000000); //nanosecond can not be larger or equal to 1e9.
  //5e8 nanosecond equals 2147483647 frac second.
  messageBaseTest->SetTimeStamp(ts_input);
  messageBaseTest->GetTimeStamp(&sec,&nanosec);
  EXPECT_EQ(sec, 123);
  EXPECT_EQ(nanosec, 2147483647);
}

TEST(MessageBaseTest, UNPACKTEST)
{
  igtl::MessageBase::Pointer messageBaseTest = igtl::MessageBase::New();
  int status = messageBaseTest->Unpack(); // The m_packSize cannot be set, so the unpack cannot be tested
  EXPECT_EQ(status, static_cast<int>(messageBaseTest->UNPACK_UNDEF));
}

int main(int argc, char **argv)
{
  testing::InitGoogleTest(&argc, argv);
  return RUN_ALL_TESTS();
}

<|endoftext|>


<commit_before>#pragma once
#include <array>
#include <string>
#include <memory>
#include <typeinfo>
#include <typeindex>
namespace darwin {
	enum class status {
		null,ready,busy,leisure,error
	};
	enum class results {
		null,success,failure
	};
	enum class colors {
		white,black,red,green,blue,pink,yellow,cyan
	};
	enum class attris {
		bright,underline
	};
	enum class commands {
		echo_on,echo_off,reset_cursor,reset_attri,clrscr
	};
	class pixel final {
		char mChar=' ';
		std::array<bool,2> mAttris= {{false,false}};
		std::array<colors,2> mColors= {{colors::white,colors::black}};
	public:
		pixel()=default;
		pixel(const pixel&)=default;
		pixel(char ch,const std::array<bool,2>& a,const std::array<colors,2>& c):mChar(ch),mAttris(a),mColors(c) {}
		~pixel()=default;
		void set_char(char c)
		{
			mChar=c;
		}
		char get_char() const
		{
			return mChar;
		}
		void set_front_color(colors c)
		{
			mColors[0]=c;
		}
		colors get_front_color() const
		{
			return mColors[0];
		}
		void set_back_color(colors c)
		{
			mColors[1]=c;
		}
		colors get_back_color() const
		{
			return mColors[1];
		}
		void set_colors(const std::array<colors,2>& c)
		{
			mColors=c;
		}
		const std::array<colors,2>& get_colors() const
		{
			return mColors;
		}
		void set_bright(bool value)
		{
			mAttris[0]=value;
		}
		bool is_bright() const
		{
			return mAttris[0];
		}
		void set_underline(bool value)
		{
			mAttris[1]=value;
		}
		bool is_underline() const
		{
			return mAttris[1];
		}
		void set_attris(const std::array<bool,2>& a)
		{
			mAttris=a;
		}
		const std::array<bool,2>& get_attris() const
		{
			return mAttris;
		}
	};
	class drawable {
	public:
		drawable()=default;
		drawable(const drawable&)=default;
		virtual ~drawable()=default;
		virtual std::type_index get_type() const final
		{
			return typeid(*this);
		}
		virtual std::shared_ptr<drawable> clone() noexcept
		{
			return nullptr;
		}
		virtual bool usable() const noexcept=0;
		virtual void clear()=0;
		virtual void fill(const pixel&)=0;
		virtual void resize(std::size_t,std::size_t)=0;
		virtual std::size_t get_width() const=0;
		virtual std::size_t get_height() const=0;
		virtual const pixel& get_pixel(const std::array<std::size_t,2>&) const=0;
		virtual void draw_pixel(const std::array<std::size_t,2>&,const pixel&)=0;
		virtual void draw_picture(const std::array<std::size_t,2>& posit,const drawable& img)
		{
			std::size_t col(posit[0]),row(posit[1]);
			if(!this->usable())
				throw std::logic_error(__func__);
			if(col>this->get_width()-1||row>this->get_height()-1)
				throw std::out_of_range(__func__);
			for(std::size_t r=row; r<this->get_height()&&r-row<img.get_height(); ++r)
				for(std::size_t c=col; c<this->get_width()&&c-col<img.get_width(); ++c)
					this->draw_pixel({r,c},img.get_pixel({r-row,c-col}));
		}
	};
}<commit_msg>Signed-off-by: Mike Lee <mikecovlee@163.com><commit_after>#pragma once
#include <array>
#include <cmath>
#include <string>
#include <memory>
#include <typeinfo>
#include <typeindex>
namespace darwin {
	enum class status {
		null,ready,busy,leisure,error
	};
	enum class results {
		null,success,failure
	};
	enum class colors {
		white,black,red,green,blue,pink,yellow,cyan
	};
	enum class attris {
		bright,underline
	};
	enum class commands {
		echo_on,echo_off,reset_cursor,reset_attri,clrscr
	};
	class pixel final {
		char mChar=' ';
		std::array<bool,2> mAttris= {{false,false}};
		std::array<colors,2> mColors= {{colors::white,colors::black}};
	public:
		pixel()=default;
		pixel(const pixel&)=default;
		pixel(char ch,const std::array<bool,2>& a,const std::array<colors,2>& c):mChar(ch),mAttris(a),mColors(c) {}
		~pixel()=default;
		void set_char(char c)
		{
			mChar=c;
		}
		char get_char() const
		{
			return mChar;
		}
		void set_front_color(colors c)
		{
			mColors[0]=c;
		}
		colors get_front_color() const
		{
			return mColors[0];
		}
		void set_back_color(colors c)
		{
			mColors[1]=c;
		}
		colors get_back_color() const
		{
			return mColors[1];
		}
		void set_colors(const std::array<colors,2>& c)
		{
			mColors=c;
		}
		const std::array<colors,2>& get_colors() const
		{
			return mColors;
		}
		void set_bright(bool value)
		{
			mAttris[0]=value;
		}
		bool is_bright() const
		{
			return mAttris[0];
		}
		void set_underline(bool value)
		{
			mAttris[1]=value;
		}
		bool is_underline() const
		{
			return mAttris[1];
		}
		void set_attris(const std::array<bool,2>& a)
		{
			mAttris=a;
		}
		const std::array<bool,2>& get_attris() const
		{
			return mAttris;
		}
	};
	class drawable {
	public:
		drawable()=default;
		drawable(const drawable&)=default;
		virtual ~drawable()=default;
		virtual std::type_index get_type() const final
		{
			return typeid(*this);
		}
		virtual std::shared_ptr<drawable> clone() noexcept
		{
			return nullptr;
		}
		virtual bool usable() const noexcept=0;
		virtual void clear()=0;
		virtual void fill(const pixel&)=0;
		virtual void resize(std::size_t,std::size_t)=0;
		virtual std::size_t get_width() const=0;
		virtual std::size_t get_height() const=0;
		virtual const pixel& get_pixel(const std::array<std::size_t,2>&) const=0;
		virtual void draw_pixel(const std::array<std::size_t,2>&,const pixel&)=0;
		virtual void draw_line(const std::array<std::size_t,2>& p0,const std::array<std::size_t,2>& p1,const pixel& pix)
		{
			if(p0==p1) return;
			if(p0[0]>this->get_width()-1||p0[1]>this->get_height()-1||p1[0]>this->get_width()-1||p1[1]>this->get_height()-1)
				throw std::out_of_range(__func__);
			long w(p0[0]-p1[0]),h(p0[1]-p1[1]);
			double distance(std::sqrt(std::pow(w,2)+std::pow(h,2)));
			for(double c=0;c<=1;c+=1.0/distance)
				this->draw_pixel({p0[0]+w*c,p0[1]+h*c},pix);
		}
		virtual void draw_picture(const std::array<std::size_t,2>& posit,const drawable& img)
		{
			std::size_t col(posit[0]),row(posit[1]);
			if(!this->usable())
				throw std::logic_error(__func__);
			if(col>this->get_width()-1||row>this->get_height()-1)
				throw std::out_of_range(__func__);
			for(std::size_t r=row; r<this->get_height()&&r-row<img.get_height(); ++r)
				for(std::size_t c=col; c<this->get_width()&&c-col<img.get_width(); ++c)
					this->draw_pixel({r,c},img.get_pixel({r-row,c-col}));
		}
	};
}<|endoftext|>


<commit_before>/*
 * This file is part of the OpenKinect Project. http://www.openkinect.org
 *
 * Copyright (c) 2011 individual OpenKinect contributors. See the CONTRIB file
 * for details.
 *
 * This code is licensed to you under the terms of the Apache License, version
 * 2.0, or, at your option, the terms of the GNU General Public License,
 * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses,
 * or the following URLs:
 * http://www.apache.org/licenses/LICENSE-2.0
 * http://www.gnu.org/licenses/gpl-2.0.txt
 *
 * If you redistribute this file in source form, modified or unmodified, you
 * may:
 *   1) Leave this header intact and distribute it under the same terms,
 *      accompanying it with the APACHE20 and GPL20 files, or
 *   2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or
 *   3) Delete the GPL v2 clause and accompany it with the APACHE20 file
 * In all cases you must keep the copyright notice intact and include a copy
 * of the CONTRIB file.
 *
 * Binary distributions must follow the binary distribution requirements of
 * either License.
 */

#include <iostream>
#include <sstream>
#include <stdio.h>
#include <signal.h>

#include <opencv2/opencv.hpp>

#include <libfreenect2/libfreenect2.hpp>
#include <libfreenect2/frame_listener_impl.h>
#include <libfreenect2/threading.h>
#include <libfreenect2/registration.h>
#include <libfreenect2/packet_pipeline.h>

bool protonect_shutdown = false;

void sigint_handler(int s)
{
  protonect_shutdown = true;
}

std::string tostr(int x)
{
    std::stringstream str;
    str << x;
    return str.str();
}

int main(int argc, char *argv[])
{
  std::string program_path(argv[0]);
  size_t executable_name_idx = program_path.rfind("Protonect");

  std::string binpath = "/";

  if(executable_name_idx != std::string::npos)
  {
    binpath = program_path.substr(0, executable_name_idx);
  }

  libfreenect2::Freenect2 freenect2;
  libfreenect2::Freenect2Device *dev = 0;
  libfreenect2::PacketPipeline *pipeline = 0;

  if(freenect2.enumerateDevices() == 0)
  {
    std::cout << "no device connected!" << std::endl;
    return -1;
  }

  std::string serial = freenect2.getDefaultDeviceSerialNumber();
  int threshold = 128;

  for(int argI = 1; argI < argc; ++argI)
  {
    const std::string arg(argv[argI]);

    if(arg == "cpu")
    {
      if(!pipeline)
        pipeline = new libfreenect2::CpuPacketPipeline();
    }
    else if(arg == "gl")
    {
#ifdef LIBFREENECT2_WITH_OPENGL_SUPPORT
      if(!pipeline)
        pipeline = new libfreenect2::OpenGLPacketPipeline();
#else
      std::cout << "OpenGL pipeline is not supported!" << std::endl;
#endif
    }
    else if(arg == "cl")
    {
#ifdef LIBFREENECT2_WITH_OPENCL_SUPPORT
      if(!pipeline)
        pipeline = new libfreenect2::OpenCLPacketPipeline();
#else
      std::cout << "OpenCL pipeline is not supported!" << std::endl;
#endif
    }
    else if (arg == "-t") {
      std::string thresholdString (argv[argI+1]);

      std::istringstream ss(argv[argI+1]);
      int x;
      if (!(ss >> threshold)) {
        std::cerr << "Invalid number " << argv[argI+1] << '\n';
      }

      argI += 1;
    }
    else if(arg.find_first_not_of("0123456789") == std::string::npos) //check if parameter could be a serial number
    {
      serial = arg;
    }
    else
    {
      std::cout << "Unknown argument: " << arg << std::endl;
    }
  }

  if(pipeline)
  {
    dev = freenect2.openDevice(serial, pipeline);
  }
  else
  {
    dev = freenect2.openDevice(serial);
  }

  if(dev == 0)
  {
    std::cout << "failure opening device!" << std::endl;
    return -1;
  }

  signal(SIGINT,sigint_handler);
  protonect_shutdown = false;

  libfreenect2::SyncMultiFrameListener listener(libfreenect2::Frame::Color | libfreenect2::Frame::Ir | libfreenect2::Frame::Depth);
  libfreenect2::FrameMap frames;
  libfreenect2::Frame undistorted(512, 424, 4), registered(512, 424, 4);

  dev->setColorFrameListener(&listener);
  dev->setIrAndDepthFrameListener(&listener);
  dev->start();

  std::cout << "device serial: " << dev->getSerialNumber() << std::endl;
  std::cout << "device firmware: " << dev->getFirmwareVersion() << std::endl;

  libfreenect2::Registration* registration = new libfreenect2::Registration(dev->getIrCameraParams(), dev->getColorCameraParams());

  std::string filename ("test_" );
  int i = 0;
  while(!protonect_shutdown)
  {
    listener.waitForNewFrame(frames);
    libfreenect2::Frame *rgb = frames[libfreenect2::Frame::Color];
    libfreenect2::Frame *ir = frames[libfreenect2::Frame::Ir];
    libfreenect2::Frame *depth = frames[libfreenect2::Frame::Depth];

    cv::imshow("rgb", cv::Mat(rgb->height, rgb->width, CV_8UC4, rgb->data));
    //cv::imshow("ir", cv::Mat(ir->height, ir->width, CV_32FC1, ir->data) / 20000.0f);
    //cv::imshow("depth", cv::Mat(depth->height, depth->width, CV_32FC1, depth->data) / 4500.0f);

    registration->apply(rgb, depth, &undistorted, &registered);

    //cv::imshow("undistorted", cv::Mat(undistorted.height, undistorted.width, CV_32FC1, undistorted.data) / 4500.0f);
    //cv::imshow("registered", cv::Mat(registered.height, registered.width, CV_8UC4, registered.data));

    if (i > 10) {
      i = 0;
      for (int j=0; j<=10; j++) {
        std::string jIndex = tostr(j);
        if(remove((filename + jIndex + ".jpg").c_str()) != 0) {
          perror( "Error deleting file" );
        } else {
          puts( "File successfully deleted" );
        }
      }
    }

    cv::Mat undistortedFrame = cv::Mat(undistorted.height, undistorted.width, CV_32FC1, undistorted.data) / 4500.0f;
    cv::Mat img_bw;
    undistortedFrame.convertTo(img_bw, CV_8UC4, 255);
    cv::Mat thresh = img_bw > threshold;

    cv::imshow("undistorted", thresh);

    std::string index = tostr(i);
    cv::imwrite((filename + index + ".jpg").c_str(), thresh);
    i += 1;

    int key = cv::waitKey(1);
    protonect_shutdown = protonect_shutdown || (key > 0 && ((key & 0xFF) == 27)); // shutdown on escape
    if (!protonect_shutdown) {
      std::cout << "key=" << (key & 0xFF) << std::endl;
      if (key == 82) {
        threshold += 1;
        std::cout << "increasing threshold" << std::endl;
      } else if (key == 83) {
        threshold -= 1;
        std::cout << "decreasing threshold" << std::endl;
      }
    }

    listener.release(frames);
    libfreenect2::this_thread::sleep_for(libfreenect2::chrono::milliseconds(1000));
  }

  // TODO: restarting ir stream doesn't work!
  // TODO: bad things will happen, if frame listeners are freed before dev->stop() :(
  dev->stop();
  dev->close();

  delete registration;

  return 0;
}
<commit_msg>added optional threshol parameter<commit_after>/*
 * This file is part of the OpenKinect Project. http://www.openkinect.org
 *
 * Copyright (c) 2011 individual OpenKinect contributors. See the CONTRIB file
 * for details.
 *
 * This code is licensed to you under the terms of the Apache License, version
 * 2.0, or, at your option, the terms of the GNU General Public License,
 * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses,
 * or the following URLs:
 * http://www.apache.org/licenses/LICENSE-2.0
 * http://www.gnu.org/licenses/gpl-2.0.txt
 *
 * If you redistribute this file in source form, modified or unmodified, you
 * may:
 *   1) Leave this header intact and distribute it under the same terms,
 *      accompanying it with the APACHE20 and GPL20 files, or
 *   2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or
 *   3) Delete the GPL v2 clause and accompany it with the APACHE20 file
 * In all cases you must keep the copyright notice intact and include a copy
 * of the CONTRIB file.
 *
 * Binary distributions must follow the binary distribution requirements of
 * either License.
 */

#include <iostream>
#include <sstream>
#include <stdio.h>
#include <signal.h>

#include <opencv2/opencv.hpp>

#include <libfreenect2/libfreenect2.hpp>
#include <libfreenect2/frame_listener_impl.h>
#include <libfreenect2/threading.h>
#include <libfreenect2/registration.h>
#include <libfreenect2/packet_pipeline.h>

bool protonect_shutdown = false;

void sigint_handler(int s)
{
  protonect_shutdown = true;
}

std::string tostr(int x)
{
    std::stringstream str;
    str << x;
    return str.str();
}

int main(int argc, char *argv[])
{
  std::string program_path(argv[0]);
  size_t executable_name_idx = program_path.rfind("Protonect");

  std::string binpath = "/";

  if(executable_name_idx != std::string::npos)
  {
    binpath = program_path.substr(0, executable_name_idx);
  }

  libfreenect2::Freenect2 freenect2;
  libfreenect2::Freenect2Device *dev = 0;
  libfreenect2::PacketPipeline *pipeline = 0;

  if(freenect2.enumerateDevices() == 0)
  {
    std::cout << "no device connected!" << std::endl;
    return -1;
  }

  std::string serial = freenect2.getDefaultDeviceSerialNumber();
  int threshold = -1;

  for(int argI = 1; argI < argc; ++argI)
  {
    const std::string arg(argv[argI]);

    if(arg == "cpu")
    {
      if(!pipeline)
        pipeline = new libfreenect2::CpuPacketPipeline();
    }
    else if(arg == "gl")
    {
#ifdef LIBFREENECT2_WITH_OPENGL_SUPPORT
      if(!pipeline)
        pipeline = new libfreenect2::OpenGLPacketPipeline();
#else
      std::cout << "OpenGL pipeline is not supported!" << std::endl;
#endif
    }
    else if(arg == "cl")
    {
#ifdef LIBFREENECT2_WITH_OPENCL_SUPPORT
      if(!pipeline)
        pipeline = new libfreenect2::OpenCLPacketPipeline();
#else
      std::cout << "OpenCL pipeline is not supported!" << std::endl;
#endif
    }
    else if (arg == "-t") {
      std::string thresholdString (argv[argI+1]);

      std::istringstream ss(argv[argI+1]);
      int x;
      if (!(ss >> threshold)) {
        std::cerr << "Invalid number " << argv[argI+1] << '\n';
      }

      argI += 1;
    }
    else if(arg.find_first_not_of("0123456789") == std::string::npos) //check if parameter could be a serial number
    {
      serial = arg;
    }
    else
    {
      std::cout << "Unknown argument: " << arg << std::endl;
    }
  }

  if(pipeline)
  {
    dev = freenect2.openDevice(serial, pipeline);
  }
  else
  {
    dev = freenect2.openDevice(serial);
  }

  if(dev == 0)
  {
    std::cout << "failure opening device!" << std::endl;
    return -1;
  }

  signal(SIGINT,sigint_handler);
  protonect_shutdown = false;

  libfreenect2::SyncMultiFrameListener listener(libfreenect2::Frame::Color | libfreenect2::Frame::Ir | libfreenect2::Frame::Depth);
  libfreenect2::FrameMap frames;
  libfreenect2::Frame undistorted(512, 424, 4), registered(512, 424, 4);

  dev->setColorFrameListener(&listener);
  dev->setIrAndDepthFrameListener(&listener);
  dev->start();

  std::cout << "device serial: " << dev->getSerialNumber() << std::endl;
  std::cout << "device firmware: " << dev->getFirmwareVersion() << std::endl;

  libfreenect2::Registration* registration = new libfreenect2::Registration(dev->getIrCameraParams(), dev->getColorCameraParams());

  std::string filename ("test_" );
  int i = 0;
  while(!protonect_shutdown)
  {
    listener.waitForNewFrame(frames);
    libfreenect2::Frame *rgb = frames[libfreenect2::Frame::Color];
    libfreenect2::Frame *ir = frames[libfreenect2::Frame::Ir];
    libfreenect2::Frame *depth = frames[libfreenect2::Frame::Depth];

    cv::imshow("rgb", cv::Mat(rgb->height, rgb->width, CV_8UC4, rgb->data));
    //cv::imshow("ir", cv::Mat(ir->height, ir->width, CV_32FC1, ir->data) / 20000.0f);
    //cv::imshow("depth", cv::Mat(depth->height, depth->width, CV_32FC1, depth->data) / 4500.0f);

    registration->apply(rgb, depth, &undistorted, &registered);

    //cv::imshow("undistorted", cv::Mat(undistorted.height, undistorted.width, CV_32FC1, undistorted.data) / 4500.0f);
    //cv::imshow("registered", cv::Mat(registered.height, registered.width, CV_8UC4, registered.data));

    if (i > 10) {
      i = 0;
      for (int j=0; j<=10; j++) {
        std::string jIndex = tostr(j);
        if(remove((filename + jIndex + ".jpg").c_str()) != 0) {
          perror( "Error deleting file" );
        } else {
          puts( "File successfully deleted" );
        }
      }
    }

    cv::Mat undistortedFrame = cv::Mat(undistorted.height, undistorted.width, CV_32FC1, undistorted.data) / 4500.0f;
    cv::Mat img_bw;
    undistortedFrame.convertTo(img_bw, CV_8UC4, 255);
    cv::Mat thresh;
    if (threshold >= 0) {
      thresh = img_bw > threshold;
    } else {
      thresh = img_bw;
    }

    cv::imshow("undistorted", thresh);

    std::string index = tostr(i);
    cv::imwrite((filename + index + ".jpg").c_str(), thresh);
    i += 1;

    int key = cv::waitKey(1);
    protonect_shutdown = protonect_shutdown || (key > 0 && ((key & 0xFF) == 27)); // shutdown on escape
    if (!protonect_shutdown) {
      std::cout << "key=" << (key & 0xFF) << std::endl;
      if (key == 82) {
        threshold += 1;
        std::cout << "increasing threshold" << std::endl;
      } else if (key == 83) {
        threshold -= 1;
        std::cout << "decreasing threshold" << std::endl;
      }
    }

    listener.release(frames);
    libfreenect2::this_thread::sleep_for(libfreenect2::chrono::milliseconds(1000));
  }

  // TODO: restarting ir stream doesn't work!
  // TODO: bad things will happen, if frame listeners are freed before dev->stop() :(
  dev->stop();
  dev->close();

  delete registration;

  return 0;
}
<|endoftext|>


<commit_before>////////////////////////////////////////////////////////////////////////////////
// Name:      toolbar.cpp
// Purpose:   Implementation of wxExToolBar class
// Author:    Anton van Wezenbeek
// Created:   2010-03-26
// RCS-ID:    $Id$
// Copyright: (c) 2010 Anton van Wezenbeek
////////////////////////////////////////////////////////////////////////////////

#include <wx/wxprec.h>
#ifndef WX_PRECOMP
#include <wx/wx.h>
#endif
#include <wx/config.h>
#include <wx/extension/toolbar.h>
#include <wx/extension/art.h>
#include <wx/extension/filedlg.h>
#include <wx/extension/frame.h>
#include <wx/extension/frd.h>
#include <wx/extension/stcfile.h>
#include <wx/extension/util.h>

#if wxUSE_GUI
#if wxUSE_AUI

// Cannot use wxNewId here, as these are used in a switch statement.
enum
{
  ID_MATCH_WHOLE_WORD = 100,
  ID_MATCH_CASE,
  ID_REGULAR_EXPRESSION,
  ID_EDIT_HEX_MODE,
  ID_SYNC_MODE,
};

BEGIN_EVENT_TABLE(wxExToolBar, wxAuiToolBar)
  EVT_CHECKBOX(ID_EDIT_HEX_MODE, wxExToolBar::OnCommand)
  EVT_CHECKBOX(ID_SYNC_MODE, wxExToolBar::OnCommand)
END_EVENT_TABLE()

wxExToolBar::wxExToolBar(wxExFrame* frame,
  wxWindowID id,
  const wxPoint& pos,
  const wxSize& size,
  long style)
  : wxAuiToolBar(frame, id, pos, size, style | wxAUI_TB_HORZ_TEXT)
  , m_Frame(frame)
  , m_HexModeCheckBox(NULL)
  , m_SyncCheckBox(NULL)
{
}

wxExToolBar::~wxExToolBar()
{
  if (m_HexModeCheckBox != NULL)
  {
    wxConfigBase::Get()->Write("HexMode", m_HexModeCheckBox->GetValue());
  }
}

void wxExToolBar::AddControls()
{
  AddTool(wxID_OPEN);
  AddTool(wxID_SAVE);
  AddTool(wxID_PRINT);
  AddSeparator();
  AddTool(wxID_FIND);

#ifdef __WXGTK__
  // wxID_EXECUTE is not part of art provider, but GTK directly,
  // so the following does not present a bitmap.
  AddSeparator();
  AddTool(wxID_EXECUTE);
#endif

  AddSeparator();

  AddControl(
    m_HexModeCheckBox = new wxCheckBox(
      this,
      ID_EDIT_HEX_MODE,
      "Hex"));

//  m_HexModeCheckBox->SetBackgroundColour(m_Frame->GetBackgroundColour());

//  AddTool(ID_SYNC_MODE, "Sync", wxNullBitmap, wxEmptyString, wxITEM_CHECK);
  AddControl(
    m_SyncCheckBox = new wxCheckBox(
      this,
      ID_SYNC_MODE,
      "Sync"));

#if wxUSE_TOOLTIPS
  m_HexModeCheckBox->SetToolTip(_("View in hex mode"));
  m_SyncCheckBox->SetToolTip(_("Synchronize modified files"));
#endif

  m_HexModeCheckBox->SetValue(wxConfigBase::Get()->ReadBool("HexMode", false)); // default no hex
  m_SyncCheckBox->SetValue(wxConfigBase::Get()->ReadBool("AllowSync", true));

  Realize();
}

wxAuiToolBarItem* wxExToolBar::AddTool(
  int toolId,
  const wxString& label,
  const wxBitmap& bitmap,
  const wxString& shortHelp,
  wxItemKind kind)
{
  const wxExStockArt art(toolId);

  if (art.GetBitmap().IsOk())
  {
    return wxAuiToolBar::AddTool(
      toolId,
      wxEmptyString,
      art.GetBitmap(wxART_TOOLBAR, GetToolBitmapSize()),
      wxGetStockLabel(toolId, wxSTOCK_NOFLAGS),
      kind);
  }
  else
  {
    return wxAuiToolBar::AddTool(
      toolId,
      label,
      bitmap,
      shortHelp,
      kind);
  }
}

void wxExToolBar::OnCommand(wxCommandEvent& event)
{
  switch (event.GetId())
  {
  case ID_EDIT_HEX_MODE:
    wxConfigBase::Get()->Write("HexMode", m_HexModeCheckBox->GetValue());

    {
      wxExSTCFile* stc = m_Frame->GetSTC();

      if (stc != NULL)
      {
        long flags = 0;
        if (m_HexModeCheckBox->GetValue()) flags |= wxExSTCFile::STC_WIN_HEX;
        wxExFileDialog dlg(m_Frame, stc);
        if (dlg.ShowModalIfChanged() == wxID_CANCEL) return;
        stc->Open(stc->GetFileName(), 0, wxEmptyString, flags);
      }
    }
    break;

  case ID_SYNC_MODE:
    wxConfigBase::Get()->Write("AllowSync", m_SyncCheckBox->GetValue());
    break;

  default:
    wxFAIL;
    break;
  }
}

/// Offers a find combobox that allows you to find text
/// on a current STC on an wxExFrame.
class ComboBox : public wxComboBox
{
public:
  /// Constructor. Fills the combobox box with values from FindReplace from config.
  ComboBox(
    wxWindow* parent,
    wxExFrame* frame,
    wxWindowID id = wxID_ANY,
    const wxPoint& pos = wxDefaultPosition,
    const wxSize& size = wxDefaultSize);
private:
  void OnCommand(wxCommandEvent& event);
  void OnKey(wxKeyEvent& event);
  wxExFrame* m_Frame;

  DECLARE_EVENT_TABLE()
};

BEGIN_EVENT_TABLE(ComboBox, wxComboBox)
  EVT_CHAR(ComboBox::OnKey)
  EVT_MENU(wxID_DELETE, ComboBox::OnCommand)
END_EVENT_TABLE()

ComboBox::ComboBox(
  wxWindow* parent,
  wxExFrame* frame,
  wxWindowID id,
  const wxPoint& pos,
  const wxSize& size)
  : wxComboBox(parent, id, wxEmptyString, pos, size)
  , m_Frame(frame)
{
  const int accels = 1;
  wxAcceleratorEntry entries[accels];
  entries[0].Set(wxACCEL_NORMAL, WXK_DELETE, wxID_DELETE);
  wxAcceleratorTable accel(accels, entries);
  SetAcceleratorTable(accel);

  SetFont(wxConfigBase::Get()->ReadObject("FindFont",
    wxSystemSettings::GetFont(wxSYS_OEM_FIXED_FONT)));

  wxExComboBoxFromList(
    this,
    wxExFindReplaceData::Get()->GetFindStrings());

  // And override the value set by previous, as we want text to be same as in Find.
  SetValue(wxExFindReplaceData::Get()->GetFindString());
}

void ComboBox::OnCommand(wxCommandEvent& event)
{
  // README: The delete key default behaviour does not delete the char right from insertion point.
  // Instead, the event is sent to the editor and a char is deleted from the editor.
  // Therefore implement the delete here.
  switch (event.GetId())
  {
  case wxID_DELETE:
    Remove(GetInsertionPoint(), GetInsertionPoint() + 1);
    break;
  default:
    wxFAIL;
    break;
  }
}

void ComboBox::OnKey(wxKeyEvent& event)
{
  const int key = event.GetKeyCode();

  if (key == WXK_RETURN)
  {
    wxExSTC* stc = m_Frame->GetSTC();

    if (stc != NULL)
    {
      stc->FindNext(GetValue());

      wxExFindReplaceData::Get()->SetFindString(GetValue());

      Clear(); // so we can append again
      wxExComboBoxFromList(this, wxExFindReplaceData::Get()->GetFindStrings());
    }
  }
  else
  {
    event.Skip();
  }
}

BEGIN_EVENT_TABLE(wxExFindToolBar, wxExToolBar)
  EVT_CHECKBOX(ID_MATCH_WHOLE_WORD, wxExFindToolBar::OnCommand)
  EVT_CHECKBOX(ID_MATCH_CASE, wxExFindToolBar::OnCommand)
  EVT_CHECKBOX(ID_REGULAR_EXPRESSION, wxExFindToolBar::OnCommand)
  EVT_MENU(wxID_DOWN, wxExFindToolBar::OnCommand)
  EVT_MENU(wxID_UP, wxExFindToolBar::OnCommand)
  EVT_UPDATE_UI(wxID_DOWN, wxExFindToolBar::OnUpdateUI)
  EVT_UPDATE_UI(wxID_UP, wxExFindToolBar::OnUpdateUI)
END_EVENT_TABLE()

wxExFindToolBar::wxExFindToolBar(
  wxExFrame* frame,
  wxWindowID id,
  const wxPoint& pos,
  const wxSize& size,
  long style)
  : wxExToolBar(frame, id, pos, size, style)
{
  Initialize();

  // And place the controls on the toolbar.
  AddControl(m_ComboBox);
  AddSeparator();

  AddTool(
    wxID_DOWN,
    wxEmptyString,
    wxArtProvider::GetBitmap(wxART_GO_DOWN, wxART_TOOLBAR, GetToolBitmapSize()),
    _("Find next"));
  AddTool(
    wxID_UP,
    wxEmptyString,
    wxArtProvider::GetBitmap(wxART_GO_UP, wxART_TOOLBAR, GetToolBitmapSize()),
    _("Find previous"));
  AddSeparator();

  AddControl(m_MatchWholeWord);
  AddControl(m_MatchCase);
  AddControl(m_RegularExpression);

  Realize();
}

void wxExFindToolBar::Initialize()
{
#ifdef __WXMSW__
  const wxSize size(150, 20);
#else
  const wxSize size(150, -1);
#endif
  ComboBox* cb = new ComboBox(this, m_Frame, wxID_ANY, wxDefaultPosition, size);
  m_ComboBox = cb;

  m_MatchCase = new wxCheckBox(this,
    ID_MATCH_CASE, wxExFindReplaceData::Get()->GetTextMatchCase());

  m_MatchWholeWord = new wxCheckBox(this,
    ID_MATCH_WHOLE_WORD, wxExFindReplaceData::Get()->GetTextMatchWholeWord());

  m_RegularExpression= new wxCheckBox(this,
    ID_REGULAR_EXPRESSION, wxExFindReplaceData::Get()->GetTextRegEx());

  m_MatchCase->SetValue(wxExFindReplaceData::Get()->MatchCase());
  m_MatchWholeWord->SetValue(wxExFindReplaceData::Get()->MatchWord());
  m_RegularExpression->SetValue(wxExFindReplaceData::Get()->UseRegularExpression());
}

void wxExFindToolBar::OnCommand(wxCommandEvent& event)
{
  switch (event.GetId())
  {
  case wxID_DOWN:
  case wxID_UP:
    {
      wxExSTC* stc = m_Frame->GetSTC();

      if (stc != NULL)
      {
        stc->FindNext(m_ComboBox->GetValue(), (event.GetId() == wxID_DOWN));
      }
    }
    break;

  case ID_MATCH_WHOLE_WORD:
    wxExFindReplaceData::Get()->SetMatchWord(
      m_MatchWholeWord->GetValue());
    break;
  case ID_MATCH_CASE:
    wxExFindReplaceData::Get()->SetMatchCase(
      m_MatchCase->GetValue());
    break;
  case ID_REGULAR_EXPRESSION:
    wxExFindReplaceData::Get()->SetUseRegularExpression(
      m_RegularExpression->GetValue());
    break;

  default:
    wxFAIL;
    break;
  }
}

void wxExFindToolBar::OnUpdateUI(wxUpdateUIEvent& event)
{
  event.Enable(!m_ComboBox->GetValue().empty());
}
#endif // wxUSE_AUI
#endif // wxUSE_GUI
<commit_msg>reordered code<commit_after>////////////////////////////////////////////////////////////////////////////////
// Name:      toolbar.cpp
// Purpose:   Implementation of wxExToolBar class
// Author:    Anton van Wezenbeek
// Created:   2010-03-26
// RCS-ID:    $Id$
// Copyright: (c) 2010 Anton van Wezenbeek
////////////////////////////////////////////////////////////////////////////////

#include <wx/wxprec.h>
#ifndef WX_PRECOMP
#include <wx/wx.h>
#endif
#include <wx/config.h>
#include <wx/extension/toolbar.h>
#include <wx/extension/art.h>
#include <wx/extension/filedlg.h>
#include <wx/extension/frame.h>
#include <wx/extension/frd.h>
#include <wx/extension/stcfile.h>
#include <wx/extension/util.h>

#if wxUSE_GUI
#if wxUSE_AUI

// Cannot use wxNewId here, as these are used in a switch statement.
enum
{
  ID_MATCH_WHOLE_WORD = 100,
  ID_MATCH_CASE,
  ID_REGULAR_EXPRESSION,
  ID_EDIT_HEX_MODE,
  ID_SYNC_MODE,
};

// Support class.
// Offers a find combobox that allows you to find text
// on a current STC on an wxExFrame.
class ComboBox : public wxComboBox
{
public:
  /// Constructor. Fills the combobox box with values from FindReplace from config.
  ComboBox(
    wxWindow* parent,
    wxExFrame* frame,
    wxWindowID id = wxID_ANY,
    const wxPoint& pos = wxDefaultPosition,
    const wxSize& size = wxDefaultSize);
private:
  void OnCommand(wxCommandEvent& event);
  void OnKey(wxKeyEvent& event);
  wxExFrame* m_Frame;

  DECLARE_EVENT_TABLE()
};

BEGIN_EVENT_TABLE(wxExToolBar, wxAuiToolBar)
  EVT_CHECKBOX(ID_EDIT_HEX_MODE, wxExToolBar::OnCommand)
  EVT_CHECKBOX(ID_SYNC_MODE, wxExToolBar::OnCommand)
END_EVENT_TABLE()

wxExToolBar::wxExToolBar(wxExFrame* frame,
  wxWindowID id,
  const wxPoint& pos,
  const wxSize& size,
  long style)
  : wxAuiToolBar(frame, id, pos, size, style | wxAUI_TB_HORZ_TEXT)
  , m_Frame(frame)
  , m_HexModeCheckBox(NULL)
  , m_SyncCheckBox(NULL)
{
}

wxExToolBar::~wxExToolBar()
{
  if (m_HexModeCheckBox != NULL)
  {
    wxConfigBase::Get()->Write("HexMode", m_HexModeCheckBox->GetValue());
  }
}

void wxExToolBar::AddControls()
{
  AddTool(wxID_OPEN);
  AddTool(wxID_SAVE);
  AddTool(wxID_PRINT);
  AddSeparator();
  AddTool(wxID_FIND);

#ifdef __WXGTK__
  // wxID_EXECUTE is not part of art provider, but GTK directly,
  // so the following does not present a bitmap.
  AddSeparator();
  AddTool(wxID_EXECUTE);
#endif

  AddSeparator();

  AddControl(
    m_HexModeCheckBox = new wxCheckBox(
      this,
      ID_EDIT_HEX_MODE,
      "Hex"));

//  m_HexModeCheckBox->SetBackgroundColour(m_Frame->GetBackgroundColour());

//  AddTool(ID_SYNC_MODE, "Sync", wxNullBitmap, wxEmptyString, wxITEM_CHECK);
  AddControl(
    m_SyncCheckBox = new wxCheckBox(
      this,
      ID_SYNC_MODE,
      "Sync"));

#if wxUSE_TOOLTIPS
  m_HexModeCheckBox->SetToolTip(_("View in hex mode"));
  m_SyncCheckBox->SetToolTip(_("Synchronize modified files"));
#endif

  m_HexModeCheckBox->SetValue(wxConfigBase::Get()->ReadBool("HexMode", false)); // default no hex
  m_SyncCheckBox->SetValue(wxConfigBase::Get()->ReadBool("AllowSync", true));

  Realize();
}

wxAuiToolBarItem* wxExToolBar::AddTool(
  int toolId,
  const wxString& label,
  const wxBitmap& bitmap,
  const wxString& shortHelp,
  wxItemKind kind)
{
  const wxExStockArt art(toolId);

  if (art.GetBitmap().IsOk())
  {
    return wxAuiToolBar::AddTool(
      toolId,
      wxEmptyString,
      art.GetBitmap(wxART_TOOLBAR, GetToolBitmapSize()),
      wxGetStockLabel(toolId, wxSTOCK_NOFLAGS),
      kind);
  }
  else
  {
    return wxAuiToolBar::AddTool(
      toolId,
      label,
      bitmap,
      shortHelp,
      kind);
  }
}

void wxExToolBar::OnCommand(wxCommandEvent& event)
{
  switch (event.GetId())
  {
  case ID_EDIT_HEX_MODE:
    wxConfigBase::Get()->Write("HexMode", m_HexModeCheckBox->GetValue());

    {
      wxExSTCFile* stc = m_Frame->GetSTC();

      if (stc != NULL)
      {
        long flags = 0;
        if (m_HexModeCheckBox->GetValue()) flags |= wxExSTCFile::STC_WIN_HEX;
        wxExFileDialog dlg(m_Frame, stc);
        if (dlg.ShowModalIfChanged() == wxID_CANCEL) return;
        stc->Open(stc->GetFileName(), 0, wxEmptyString, flags);
      }
    }
    break;

  case ID_SYNC_MODE:
    wxConfigBase::Get()->Write("AllowSync", m_SyncCheckBox->GetValue());
    break;

  default:
    wxFAIL;
    break;
  }
}

BEGIN_EVENT_TABLE(wxExFindToolBar, wxExToolBar)
  EVT_CHECKBOX(ID_MATCH_WHOLE_WORD, wxExFindToolBar::OnCommand)
  EVT_CHECKBOX(ID_MATCH_CASE, wxExFindToolBar::OnCommand)
  EVT_CHECKBOX(ID_REGULAR_EXPRESSION, wxExFindToolBar::OnCommand)
  EVT_MENU(wxID_DOWN, wxExFindToolBar::OnCommand)
  EVT_MENU(wxID_UP, wxExFindToolBar::OnCommand)
  EVT_UPDATE_UI(wxID_DOWN, wxExFindToolBar::OnUpdateUI)
  EVT_UPDATE_UI(wxID_UP, wxExFindToolBar::OnUpdateUI)
END_EVENT_TABLE()

wxExFindToolBar::wxExFindToolBar(
  wxExFrame* frame,
  wxWindowID id,
  const wxPoint& pos,
  const wxSize& size,
  long style)
  : wxExToolBar(frame, id, pos, size, style)
{
  Initialize();

  // And place the controls on the toolbar.
  AddControl(m_ComboBox);
  AddSeparator();

  AddTool(
    wxID_DOWN,
    wxEmptyString,
    wxArtProvider::GetBitmap(wxART_GO_DOWN, wxART_TOOLBAR, GetToolBitmapSize()),
    _("Find next"));
  AddTool(
    wxID_UP,
    wxEmptyString,
    wxArtProvider::GetBitmap(wxART_GO_UP, wxART_TOOLBAR, GetToolBitmapSize()),
    _("Find previous"));
  AddSeparator();

  AddControl(m_MatchWholeWord);
  AddControl(m_MatchCase);
  AddControl(m_RegularExpression);

  Realize();
}

void wxExFindToolBar::Initialize()
{
#ifdef __WXMSW__
  const wxSize size(150, 20);
#else
  const wxSize size(150, -1);
#endif
  ComboBox* cb = new ComboBox(this, m_Frame, wxID_ANY, wxDefaultPosition, size);
  m_ComboBox = cb;

  m_MatchCase = new wxCheckBox(this,
    ID_MATCH_CASE, wxExFindReplaceData::Get()->GetTextMatchCase());

  m_MatchWholeWord = new wxCheckBox(this,
    ID_MATCH_WHOLE_WORD, wxExFindReplaceData::Get()->GetTextMatchWholeWord());

  m_RegularExpression= new wxCheckBox(this,
    ID_REGULAR_EXPRESSION, wxExFindReplaceData::Get()->GetTextRegEx());

  m_MatchCase->SetValue(wxExFindReplaceData::Get()->MatchCase());
  m_MatchWholeWord->SetValue(wxExFindReplaceData::Get()->MatchWord());
  m_RegularExpression->SetValue(wxExFindReplaceData::Get()->UseRegularExpression());
}

void wxExFindToolBar::OnCommand(wxCommandEvent& event)
{
  switch (event.GetId())
  {
  case wxID_DOWN:
  case wxID_UP:
    {
      wxExSTC* stc = m_Frame->GetSTC();

      if (stc != NULL)
      {
        stc->FindNext(m_ComboBox->GetValue(), (event.GetId() == wxID_DOWN));
      }
    }
    break;

  case ID_MATCH_WHOLE_WORD:
    wxExFindReplaceData::Get()->SetMatchWord(
      m_MatchWholeWord->GetValue());
    break;
  case ID_MATCH_CASE:
    wxExFindReplaceData::Get()->SetMatchCase(
      m_MatchCase->GetValue());
    break;
  case ID_REGULAR_EXPRESSION:
    wxExFindReplaceData::Get()->SetUseRegularExpression(
      m_RegularExpression->GetValue());
    break;

  default:
    wxFAIL;
    break;
  }
}

void wxExFindToolBar::OnUpdateUI(wxUpdateUIEvent& event)
{
  event.Enable(!m_ComboBox->GetValue().empty());
}

// Implementation of support class.

BEGIN_EVENT_TABLE(ComboBox, wxComboBox)
  EVT_CHAR(ComboBox::OnKey)
  EVT_MENU(wxID_DELETE, ComboBox::OnCommand)
END_EVENT_TABLE()

ComboBox::ComboBox(
  wxWindow* parent,
  wxExFrame* frame,
  wxWindowID id,
  const wxPoint& pos,
  const wxSize& size)
  : wxComboBox(parent, id, wxEmptyString, pos, size)
  , m_Frame(frame)
{
  const int accels = 1;
  wxAcceleratorEntry entries[accels];
  entries[0].Set(wxACCEL_NORMAL, WXK_DELETE, wxID_DELETE);
  wxAcceleratorTable accel(accels, entries);
  SetAcceleratorTable(accel);

  SetFont(wxConfigBase::Get()->ReadObject("FindFont",
    wxSystemSettings::GetFont(wxSYS_OEM_FIXED_FONT)));

  wxExComboBoxFromList(
    this,
    wxExFindReplaceData::Get()->GetFindStrings());

  // And override the value set by previous, as we want text to be same as in Find.
  SetValue(wxExFindReplaceData::Get()->GetFindString());
}

void ComboBox::OnCommand(wxCommandEvent& event)
{
  // README: The delete key default behaviour does not delete the char right from insertion point.
  // Instead, the event is sent to the editor and a char is deleted from the editor.
  // Therefore implement the delete here.
  switch (event.GetId())
  {
  case wxID_DELETE:
    Remove(GetInsertionPoint(), GetInsertionPoint() + 1);
    break;
  default:
    wxFAIL;
    break;
  }
}

void ComboBox::OnKey(wxKeyEvent& event)
{
  const int key = event.GetKeyCode();

  if (key == WXK_RETURN)
  {
    wxExSTC* stc = m_Frame->GetSTC();

    if (stc != NULL)
    {
      stc->FindNext(GetValue());

      wxExFindReplaceData::Get()->SetFindString(GetValue());

      Clear(); // so we can append again
      wxExComboBoxFromList(this, wxExFindReplaceData::Get()->GetFindStrings());
    }
  }
  else
  {
    event.Skip();
  }
}

#endif // wxUSE_AUI
#endif // wxUSE_GUI
<|endoftext|>


<commit_before>/**
 * @file   trajectory_controller.cpp
 * @author Matheus Vieira Portela
 * @date   03/08/2015
 *
 * @attention Copyright (C) 2015 UnBall Robot Soccer Team
 *
 * @brief Control robots trajectory by applying potential fields.
 */

#include <unball/strategy/trajectory_controller.hpp>

TrajectoryController::TrajectoryController()
{
    player_[0] = new AssistentPlayer();
    player_[1] = new AssistentPlayer();
    player_[2] = new Goalkeeper();
    direct_motion_ = true;
}

TrajectoryController::~TrajectoryController()
{
    for (int i = 2; i >= 0; --i)
        delete player_[i];
}

void TrajectoryController::run()
{
    Vector resultant_force;
    for (int i=0;i<3;i++)
    {
        player_[i]->buildPotentialFields(i);
        resultant_force = player_[i]->calculateResultantForce(i);
        //ROS_ERROR("resultant_force: mag: %.2f ang: %.2f", resultant_force.getMagnitude(),
            resultant_force.getDirection()*180/M_PI);
        player_[i]->clearPotentialFields();
        controlRobot(i, resultant_force);
    }
    robot[2].setAngVel(5);
    robot[2].setLinVel(0);
}

void TrajectoryController::controlRobot(int robot_number, Vector force)
{
    // Use histeresis to void quickly changing direction.
    float error_margin = 15*M_PI/180;

    if (direct_motion_)
    {
        if (fabs(math::reduceAngle(M_PI + force.getDirection() - robot[robot_number].getTh()))
            > M_PI/2 + error_margin)
        {
            direct_motion_ = false;
        }
    }
    else
    {
        if (fabs(math::reduceAngle(M_PI + force.getDirection() - robot[robot_number].getTh()))
            < M_PI/2 - error_margin)
        {
            direct_motion_ = true;
        }
    }

    //HACK: issue80 -  We have to add M_PI because the force is being calculated backwards
     if (direct_motion_)
     {
        move(robot_number, force.getMagnitude());
        turn(robot_number, force.getDirection());
     }
     else
     {
        move(robot_number, -force.getMagnitude());
        turn(robot_number, math::invertAngle(force.getDirection()));
     }
}

void TrajectoryController::move(int robot_number, float distance)
{
    const float DIST_KP = 1;
    const float distance_tolerance = 0.05; // m

    float lin_vel = DIST_KP*distance; // P control

    // if (fabs(distance) > distance_tolerance)
        robot[robot_number].setLinVel(lin_vel);
    // else
    //     robot[robot_number].setLinVel(0);
}

void TrajectoryController::turn(int robot_number, float angle)
{
    const float ANG_KP = 0.008;
    const float ANG_KD = 0;

    //HACK: issue80 - Should be: angle - robot.getTh()
    float angle_error = math::reduceAngle(robot[robot_number].getTh() - angle);
    float angle_error_d = angle_error - angle_error_prev_;
    float ang_vel = ANG_KP*angle_error + ANG_KD*angle_error_d; // PD control
    angle_error_prev_ = angle_error;

    robot[robot_number].setAngVel(ang_vel);
}

void TrajectoryController::stopRobot(int robot_number)
{
    robot[robot_number].setAngVel(0);
    robot[robot_number].setLinVel(0);
}

void TrajectoryController::updatePlayer(int robot_number, player_behaviour behaviour)
{
    delete player_[robot_number];

    if (behaviour == INITIAL_GOALKEEPER)
        player_[robot_number] = new InitialGoalkeeper();
    if (behaviour == GOALKEEPER)
        player_[robot_number] = new Goalkeeper();
    if (behaviour == REGULAR_PLAYER)
        player_[robot_number] = new RegularPlayer();
    if (behaviour == KICKER_PLAYER)
        player_[robot_number] = new KickerPlayer();
    if (behaviour == ASSISTENT_PLAYER)
        player_[robot_number] = new AssistentPlayer();
    if (behaviour == GOALKEEPER_KICKER)
        player_[robot_number] = new GoalkeeperKicker();
}

Player* TrajectoryController::getPlayer(int robot_number)
{
    return player_[robot_number];
}
<commit_msg>Sorry Vieira. Fixed last commit<commit_after>/**
 * @file   trajectory_controller.cpp
 * @author Matheus Vieira Portela
 * @date   03/08/2015
 *
 * @attention Copyright (C) 2015 UnBall Robot Soccer Team
 *
 * @brief Control robots trajectory by applying potential fields.
 */

#include <unball/strategy/trajectory_controller.hpp>

TrajectoryController::TrajectoryController()
{
    player_[0] = new AssistentPlayer();
    player_[1] = new AssistentPlayer();
    player_[2] = new Goalkeeper();
    direct_motion_ = true;
}

TrajectoryController::~TrajectoryController()
{
    for (int i = 2; i >= 0; --i)
        delete player_[i];
}

void TrajectoryController::run()
{
    Vector resultant_force;
    for (int i=0;i<3;i++)
    {
        player_[i]->buildPotentialFields(i);
        resultant_force = player_[i]->calculateResultantForce(i);
        //ROS_ERROR("resultant_force: mag: %.2f ang: %.2f", resultant_force.getMagnitude(),
        //    resultant_force.getDirection()*180/M_PI);
        player_[i]->clearPotentialFields();
        controlRobot(i, resultant_force);
    }
    robot[2].setAngVel(5);
    robot[2].setLinVel(0);
}

void TrajectoryController::controlRobot(int robot_number, Vector force)
{
    // Use histeresis to void quickly changing direction.
    float error_margin = 15*M_PI/180;

    if (direct_motion_)
    {
        if (fabs(math::reduceAngle(M_PI + force.getDirection() - robot[robot_number].getTh()))
            > M_PI/2 + error_margin)
        {
            direct_motion_ = false;
        }
    }
    else
    {
        if (fabs(math::reduceAngle(M_PI + force.getDirection() - robot[robot_number].getTh()))
            < M_PI/2 - error_margin)
        {
            direct_motion_ = true;
        }
    }

    //HACK: issue80 -  We have to add M_PI because the force is being calculated backwards
     if (direct_motion_)
     {
        move(robot_number, force.getMagnitude());
        turn(robot_number, force.getDirection());
     }
     else
     {
        move(robot_number, -force.getMagnitude());
        turn(robot_number, math::invertAngle(force.getDirection()));
     }
}

void TrajectoryController::move(int robot_number, float distance)
{
    const float DIST_KP = 1;
    const float distance_tolerance = 0.05; // m

    float lin_vel = DIST_KP*distance; // P control

    // if (fabs(distance) > distance_tolerance)
        robot[robot_number].setLinVel(lin_vel);
    // else
    //     robot[robot_number].setLinVel(0);
}

void TrajectoryController::turn(int robot_number, float angle)
{
    const float ANG_KP = 0.008;
    const float ANG_KD = 0;

    //HACK: issue80 - Should be: angle - robot.getTh()
    float angle_error = math::reduceAngle(robot[robot_number].getTh() - angle);
    float angle_error_d = angle_error - angle_error_prev_;
    float ang_vel = ANG_KP*angle_error + ANG_KD*angle_error_d; // PD control
    angle_error_prev_ = angle_error;

    robot[robot_number].setAngVel(ang_vel);
}

void TrajectoryController::stopRobot(int robot_number)
{
    robot[robot_number].setAngVel(0);
    robot[robot_number].setLinVel(0);
}

void TrajectoryController::updatePlayer(int robot_number, player_behaviour behaviour)
{
    delete player_[robot_number];

    if (behaviour == INITIAL_GOALKEEPER)
        player_[robot_number] = new InitialGoalkeeper();
    if (behaviour == GOALKEEPER)
        player_[robot_number] = new Goalkeeper();
    if (behaviour == REGULAR_PLAYER)
        player_[robot_number] = new RegularPlayer();
    if (behaviour == KICKER_PLAYER)
        player_[robot_number] = new KickerPlayer();
    if (behaviour == ASSISTENT_PLAYER)
        player_[robot_number] = new AssistentPlayer();
    if (behaviour == GOALKEEPER_KICKER)
        player_[robot_number] = new GoalkeeperKicker();
}

Player* TrajectoryController::getPlayer(int robot_number)
{
    return player_[robot_number];
}
<|endoftext|>