    /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 *
 *   This file is part of
 *       _______   ______________  ______     _____
 *      / ____/ | / /  _/ ____/  |/  /   |   |__  /
 *     / __/ /  |/ // // / __/ /|_/ / /| |    /_ <
 *    / /___/ /|  // // /_/ / /  / / ___ |  ___/ /
 *   /_____/_/ |_/___/\____/_/  /_/_/  |_| /____/.
 * 
 *   Copyright © 2003-2010 Brain Control, all rights reserved.
 *
 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

#include "../eshared.hpp"
/*
#if defined(HAVE_OP_EFFECT_FRACTAL) || defined(eEDITOR)
OP_DEFINE_EFFECT(eFxFractalOp, eFxFractalOp_ID, "Fractal", ' ', 1, 1, "-1,Effect")
    OP_INIT()
    {
        eOP_PARAM_ADD_FLOAT("Field of view", eALMOST_ZERO, 180.0f, 45.0f);
        eOP_PARAM_ADD_FXYZ("Position", eF32_MIN, eF32_MAX, 0.0f, 0.0f, 10.0f);
        eOP_PARAM_ADD_FXYZ("Look at", eF32_MIN, eF32_MAX, 0.0f, 0.0f, 0.0f);
        eOP_PARAM_ADD_FXYZ("Up vector", eF32_MIN, eF32_MAX, 0.0f, 1.0f, 0.0f);

        eOP_PARAM_ADD_LABEL("Fractal", "Fractal");
        eOP_PARAM_ADD_FLOAT("Scale", eF32_MIN, eF32_MAX, -1.918f);
        eOP_PARAM_ADD_FLOAT("Minimum radius", eF32_MIN, eF32_MAX, 0.425f);
        eOP_PARAM_ADD_FLOAT("Distance multiplier", eF32_MIN, eF32_MAX, 1.0f);
        eOP_PARAM_ADD_FLOAT("Maximum distance", eF32_MIN, eF32_MAX, 4.0f);
        eOP_PARAM_ADD_FLOAT("Minimum distance", eF32_MIN, eF32_MAX, 8.0e-002f);
        eOP_PARAM_ADD_INT("Iterations", 1, 255, 18);
        eOP_PARAM_ADD_INT("Maximum steps", 1, 512, 256);
    }

    OP_EXEC(eGraphicsApiDx9 *gfx, eF32 fov, const eVector3 &pos, const eVector3 &lookAt, const eVector3 &up,
            float scale, float minRadius, float distMul, float maxDist, float minDist, eU32 iters, eU32 maxSteps)
    {
        eMatrix4x4 mtx;

        mtx.lookAt(pos, lookAt, up);

        eVector3 ro = pos;//mtx*pos;

        m_fxFractal = eFractalEffect(mtx, fov, ro, scale, minRadius, distMul, maxDist, minDist/100000.0f, iters, maxSteps);
        _appendEffect(&m_fxFractal);
    }

    class eFractalEffect : public eIEffect
    {
    public:
        eFractalEffect(const eMatrix4x4 &mtxModelView=eMatrix4x4(), eF32 fov=45.0f, const eVector3 &rayOrigin=eVector3(),
                        float scale=0, float minRadius=0, float distMul=0, float maxDist=0, float minDist=0, eU32 iters=0, eU32 maxSteps=0) :
            m_mtxModelView(mtxModelView),
            m_fov(fov),
            m_rayOrigin(rayOrigin),
            m_scale(scale),
            m_minRadius(minRadius),
            m_distMul(distMul),
            m_maxDist(maxDist),
            m_minDist(minDist),
            m_iters(iters),
            m_maxSteps(maxSteps)
        {
            m_ps = eShaderManager::loadPixelShader(ePS(fx_fractal));
        }

    protected:
        virtual Target * _run(TargetPtrArray &srcs)
        {
            m_gfx->setPsConst(0, m_rayOrigin);
            m_gfx->setPsConst(5, m_scale);
            m_gfx->setPsConst(6, m_minRadius);
            m_gfx->setPsConst(7, m_distMul);
            m_gfx->setPsConst(8, m_maxDist);
            m_gfx->setPsConst(9, m_minDist);
            m_gfx->setPsConst(10, m_iters);
            m_gfx->setPsConst(11, m_maxSteps);

            m_gfx->setPsConst(15, 1.0f/eVector2((eF32)srcs[0]->tex->getWidth(), (eF32)srcs[0]->tex->getHeight()));

	        return _renderSimple(srcs[0], m_ps);
        }

    private:
        eMatrix4x4  m_mtxModelView;
        eVector3    m_rayOrigin;
        eF32        m_fov;
        float m_scale, m_minRadius, m_distMul, m_maxDist, m_minDist, m_iters, m_maxSteps;
    };

    OP_VAR(eFractalEffect m_fxFractal);
OP_END(eFxFractalOp);
#endif
*/
// Camera (effect) operator
// ------------------------
// Converts the model input-operator to an effect
// and adds a camera to new effect.

#if defined(HAVE_OP_EFFECT_CAMERA) || defined(eEDITOR)
OP_DEFINE_EFFECT(eFxCameraOp, eFxCameraOp_ID, "Camera", 'c', 1, 1, "0,Misc : Scene")
    OP_INIT()
    {
        eU32 flags = 0;
        eSetBit(flags, 0);
        eSetBit(flags, 1);
        eSetBit(flags, 2);

        eOP_PARAM_ADD_FLOAT("Field of view", eALMOST_ZERO, 180.0f, 45.0f);
        eOP_PARAM_ADD_ENUM("Aspect ratio", "4:3|16:9|16:10", 0);
        eOP_PARAM_ADD_FLOAT("Near plane", eF32_MIN, eF32_MAX, 0.01f);
        eOP_PARAM_ADD_FLOAT("Far plane", eF32_MIN, eF32_MAX, 1000.0f);
        eOP_PARAM_ADD_FXYZ("Position", eF32_MIN, eF32_MAX, 0.0f, 0.0f, 10.0f);
        eOP_PARAM_ADD_FXYZ("Look at", eF32_MIN, eF32_MAX, 0.0f, 0.0f, 0.0f);
        eOP_PARAM_ADD_FXYZ("Up vector", eF32_MIN, eF32_MAX, 0.0f, 1.0f, 0.0f);
    }

    OP_DEINIT()
    {
        eSAFE_DELETE(m_effect);
    }

    OP_EXEC(eGraphicsApiDx9 *gfx, eF32 fov, eInt aspectSel, eF32 zNear, eF32 zFar,
            const eVector3 &pos, const eVector3 &lookAt, const eVector3 &upVec)
    {
        eScene &scene = ((eISceneOp *)getInputOperator(0))->getResult().scene;

        const eF32 aspectRatios[] =
        {
            4.0f/3.0f,
            16.0f/9.0f,
            16.0f/10.0f
        };

        const eF32 aspect = aspectRatios[aspectSel];

        eCamera cam(fov, aspect, zNear, zFar);
        eMatrix4x4 mtx;
        mtx.lookAt(pos, lookAt, upVec);
        cam.setViewMatrix(mtx);

        eSAFE_DELETE(m_effect);
        m_effect = new eInputEffect(scene, cam);
        eASSERT(m_effect != eNULL);
    }
OP_END(eFxCameraOp);
#endif

// Blur (effect) operator
// ----------------------
// Blurs a render target.

#if defined(HAVE_OP_EFFECT_BLUR) || defined(eEDITOR)
OP_DEFINE_EFFECT(eFxBlurOp, eFxBlurOp_ID, "Blur", 'b', 1, 1, "-1,Effect")
    OP_INIT()
    {
        eOP_PARAM_ADD_INT("Iterations", 0, eU8_MAX, 1);
        eOP_PARAM_ADD_IXY("Distance", 1, 64, 1, 1);
        eOP_PARAM_ADD_ENUM("Direction", "Horizontal|Vertical|Both", 2);
    }

    OP_EXEC(eGraphicsApiDx9 *gfx, eU32 iterations, const ePoint &dist, eInt dir)
    {
        // Add horizontal blur effect.
        if (dir == 0 || dir == 2)
        {
            m_fxBlurH = eBlurEffect(eBlurEffect::DIR_HORZ, dist.x);
            m_fxBlurH.setIterations(iterations);

            _appendEffect(&m_fxBlurH);
        }
    
        // Add vertical blur effect.
        if (dir == 1 || dir == 2)
        {
            m_fxBlurV = eBlurEffect(eBlurEffect::DIR_VERT, dist.y);
            m_fxBlurV.setIterations(iterations);

            _appendEffect(&m_fxBlurV);
        }
    }

    OP_VAR(eBlurEffect m_fxBlurH);
    OP_VAR(eBlurEffect m_fxBlurV);
OP_END(eFxBlurOp);
#endif

// Merge (effect) operator
// -----------------------
// Merges two or more input render-targets.

#if defined(HAVE_OP_EFFECT_MERGE) || defined(eEDITOR)
OP_DEFINE_EFFECT(eFxMergeOp, eFxMergeOp_ID, "Merge", 'm', 2, 64, "-1,Effect")
    OP_INIT()
    {
        eOP_PARAM_ADD_ENUM("Blending", "Additive|Subtractive|Multiplicative|Brighter|Darker", 0);
        eOP_PARAM_ADD_FXY("Blend ratios", 0.0f, 1.0f, 1.0f, 1.0f);
    }

    OP_EXEC(eGraphicsApiDx9 *gfx, eMergeEffect::BlendMode blendMode, const eVector2 &blendRatios)
    {
        m_fxMerge = eMergeEffect(blendMode, blendRatios);
        _appendEffect(&m_fxMerge);

        for (eU32 i=1; i<getInputCount(); i++)
        {
            const eIEffectOp::Result &res = ((eIEffectOp *)getInputOperator(i))->getResult();
            m_fxMerge.addInput(res.effect);
        }
    }

    OP_VAR(eMergeEffect m_fxMerge);
OP_END(eFxMergeOp);
#endif

// Adjust (effect) operator
// ------------------------
// Adjusts brightness/contrast/color of a render target.

#if defined(HAVE_OP_EFFECT_ADJUST) || defined(eEDITOR)
OP_DEFINE_EFFECT(eFxAdjustOp, eFxAdjustOp_ID, "Adjust", 'a', 1, 1, "-1,Effect")
    OP_INIT()
    {
        eOP_PARAM_ADD_INT("Iterations", 0, eU8_MAX, 1);
        eOP_PARAM_ADD_FLOAT("Brightness", 0.0f, eF32_MAX, 1.0f);
        eOP_PARAM_ADD_FLOAT("Contrast", 0.0f, eF32_MAX, 1.0f);
        eOP_PARAM_ADD_RGB("Color", 1.0f, 1.0f, 1.0f);
        eOP_PARAM_ADD_RGB("Subtract", 0.0f, 0.0f, 0.0f);
    }

    OP_EXEC(eGraphicsApiDx9 *gfx, eU32 iterations, eF32 brightness, eF32 contrast,
            const eFloatColor &adjCol, const eFloatColor &subCol)
    {
        m_fxAdjust = eAdjustEffect(brightness, contrast, adjCol, subCol);
        _appendEffect(&m_fxAdjust);
    }

    OP_VAR(eAdjustEffect m_fxAdjust);
OP_END(eFxAdjustOp);
#endif

// Radial blur (effect) operator
// -----------------------------
// Applies a radial blur on a render target.

#if defined(HAVE_OP_EFFECT_RADIAL_BLUR) || defined(eEDITOR)
OP_DEFINE_EFFECT(eFxRadialBlurOp, eFxRadialBlurOp_ID, "Radial blur", 'i', 1, 1, "-1,Effect")
    OP_INIT()
    {
        eOP_PARAM_ADD_FXY("Origin", 0.0f, 1.0f, 0.5f, 0.5f);
        eOP_PARAM_ADD_FLOAT("Distance", 0.0f, eF32_MAX, 1.0f);
        eOP_PARAM_ADD_FLOAT("Strength", 0.0f, eF32_MAX, 2.0f);
    }

    OP_EXEC(eGraphicsApiDx9 *gfx, const eVector2 &origin, eF32 dist, eF32 strength)
    {
        m_fxRadial = eRadialBlurEffect(origin, dist, strength);
        _appendEffect(&m_fxRadial);
    }

    OP_VAR(eRadialBlurEffect m_fxRadial);
OP_END(eFxRadialBlurOp);
#endif

// Ripple (effect) operator
// ------------------------
// Ripples a render target.

#if defined(HAVE_OP_EFFECT_RIPPLE) || defined(eEDITOR)
OP_DEFINE_EFFECT(eFxRippleOp, eFxRippleOp_ID, "Ripple", 'r', 1, 1, "-1,Effect")
    OP_INIT()
    {
        eOP_PARAM_ADD_INT("Iterations", 0, eU8_MAX, 1);
        eOP_PARAM_ADD_FLOAT("Amplitude", 0.0f, eF32_MAX, 0.5f);
        eOP_PARAM_ADD_FLOAT("Length", 0.01f, eF32_MAX, 5.0f);
        eOP_PARAM_ADD_FLOAT("Speed", 0.0f, eF32_MAX, 5.0f);
        eOP_PARAM_ADD_FLOAT("Time", 0.0f, eF32_MAX, 0.0f);
        eOP_PARAM_ADD_FXY("Offset", 0.0f, 1.0f, 0.5f, 0.5f);
        eOP_PARAM_ADD_ENUM("Mode", "Standard|Concentric", 0);
    }

    OP_EXEC(eGraphicsApiDx9 *gfx, eU32 iterations, eF32 ampli, eF32 length, eF32 speed,
            eF32 time, const eVector2 &offset, eRippleEffect::Mode mode)
    {
        ampli /= 10.0f;

        m_fxRipple = eRippleEffect(ampli, length, speed, time, offset, mode);
        m_fxRipple.setIterations(iterations);

        _appendEffect(&m_fxRipple);
    }

    OP_VAR(eRippleEffect m_fxRipple);
OP_END(eFxRippleOp);
#endif

// Fog (effect) operator
// ---------------------
// Adds fog (linear, exponential, exponential squared)
// to a render target.

#if defined(HAVE_OP_EFFECT_FOG) || defined(eEDITOR)
OP_DEFINE_EFFECT(eFxFogOp, eFxFogOp_ID, "Fog", 'f', 1, 1, "-1,Effect")
    OP_INIT()
    {
        eOP_PARAM_ADD_ENUM("Type", "Linear|Exponential|Exponential squared", 0);
        eOP_PARAM_ADD_FLOAT("Start", 0.01f, eF32_MAX, 1.0f);
        eOP_PARAM_ADD_FLOAT("End", 0.01f, eF32_MAX, 10.0f);
        eOP_PARAM_ADD_FLOAT("Density", 0.01f, eF32_MAX, 0.1f);
        eOP_PARAM_ADD_RGB("Color", 1.0f, 1.0f, 1.0f);
    }

    OP_EXEC(eGraphicsApiDx9 *gfx, eInt type, eF32 start, eF32 end, eF32 density, const eFloatColor &color)
    {
        m_fxFog = eFogEffect((eFogEffect::Type)type, start, end, density, color);
        _appendEffect(&m_fxFog);
    }

    OP_VAR(eFogEffect m_fxFog);
OP_END(eFxFogOp);
#endif

// Save (effect) operator
// ----------------------
// Copies render target into another render target,
// which can the be used for texturing purposes
// (aka render-to-texture).

#if defined(HAVE_OP_EFFECT_SAVE) || defined(eEDITOR)
OP_DEFINE_EFFECT(eFxSaveOp, eFxSaveOp_ID, "Save", 's', 1, 1, "-1,Effect")
    OP_INIT()
    {
        eOP_PARAM_ADD_LINK("Render target", "R2T");
    }

    OP_EXEC(eGraphicsApiDx9 *gfx, eIRenderToTextureOp *r2tOp)
    {
        if (r2tOp)
        {
            const eIRenderToTextureOp::Result &res = r2tOp->getResult();

            m_fxSave = eSaveEffect(res.renderTarget, res.depthTarget);
            _appendEffect(&m_fxSave);
        }
    }

    OP_VAR(eSaveEffect m_fxSave);
OP_END(eFxSaveOp);
#endif

// Depth of field (effect) operator
// --------------------------------
// Adds a depth of field effect to a render target.
// Requires an additional normal and blurred target
// as input operators.

#if defined(HAVE_OP_EFFECT_DOF) || defined(eEDITOR)
OP_DEFINE_EFFECT(eFxDofOp, eFxDofOp_ID, "DOF", 'o', 2, 2, "-1,Effect")
    OP_INIT()
    {
        eOP_PARAM_ADD_FLOAT("Focus depth", 0.01f, eF32_MAX, 1.0f);
        eOP_PARAM_ADD_FLOAT("Focus range", 0.01f, eF32_MAX, 10.0f);
    }

    OP_EXEC(eGraphicsApiDx9 *gfx, eF32 focusDepth, eF32 focusRange)
    {
        m_fxDof = eDofEffect(focusDepth, focusRange);
        _appendEffect(&m_fxDof);
        m_fxDof.addInput(((eIEffectOp *)getInputOperator(1))->getResult().effect);
    }

    OP_VAR(eDofEffect m_fxDof);
OP_END(eFxDofOp);
#endif

// Downsample (effect) operator
// ----------------------------
// Downsamples a render target.

#if defined(HAVE_OP_EFFECT_DOWNSAMPLE) || defined(eEDITOR)
OP_DEFINE_EFFECT(eFxDownsampleOp, eFxDownsampleOp_ID, "Downsample", 'd', 1, 1, "-1,Effect")
    OP_INIT()
    {
        eOP_PARAM_ADD_INT("Iterations", 0, eU8_MAX, 1);
        eOP_PARAM_ADD_FXY("Amount", 0.01f, 1.0f, 0.5f, 0.5f);
    }

    OP_EXEC(eGraphicsApiDx9 *gfx, eU32 iterations, const eVector2 &amount) 
    {
        m_fxDown = eDownsampleEffect(amount);
        m_fxDown.setIterations(iterations);

        _appendEffect(&m_fxDown);
    }

    OP_VAR(eDownsampleEffect m_fxDown);
OP_END(eFxDownsampleOp);
#endif

// SSAO (effect) operator
// ----------------------
// Adds screen space ambient occlusion to a render target.
// Requires an additional noise lookup texture linked.

#if defined(HAVE_OP_EFFECT_SSAO) || defined(eEDITOR)
OP_DEFINE_EFFECT(eFxSsaoOp, eFxSsaoOp_ID, "SSAO", 's', 1, 1, "-1,Effect")
    OP_INIT()
    {
        m_noiseMap = eNULL;

        eOP_PARAM_ADD_FLOAT("Scale", 0.01f, eF32_MAX, 0.5f);
        eOP_PARAM_ADD_FLOAT("Intensity", 0.01f, eF32_MAX, 2.5f);
        eOP_PARAM_ADD_FLOAT("Bias", 0.01f, eF32_MAX, 0.25f);
        eOP_PARAM_ADD_FLOAT("Radius", 0.01f, eF32_MAX, 0.5f);
        eOP_PARAM_ADD_LINK("Noise map", "Bitmap");
    }

    OP_DEINIT()
    {
        eSAFE_DELETE(m_noiseMap);
    }

    OP_EXEC(eGraphicsApiDx9 *gfx, eF32 scale, eF32 intensity, eF32 bias, eF32 radius, eIBitmapOp *noiseMapOp) 
    {
        if (getParameter(4).getChanged() && noiseMapOp)
        {
            const eIBitmapOp::Result &res = noiseMapOp->getResult();

            eSAFE_DELETE(m_noiseMap);
            m_noiseMap = gfx->createTexture2d(res.width, res.height, eFALSE, eFALSE, eFALSE, eFORMAT_ARGB8);
            ePtr data = m_noiseMap->lock();
            eMemCopy(data, res.bitmap, res.size*sizeof(eColor));
            m_noiseMap->unlock();
        }

        // Add effect if there's a valid noise map given.
        if (m_noiseMap)
        {
            m_fxSsao = eSsaoEffect(scale, intensity, bias, radius, m_noiseMap);
            m_fxSsao.setNoiseMap(m_noiseMap);

            _appendEffect(&m_fxSsao);
        }
    }

    OP_VAR(eSsaoEffect   m_fxSsao);
    OP_VAR(eITexture2d * m_noiseMap);
OP_END(eFxSsaoOp);
#endif

// FXAA (effect) operator
// ---------------------
// Adds screen space ambient occlusion to a render target.
// Requires an additional noise lookup texture linked.

#if defined(HAVE_OP_EFFECT_FXAA) || defined(eEDITOR)
OP_DEFINE_EFFECT(eFxFxaaOp, eFxFxaaOp_ID, "FXAA", 'x', 1, 1, "-1,Effect")
    OP_EXEC(eGraphicsApiDx9 *gfx) 
    {
        m_fxFxaa.clearInputs();
        _appendEffect(&m_fxFxaa);
    }

    OP_VAR(eFxaaEffect m_fxFxaa);
OP_END(eFxFxaaOp);
#endif

// Color Grading (effect) operator
// ----------------------
// Adds color grading to a render target.
// Requires an additional color grading lookup texture linked.

#if defined(HAVE_OP_EFFECT_COLOR_GRADING) || defined(eEDITOR)
OP_DEFINE_EFFECT(eFxColorGradingOp, eFxColorGradingOp_ID, "Color grading", ' ', 1, 1, "-1,Effect")
    OP_INIT()
    {
		eOP_PARAM_ADD_LINK("Lookup map", "Bitmap");

        m_lookupMap = eNULL;
    }

    OP_DEINIT()
    {
        eSAFE_DELETE(m_lookupMap);
    }

    OP_EXEC(eGraphicsApiDx9 *gfx, eIBitmapOp *lookupMapOp) 
    {
        if (getParameter(0).getChanged() && lookupMapOp)
        {
            const eIBitmapOp::Result &res = lookupMapOp->getResult();

            eSAFE_DELETE(m_lookupMap);

			if (res.width == res.height * res.height)
			{
				m_lookupMap = gfx->createTexture3d(res.height, res.height, res.height, eFALSE, eFALSE, eFORMAT_ARGB8);
				ePtr data = m_lookupMap->lock();
				eMemCopy(data, res.bitmap, res.size*sizeof(eColor));
				m_lookupMap->unlock();
			}
        }

        // Add effect if there's a valid grading bitmap given.
        if (m_lookupMap)
        {
            m_fxColorGrading = eColorGradingEffect(m_lookupMap);
            _appendEffect(&m_fxColorGrading);
        }
    }

    OP_VAR(eColorGradingEffect  m_fxColorGrading);
    OP_VAR(eITexture3d *        m_lookupMap);
OP_END(eFxColorGradingOp);
#endif

// Distort (effect) operator
// ----------------------
// Adds distortion to a render target.
// Requires an additional distortion lookup normal texture linked.

#if defined(HAVE_OP_EFFECT_DISTORT) || defined(eEDITOR)
OP_DEFINE_EFFECT(eFxDistortOp, eFxDistortOp_ID, "Distort", 's', 1, 1, "-1,Effect")
	OP_INIT()
	{
		m_distortMap = eNULL;

		eOP_PARAM_ADD_FXY("Intensity", -eF32_MAX, eF32_MAX, 1.0f, 1.0f);
		eOP_PARAM_ADD_FXY("Offset", -eF32_MAX, eF32_MAX, 0.0f, 0.0f);
		eOP_PARAM_ADD_LINK("Distort map", "Bitmap");
	}

	OP_DEINIT()
	{
		eSAFE_DELETE(m_distortMap);
	}

	OP_EXEC(eGraphicsApiDx9 *gfx, const eVector2 &intensity, const eVector2 &offset, eIBitmapOp *distortMapOp) 
	{
		if (getParameter(2).getChanged() && distortMapOp)
		{
			const eIBitmapOp::Result &res = distortMapOp->getResult();

			eSAFE_DELETE(m_distortMap);
			m_distortMap = gfx->createTexture2d(res.width, res.height, eFALSE, eFALSE, eFALSE, eFORMAT_ARGB8);
			ePtr data = m_distortMap->lock();
			eMemCopy(data, res.bitmap, res.size*sizeof(eColor));
			m_distortMap->unlock();
		}

		// Add effect if there's a valid noise map given.
		if (m_distortMap)
		{
			m_fxDistort = eDistortEffect(intensity, offset, m_distortMap);
			m_fxDistort.setDistortMap(m_distortMap);

			_appendEffect(&m_fxDistort);
		}
	}

	OP_VAR(eDistortEffect m_fxDistort);
	OP_VAR(eITexture2d * m_distortMap);
OP_END(eFxDistortOp);
#endif


// Custom 1 (effect) operator
// ----------------------

#if defined(HAVE_OP_EFFECT_EDGES) || defined(eEDITOR)
OP_DEFINE_EFFECT(eFxEdgesOp, eFxEdgesOp_ID, "Edges", ' ', 1, 1, "-1,Effect")
    OP_INIT()
    {
        eOP_PARAM_ADD_FXYZ("Parameter", -eF32_MAX, eF32_MAX, 1.0f, 1.0f, 1.0f);
    }

    OP_DEINIT()
    {

    }

    OP_EXEC(eGraphicsApiDx9 *gfx, const eVector3 &parameter) 
    {
        m_fxCustom = eEdgesEffect(parameter);
        _appendEffect(&m_fxCustom);
    }

    OP_VAR(eEdgesEffect m_fxCustom);
OP_END(eFxEdgesOp);
#endif

// Custom 2 (effect) operator
// ----------------------
#if defined(HAVE_OP_EFFECT_SINEPATTERN) || defined(eEDITOR)
OP_DEFINE_EFFECT(eFxSinePatternOp, eFxSinePatternOp_ID, "SinePattern", ' ', 1, 1, "-1,Effect")
    OP_INIT()
{
    eOP_PARAM_ADD_FXYZ("Parameter", -eF32_MAX, eF32_MAX, 1.0f, 1.0f, 1.0f);
    eOP_PARAM_ADD_RGB("Color", 1.0, 1.0, 1.0);
}

OP_DEINIT()
{

}

OP_EXEC(eGraphicsApiDx9 *gfx, const eVector3 &parameter, const eVector4 &color) 
{
    m_fxCustom = eSinePatternEffect(parameter, color);
    _appendEffect(&m_fxCustom);
}

OP_VAR(eSinePatternEffect m_fxCustom);
OP_END(eFxSinePatternOp);
#endif

// Custom 3 (effect) operator
// ----------------------
#if defined(HAVE_OP_EFFECT_SPARKLE) || defined(eEDITOR)
OP_DEFINE_EFFECT(eFxSparkleOp, eFxSparkleOp_ID, "Sparkle", ' ', 1, 1, "-1,Effect")
    OP_INIT()
{
    eOP_PARAM_ADD_FXYZ("Parameter", -eF32_MAX, eF32_MAX, 1.0f, 1.0f, 1.0f);
}

OP_DEINIT()
{

}

OP_EXEC(eGraphicsApiDx9 *gfx, const eVector3 &parameter) 
{
    m_fxCustom = eSparkleEffect(parameter);
    _appendEffect(&m_fxCustom);
}

OP_VAR(eSparkleEffect m_fxCustom);
OP_END(eFxSparkleOp);
#endif

// Dissolve (effect) operator
// ----------------------
// Dissolves the image based on gradient texture

#if defined(HAVE_OP_EFFECT_DISSOLVE) || defined(eEDITOR)
OP_DEFINE_EFFECT(eFxDissolveOp, eFxDissolveOp_ID, "Dissolve", 's', 1, 1, "-1,Effect")
    OP_INIT()
{
    m_dissolveMap = eNULL;

    eOP_PARAM_ADD_FXYZ("Center", -eF32_MAX, eF32_MAX, 0.0f, 0.0f, 0.0f);
    eOP_PARAM_ADD_FXYZ("Dissolve start", -eF32_MAX, eF32_MAX, 10.0f, 10.0f, 10.0f);
    eOP_PARAM_ADD_FXYZ("Dissolve range", -eF32_MAX, eF32_MAX, 10.0f, 10.0f, 10.0f);
    eOP_PARAM_ADD_FXYZ("Scale", -eF32_MAX, eF32_MAX, 1.0f, 1.0f, 1.0f);
    eOP_PARAM_ADD_LINK("Dissolve map", "Bitmap");
}

OP_DEINIT()
{
    eSAFE_DELETE(m_dissolveMap);
}

OP_EXEC(eGraphicsApiDx9 *gfx, const eVector3 &center, const eVector3 &dissolveStart, const eVector3 &dissolveRange, const eVector3 &scale, eIBitmapOp *dissolveMapOp) 
{
    if (getParameter(4).getChanged() && dissolveMapOp)
    {
        const eIBitmapOp::Result &res = dissolveMapOp->getResult();

        eSAFE_DELETE(m_dissolveMap);
        m_dissolveMap = gfx->createTexture2d(res.width, res.height, eFALSE, eFALSE, eFALSE, eFORMAT_ARGB8);
        ePtr data = m_dissolveMap->lock();
        eMemCopy(data, res.bitmap, res.size*sizeof(eColor));
        m_dissolveMap->unlock();
    }

    // Add effect if there's a valid noise map given.
    if (m_dissolveMap)
    {
        m_fxDissolve = eDissolveEffect(center, dissolveStart, dissolveRange, scale);
        m_fxDissolve.setDissolveMap(m_dissolveMap);

        _appendEffect(&m_fxDissolve);
    }
}

OP_VAR(eDissolveEffect m_fxDissolve);
OP_VAR(eITexture2d * m_dissolveMap);
OP_END(eFxDissolveOp);
#endif