/// ****************************************************************************
/// @file   
/// @author Dr.Neeton
/// @date   200X/X/X - 2016/12/08
/// 
/// @brief  DirectX  頂点シェーダー関連。
/// 
/// ※ 自動シェーダー生成について\n
///  シェーダクラスは、シェーダコードクラスを用いることにより、プログラム上で
///  シェーダソースコードを生成することを目的としたもの。\n
///  頂点シェーダにはVSCodeクラスを用いる。\n
///  このクラスに複数のシェーダフラグメントクラスを渡す。このシェーダフラグメン
///  トクラスの組み合わせでいろいろなシェーダを作成する。\n
///  シェーダフラグメントクラスを拡張または作成することで、オリジナルのシェーダー
///  を作成することも可能。
/// 
/// ****************************************************************************

#include "../Win/Base/CPL_WIN_Base.h"
#include "CPL_DX_Shader_VS.h"
#include "CPL_DX_Exception.h"

namespace CPL {
namespace DX {
namespace Shader {

//const int LIGHT_MAX = 8;


// _____________________________________________________________________________
/// @brief コンストラクタ　頂点シェーダー生成（メモリ読み込みversion）
/// 
/// @param[in] in_shader_code
///   : 頂点シェーダ―用コードオブジェクトを指定します。
/// @param[in] in_vertex_shader_function_name
///   : 頂点シェーダ―のメイン関数名を指定します。
/// @param[in] in_target_version
///   : 頂点シェーダ―のターゲットバージョンを指定します。\n
///   : 例 "vs_4_0"
/// @param[in] in_ptr_defines
///   : シェーダ―マクロを指定します。\n
///   : 詳しくはD3D10_SHADER_MACROで検索してください。\n
///   : 省略する場合、nullptrを指定します。
/// @param[in] in_flag_compile
///   : シェーダ―のコンパイルオプションです。\n
///   : 詳細はD3DCompileのFlags1を検索してください。
/// @param[in] in_flag_effect
///   : エフェクトのコンパイルオプションです。\n
///   : 詳細はD3DCompileのFlags2を検索してください。
/// @param[out] out_pp_error
///   : コンパイラのエラーメッセージを格納するID3D10Blobへのポインターを指定します。\n
///   : 省略する場合、nullptrを指定します。
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
VertexShader::VertexShader
( _in <VSCode            > in_shader_code
, _in <char_cptr         > in_vertex_shader_function_name
, _in <LPCSTR            > in_target_version
, pin <D3D10_SHADER_MACRO> in_ptr_defines
, _in <UINT              > in_flag_compile
, _in <UINT              > in_flag_effect
, pout<ID3DBlob*         > out_pp_error
)
{
  CPL_THROW_FAILED(
    CreateFromMemory
      ( in_shader_code
      , in_vertex_shader_function_name
      , in_target_version
      , in_ptr_defines
      , in_flag_compile
      , in_flag_effect
      , out_pp_error
      )
    , "Failed to construct VertexShader.\n"
    );
}


// _____________________________________________________________________________
/// @brief コンストラクタ　頂点シェーダ生成（ファイル読み込みversion）
/// 
/// @param[in] in_file_name
///   : 頂点シェーダ―ファイルのパスを指定します。
/// @param[in] in_vertex_shader_function_name
///   : 頂点シェーダ―のメイン関数名を指定します。
/// @param[in] in_target_version
///   : 頂点シェーダ―のターゲットバージョンを指定します。\n
///   : 例 "vs_4_0"
/// @param[in] in_ptr_defines
///   : シェーダ―マクロを指定します。\n
///   : 詳しくはD3D10_SHADER_MACROで検索してください。\n
///   : 省略する場合、nullptrを指定します。
/// @param[in] in_flag_compile
///   : シェーダ―のコンパイルオプションです。\n
///   : 詳細はD3DCompileのFlags1を検索してください。
/// @param[in] in_flag_effect
///   : エフェクトのコンパイルオプションです。\n
///   : 詳細はD3DCompileのFlags2を検索してください。
/// @param[out] out_pp_error
///   : コンパイラのエラーメッセージを格納するID3D10Blobへのポインターを指定します。\n
///   : 省略する場合、nullptrを指定します。
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
VertexShader::VertexShader
( _in <str_cptr          > in_file_name
, _in <char_cptr         > in_vertex_shader_function_name
, _in <LPCSTR            > in_target_version
, pin <D3D10_SHADER_MACRO> in_ptr_defines
, _in <UINT              > in_flag_compile
, _in <UINT              > in_flag_effect
, pout<ID3DBlob*         > out_pp_error
)
{
  CPL_THROW_FAILED
    ( CreateFromFile
        ( in_file_name
        , in_vertex_shader_function_name
        , in_target_version
        , in_ptr_defines
        , in_flag_compile
        , in_flag_effect
        , out_pp_error
        )
    , "Failed to construct VertexShader.\n"
    );
}


// _____________________________________________________________________________
/// @brief リソースの開放
/// 
/// @return なし。
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void VertexShader::Release()
{
  m_cp_vertex_shader.Release();
}


// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// 描画設定（頂点シェーダーを登録）
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
HRESULT VertexShader::RenderSetup( DXDeviceContext* in_ptr_d3d_IC )
{
  in_ptr_d3d_IC->VSSetShader( m_cp_vertex_shader, 0, 0 );

  return S_OK;
}


// _____________________________________________________________________________
/// @brief 頂点シェーダーのコンパイル（メモリ読み込みversion）
/// 
/// @param[in] in_shader_code
///   : 頂点シェーダ―用コードオブジェクトを指定します。
/// @param[in] in_vertex_shader_function_name
///   : 頂点シェーダ―のメイン関数名を指定します。
/// @param[in] in_target_version
///   : 頂点シェーダ―のターゲットバージョンを指定します。\n
///   : 例 "vs_4_0"
/// @param[in] in_ptr_defines
///   : シェーダ―マクロを指定します。\n
///   : 詳しくはD3D10_SHADER_MACROで検索してください。\n
///   : 省略する場合、nullptrを指定します。
/// @param[in] in_flag_compile
///   : シェーダ―のコンパイルオプションです。\n
///   : 詳細はD3DCompileのFlags1を検索してください。
/// @param[in] in_flag_effect
///   : エフェクトのコンパイルオプションです。\n
///   : 詳細はD3DCompileのFlags2を検索してください。
/// @param[out] out_pp_error
///   : コンパイラのエラーメッセージを格納するID3D10Blobへのポインターを指定します。\n
///   : 省略する場合、nullptrを指定します。
/// 
/// @return DirectXのリターンコード(HRESULT)を返します。
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
HRESULT
  VertexShader::CompileFromMemory
    ( _in <VSCode            > in_shader_code
    , _in <char_cptr         > in_vertex_shader_function_name
    , _in <LPCSTR            > in_target_version
    , pin <D3D10_SHADER_MACRO> in_ptr_defines
    , _in <UINT              > in_flag_compile
    , _in <UINT              > in_flag_effect
    , pout<ID3DBlob*         > out_pp_error
    )
{
  HRESULT hr =
    zzf_CompileFromMemory
      ( in_shader_code
      , in_vertex_shader_function_name
      , in_target_version
      , in_ptr_defines
      , in_flag_compile
      , in_flag_effect
      , out_pp_error
      );

  if( FAILED(hr) )
  {
    Release();
    return hr;
  }

  return hr;
}


// _____________________________________________________________________________
/// @brief 頂点シェーダーのコンパイル（ファイル読み込みversion）
/// 
/// @param[in] in_file_name
///   : 頂点シェーダ―ファイルのパスを指定します。
/// @param[in] in_vertex_shader_function_name
///   : 頂点シェーダ―のメイン関数名を指定します。
/// @param[in] in_target_version
///   : 頂点シェーダ―のターゲットバージョンを指定します。\n
///   : 例 "vs_4_0"
/// @param[in] in_ptr_defines
///   : シェーダ―マクロを指定します。\n
///   : 詳しくはD3D10_SHADER_MACROで検索してください。\n
///   : 省略する場合、nullptrを指定します。
/// @param[in] in_flag_compile
///   : シェーダ―のコンパイルオプションです。\n
///   : 詳細はD3DCompileのFlags1を検索してください。
/// @param[in] in_flag_effect
///   : エフェクトのコンパイルオプションです。\n
///   : 詳細はD3DCompileのFlags2を検索してください。
/// @param[out] out_pp_error
///   : コンパイラのエラーメッセージを格納するID3D10Blobへのポインターを指定します。\n
///   : 省略する場合、nullptrを指定します。
/// 
/// @return DirectXのリターンコード(HRESULT)を返します。
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
HRESULT
  VertexShader::CompileFromFile
    ( _in <str_cptr          > in_file_name
    , _in <char_cptr         > in_vertex_shader_function_name
    , _in <LPCSTR            > in_target_version
    , pin <D3D10_SHADER_MACRO> in_ptr_defines
    , _in <UINT              > in_flag_compile
    , _in <UINT              > in_flag_effect
    , pout<ID3DBlob*         > out_pp_error
    )
{
  HRESULT hr =
    zzf_CompileFromFile
      ( in_file_name
      , in_vertex_shader_function_name
      , in_target_version
      , in_ptr_defines
      , in_flag_compile
      , in_flag_effect
      , out_pp_error
      );

  if( FAILED(hr) )
  {
    Release();
    return hr;
  }

  return hr;
}


// _____________________________________________________________________________
/// @brief シェーダオブジェクト作成
/// 
/// @copydetails CompileFromMemory
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
HRESULT
  VertexShader::CreateFromMemory
    ( _in <VSCode            > in_shader_code
    , _in <char_cptr         > in_vertex_shader_function_name
    , _in <LPCSTR            > in_target_version
    , pin <D3D10_SHADER_MACRO> in_ptr_defines
    , _in <UINT              > in_flag_compile
    , _in <UINT              > in_flag_effect
    , pout<ID3DBlob*         > out_pp_error
    )
{
  // コンパイル
  HRESULT hr;
  
  hr =
    CompileFromMemory
      ( in_shader_code
      , in_vertex_shader_function_name
      , in_target_version
      , in_ptr_defines
      , in_flag_compile
      , in_flag_effect
      , out_pp_error
      );

  if( FAILED(hr) )
  {
    return hr;
  }
  // 頂点シェーダー作成
  hr =
    Graphics_i_::GetDevice()->CreateVertexShader
      ( m_cp_dx_blob->GetBufferPointer()
      , m_cp_dx_blob->GetBufferSize()
      , nullptr
      , &m_cp_vertex_shader
      );

  if( FAILED(hr) )
  {
    Release();
  }
  return hr;
}


// _____________________________________________________________________________
/// @brief シェーダオブジェクト作成
/// 
/// @copydetails CompileFromFile
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
HRESULT
  VertexShader::CreateFromFile
    ( _in <str_cptr          > in_file_name
    , _in <char_cptr         > in_vertex_shader_function_name
    , _in <LPCSTR            > in_target_version
    , pin <D3D10_SHADER_MACRO> in_ptr_defines
    , _in <UINT              > in_flag_compile
    , _in <UINT              > in_flag_effect
    , pout<ID3DBlob*         > out_pp_error
    )
{
  HRESULT hr =
    CompileFromFile
      ( in_file_name
      , in_vertex_shader_function_name
      , in_target_version
      , in_ptr_defines
      , in_flag_compile
      , in_flag_effect
      , out_pp_error
      );
  if( FAILED(hr) )
  {
    return hr;
  }
  // 頂点シェーダー作成
  hr =
    Graphics_i_::GetDevice()->CreateVertexShader
      ( m_cp_dx_blob->GetBufferPointer()
      , m_cp_dx_blob->GetBufferSize()
      , nullptr
      , &m_cp_vertex_shader
      );

  if( FAILED(hr) )
  {
    Release();
  }
  return hr;
}





// _____________________________________________________________________________
/// @brief コンストラクタ
/// 
/// @param[in] in_vertex_shader_function_name
///   : 頂点シェーダ―のメイン関数名を指定します。
/// @param[in] in_VSCFC
///   : シェーダコードフラグメントコレクションを指定します。\n
///   : 詳しくはCodeFragmentCollectionを参照してください。
/// @param[in] in_semantic
///   : 頂点シェーダー関数のセマンティクスを指定します。
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
VSCode::VSCode
( _in<char_cptr             > in_vertex_shader_function_name
, _in<CodeFragmentCollection> in_VSCFC
, _in<CodeItem::Semantic    > in_semantic
)
{
  Create( in_vertex_shader_function_name, in_VSCFC );
}



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