#include "SM_CommonFXPCH.h"
#include "SM_DemoEffect.h"
#include "FXFilter.h"
#include "SM_CommonVF.h"
#include "SM_ResourceManager.h"
#include "SM_Slider.h"

  /*

static SM_DemoEffect::Helper CommandsHelp[] =
{
  {"MOTIONBLUR FADEIN time factor iStartLayer iEndLayer", "Does motion blur fade in on selected layers\r\nfactor: [0..1] \r\niStartLayer-iEndLayer: range of layers affected by blur.\r\nRequires FXFILTER COMMAND BYPYASS ON"},   
  {"MOTIONBLUR OFF", "turns off motion blur"},   
  {"CROSSFADE time startgrade endgrade startlayer endlayer", "crossfade between previous render and the layer range selected in selected time\r\nRequires FXFILTER COMMAND BYPYASS ON"},   
  {"CROSSFADE OFF", "turns off crossfade"},
};

static  SM_DemoEffect::Helper  LoadHelp[] =
{
  {"RENDERTARGET", "enables post fx"},
  {"NORENDERTARGET", "disables post fx"},  
};


class SingleFilterFX : public SM_DemoEffect
{
public:              
  SingleFilterFX(char const* pcName) : SM_DemoEffect(pcName)
  {
    ResetStatus(); 
    m_iBlurTexture=-1;
    m_iTransparentTexture=-1;
  }

  virtual          ~SingleFilterFX()
  {
  }

  int LoadArgumentsHelp     (Helper*& pHelpers)
  {
    pHelpers = LoadHelp;
    return (sizeof(LoadHelp)/sizeof(Helper));
  }

  
  int      Init(const char* pcCommand)
  {
    //m_iBlurTexture=ResourceManager::CreateRenderTexture(SIZESIZE, SIZESIZE, SM_D3d::GetCurrentMode()->d3dFormat);
    Shutdown();
    ResetStatus();

    
    if ((m_iBlurTexture=ResourceManager::CreateRenderTexture(SIZEWIDTH, SIZEHEIGHT, D3DFMT_X8R8G8B8))==-1)
    {
      SM_Main::OutputError("Failed to initializa render to texture infrastructure. If your card supports this consider updating your drivers");
      return -1;
    }

    if ((m_iTransparentTexture=ResourceManager::CreateRenderTexture(SIZEWIDTH, SIZEHEIGHT, D3DFMT_X8R8G8B8))==-1)
    {
      SM_Main::OutputError("Failed to initializa render to texture infrastructure. If your card supports this consider updating your drivers");
      return -1;
    }
    
    
    return (0);
  }


  int      Shutdown()
  {
    if (m_iBlurTexture!=-1)
    {
      ResourceManager::ReleaseTexture(m_iBlurTexture);
      m_iBlurTexture=-1;
    }

    if (m_iTransparentTexture!=-1)
    {
      ResourceManager::ReleaseTexture(m_iTransparentTexture);
      m_iTransparentTexture=-1;
    }

    ResetStatus();
    
    return (0);
  }
    

  int      Reset()
  {
    ResetStatus();
    return (0);
  }


  void ResetStatus()
  {
    m_bBlur       =false;
    m_bTransparentTransition=false;    
  }
   
    
  int      Start(float fTime)
  {
    
    return (0);
  }

  int      Stop()
  {
    return (0);
  }

  void     RenderTransparent(float fAlpha)
  {
    g_SceneFilter->RestoreRenderDepthTarget();


    FVF_PosRhwDiffuseTex1 pVertices[4];
    unsigned short        pIndices[6]={0,2,1,0,3,2};
    SM_D3d::Device()->SetTexture(0, ResourceManager::GetTextureFromID(m_iTransparentTexture));    
 
    float fScaleU=1.0f;
    float fScaleV=1.0f;        
    
    pVertices[0].x=0               ; pVertices[0].y=0                ; pVertices[0].z=0.0f; pVertices[0].u=0.0f; pVertices[0].v=0; pVertices[0].oow=1.0f; pVertices[0].diffuse=0xFFFFFFFF;
    pVertices[1].x=(float)SIZEWIDTH; pVertices[1].y=0                ; pVertices[1].z=0.0f; pVertices[1].u=fScaleU; pVertices[1].v=0; pVertices[1].oow=1.0f; pVertices[1].diffuse=0x00FFFFFF;
    pVertices[2].x=(float)SIZEWIDTH; pVertices[2].y=(float)SIZEHEIGHT; pVertices[2].z=0.0f; pVertices[2].u=fScaleU; pVertices[2].v=fScaleV; pVertices[2].oow=1.0f; pVertices[2].diffuse=0xFFFFFFFF;
    pVertices[3].x=0               ; pVertices[3].y=(float)SIZEHEIGHT; pVertices[3].z=0.0f; pVertices[3].u=0.0f; pVertices[3].v=fScaleV; pVertices[3].oow=1.0f; pVertices[3].diffuse=0x00FFFFFF;

    SM_D3d::Device()->SetVertexShader(FVF_POSRHWDIFFUSETEX1);
    SM_D3d::SetTextureStageState(0, D3DTSS_MAGFILTER, D3DTEXF_LINEAR);  
    SM_D3d::SetTextureStageState(0, D3DTSS_MINFILTER, D3DTEXF_LINEAR);  
    SM_D3d::SetTextureStageState(0, D3DTSS_MIPFILTER, D3DTEXF_NONE);
    SM_D3d::SetTextureStageState(0, D3DTSS_ADDRESSU, D3DTADDRESS_CLAMP);
    SM_D3d::SetTextureStageState(0, D3DTSS_ADDRESSV, D3DTADDRESS_CLAMP);
    

    SM_D3d::SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);                        
    SM_D3d::SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
    SM_D3d::SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);  
    SM_D3d::SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);
      

    SM_D3d::SetTextureStageState(0, D3DTSS_COLOROP   , D3DTOP_MODULATE);
    SM_D3d::SetTextureStageState(0, D3DTSS_COLORARG1 , D3DTA_TEXTURE );
    SM_D3d::SetTextureStageState(0, D3DTSS_COLORARG2 , D3DTA_DIFFUSE );

    SM_D3d::SetTextureStageState(0, D3DTSS_ALPHAOP   , D3DTOP_SELECTARG1);
    SM_D3d::SetTextureStageState(0, D3DTSS_ALPHAARG1 , D3DTA_TFACTOR );

    SM_D3d::SetRenderState(D3DRS_ZFUNC, D3DCMP_ALWAYS);    
    

    unsigned uFactor=int(fAlpha*255.0f)<<24;
    SM_D3d::SetRenderState(D3DRS_TEXTUREFACTOR, uFactor);
    

    SM_D3d::Device()->DrawIndexedPrimitiveUP(
        D3DPT_TRIANGLELIST, 
        0,
        6,
        2,
        pIndices,
        D3DFMT_INDEX16,
        pVertices, sizeof(FVF_PosRhwDiffuseTex1));

    SM_D3d::SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);                        
    SM_D3d::SetRenderState(D3DRS_ALPHATESTENABLE, TRUE);    
  }

  void     RenderBlur()
  {

    IDirect3DTexture8* pTexture=0;
    g_SceneFilter->GetCurrent(0, 0, &pTexture, 0, 0);

    assert(pTexture);
  
    static bool bFirst=true;
    if (m_bBlur)
    {
      g_SceneFilter->SetRenderDepthTarget(m_iBlurTexture, -1);
      Coordinates::UpdatePhysicalSize();

      if (bFirst)
      {
        bFirst=false;

        if (g_SceneFilter)
        {
          SM_D3d::Device()->Clear(0, NULL, D3DCLEAR_TARGET , g_SceneFilter->GetBackColor(), 1.0f, 0 );
        }
        else
        {
        #ifdef _DEBUG
        SM_D3d::Device()->Clear(0, NULL, D3DCLEAR_TARGET , D3DCOLOR_XRGB(0,int(128+127.0f*sinf(Timer::GetTime())),0), 1.0f, 0 );
        #else
        SM_D3d::Device()->Clear(0, NULL, D3DCLEAR_TARGET , D3DCOLOR_XRGB(0,0,0), 1.0f, 0 );
        #endif
        }
      }
    }

    float fOffset;
    if (!m_BlurSlider.GetValue(Timer::GetTime(), &fOffset) && !m_bBlurFadeIn)
    {
      m_bBlur=false;
    }

    float fBlurValue;
    if (m_bBlurFadeIn)
    {
      fBlurValue=1.0f+fOffset*(m_fBlurFactor-1.0f);
    }
    else
    {
      fBlurValue=m_fBlurFactor+fOffset*(1.0f-m_fBlurFactor);
    }
      
    //fBlurValue=0.05;
    FVF_PosRhwDiffuseTex1 pVertices[4];
    unsigned short        pIndices[6]={0,2,1,0,3,2};
    SM_D3d::Device()->SetTexture(0, pTexture);    
 
    float fScaleU=1.0f;
    float fScaleV=1.0f;    

    
    //float fScale  =1.0f+0.0f*sinf(fTime);

    pVertices[0].x=0               -0.5f; pVertices[0].y=0                -0.5f; pVertices[0].z=0.0f; pVertices[0].u=0.0f; pVertices[0].v=0; pVertices[0].oow=1.0f; pVertices[0].diffuse=0xFFFFFFFF;
    pVertices[1].x=(float)SIZEWIDTH-0.5f; pVertices[1].y=0                -0.5f; pVertices[1].z=0.0f; pVertices[1].u=fScaleU; pVertices[1].v=0; pVertices[1].oow=1.0f; pVertices[1].diffuse=0x00FFFFFF;
    pVertices[2].x=(float)SIZEWIDTH-0.5f; pVertices[2].y=(float)SIZEHEIGHT-0.5f; pVertices[2].z=0.0f; pVertices[2].u=fScaleU; pVertices[2].v=fScaleV; pVertices[2].oow=1.0f; pVertices[2].diffuse=0xFFFFFFFF;
    pVertices[3].x=0               -0.5f; pVertices[3].y=(float)SIZEHEIGHT-0.5f; pVertices[3].z=0.0f; pVertices[3].u=0.0f; pVertices[3].v=fScaleV; pVertices[3].oow=1.0f; pVertices[3].diffuse=0x00FFFFFF;

    SM_D3d::SetRenderState(D3DRS_ZFUNC, D3DCMP_ALWAYS);    
    SM_D3d::Device()->SetVertexShader(FVF_POSRHWDIFFUSETEX1);
    SM_D3d::SetTextureStageState(0, D3DTSS_MAGFILTER, D3DTEXF_LINEAR);  
    SM_D3d::SetTextureStageState(0, D3DTSS_MINFILTER, D3DTEXF_LINEAR);  
    SM_D3d::SetTextureStageState(0, D3DTSS_MIPFILTER, D3DTEXF_NONE);
    SM_D3d::SetTextureStageState(0, D3DTSS_ADDRESSU, D3DTADDRESS_CLAMP);
    SM_D3d::SetTextureStageState(0, D3DTSS_ADDRESSV, D3DTADDRESS_CLAMP);
    

    SM_D3d::SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);                        
    SM_D3d::SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
    SM_D3d::SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);  
      

    SM_D3d::SetTextureStageState(0, D3DTSS_COLOROP   , D3DTOP_MODULATE);
    SM_D3d::SetTextureStageState(0, D3DTSS_COLORARG1 , D3DTA_TEXTURE );
    SM_D3d::SetTextureStageState(0, D3DTSS_COLORARG2 , D3DTA_DIFFUSE );

    SM_D3d::SetTextureStageState(0, D3DTSS_ALPHAOP   , D3DTOP_SELECTARG1);
    SM_D3d::SetTextureStageState(0, D3DTSS_ALPHAARG1 , D3DTA_TFACTOR );

    unsigned uFactor=int(fBlurValue*255.0f)<<24;
    SM_D3d::SetRenderState(D3DRS_TEXTUREFACTOR, uFactor);
    

    SM_D3d::Device()->DrawIndexedPrimitiveUP(
        D3DPT_TRIANGLELIST, 
        0,
        6,
        2,
        pIndices,
        D3DFMT_INDEX16,
        pVertices, sizeof(FVF_PosRhwDiffuseTex1));

    g_SceneFilter->RestoreRenderDepthTarget();

    pVertices[0].x=0  ; pVertices[0].y=0  ; pVertices[0].z=1.0f; pVertices[0].u=0.0f; pVertices[0].v=0; pVertices[0].oow=1.0f; pVertices[0].diffuse=0xFFFFFFFF;
    pVertices[1].x=(float)SIZEWIDTH; pVertices[1].y=0  ; pVertices[1].z=1.0f; pVertices[1].u=fScaleU; pVertices[1].v=0; pVertices[1].oow=1.0f; pVertices[1].diffuse=0x00FFFFFF;
    pVertices[2].x=(float)SIZEWIDTH; pVertices[2].y=(float)SIZEHEIGHT; pVertices[2].z=1.0f; pVertices[2].u=fScaleU; pVertices[2].v=fScaleV; pVertices[2].oow=1.0f; pVertices[2].diffuse=0xFFFFFFFF;
    pVertices[3].x=0  ; pVertices[3].y=(float)SIZEHEIGHT; pVertices[3].z=1.0f; pVertices[3].u=0.0f; pVertices[3].v=fScaleV; pVertices[3].oow=1.0f; pVertices[3].diffuse=0x00FFFFFF;


    SM_D3d::SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
    SM_D3d::Device()->SetTexture(0, ResourceManager::GetTextureFromID(m_iBlurTexture));    
    SM_D3d::Device()->DrawIndexedPrimitiveUP(
        D3DPT_TRIANGLELIST, 
        0,
        6,
        2,
        pIndices,
        D3DFMT_INDEX16,
        pVertices, sizeof(FVF_PosRhwDiffuseTex1));


  }
  

  void RunPreLayer(int iLayer, float fTime)
  {
    if (iLayer==m_iTransparentStartLayer)
    {      
      if (m_bTransparentTransition)
      {
        // Setup fake buffer
        int iDepthID=-1;
        g_SceneFilter->GetCurrent(0, 0, 0, &iDepthID, 0);  
        g_SceneFilter->SetRenderDepthTarget(m_iTransparentTexture, g_SceneFilter->GetAuxDepthBufferID());

        if (g_SceneFilter)
        {
          SM_D3d::Device()->Clear(0, NULL, D3DCLEAR_TARGET |D3DCLEAR_ZBUFFER, g_SceneFilter->GetBackColor(), 1.0f, 0 );
        }
        else
        {
        #ifdef _DEBUG
        SM_D3d::Device()->Clear(0, NULL, D3DCLEAR_TARGET |D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(0,int(128+127.0f*sinf(Timer::GetTime())),0), 1.0f, 0 );
        #else
        SM_D3d::Device()->Clear(0, NULL, D3DCLEAR_TARGET |D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(0,0,0), 1.0f, 0 );
        #endif
        }

        Coordinates::UpdatePhysicalSize();
      }
    }
  }

  void RunPostLayer(int iLayer, float fTime)
  {
    if (iLayer==m_iBlurEndLayer)
    {
      if (m_bBlur)
      {
        if (!g_SceneFilter->m_bInterceptRender)
        {
          SM_Main::OutputError("Filter has to be on!!!!\n");
          return;
        }
      
        RenderBlur();
        Coordinates::UpdatePhysicalSize();
      }
    }

    if (m_bTransparentTransition && iLayer==m_iTransparentEndLayer)
    {      
      float fAlpha;
      m_TransparentSlider.GetValue(fTime, &fAlpha);
      RenderTransparent(m_fTransparentStart+(m_fTransparentEnd-m_fTransparentStart)*fAlpha);
    }
  }


  int      Run(float fTime)
  {    

    return (1);
  }
  

  int CommandArgumentsHelp  (Helper*& pHelpers)
  {
    pHelpers = CommandsHelp;
    return (sizeof(CommandsHelp)/sizeof(Helper));
  }

  int      Command           (float fTime, const char* pcCommand)
  {
    SM_DemoEffect::Command(fTime, pcCommand);

    char* pcToken;

    char* pcAux=new char[strlen(pcCommand)+1];
    strcpy(pcAux, pcCommand);

    pcToken=strtok(pcAux, " \t");
    if (strcmp(pcToken, "MOTIONBLUR")==0)
    {
      pcToken=strtok(0, " \t");
      if (strcmp(pcToken, "FADEIN")==0)
      {
        m_bBlurFadeIn=true;
      }
      else
      {
        m_bBlurFadeIn=false;
      }

      pcToken=strtok(0, " \t");
      m_BlurSlider.Init((float)SafeAtof(pcToken));
      m_BlurSlider.Start(fTime);                    

      pcToken=strtok(0, " \t");
      m_fBlurFactor=(float)SafeAtof(pcToken);      

      pcToken=strtok(0, " \t");
      m_iBlurStartLayer=SafeAtoi(pcToken);

      pcToken=strtok(0, " \t");
      m_iBlurEndLayer=SafeAtoi(pcToken);
    
      if (m_fBlurFactor==0.0f)
      {
        m_bBlur=false;
      }
      else
      {
        m_bBlur=true;
      }
    }
    else
    if (strcmp(pcToken, "MOTIONBLUROFF")==0)
    {
      m_bBlur=false;
    }
    else
    if (strcmp(pcToken, "CROSSFADE")==0)
    {
      m_bTransparentTransition=true;

      pcToken=strtok(0, " \t");
      m_TransparentSlider.Init((float)SafeAtof(pcToken));
      m_TransparentSlider.Start(fTime);              

      pcToken=strtok(0, " \t");
      m_fTransparentStart=(float)SafeAtof(pcToken);

      pcToken=strtok(0, " \t");
      m_fTransparentEnd=(float)SafeAtof(pcToken);
      
      pcToken=strtok(0, " \t");
      m_iTransparentStartLayer=SafeAtoi(pcToken);

      pcToken=strtok(0, " \t");
      m_iTransparentEndLayer=SafeAtoi(pcToken);
    }
    else
    if (strcmp(pcToken, "CROSSFADEOFF")==0)
    {
      m_bTransparentTransition=false;
    }
    
    delete[] pcAux;

    return (0);
  }  

  float          m_fBlurFactor;
  int            m_iBlurTexture;
  int            m_iBlurStartLayer;
  int            m_iBlurEndLayer;
  bool           m_bBlur;
  bool           m_bBlurFadeIn;
  LinearSlider   m_BlurSlider;



  bool           m_bTransparentTransition;
  int            m_iTransparentTexture;
  float          m_fTransparentStart;
  float          m_fTransparentEnd;
  LinearSlider   m_TransparentSlider;

  int            m_iTransparentStartLayer;
  int            m_iTransparentEndLayer;


  
};

DEFINE_EFFECT(SingleFilterFX)
SingleFilterFX FiltroIndividual("FILTROEFECTO");

    */
