/// ****************************************************************************
/// @file   
/// @author Dr.Neeton
/// @date   200X/X/X - 2014/03/10
/// 
/// @brief  DirectX 頂点シェーダフラグメント。
/// 
/// ****************************************************************************

#pragma once

#include "CPL_DX_CommonShaderFragment.h"

namespace CPL {
namespace DX {
namespace Shader {
namespace VSF {

  // _____________________________________________________________________________
  /// @brief 入力パラメーター：３Ｄ座標
  ///
  // *****************************************************************************
  class Input_Position
    : virtual public CodeFragment
    , public CSF::KW_InPosition
  {
  protected:
    int m_in_position_No;
    
    void On_SetupInputParameter( rout<CIV_Input> out_input_param ) override;

    CPL_DEF_GET_THIS_FRAGMENT_COLLECTION
  public:
    Input_Position( _in<int> in_No ) : m_in_position_No( in_No ) {}
  };

  // _____________________________________________________________________________
  /// @copydoc Input_Position
  /// ナンバーtemplate版
  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  CPL_DX_CSF_DEFINED_DERIVED_CLASS_N_TYPE( Input_Position );

  // _____________________________________________________________________________
  /// @brief 入力パラメーター：２Ｄ座標
  ///
  // *****************************************************************************
  class Input_PositionT
    : virtual public CodeFragment
    , public CSF::KW_InPositionT
  {
  protected:
    void On_SetupInputParameter( rout<CIV_Input> out_input_param ) override;

    CPL_DEF_GET_THIS_FRAGMENT_COLLECTION
  public:
    Input_PositionT(){}
  };

  // _____________________________________________________________________________
  /// @brief 入力パラメーター：ブレンドの重み＆インデックス
  ///
  // *****************************************************************************
  class Input_Blend
    : virtual public CodeFragment
    , public CSF::KW_InBWeight
    , public CSF::KW_InBIndex
  {
  protected:
    U16 m_in_vtx_bweight_No;
    U16 m_in_vtx_bindex_No;

    void On_SetupInputParameter( rout<CIV_Input> out_input_param ) override;

    CPL_DEF_GET_THIS_FRAGMENT_COLLECTION
  public:
    Input_Blend
    ( U16 in_vtx_bwight_No = 0
    , U16 in_vtx_bindex_No = 0 );
  };

  // _____________________________________________________________________________
  /// @copydoc Input_Blend
  /// ナンバーtemplate版
  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  CPL_DX_CSF_DEFINED_DERIVED_CLASS_N_TYPE( Input_Blend );


  // _____________________________________________________________________________
  /// @brief 入力パラメーター：法線ベクトル
  ///
  // *****************************************************************************
  class Input_Normal
    : virtual public CodeFragment
    , public CSF::KW_InNormal
  {
  protected:
    int m_in_normal_No;

    void On_SetupInputParameter( rout<CIV_Input> out_input_param ) override;
    
    CPL_DEF_GET_THIS_FRAGMENT_COLLECTION
  public:
    Input_Normal( _in<int> in_No = 0 ) : m_in_normal_No( in_No ) {}
  };

  // _____________________________________________________________________________
  /// @copydoc Input_Normal
  /// ナンバーtemplate版
  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  CPL_DX_CSF_DEFINED_DERIVED_CLASS_N_TYPE( Input_Normal );

  // _____________________________________________________________________________
  /// @brief 入力パラメーター：ポイントサイズ
  ///
  // *****************************************************************************
  class Input_PSize
    : virtual public CodeFragment
    , public CSF::KW_InPSize
  {
  protected:
    int m_in_psize_No;

    void On_SetupInputParameter( rout<CIV_Input> out_input_param ) override;
    
    CPL_DEF_GET_THIS_FRAGMENT_COLLECTION
  public:
    Input_PSize( _in<int> in_No = 0 ) : m_in_psize_No( in_No ) {}
  };

  // _____________________________________________________________________________
  /// @copydoc Input_PSize
  /// ナンバーtemplate版
  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  CPL_DX_CSF_DEFINED_DERIVED_CLASS_N_TYPE( Input_PSize );

  // _____________________________________________________________________________
  /// @brief 入力パラメーター：カラー
  ///
  // *****************************************************************************
  class Input_Color
    : virtual public CodeFragment
    , public CSF::KW_InColor
  {
  protected:
    int m_in_color_No;

    void On_SetupInputParameter( rout<CIV_Input> out_input_param ) override;

    CPL_DEF_GET_THIS_FRAGMENT_COLLECTION
  public:
    Input_Color( _in<int> in_No = 0 ) : m_in_color_No( in_No ) {}
  };

  // _____________________________________________________________________________
  /// @copydoc Input_Color
  /// ナンバーtemplate版
  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  CPL_DX_CSF_DEFINED_DERIVED_CLASS_N_TYPE( Input_Color );

  // _____________________________________________________________________________
  /// @brief 入力パラメーター：テクスチャ座標
  ///
  // *****************************************************************************
  class Input_TexCoord
    : virtual public CodeFragment
    , public CSF::KW_InTexCoord
  {
  protected:
    int m_in_texcoord_No;

    void On_SetupInputParameter( rout<CIV_Input> out_input_param ) override;

    CPL_DEF_GET_THIS_FRAGMENT_COLLECTION
  public:
    Input_TexCoord( _in<int> in_No = 0 ) : m_in_texcoord_No( in_No ) {}
  };

  // _____________________________________________________________________________
  /// @copydoc Input_TexCoord
  /// ナンバーtemplate版
  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  CPL_DX_CSF_DEFINED_DERIVED_CLASS_N_TYPE( Input_TexCoord );

  // _____________________________________________________________________________
  /// @brief 入力パラメーター：接線
  ///
  // *****************************************************************************
  class Input_Tangent
    : virtual public CodeFragment
    , public CSF::KW_InTangent
  {
  protected:
    int m_in_tangent_No;

    void On_SetupInputParameter( rout<CIV_Input> out_input_param ) override;

    CPL_DEF_GET_THIS_FRAGMENT_COLLECTION
  public:
    Input_Tangent( _in<int> in_No = 0 )
      : m_in_tangent_No( in_No )
    {}
  };

  // _____________________________________________________________________________
  /// @copydoc Input_Tangent
  /// ナンバーtemplate版
  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  CPL_DX_CSF_DEFINED_DERIVED_CLASS_N_TYPE( Input_Tangent );

  // _____________________________________________________________________________
  /// @brief 入力パラメーター：従法線
  ///
  // *****************************************************************************
  class Input_BiNormal
    : virtual public CodeFragment
    , public CSF::KW_InBiNormal
  {
  protected:
    int m_in_binormal_No;

    void On_SetupInputParameter( rout<CIV_Input> out_input_param ) override;

    CPL_DEF_GET_THIS_FRAGMENT_COLLECTION
  public:
    Input_BiNormal( _in<int> in_No = 0 ) : m_in_binormal_No( in_No ) {}
  };

  // _____________________________________________________________________________
  /// @copydoc Input_BiNormal
  /// ナンバーtemplate版
  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  CPL_DX_CSF_DEFINED_DERIVED_CLASS_N_TYPE( Input_BiNormal );




  // _____________________________________________________________________________
  /// @brief 出力パラメーター：スクリーン座標
  ///
  // *****************************************************************************
  class Output_Position
    : virtual public CodeFragment
    , public CSF::KW_OutPosition
  {
  protected:
    int m_out_position_No;

    void On_SetupOutputParameter( rout<CIV_Output> out_output_param ) override;

    CPL_DEF_GET_THIS_FRAGMENT_COLLECTION
  public:
    Output_Position( _in<int> in_No = 0 )
      : m_out_position_No( in_No )
    {}
  };

  // _____________________________________________________________________________
  /// @copydoc Output_Position
  /// ナンバーtemplate版
  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  CPL_DX_CSF_DEFINED_DERIVED_CLASS_N_TYPE( Output_Position );


  // _____________________________________________________________________________
  /// @brief 出力パラメーター：ポイントサイズ
  ///
  // *****************************************************************************
  class Output_PSize
    : virtual public CodeFragment
    , public CSF::KW_OutPSize
  {
  protected:
    int m_out_psize_No;

    void On_SetupOutputParameter( rout<CIV_Output> out_output_param ) override;

    CPL_DEF_GET_THIS_FRAGMENT_COLLECTION
  public:
    Output_PSize( _in<int> in_No = 0 )
      : m_out_psize_No( in_No )
    {}
  };

  // _____________________________________________________________________________
  /// @brief 出力パラメーター：フォグ
  ///
  // *****************************************************************************
  class Output_Fog
    : virtual public CodeFragment
    , public CSF::KW_OutFog
  {
  protected:
    int m_out_fog;

    void On_SetupOutputParameter( rout<CIV_Output> out_output_param ) override;

    CPL_DEF_GET_THIS_FRAGMENT_COLLECTION
  public:
    Output_Fog( _in<int> in_No = 0 )
      : m_out_fog( in_No )
    {}
  };

  // _____________________________________________________________________________
  /// @brief 出力パラメーター：カラー
  ///
  // *****************************************************************************
  class Output_Color
    : virtual public CodeFragment
    , public CSF::KW_OutColor
  {
  protected:
    int m_out_color_No;

    void On_SetupOutputParameter( rout<CIV_Output> out_output_param ) override;

    CPL_DEF_GET_THIS_FRAGMENT_COLLECTION
  public:
    Output_Color( _in<int> in_No = 0 )
      : m_out_color_No( in_No )
    {}
  };

  // _____________________________________________________________________________
  /// @copydoc Output_Color
  /// ナンバーtemplate版
  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  CPL_DX_CSF_DEFINED_DERIVED_CLASS_N_TYPE( Output_Color );


  // _____________________________________________________________________________
  /// @brief 出力パラメーター：テクスチャ座標
  ///
  // *****************************************************************************
  class Output_TexCoord
    : virtual public CodeFragment
    , public CSF::KW_OutTexCoord
  {
  protected:
    int m_out_texcoord_No;

    void On_SetupOutputParameter( rout<CIV_Output> out_output_param ) override;

    CPL_DEF_GET_THIS_FRAGMENT_COLLECTION
  public:
    Output_TexCoord( _in<int> in_No = 0 )
      : m_out_texcoord_No( in_No )
    {}
  };

  // _____________________________________________________________________________
  /// @copydoc Output_TexCoord
  /// ナンバーtemplate版
  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  CPL_DX_CSF_DEFINED_DERIVED_CLASS_N_TYPE( Output_TexCoord );


  // _____________________________________________________________________________
  /// @brief 出力パラメーター：テセレーション係数
  ///
  // *****************************************************************************
  class Output_TessFactor
    : virtual public CodeFragment
    , public CSF::KW_OutTessFactor
  {
  protected:
    int m_out_tess_factor_No;

    void On_SetupOutputParameter( rout<CIV_Output> out_output_param ) override;

    CPL_DEF_GET_THIS_FRAGMENT_COLLECTION
  public:
    Output_TessFactor( _in<int> in_No = 0 )
      : m_out_tess_factor_No( in_No )
    {}
  };

  // _____________________________________________________________________________
  /// @copydoc Output_TessFactor
  /// ナンバーtemplate版
  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  CPL_DX_CSF_DEFINED_DERIVED_CLASS_N_TYPE( Output_TessFactor );




  
  // _____________________________________________________________________________
  /// @brief 頂点レイアウト
  ///
  // *****************************************************************************
  class VertexLayout
    : public CodeFragment
    , public Layout::Buffer
  {
  protected:
    void On_SetupInputParameter( rout<CIV_Input> out_input_param ) override;

    CPL_DEF_GET_THIS_FRAGMENT_COLLECTION
  public:
    VertexLayout( Layout::Buffer const& in_layout_buf );
  };



  // _____________________________________________________________________________
  /// @brief 変換済み頂点座標をそのまま転送
  ///
  // *****************************************************************************
  class ImmediateInputPositionT
    : public Input_PositionT
    , public Output_Position
  {
  protected:
    void On_SetupInputParameter( rout<CIV_Input> out_input_param ) override;
    void On_SetupOutputParameter( rout<CIV_Output> out_output_param ) override;
    void On_CallFunction( rout<ss> out_statement, _in<CodeItemSet> in_parameter ) override;

    CPL_DEF_GET_THIS_FRAGMENT_COLLECTION
  public:
    ImmediateInputPositionT( int in_output_pos_No );
  };

  // _____________________________________________________________________________
  /// @brief 頂点カラーをそのまま転送
  ///
  // *****************************************************************************
  class ImmediateInputColor
    : public Input_Color
    , public Output_Color
  {
  protected:
    void On_SetupInputParameter( rout<CIV_Input> out_input_param ) override;
    void On_SetupOutputParameter( rout<CIV_Output> out_output_param ) override;
    void On_CallFunction( rout<ss> out_statement, _in<CodeItemSet> in_parameter ) override;

    CPL_DEF_GET_THIS_FRAGMENT_COLLECTION
  public:
    ImmediateInputColor( int in_input_color_No, int in_output_color_No );
  };
  
  // _____________________________________________________________________________
  /// @brief テクスチャ座標をそのまま転送
  ///
  // *****************************************************************************
  class ImmediateTextureCoord
    : public Input_TexCoord
    , public Output_TexCoord
  {
  protected:
    void On_SetupInputParameter( rout<CIV_Input> out_input_param ) override;
    void On_SetupOutputParameter( rout<CIV_Output> out_output_param ) override;
    void On_CallFunction( rout<ss> out_statement, _in<CodeItemSet> in_parameter ) override;

    CPL_DEF_GET_THIS_FRAGMENT_COLLECTION
  public:
    ImmediateTextureCoord(
      int in_input_texcoord_No,
      int in_output_texcoord_No );
  };



  // _____________________________________________________________________________
  /// @brief 頂点トランスフォームコード
  ///
  // *****************************************************************************
  class VertexTransform
    : public Input_Position
    , public Output_Position
    , public CSF::Local_Position
    , public CSF::Local_Matrix
    , public CSF::KW_G_MtxViewProj
    , public CSF::KW_G_MtxWorld
  {
  protected:
    void On_SetupGlobalParameter( rout<CIV_Global> out_global_param ) override;
    void On_SetupInputParameter ( rout<CIV_Input> out_input_param ) override
    {
      Input_Position::On_SetupInputParameter( out_input_param );
    }
    void On_SetupOutputParameter( rout<CIV_Output> out_output_param ) override
    {
      Output_Position::On_SetupOutputParameter( out_output_param );
    }
    void On_SetupInitializer( rout<CIV_Initializer> out_initialize_param ) override;
    void On_SetupFunction
          ( rout<CIFunctionSet> out_functions
          , _in <CIV_Global   > in_global_param
          ) override;
    void On_CallFunction( rout<ss> out_statement, _in<CodeItemSet> in_parameter ) override;

    CPL_DEF_GET_THIS_FRAGMENT_COLLECTION

  public:
    VertexTransform( int in_input_pos_No = 0, int in_output_pos_No = 0 );
    ~VertexTransform(){}
  };


  // _____________________________________________________________________________
  /// @brief マトリクスブレンドコード
  ///
  // *****************************************************************************
  class MatrixBlending
    : public Input_Blend
    , public CSF::Local_Matrix
    , public CSF::KW_G_MtxWorld
  {
  protected:
    int m_in_blend_matrix_max;

    void On_SetupGlobalParameter( rout<CIV_Global> out_global_param ) override;
    void On_SetupInputParameter( rout<CIV_Input> out_input_param ) override
    {
      Input_Blend::On_SetupInputParameter( out_input_param );
    }
    void On_SetupInitializer( CIV_Initializer& out_initialize_param ) override
    {
      Local_Matrix::On_SetupInitializer( out_initialize_param );
    }
    void On_SetupFunction
          ( rout<CIFunctionSet> out_functions
          , _in <CIV_Global   > in_global_param
          ) override;
    void On_CallFunction( rout<ss> out_statement, _in<CodeItemSet> in_parameter ) override;

    CPL_DEF_GET_THIS_FRAGMENT_COLLECTION

  public:
    MatrixBlending
    ( _in<U16> in_vtx_bweight_No
    , _in<U16> in_vtx_bindex_No
    , _in<int> in_blend_matrix_max
    );
  };
  

  // _____________________________________________________________________________
  /// @brief 法線トランスフォーム
  ///
  // *****************************************************************************
  class NormalTransform
    : public Input_Normal
    , public CSF::Local_Normal
    , public CSF::Local_Matrix
  {
  protected:
    void On_SetupInputParameter( rout<CIV_Input> out_input_param ) override
    {
      Input_Normal::On_SetupInputParameter( out_input_param );
    }
    void On_SetupInitializer( rout<CIV_Initializer> out_initialize_param ) override;
    void On_SetupFunction
          ( rout<CIFunctionSet> out_functions
          , _in <CIV_Global   > in_global_param
          ) override;
    void On_CallFunction( rout<ss> out_statement, _in<CodeItemSet> in_parameter ) override;

    CPL_DEF_GET_THIS_FRAGMENT_COLLECTION
  public:
    NormalTransform( int in_normal_No = 0 )
      : Input_Normal( in_normal_No )
      , Local_Normal( in_normal_No )
    {}
  };

  
  // _____________________________________________________________________________
  /// @brief ビルボード
  ///
  // *****************************************************************************
  class MatrixBillboard
    : public CSF::Local_Matrix
    , public CSF::KW_G_MtxBillboard
  {
  protected:
    void On_SetupGlobalParameter( rout<CIV_Global> out_global_param ) override;
    void On_SetupFunction
          ( rout<CIFunctionSet> out_functions
          , _in <CIV_Global   > in_global_param
          ) override;
    void On_CallFunction( rout<ss> out_statement, _in<CodeItemSet> in_parameter ) override;

    CPL_DEF_GET_THIS_FRAGMENT_COLLECTION
  public:
    MatrixBillboard()
    {}
  };

  

  // _____________________________________________________________________________
  /// @brief ポイントライト計算コード
  ///
  // *****************************************************************************
  class PointLight
    : public CSF::zzz_::BaseLight
    , public CSF::KW_G_PointLight
    , public CSF::KW_G_EyePosition
    , public CSF::KW_Diffuse
    , public CSF::KW_Specular
    , public CSF::KW_Position
    , public CSF::KW_Normal
    , public Input_Position
    , public Input_Normal
    , public Input_Color
    , public Output_Color
    , public CSF::KW_L_Position
    , public CSF::KW_L_Normal
    , public CSF::Local_Matrix
  {
  protected:
    void On_SetupGlobalParameter( rout<CIV_Global> out_global_param ) override;
    void On_SetupInputParameter( rout<CIV_Input> out_input_param ) override;
    void On_SetupOutputParameter( rout<CIV_Output> out_output_param ) override
    {
      Output_Color::On_SetupOutputParameter( out_output_param );
    }
    void On_SetupFunction
          ( rout<CIFunctionSet> out_functions
          , _in <CIV_Global   > in_global_param
          ) override;
    void On_CallFunction( rout<ss> out_statement, _in<CodeItemSet> in_parameter ) override;
    void On_SetupInitializer( rout<CIV_Initializer> out_initialize_param ) override;

    CPL_DEF_GET_THIS_FRAGMENT_COLLECTION

  public:
    PointLight
    ( U32 in_light_num
    , U32 in_pos_No )
      : CSF::zzz_::BaseLight( in_light_num )
      , Input_Position( in_pos_No )
    {}
  };


  // _____________________________________________________________________________
  /// @brief ピクセルシェーダライティングのデータ設定コード
  ///
  // *****************************************************************************
  class SetupPixelShaderLighting
    : public CSF::zzz_::BaseLight
    , public Input_Position
    , public Input_Normal
    , public Output_TexCoordN<4>
    , public Output_TexCoordN<5>
    , public CSF::Local_Position
    , public CSF::Local_Normal
  {
  protected:
    void On_SetupInputParameter( rout<CIV_Input> out_input_param ) override;
    void On_SetupOutputParameter( rout<CIV_Output> out_output_param ) override;
    void On_SetupFunction
          ( rout<CIFunctionSet> out_functions
          , _in <CIV_Global   > in_global_param
          ) override;
    void On_CallFunction( rout<ss> out_statement, _in<CodeItemSet> in_parameter ) override;
    void On_SetupInitializer( rout<CIV_Initializer> out_initialize_param ) override;

    CPL_DEF_GET_THIS_FRAGMENT_COLLECTION
  public:
    SetupPixelShaderLighting( int in_pos_No, int in_normal_No, U32 in_light_num )
      : CSF::zzz_::BaseLight( in_light_num )
      , Input_Position( in_pos_No )
      , Input_Normal( in_normal_No )
    {}
  };


} // namespace VSF



} // namespace Shader
} // namespace DX
} // namespace CPL
