/// ****************************************************************************
/// @file   
/// @author Dr.Neeton
/// @date   200X/X/X - 2016/12/08
/// 
/// @brief  DirectX 頂点シェーダー関連。
/// 
/// ****************************************************************************

#pragma once

#include "CPL_DX_Shader_Base.h"
#include "CPL_DX_Shader_CodeFragment.h"
#include "CPL_DX_Shader_VS_Fragment.h"

namespace CPL {
namespace DX {
namespace Shader {


// _____________________________________________________________________________
/// @brief 頂点シェーダコードマネージャ
///
// *****************************************************************************
class VSCode
  : public ShaderCode
{
public:
  VSCode
  ( _in<char_cptr             > in_vertex_shader_function_name
  , _in<CodeFragmentCollection> in_VSCFC
  , _in<CodeItem::Semantic    > in_semantic = CodeItem::Semantic("")
  );
  ~VSCode(){}
};



#define CPL_VS_DEFAULT_VERSION "vs_4_0"
  
// _____________________________________________________________________________
/// @brief 頂点シェーダ管理クラス
///
// *****************************************************************************
class VertexShader
  : public ShaderBase
{
private:
  CpDXVertexShader m_cp_vertex_shader;

  //char_cptr zzf_GetFunctionName() const;

public:
  DXVertexShader const* GetVS() const { return m_cp_vertex_shader; }
  DXVertexShader*       GetVS()       { return m_cp_vertex_shader; }
  
  // _____________________________________________________________________________
  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  void Release();
  
  // _____________________________________________________________________________
  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  HRESULT RenderSetup( DXDeviceContext* in_ptr_d3d_IC );
  
  // _____________________________________________________________________________
  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  HRESULT
    CompileFromMemory
      ( _in <VSCode            > in_shader_code
      , _in <char_cptr         > in_vertex_shader_function_name
      , _in <LPCSTR            > in_target_version = CPL_VS_DEFAULT_VERSION
      , pin <D3D10_SHADER_MACRO> in_ptr_defines    = nullptr
      , _in <UINT              > in_flag_compile   = D3D10_SHADER_ENABLE_STRICTNESS
      , _in <UINT              > in_flag_effect    = 0
      , pout<ID3DBlob*         > out_pp_error      = nullptr
      );

  // _____________________________________________________________________________
  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  HRESULT
    CompileFromFile
      ( _in <str_cptr          > in_file_name
      , _in <char_cptr         > in_vertex_shader_function_name
      , _in <LPCSTR            > in_target_version = CPL_VS_DEFAULT_VERSION
      , pin <D3D10_SHADER_MACRO> in_ptr_defines    = nullptr
      , _in <UINT              > in_flag_compile   = D3D10_SHADER_ENABLE_STRICTNESS
      , _in <UINT              > in_flag_effect    = 0
      , pout<ID3DBlob*         > out_pp_error      = nullptr
      );

  // _____________________________________________________________________________
  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  HRESULT
    CreateFromMemory
      ( _in <VSCode            > in_shader_code
      , _in <char_cptr         > in_vertex_shader_function_name
      , _in <LPCSTR            > in_target_version = CPL_VS_DEFAULT_VERSION
      , pin <D3D10_SHADER_MACRO> in_ptr_defines    = nullptr
      , _in <UINT              > in_flag_compile   = D3D10_SHADER_ENABLE_STRICTNESS
      , _in <UINT              > in_flag_effect    = 0
      , pout<ID3DBlob*         > out_pp_error      = nullptr
      );

  // _____________________________________________________________________________
  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  HRESULT
    CreateFromFile
      ( _in <str_cptr          > in_file_name
      , _in <char_cptr         > in_vertex_shader_function_name
      , _in <LPCSTR            > in_target_version = CPL_VS_DEFAULT_VERSION
      , pin <D3D10_SHADER_MACRO> in_ptr_defines    = nullptr
      , _in <UINT              > in_flag_compile   = D3D10_SHADER_ENABLE_STRICTNESS
      , _in <UINT              > in_flag_effect    = 0
      , pout<ID3DBlob*         > out_pp_error      = nullptr
      );

  // _____________________________________________________________________________
  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  VertexShader
  ( _in <VSCode            > in_shader_code
  , _in <char_cptr         > in_vertex_shader_function_name
  , _in <LPCSTR            > in_target_version = CPL_VS_DEFAULT_VERSION
  , pin <D3D10_SHADER_MACRO> in_ptr_defines    = nullptr
  , _in <UINT              > in_flag_compile   = D3D10_SHADER_ENABLE_STRICTNESS
  , _in <UINT              > in_flag_effect    = 0
  , pout<ID3DBlob*         > out_pp_error      = nullptr
  ) CPL_THROW_RESTRICTION( ExceptionHR );

  // _____________________________________________________________________________
  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  VertexShader
  ( _in <str_cptr          > in_file_name
  , _in <char_cptr         > in_vertex_shader_function_name
  , _in <LPCSTR            > in_target_version = CPL_VS_DEFAULT_VERSION
  , pin <D3D10_SHADER_MACRO> in_ptr_defines    = nullptr
  , _in <UINT              > in_flag_compile   = D3D10_SHADER_ENABLE_STRICTNESS
  , _in <UINT              > in_flag_effect    = 0
  , pout<ID3DBlob*         > out_pp_error      = nullptr
  );

  // _____________________________________________________________________________
  /// @brief デストラクタ
  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  virtual ~VertexShader()
  {
    Release();
  }
};


// _____________________________________________________________________________
/// @brief デフォルトの頂点シェーダー生成関数（座標＋カラー）
/// 
/// 頂点座標変換を行い、変換座標とカラーをそのまま出力する頂点シェーダーを生成します。
/// 
/// @tparam POS_NO       : 入出力頂点座標の番号を指定します。
/// @tparam IN_COLOR_NO  : 入力頂点カラーの番号を指定します。
/// @tparam OUT_COLOR_NO : 出力頂点カラーの番号を指定します。
/// 
/// @return 生成された頂点シェーダーオブジェクトを指すスマートポインタを返します。
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
template<int POS_NO, int IN_COLOR_NO, int OUT_COLOR_NO>
sdptr<VertexShader> GetDefaultVS_PosColor()
{
  // 頂点シェーダコード作成
  static auto
    sp_vsc =
      CPL_MAKE_SHARED
        ( VSCode
        , VSF::VertexTransform( POS_NO )
        , VSF::ImmediateTextureCoord( IN_COLOR_NO, OUT_COLOR_NO )
        );
  // 頂点シェーダー作成
  static auto
    sp_vs = CPL_MAKE_SHARED( VertexShader, *sp_vsc );

  // 
  return sp_vs;
}


// _____________________________________________________________________________
/// @brief デフォルトの頂点シェーダー生成関数（座標＋カラー＋テクスチャ１）
/// 
/// 頂点座標変換を行い、変換座標とカラーおよびテクスチャ座標をそのまま出力する
/// 頂点シェーダーを生成します。
/// 
/// @tparam POS_NO       : 入出力頂点座標の番号を指定します。
/// @tparam IN_COLOR_NO  : 入力頂点カラーの番号を指定します。
/// @tparam OUT_COLOR_NO : 出力頂点カラーの番号を指定します。
/// @tparam IN_TEX_NO    : 入力ＵＶ座標の番号を指定します。
/// @tparam OUT_TEX_NO   : 出力ＵＶ座標の番号を指定します。
/// 
/// @return 生成された頂点シェーダーオブジェクトを指すスマートポインタを返します。
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
template
< int POS_NO
, int IN_COLOR_NO, int OUT_COLOR_NO
, int IN_TEX_NO  , int OUT_TEX_NO >
sdptr<VertexShader> GetDefaultVS_PosColorTex1()
{
  // 頂点シェーダコード作成
  static auto
    sp_vsc =
      CPL_MAKE_SHARED
        ( VSCode
        , VSF::VertexTransform(POS_NO)
        , VSF::ImmediateTextureCoord(IN_COLOR_NO,OUT_COLOR_NO)
        , VSF::ImmediateTextureCoord(IN_TEX_NO,OUT_TEX_NO)
        );
  // 頂点シェーダー作成
  static auto
    sp_vs = CPL_MAKE_SHARED(VertexShader, *sp_vsc );

  // 
  return sp_vs;
}


// _____________________________________________________________________________
/// @brief デフォルトの頂点シェーダー生成関数（変換済み座標＋カラー）
/// 
/// 入力された座標とカラーをそのまま出力する頂点シェーダーを生成します。
/// 
/// @tparam POS_NO       : 入出力頂点座標の番号を指定します。
/// @tparam IN_COLOR_NO  : 入力頂点カラーの番号を指定します。
/// @tparam OUT_COLOR_NO : 出力頂点カラーの番号を指定します。
/// 
/// @return 生成された頂点シェーダーオブジェクトを指すスマートポインタを返します。
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
template<int POS_NO, int IN_COLOR_NO, int OUT_COLOR_NO>
sdptr<VertexShader> GetDefaultVS_PosTColor()
{
  // 頂点シェーダコード作成
  static auto
    sp_vsc =
      CPL_MAKE_SHARED
        ( VSCode
        , VSF::ImmediateInputPositionT(POS_NO)
        , VSF::ImmediateTextureCoord(IN_COLOR_NO,OUT_COLOR_NO)
        );
  // 頂点シェーダー作成
  static auto
    sp_vs = CPL_MAKE_SHARED( VertexShader, *sp_vsc );

  // 
  return sp_vs;
}


// _____________________________________________________________________________
/// @brief デフォルトの頂点シェーダー生成関数（変換済み座標＋カラー＋テクスチャ１）
/// 
/// 入力された座標とカラーとテクスチャ座標をそのまま出力する
/// 頂点シェーダーを生成します。
/// 
/// @tparam POS_NO       : 入出力頂点座標の番号を指定します。
/// @tparam IN_COLOR_NO  : 入力頂点カラーの番号を指定します。
/// @tparam OUT_COLOR_NO : 出力頂点カラーの番号を指定します。
/// @tparam IN_TEX_NO    : 入力ＵＶ座標の番号を指定します。
/// @tparam OUT_TEX_NO   : 出力ＵＶ座標の番号を指定します。
/// 
/// @return 生成された頂点シェーダーオブジェクトを指すスマートポインタを返します。
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
template
< int POS_NO
, int IN_COLOR_NO, int OUT_COLOR_NO
, int IN_TEX_NO, int OUT_TEX_NO
>
sdptr<VertexShader> GetDefaultVS_PosTColorTex1()
{
  // 頂点シェーダコード作成
  static auto
    sp_vsc =
      CPL_MAKE_SHARED
        ( VSCode
        , VSF::ImmediateInputPositionT(POS_NO)
        , VSF::ImmediateTextureCoord(IN_COLOR_NO, OUT_COLOR_NO)
        , VSF::ImmediateTextureCoord(IN_TEX_NO, OUT_TEX_NO)
        );
  // 頂点シェーダー作成
  static auto
    sp_vs = CPL_MAKE_SHARED( VertexShader, *sp_vsc );

  // 
  return sp_vs;
}


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