#ifndef __DEMOEFFECT

#define __DEMOEFFECT

#include "SM_Leaks.h"
#include <stdlib.h>


#define MAX_LAYERS 16

class SM_DemoEffect
{
public:              
                    SM_DemoEffect    (char const* pcName);
  virtual          ~SM_DemoEffect    ();

  virtual int      Init              (const char* pcCommand) = 0; // 0: OK ; -1: ERROR
  virtual int      Shutdown          ()                      ; // 0: OK ; -1: ERROR
  virtual int      Reload            (const char* pcCommand) ; // 0: OK ; -1: ERROR


  virtual int      Start             (float fTime)           = 0; // Tiempo en segundos
  virtual int      Stop              ()                      = 0;
  virtual int      Reset             ()                      = 0;  



  void             SetLayer          (int iLayer);

  virtual int      SetParent         (SM_DemoEffect* pDemoEffect);

  virtual bool     DoPrecache        ();                        // Do precaching on this effect

  virtual void     RunPreStartFrame  (float fTime);           
  virtual void     RunPreRender      (float fTime);           
  virtual int      Run               (float fTime);             // 1: Vuelve a llamarme ; 0: Stop() y no me llames mas
  virtual void     RunPostRender     (float fTime);           
  virtual void     RunPostEndFrame   (float fTime);           
  virtual void     RunPreLayer       (int iLayer, float fTime); 
  virtual void     RunPostLayer      (int iLayer, float fTime);
  

  virtual int      Command           (float fTime, const char* pcCommand); // Procesa un commando mandado desde script


  SM_DemoEffect*   m_pNextEffect;    // No tocar!. Se usa para las autoenumeraciones  
  char const*      m_pcInstanceName; 
  int              m_iLayer;
  SM_DemoEffect*   m_pParent;
  static int       m_iRandCount;

  // Editor functions
public:
  static  HMODULE       m_Resources;
  static  int           InitResources         ();
  static  int           ShutdownResources     ();
  virtual int           NewCommand            (char* pcCommand, int iSize);
  virtual int           NewEffect             (char* pcLoadArguments, int iSize);

  struct Helper
  {
    char* pcCommand;
    char* pcHelp;
  };
  virtual int           LoadArgumentsHelp     (Helper*& pHelpers);
  virtual int           CommandArgumentsHelp  (Helper*& pHelpers);

protected:
  static float SafeAtof(const char* pcToken)
  {
    return pcToken?((float)atof(pcToken)):1.0f;
  }

  static int SafeAtoi(const char* pcToken)
  {
    return pcToken?atoi(pcToken):1;
  }

  struct NewEffectDlgProcData
  {
    SM_DemoEffect* m_pEffect;
    char*          m_pcLoadArguments;
    int            m_iMaxLength;
    Helper*        m_pHelpers;
  };
  static  BOOL CALLBACK NewEffectDlgProc   ( HWND _hdlg, UINT _uMsg, WPARAM _wparam, LPARAM _lparam);

  struct NewCommandDlgProcData
  {
    SM_DemoEffect*         m_pEffect;
    char*                  m_pcCommandArguments;
    int                    m_iMaxLength;
    Helper*                m_pHelpers;
  };
  static  BOOL CALLBACK NewCommandDlgProc  ( HWND _hdlg, UINT _uMsg, WPARAM _wparam, LPARAM _lparam);



};

#define DEFINE_EFFECT(Efecto) void EnumeraLinka##Efecto##() {}

extern SM_DemoEffect* EffectInstances;

SM_DemoEffect* GetEffect(const char* pcName);


// Datos accesibles desde un efecto
namespace SM_DEData
{
  struct CVideoBuffer
  {
	unsigned m_uBPP;
	unsigned m_uRMask;
	unsigned m_uGMask;
	unsigned m_uBMask;
	unsigned m_uRShiftLeft;
	unsigned m_uGShiftLeft;
	unsigned m_uBShiftLeft;
	unsigned m_uRShiftRight;
	unsigned m_uGShiftRight;
	unsigned m_uBShiftRight;
	unsigned m_uWidth;
	unsigned m_uHeight;  
	unsigned m_uByteStride;
  void*    m_pVideo;

  void* GetSurfacePointer();
  void* GetSurfacePointer(unsigned x, unsigned y);
  };  

  extern CVideoBuffer VideoBuffer;  
}


extern void EnumerateFx();
#endif


