/// ****************************************************************************
/// @file   
/// @author Dr.Neeton
/// @date   200X/X/X - 2016/12/09
/// 
/// @brief  DirectX スプライト周り。
/// 
/// ****************************************************************************


#include "../Win/Base/CPL_WIN_Base.h"
#include "CPL_DX_Sprite.h"
#include "CPL_DX_SamplerState.h"
#include "CPL_DX_RasterizerState.h"
#include "CPL_DX_BlendState.h"
#include "CPL_DX_DepthStencilState.h"

namespace CPL {
namespace DX {


// _____________________________________________________________________________
/// @brief コピーコンストラクタ。
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
RectColor4P::RectColor4P( cref<RectColor4P> in_dcr4p )
{
  color[ 0 ] = in_dcr4p.color[ 0 ];
  color[ 1 ] = in_dcr4p.color[ 1 ];
  color[ 2 ] = in_dcr4p.color[ 2 ];
  color[ 3 ] = in_dcr4p.color[ 3 ];
}

// _____________________________________________________________________________
/// @brief コンストラクタ（１色カラー）。
/// 
/// @param[in] in_color : カラー値を指定（４点全てがこの色に設定される）
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
RectColor4P::RectColor4P( _in<ColorType> in_color )
{
  color[0] = color[1] = color[2] = color[3] = in_color;
}

// _____________________________________________________________________________
/// @brief コンストラクタ（全要素共通指定）。
/// 
/// @param[in] in_value : １要素の値を指定。（４点の全要素がこの値に設定される）
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
RectColor4P::RectColor4P( _in<float> in_value )
{
  color[0] = color[1] = color[2] = color[3] = in_value;
}

// _____________________________________________________________________________
/// @brief コンストラクタ（２色グラデーション）。
/// 
/// @param[in] in_color0 : 右もしくは上側のカラー。
/// @param[in] in_color1 : 左もしくは下側のカラー。
/// @param[in] in_gradation_type
///   : グラデーションのタイプ。\n 0:横　1:縦　2:左上から右下　3:右上から左下
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
RectColor4P::RectColor4P
( _in<ColorType> in_color0
, _in<ColorType> in_color1
, _in<int      > in_gradation_type
)
{
  switch( in_gradation_type )
  {
  case 0: // 横
    color[0] = color[2] = in_color0;
    color[1] = color[3] = in_color1;
    break;

  case 1: // 縦
    color[0] = color[1] = in_color0;
    color[2] = color[3] = in_color1;
    break;

  case 2:
    color[0] = in_color0;
    color[1] =
    color[2] = (in_color0 + in_color1) / 2.0f;
    color[3] = in_color1;
    break;

  case 3:
    color[1] = in_color0;
    color[0] =
    color[3] = (in_color0 + in_color1) / 2.0f;
    color[2] = in_color1;
    break;
  }
}
  
// _____________________________________________________________________________
/// @brief コンストラクタ（４点指定）。
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
RectColor4P::RectColor4P
( _in<ColorType> in_color0
, _in<ColorType> in_color1
, _in<ColorType> in_color2
, _in<ColorType> in_color3
)
{
  color[0] = in_color0;
  color[1] = in_color1;
  color[2] = in_color2;
  color[3] = in_color3;
}


// _____________________________________________________________________________
/// @brief コンストラクタ（U32x4仕様）。
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
RectColor4P::RectColor4P( _in<U32x4> in_color )
{
  CPL_LOOP2( 4, idx )
  {
    color[idx].r = ((U8*)&in_color.p[idx])[0] / 255.0f;
    color[idx].g = ((U8*)&in_color.p[idx])[1] / 255.0f;
    color[idx].b = ((U8*)&in_color.p[idx])[2] / 255.0f;
    color[idx].a = ((U8*)&in_color.p[idx])[3] / 255.0f;
  }
}


// _____________________________________________________________________________
/// @brief U32x4形式で取得。
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void RectColor4P::ConvertColor_to_U32x4( rout<U32x4> out_color ) const
{
  CPL_LOOP2( 4, idx )
  {
    U8x4 tmp_color =
    { (U8)Clamp((int)(color[idx].r * 255.0f), 0, 255)
    , (U8)Clamp((int)(color[idx].g * 255.0f), 0, 255)
    , (U8)Clamp((int)(color[idx].b * 255.0f), 0, 255)
    , (U8)Clamp((int)(color[idx].a * 255.0f), 0, 255)
    };
    out_color.p[idx] = *(U32*)&tmp_color;
  }
}


// _____________________________________________________________________________
/// @brief 反対色を取得。
/// 
/// ※ アルファ値は変更しない。
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void RectColor4P::ConvertColor_to_Reverse( rout<RectColor4P> out_color ) const
{
  CPL_LOOP2( 4, idx )
  {
    out_color.color[idx].r = 1.0f - out_color.color[idx].r;
    out_color.color[idx].g = 1.0f - out_color.color[idx].g;
    out_color.color[idx].b = 1.0f - out_color.color[idx].b;
  }
}







typedef Math::D2<float>::Matrix Mtx2D;

// _____________________________________________________________________________
/// @brief スプライトマネージャ用頂点宣言。
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Layout::Buffer const& SDM_VertexLayout()
{
  static Layout::Buffer
    layout_buf
      ( Layout::VtxElmXYZW() +
        Layout::VtxElmDiffuse() +
        Layout::VtxElmTex0()
      ); // x,y,z,w,color,tex
  return layout_buf;
}


// _____________________________________________________________________________
/// @brief アルファ有り用頂点シェーダーフラグメント
///
// *****************************************************************************
class CustomVS_VPos_to_TexCoord1
  : public Shader::VSF::ImmediateTextureCoord
{
public:
  CustomVS_VPos_to_TexCoord1( int in_input_No, int in_output_No )
    : Shader::VSF::ImmediateTextureCoord( in_input_No, in_output_No )
  {
  }
};


// _____________________________________________________________________________
/// @brief アルファ有り用ピクセルシェーダフラグメント
/// 
/// ※ ２枚のテクスチャ（テクスチャ×バックバッファサーフェイス）のブレンディング。
///
// *****************************************************************************
class CustomPS_BlendAlphaTexture
  : public Shader::PSF::Texture
{
public:
  CustomPS_BlendAlphaTexture()
    : Shader::PSF::Texture(2) {}

  void SetupImplement(){}

  // 本来、関数呼び出し処理を記述するが、直接処理を記述しています。
  void On_CallFunction( ss& out_statement, Shader::CodeItemSet const& in_parameter )
  {
    css16
      src_color("src_color"),
      dest_color("dest_color");

    out_statement,
      float4_, src_color  = tex2D( kw_g_sampler[ 0 ], ss(kw_in_texcoord,0) ), Ends,
      float4_, dest_color = tex2D( kw_g_sampler[ 1 ], ss(kw_in_texcoord,1) ), Ends,
      ss(kw_out_target,0).rgb() =
        dest_color.rgb() * &(css16(1.0f) - src_color.a()) +
        src_color.rgb() * src_color.a(), Ends,
      ss(kw_out_target,0).a() =
        dest_color.a() + &(css16(1.0f) - dest_color.a()) * src_color.a(), Ends;
  }
};



// _____________________________________________________________________________
/// @brief スプライト描画マネージャ、実装クラス
/// 
/// 2013/11/21
/// 旧仕様ではデータ量削減のためスプライト情報クラスを独自に定義し保持していたが、
/// スプライト仕様の拡張(４点カラー対応)によりデータ量の違いが小さくなったため、
/// ポリゴンデータをそのまま保持する仕様に変更する。
///
// *****************************************************************************
class SpriteDrawManager::Entity
{
  friend class SpriteDrawManager;
  // _____________________________________________________________________________
  /// @brief 頂点データクラス。
  ///
  // *****************************************************************************
  struct DrawVtx_ {
    Vtx::XYZWCT1 vtx[4];

    DrawVtx_
      ( cref<float4>      in_rect_xy
      , cref<float4>      in_rect_uv
      , float             in_Z
      , cref<RectColor4P> in_color
      , cref<float2>      in_tex_size
      );

    DrawVtx_
      ( cref<Mtx2D>       in_mtx
      , cref<float4>      in_rect_uv
      , float             in_Z
      , cref<RectColor4P> in_color
      , cref<float2>      in_tex_size
      );
    DrawVtx_(){}
  };

  // _____________________________________________________________________________
  /// @brief テクスチャ毎のスプライトリスト
  ///
  // *****************************************************************************
  struct DrawTexSprList
  {
    DxSRV*                m_ptr_SRV_texture; ///< テクスチャリソースのポインタ。
    float2                m_texture_size;    ///< テクスチャサイズ（少しでも高速化用）
    std::vector<DrawVtx_> m_vtx_table;

    // _____________________________________________________________________________
    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    DrawTexSprList()
      : m_ptr_SRV_texture( nullptr )
    {}
    // _____________________________________________________________________________
    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    DrawTexSprList( DxSRV* in_ptr_tex )
      : m_ptr_SRV_texture( in_ptr_tex )
      //, m_vtx_table( 32 )
    {
      m_vtx_table.reserve( 32 );

      if( m_ptr_SRV_texture )
      {
        m_ptr_SRV_texture->AddRef();

        // シェーダーリソースビュー情報を取得
        D3D11_SHADER_RESOURCE_VIEW_DESC desc_SRV;
        m_ptr_SRV_texture->GetDesc( &desc_SRV );
        if( desc_SRV.ViewDimension != D3D_SRV_DIMENSION_TEXTURE2D )
        {
          // シェーダーリソースが２Dテクスチャでなければ処理しない。
          CPL_THROW("テクスチャとしてサポートしていないリソースです。");
        }
        // テクスチャ取得
        CpDXResource cp_tex_resource;
        m_ptr_SRV_texture->GetResource( &cp_tex_resource );
        DX_TEXTURE2D_DESC desc_tex2D;
        DXTexture2D* ptr_texture = static_cast<DXTexture2D*>(&*cp_tex_resource);
        ptr_texture->GetDesc( &desc_tex2D );
        //
        m_texture_size.x = static_cast<float>(desc_tex2D.Width);
        m_texture_size.y = static_cast<float>(desc_tex2D.Height);
      }
    }

    // _____________________________________________________________________________
    /// @brief デストラクタ。
    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    ~DrawTexSprList()
    {
      RELEASE( m_ptr_SRV_texture );
    }
    
    // _____________________________________________________________________________
    /// @brief コピー処理。
    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    void operator = ( DrawTexSprList const& in_tsl )
    {
      if( m_ptr_SRV_texture != in_tsl.m_ptr_SRV_texture )
      {
        RELEASE( m_ptr_SRV_texture );
      }
      m_ptr_SRV_texture = in_tsl.m_ptr_SRV_texture;
      m_texture_size    = in_tsl.m_texture_size;
      m_vtx_table       = in_tsl.m_vtx_table;
      if( m_ptr_SRV_texture )
      {
        m_ptr_SRV_texture->AddRef();
      }
    }
  };

  // スプライト用レンダーコレクション
  CPL_SINGLETON( RenderCollection, sm_RC_common )

  // スプライトデータテーブル
  Core::Array::Dynamic<DrawTexSprList> m_sprite_table;
  // 頂点バッファ
  sdptr<Buffer::DynamicEX_Vertex>      m_sp_vtx_buf;
  // インデックスバッファ
  sdptr<Buffer::DynamicEX_Index>       m_sp_idx_buf;

  // _____________________________________________________________________________
  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  bool
    Draw_IsClipping
      ( _in<DrawVtx_   > in_vtx_data
      , pin<float4     > in_rect_clip
      , pin<DX_VIEWPORT> in_viewport_table
      , _in<int        > in_viewport_idx = 0
      ) const;

  // _____________________________________________________________________________
  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  void
    Draw
      ( _in<DxSRV*> in_ptr_texture
      , _in<float > in_X
      , _in<float > in_Y
      , _in<float > in_U
      , _in<float > in_V
      , _in<float > in_W
      , _in<float > in_H
      , _in<float > in_Z
      , pin<float4> in_ptr_rect_clip = nullptr
      );

  // _____________________________________________________________________________
  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  void Draw
    ( _in<DxSRV*     > in_ptr_texture
    , _in<Mtx2D      > in_mtx
    , _in<float4     > in_rect_uv
    , _in<float      > in_Z
    , _in<RectColor4P> in_color4p
    , pin<float4     > in_ptr_rect_clip = nullptr
    );

  // _____________________________________________________________________________
  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  void Transrate( _in<bool> in_flag_order );

  // _____________________________________________________________________________
  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  static int staticInitialize_();

public:
  // _____________________________________________________________________________
  /// @brief デフォルトコンストラクタ。
  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  Entity()
    : m_sprite_table( ReserveSize(4) )
  {
    m_sp_vtx_buf = CPL_MAKE_SHARED(Buffer::DynamicEX_Vertex);
    m_sp_idx_buf = CPL_MAKE_SHARED(Buffer::DynamicEX_Index);
  }

  // _____________________________________________________________________________
  /// @brief コンストラクタ。
  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  Entity( Entity const& in_sdm_enitty )
  {
    m_sprite_table = in_sdm_enitty.m_sprite_table;
  }
};







// _____________________________________________________________________________
/// @brief 静的な初期化。
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
int SpriteDrawManager::Entity::staticInitialize_()
{
  static int f_init = false;

  if( !f_init )
  {
    try {
      char_cptr vs_func_name = "VS_Main";
      char_cptr ps_func_name = "PS_Main";
      // アルファなしバッファへのレンダリング用頂点シェーダー
      Shader::CodeFragmentCollection
        vs_code_frgm =
          Shader::VSF::VertexLayout( SDM_VertexLayout() ) +
          Shader::VSF::ImmediateInputPositionT( 0 ) +
          Shader::VSF::ImmediateInputColor( 0, 0 ) +
          Shader::VSF::ImmediateTextureCoord( 0, 0 );
      Shader::VSCode vs_code( vs_func_name, vs_code_frgm );
      auto sp_VS = CPL_MAKE_SHARED( Shader::VertexShader, vs_code, vs_func_name );

      // 入力レイアウト作成
      auto sp_IL =
        CPL_MAKE_SHARED( Layout::Input, SDM_VertexLayout(), sp_VS->GetDXBlob() );

      // アルファなしバッファレンダリング用ピクセルシェーダ
      Shader::CodeFragmentCollection
        ps_code_frgm =
          Shader::PSF::Input_SV_Position() +
          //Shader::PSF::ImmediateInputColor() +
          Shader::PSF::Texture( 1 );
      Shader::PSCode ps_code( ps_func_name, ps_code_frgm );
      auto sp_PS = CPL_MAKE_SHARED( Shader::PixelShader, ps_code, ps_func_name );

      // 頂点バッファ作成
      //Buffer::Interface_::SpRefCnt sp_VB( new Buffer::DynamicEX_Vertex() );

      // インデックスバッファ作成
      //Buffer::Interface_::SpRefCnt sp_IB( new Buffer::DynamicEX_Index() );
    
      // サンプラ設定
      DX_SAMPLER_DESC desc_SS;
      memset( &desc_SS, 0, sizeof(desc_SS) );
      desc_SS.Filter         = D3D11_FILTER_MIN_MAG_MIP_LINEAR;
      desc_SS.AddressU       = D3D11_TEXTURE_ADDRESS_WRAP;
      desc_SS.AddressV       = D3D11_TEXTURE_ADDRESS_WRAP;
      desc_SS.AddressW       = D3D11_TEXTURE_ADDRESS_WRAP;
      desc_SS.ComparisonFunc = D3D11_COMPARISON_NEVER;
      desc_SS.MinLOD         = 0;
      desc_SS.MaxLOD         = D3D11_FLOAT32_MAX;
      auto sp_SS = CPL_MAKE_SHARED( SamplerState, desc_SS );
      // 描画指示
      //DrawIndexedOperator::SpLinked sp_DIO( new DrawIndexedOperator() );
      //sp_DIO->SetPrimType( D3DPT_TRIANGLELIST );

      // ラスタライザ設定
      DX_RASTERIZER_DESC desc_RS = {
        D3D11_FILL_SOLID, // D3D11_FILL_MODE FillMode;
        D3D11_CULL_NONE,  // D3D11_CULL_MODE CullMode;
        true,             // BOOL FrontCounterClockwise;
        0,                // INT DepthBias;
        0,                // FLOAT DepthBiasClamp;
        0,                // FLOAT SlopeScaledDepthBias;
        true,             // BOOL DepthClipEnable;
        false,            // BOOL ScissorEnable;
        false,            // BOOL MultisampleEnable;
        false             // BOOL AntialiasedLineEnable;
      };
      auto sp_RS = CPL_MAKE_SHARED( RasterizerState, desc_RS );

      // ブレンド設定
      DX_BLEND_DESC desc_BS;
      desc_BS.AlphaToCoverageEnable                 = FALSE;
      desc_BS.IndependentBlendEnable                = FALSE;
      desc_BS.RenderTarget[0].BlendEnable           = true;
      desc_BS.RenderTarget[0].SrcBlend              = D3D11_BLEND_SRC_ALPHA;
      desc_BS.RenderTarget[0].DestBlend             = D3D11_BLEND_INV_SRC_ALPHA;
      desc_BS.RenderTarget[0].BlendOp               = D3D11_BLEND_OP_ADD;
      desc_BS.RenderTarget[0].SrcBlendAlpha         = D3D11_BLEND_SRC_ALPHA;
      desc_BS.RenderTarget[0].DestBlendAlpha        = D3D11_BLEND_ONE;
      desc_BS.RenderTarget[0].BlendOpAlpha          = D3D11_BLEND_OP_ADD;
      desc_BS.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;
      auto sp_BS = CPL_MAKE_SHARED( BlendState, desc_BS );

      // デプスステンシルステートの作成。
      DX_DEPTH_STENCIL_DESC desc_ds = {
        TRUE,                             // BOOL DepthEnable;
        D3D11_DEPTH_WRITE_MASK_ALL,       // D3D11_DEPTH_WRITE_MASK DepthWriteMask;
        D3D11_COMPARISON_LESS_EQUAL,      // D3D11_COMPARISON_FUNC DepthFunc;
        FALSE,                            // BOOL StencilEnable;
        D3D11_DEFAULT_STENCIL_READ_MASK,  // UINT8 StencilReadMask;
        D3D11_DEFAULT_STENCIL_WRITE_MASK, // UINT8 StencilWriteMask;
        {D3D11_STENCIL_OP_KEEP,D3D11_STENCIL_OP_KEEP,D3D11_STENCIL_OP_KEEP,D3D11_COMPARISON_ALWAYS},// D3D11_DEPTH_STENCILOP_DESC FrontFace;
        {D3D11_STENCIL_OP_KEEP,D3D11_STENCIL_OP_KEEP,D3D11_STENCIL_OP_KEEP,D3D11_COMPARISON_ALWAYS},//D3D11_DEPTH_STENCILOP_DESC BackFace;
      };
      auto sp_DSS = CPL_MAKE_SHARED( DepthStencilState, desc_ds );

      // レンダーコレクションに登録
      sm_RC_common()
        << sp_IL  // 頂点レイアウト
        << sp_VS  // 頂点シェーダー
        << sp_PS  // ピクセルシェーダ
        << sp_SS  // サンプラ
        << sp_RS  // ラスタライザ
        << sp_BS  // ブレンディング
        << sp_DSS // 深度ステンシル
        //<< sp_VB  // 頂点バッファマネージャ
        //<< sp_IB; // インデックスバッファ
        //<< SDM_RSTs()  // レンダーステート
        //<< sp_DIO;     // 描画指示
        ;

      f_init = true;
    }
    catch(...)
    {
      CPL_BREAK(true);
    }
  }

  return true;
}


// _____________________________________________________________________________
/// @brief スプライト用頂点データのコンストラクタ。
/// 
/// @param[in] in_rect_xy : 対角スクリーン座標(無回転時)をピクセル単位で指定。
/// @param[in] in_rect_uv : 対角ＵＶ座標。
/// @param[in] in_Z       : 深度。
/// @param[in] in_color   : ４点カラー（float4×4）
/// @param[in] in_tex_w   : テクスチャの横幅。
/// @param[in] in_tex_h   : テクスチャの縦幅。
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
SpriteDrawManager::Entity::DrawVtx_::DrawVtx_
( cref<float4>      in_rect_xy
, cref<float4>      in_rect_uv
, float             in_Z
, cref<RectColor4P> in_color
, cref<float2>      in_tex_size
)
{
  UINT num = 1;
  DX_VIEWPORT vp;
  Graphics_i_::GetImmediateContext()->RSGetViewports( &num, &vp );
  float a_scw =  2.0f / vp.Width;  // １ピクセル当たりの横幅。
  float a_sch = -2.0f / vp.Height; // １ピクセル当たりの縦幅。
  float tex_w_ = 1.0f / in_tex_size.x;  // 
  float tex_h_ = 1.0f / in_tex_size.y;  // 
  //float4 const
  //  rect_xy
  //  { in_rect_xy.left   - 0.5f
  //  , in_rect_xy.top    - 0.5f
  //  , in_rect_xy.right  - 0.5f
  //  , in_rect_xy.bottom - 0.5f
  //  };
  float4 const& rect_xy = in_rect_xy;
  //float4 const
  //  rect_uv
  //  { in_rect_uv.left   + 0.5f
  //  , in_rect_uv.top    + 0.5f
  //  , in_rect_uv.right  + 0.5f
  //  , in_rect_uv.bottom + 0.5f
  //  };
  float4 const& rect_uv = in_rect_uv;

  vtx[0] =
    Vtx::XYZWCT1
      ( rect_xy.left * a_scw - 1.0f
      , rect_xy.top  * a_sch + 1.0f
      , in_Z
      , 1.0f
      , in_color.color[0]
      , rect_uv.left * tex_w_
      , rect_uv.top  * tex_h_
      );
  vtx[1] =
    Vtx::XYZWCT1
      ( rect_xy.right * a_scw - 1.0f
      , rect_xy.top   * a_sch + 1.0f
      , in_Z
      , 1.0f
      , in_color.color[1]
      , rect_uv.right * tex_w_
      , rect_uv.top   * tex_h_
      );
  vtx[2] =
    Vtx::XYZWCT1
      ( rect_xy.left   * a_scw - 1.0f
      , rect_xy.bottom * a_sch + 1.0f
      , in_Z
      , 1.0f
      , in_color.color[2]
      , rect_uv.left   * tex_w_
      , rect_uv.bottom * tex_h_
      );
  vtx[3] =
    Vtx::XYZWCT1
      ( rect_xy.right  * a_scw - 1.0f
      , rect_xy.bottom * a_sch + 1.0f
      , in_Z
      , 1.0f
      , in_color.color[3]
      , rect_uv.right  * tex_w_
      , rect_uv.bottom * tex_h_
      );
}

// _____________________________________________________________________________
/// @brief スプライト用頂点データのコンストラクタ。
/// 
/// @param[in] in_mtx     : 頂点変換マトリクス。
/// @param[in] in_rect_uv : 対角ＵＶ座標。
/// @param[in] in_Z       : 深度。
/// @param[in] in_color   : ４点カラー（float4×4）
/// @param[in] in_tex_w   : テクスチャの横幅。
/// @param[in] in_tex_h   : テクスチャの縦幅。
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
SpriteDrawManager::Entity::DrawVtx_::DrawVtx_
( cref<Mtx2D>       in_mtx
, cref<float4>      in_rect_uv
, float             in_Z
, cref<RectColor4P> in_color
, cref<float2>      in_tex_size )
{
  UINT num = 1;
  DX_VIEWPORT vp;
  Graphics_i_::GetImmediateContext()->RSGetViewports( &num, &vp );
  float a_scw =  2.0f / vp.Width;  // １ピクセル当たりの横幅。
  float a_sch = -2.0f / vp.Height; // １ピクセル当たりの縦幅。
  float tex_w_ = 1.0f / in_tex_size.x;  // 
  float tex_h_ = 1.0f / in_tex_size.y;  // 
  //float4 const
  //  rect_uv
  //  { in_rect_uv.left   + 0.5f
  //  , in_rect_uv.top    + 0.5f
  //  , in_rect_uv.right  + 0.5f
  //  , in_rect_uv.bottom + 0.5f
  //  };
  float4 const& rect_uv = in_rect_uv;

  float2 p0( 0.0f, 0.0f );
  float2 p1( 1.0f, 0.0f );
  float2 p2( 0.0f, 1.0f );
  float2 p3( 1.0f, 1.0f );

  // 頂点変換
  Math::D2<float>::VecTransform( p0, in_mtx );
  Math::D2<float>::VecTransform( p1, in_mtx );
  Math::D2<float>::VecTransform( p2, in_mtx );
  Math::D2<float>::VecTransform( p3, in_mtx );
  //p0.x -= 0.5f;
  //p0.y -= 0.5f;
  //p1.x -= 0.5f;
  //p1.y -= 0.5f;
  //p2.x -= 0.5f;
  //p2.y -= 0.5f;
  //p3.x -= 0.5f;
  //p3.y -= 0.5f;

  vtx[0] =
    Vtx::XYZWCT1
      ( p0.x * a_scw - 1.0f
      , p0.y * a_sch + 1.0f
      , in_Z
      , 1.0f
      , in_color.color[0]
      , rect_uv.left * tex_w_
      , rect_uv.top  * tex_h_
      );
  vtx[1] =
    Vtx::XYZWCT1
      ( p1.x * a_scw - 1.0f
      , p1.y * a_sch + 1.0f
      , in_Z
      , 1.0f
      , in_color.color[1]
      , rect_uv.right * tex_w_
      , rect_uv.top   * tex_h_
      );
  vtx[2] =
    Vtx::XYZWCT1
      ( p2.x * a_scw - 1.0f
      , p2.y * a_sch + 1.0f
      , in_Z
      , 1.0f
      , in_color.color[2]
      , rect_uv.left   * tex_w_
      , rect_uv.bottom * tex_h_
      );
  vtx[3] =
    Vtx::XYZWCT1
      ( p3.x * a_scw - 1.0f
      , p3.y * a_sch + 1.0f
      , in_Z
      , 1.0f
      , in_color.color[3]
      , rect_uv.right  * tex_w_
      , rect_uv.bottom * tex_h_
      );
}


// _____________________________________________________________________________
/// @brief クリッピングチェック。
/// 
/// @param[in] in_vtx_data
///   : 頂点データオブジェクト。
/// @param[in] in_ptr_rect_clip
///   : クリッピング対象の矩形座標(float4)へのポインタ。
///   : nullptrが渡されると必ずfalseを返す。
/// @param[in] in_viewport_table
///   : ビューポート配列(もしくは１つ)へのポインタ。
/// @param[in] in_viewport_idx
///   : 使用するビューポートの配列インデックス。
/// 
/// @retval true  : クリッピングされた。
/// @retval false : クリッピングされない（矩形範囲内）。
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
bool
  SpriteDrawManager::Entity::Draw_IsClipping
    ( _in<DrawVtx_   > in_vtx_data
    , pin<float4     > in_ptr_rect_clip
    , pin<DX_VIEWPORT> in_viewport_table
    , _in<int        > in_viewport_idx
    ) const
{
  if( in_ptr_rect_clip == nullptr )
  {
    return false;
  }

  static DX_VIEWPORT vp_default; // デフォルトのビューポート保存用。
  DX_VIEWPORT const* vp_table = &vp_default;
  int vp_idx = 0;
  if( in_viewport_table )
  {
    vp_table = in_viewport_table;
    vp_idx   = in_viewport_idx;
  }
  else
  {
    UINT num = 1;
    Graphics_i_::GetImmediateContext()->RSGetViewports( &num, &vp_default );
  }
  float scale_x = vp_table[ vp_idx ].Width * 0.5f;
  float scale_y = -vp_table[ vp_idx ].Height * 0.5f;

  // 範囲外チェック。
  if( in_ptr_rect_clip->left   > (in_vtx_data.vtx[1].x + 1) * scale_x
   || in_ptr_rect_clip->right  < (in_vtx_data.vtx[0].x + 1) * scale_x
   || in_ptr_rect_clip->top    > (in_vtx_data.vtx[2].y - 1) * scale_y
   || in_ptr_rect_clip->bottom < (in_vtx_data.vtx[0].y - 1) * scale_y )
  {
    return true; // クリッピングされた。
  }

  //
  return false;
}


// _____________________________________________________________________________
/// @brief 描画登録。
/// 
/// @param[in] in_ptr_texture : テクスチャリソースへのポインタ。
/// @param[in] in_X : スプライトのｘ座標（ターゲットのピクセル単位）
/// @param[in] in_Y : スプライトのｙ座標（ターゲットのピクセル単位）
/// @param[in] in_U : テクスチャのＵ座標（テクスチャピクセル単位）
/// @param[in] in_V : テクスチャのＶ座標（テクスチャピクセル単位）
/// @param[in] in_W : スプライトの横幅（ピクセル単位、テクスチャの使用範囲にもなる）
/// @param[in] in_H : スプライトの縦幅（ピクセル単位、テクスチャの使用範囲にもなる）
/// @param[in] in_Z : ｚ深度。
/// @param[in] in_ptr_rect_clip
///   : クリップ矩形(float4型)のポインタを指定。\n
///   : nullptrでクリップしない。
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void
  SpriteDrawManager::Entity::Draw
    ( _in<DxSRV*> in_ptr_texture
    , _in<float > in_X
    , _in<float > in_Y
    , _in<float > in_U
    , _in<float > in_V
    , _in<float > in_W
    , _in<float > in_H
    , _in<float > in_Z
    , pin<float4> in_ptr_rect_clip
    )
{
  // クリッピングチェック。
  if( in_ptr_rect_clip )
  {
    if( in_ptr_rect_clip->left   > in_X + in_W
     || in_ptr_rect_clip->right  < in_X
     || in_ptr_rect_clip->top    > in_Y + in_H
     || in_ptr_rect_clip->bottom < in_Y        )
    {
      return;
    }
  }

  //
  static const ColorType
    color_white( 1.0f, 1.0f, 1.0f, 1.0f );
  static const RectColor4P
    color_white_4p( color_white, color_white, color_white, color_white );
  
  // テクスチャ毎スプライトリストのポインタ。
  // これに追加するテクスチャ毎スプライトリストを設定する。
  DrawTexSprList* ptr_dtsl = nullptr;
  // テクスチャ比較
  size_t tex_num = m_sprite_table.GetNum();
  //CPL_LOOP2( tex_num, i )
  for( decltype(tex_num) i = 0; i < tex_num; ++i )
  {
    auto& spr = m_sprite_table[ i ];
    if( spr.m_ptr_SRV_texture == in_ptr_texture )
    {
      ptr_dtsl = &spr;
      break;
    }
  }
  
  // 該当するテクスチャ毎スプライトリストがない場合、新しく生成して配列に追加する。
  if( ptr_dtsl == nullptr )
  {
    ptr_dtsl = m_sprite_table.AddEnd( DrawTexSprList( in_ptr_texture ) );
  }

  // 頂点データ生成。
  DrawVtx_
    vtx( float4( in_X, in_Y, in_X+in_W, in_Y+in_H )
       , float4( in_U, in_V, in_U+in_W, in_V+in_H )
       , in_Z
       , color_white_4p
       , ptr_dtsl->m_texture_size
       );

  // クリッピングチェック。
  // クリッピング矩形が指定されていない場合、
  // もしくはクリッピング矩形内に含まれる場合に頂点データを追加する。
  if( !Draw_IsClipping( vtx, in_ptr_rect_clip, nullptr ) )
  {
    // 頂点データ追加。
    ptr_dtsl->m_vtx_table.push_back( vtx );
  }
}



// _____________________________________________________________________________
/// @brief 描画登録　２Ｄマトリクス・カラー、拡張版。
/// 
/// @param[in] in_ptr_texture : テクスチャリソースへのポインタ。
/// @param[in] in_mtx
///   : 描画座標変換用の２Ｄマトリクス。\n
///   : 座標（0,0 - 1,1）のスプライト座標を変換する値となる。
/// @param[in] in_rect_uv
///   : テクスチャの対角のＵＶ座標が格納されたfloat4型への参照（ピクセル単位）
/// @param[in] in_Z       : ｚ深度。
/// @param[in] in_color   : ４点カラー。
/// @param[in] in_ptr_rect_clip
///   : クリップ矩形(float4型)のポインタを指定。\n
///   : nullptrでクリップしない。
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void
  SpriteDrawManager::Entity::Draw
    ( _in<DxSRV*     > in_ptr_texture
    , _in<Mtx2D      > in_mtx
    , _in<float4     > in_rect_uv
    , _in<float      > in_Z
    , _in<RectColor4P> in_color
    , pin<float4     > in_ptr_rect_clip
    )
{
  // テクスチャ毎スプライトリストのポインタ。
  // これに追加するテクスチャ毎スプライトリストを設定する。
  DrawTexSprList* ptr_dtsl = nullptr;

  // 既存テクスチャリストのチェック。
  size_t tex_num = m_sprite_table.GetNum();
  //CPL_LOOP2( tex_num, idx )
  for( decltype(tex_num) idx = 0; idx < tex_num; ++idx )
  {
    auto& spr = m_sprite_table[ idx ];

    if( spr.m_ptr_SRV_texture == in_ptr_texture )
    {
      // テクスチャ毎スプライトリストのポインタを設定してループを抜ける。
      ptr_dtsl = &spr;
      break;
    }
  }

  // 該当するテクスチャ毎スプライトリストがない場合、新しく生成して配列に追加する。
  if( ptr_dtsl == nullptr )
  {
    ptr_dtsl = m_sprite_table.AddEnd( DrawTexSprList( in_ptr_texture ) );
  }

  // 頂点データの作成。
  DrawVtx_
    vtx( in_mtx
       , in_rect_uv
       , in_Z
       , in_color
       , ptr_dtsl->m_texture_size
       );

  // クリッピングチェック。
  // クリッピング矩形が指定されていない場合、
  // もしくはクリッピング矩形内に含まれる場合に頂点データを追加する。
  if( !Draw_IsClipping( vtx, in_ptr_rect_clip, nullptr ) )
  {
    // 頂点データ追加。
    ptr_dtsl->m_vtx_table.push_back( vtx );
  }
}


// _____________________________________________________________________________
/// @brief 登録スプライトのプリミティブ転送。
/// 
/// @param[in] in_flag_order : false（昇順）　true（降順）
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void SpriteDrawManager::Entity::Transrate( _in<bool> in_flag_order )
{
  static int f_init = staticInitialize_(); (void)f_init;

  SDEF spr_tbl_num = static_cast<SDEF>(m_sprite_table.GetNum());
  if( spr_tbl_num == 0 )
  {
    return;
  }

  CpDXDeviceContext cp_IC = Graphics_i_::GetImmediateContext();
  cp_IC->IASetPrimitiveTopology( D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST );

  // 描画設定
  sm_RC_common().RenderSetup( cp_IC );
    
  const SDEF dtsl_st  = in_flag_order ? spr_tbl_num - 1 : 0;
  const SDEF dtsl_ed  = in_flag_order ? -1 : spr_tbl_num;
  const SDEF dtsl_add = in_flag_order ? -1 : 1;
  for( SDEF dtsl_idx = dtsl_st;
       dtsl_idx != dtsl_ed;
       dtsl_idx += dtsl_add )
  {
    DrawTexSprList& dtsl = m_sprite_table[ dtsl_idx ];
    if( dtsl.m_ptr_SRV_texture == nullptr )
    {
      continue;
    }

    size_t spr_num = dtsl.m_vtx_table.size();
    if( spr_num == 0 )
    {
      continue;
    }
    // 頂点バッファサイズ比較し、不足していれば拡張する。
    size_t vtx_num = m_sp_vtx_buf->GetElementNum();
    if( vtx_num != spr_num * 4 )
    {
      m_sp_vtx_buf->Create
        ( SDM_VertexLayout().GetElementsSize(0)
        , spr_num * 4
        , nullptr
        );
    }
    //ef( vtx_num < spr_num * 4 )
    //{
    //  sp_vtx_buf->Resize( spr_num * 4 );
    //  vtx_num = spr_num * 4;
    //}

    // コピー先のデータアドレスを取得。
    DrawVtx_* ptr_data = &m_sp_vtx_buf->GetElement<DrawVtx_>( 0 );
    // コピー順序判定。
    if( in_flag_order == false )
    {
      // コピー。
      memcpy
        ( ptr_data
        , &dtsl.m_vtx_table[ 0 ]
        , sizeof(DrawVtx_) * spr_num
        );
    }
    else
    {
      // コピー。
      for( auto spr_idx = spr_num; spr_idx;)
      {
        *ptr_data = dtsl.m_vtx_table[ --spr_idx ];
        ++ptr_data;
      }
    }
    // 更新通知
    m_sp_vtx_buf->Updated();

    // インデックスバッファサイズ比較
    size_t idx_num = m_sp_idx_buf->GetElementNum();
    if( idx_num != spr_num * 6 )
    {
      size_t new_idx_num = spr_num * 6;
      if( idx_num <= 0 )
      {
        m_sp_idx_buf->Create( sizeof(U32), new_idx_num, 0 );
      }
      m_sp_idx_buf->Resize( new_idx_num );
      // 新しいインデックスデータを設定
      for( size_t idx = idx_num; idx < new_idx_num; idx += 6 )
      {
        U32 vtx_idx = static_cast<U32>(idx / 6 * 4);
        U32
          add_idx_data[ 6 ] =
          { vtx_idx
          , vtx_idx + 1
          , vtx_idx + 2
          , vtx_idx + 1
          , vtx_idx + 3
          , vtx_idx + 2
          };
        m_sp_idx_buf->SetData( idx, add_idx_data, 6 );
      }
      idx_num = new_idx_num;

      // 更新通知
      m_sp_idx_buf->Updated();
    }

    //// バッファ設定
    //ptr_vsb->SetStream();
    //ptr_ib->SetIndices();

    m_sp_vtx_buf->RenderSetup( cp_IC );
    m_sp_idx_buf->RenderSetup( cp_IC );

    // テクスチャをピクセルシェーダーに設定
    cp_IC->PSSetShaderResources( 0, 1, &dtsl.m_ptr_SRV_texture );

    // 描画
    cp_IC->DrawIndexed( static_cast<U32>(idx_num), 0, 0 );
  }

//  CPL_SAFE_PTR(ptr_surf)->Release();

  //
  m_sprite_table.Release();
}






// _____________________________________________________________________________
/// @brief デフォルトコンストラクタ。
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
SpriteDrawManager::SpriteDrawManager()
  : m_sp_entity( CPL_MAKE_SHARED(Entity) )
{
}

// _____________________________________________________________________________
/// @brief コンストラクタ。
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
SpriteDrawManager::SpriteDrawManager( cref<SpriteDrawManager> in_sdm )
  : m_sp_entity( CPL_MAKE_SHARED( Entity, *in_sdm.m_sp_entity ) )
{
}


// _____________________________________________________________________________
/// @brief デストラクタ。
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
SpriteDrawManager::~SpriteDrawManager()
{
}


// _____________________________________________________________________________
/// @brief 描画登録。
/// 
/// @param[in] in_ptr_texture
///   : テクスチャリソースへのポインタ。
/// @param[in] in_X : スプライトのｘ座標（ターゲットのピクセル単位）
/// @param[in] in_Y : スプライトのｙ座標（ターゲットのピクセル単位）
/// @param[in] in_U : テクスチャのＵ座標（テクスチャピクセル単位）
/// @param[in] in_V : テクスチャのＶ座標（テクスチャピクセル単位）
/// @param[in] in_W : スプライトの横幅（ピクセル単位、テクスチャの使用範囲にもなる）
/// @param[in] in_H : スプライトの縦幅（ピクセル単位、テクスチャの使用範囲にもなる）
/// @param[in] in_Z : ｚ深度。
/// @param[in] in_ptr_rect_clip
///   : クリップ矩形(float4型)のポインタを指定。\n
///   : nullptrでクリップしない。
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void
  SpriteDrawManager::Draw
    ( _in<DxSRV*> in_ptr_texture
    , _in<float > in_X
    , _in<float > in_Y
    , _in<float > in_U
    , _in<float > in_V
    , _in<float > in_W
    , _in<float > in_H
    , _in<float > in_Z
    , pin<float4> in_ptr_rect_clip
    ) const
{
  m_sp_entity->Draw
    ( in_ptr_texture
    , in_X, in_Y, in_U, in_V
    , in_W, in_H, in_Z
    , in_ptr_rect_clip
    );
}

// _____________________________________________________________________________
/// @brief 描画登録。
/// 
/// @param[in] in_ptr_texture : テクスチャリソースへのポインタ。
/// @param[in] in_X : 描画するｘ座標（ターゲットのピクセル単位）
/// @param[in] in_Y : 描画するｙ座標（ターゲットのピクセル単位）
/// @param[in] in_rect_uv
///   : テクスチャの対角のＵＶ座標が格納されたfloat4型への参照（ピクセル単位）\n
///   : スプライトのサイズは、ＵＶのサイズと同じになる。
/// @param[in] in_Z : ｚ深度。
/// @param[in] in_ptr_rect_clip
///   : クリップ矩形(float4型)のポインタを指定。\n
///   : nullptrでクリップしない。
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void
  SpriteDrawManager::Draw
    ( _in<DxSRV*> in_ptr_texture
    , _in<float > in_X
    , _in<float > in_Y
    , _in<float4> in_rect_uv
    , _in<float > in_Z
    , pin<float4> in_ptr_rect_clip
    ) const
{
  m_sp_entity->Draw
    ( in_ptr_texture
    , in_X
    , in_Y
    , in_rect_uv.left
    , in_rect_uv.top
    , in_rect_uv.z - in_rect_uv.x
    , in_rect_uv.w - in_rect_uv.y
    , in_Z
    , in_ptr_rect_clip
    );
}

// _____________________________________________________________________________
/// @brief 描画登録　カラー・回転・拡縮、拡張版。
/// 
/// @param[in] in_ptr_texture : テクスチャリソースへのポインタ。
/// @param[in] in_X       : 描画するｘ座標（ターゲットのピクセル単位）
/// @param[in] in_Y       : 描画するｙ座標（ターゲットのピクセル単位）
/// @param[in] in_U       : テクスチャのＵ座標（テクスチャピクセル単位）
/// @param[in] in_V       : テクスチャのＶ座標（テクスチャピクセル単位）
/// @param[in] in_UW      : テクスチャのＵ方向の幅（テクスチャピクセル単位）
/// @param[in] in_VH      : テクスチャのＶ方向の幅（テクスチャピクセル単位）
/// @param[in] in_Z       : ｚ深度。
/// @param[in] in_color   : 単色カラー。
/// @param[in] in_offs_cx : in_Xを基点とする回転中心ｘ座標。
/// @param[in] in_offs_cy : in_Yを基点とする回転中心ｙ座標。
/// @param[in] in_scale_x : ｘ方向倍率。
/// @param[in] in_scale_y : ｙ方向倍率。
/// @param[in] in_R       : 回転角度（ラジアン単位）
/// @param[in] in_ptr_rect_clip
///   : クリップ矩形(float4型)のポインタを指定。\n
///   : nullptrでクリップしない。
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void
  SpriteDrawManager::Draw
    ( _in<DxSRV*     > in_ptr_texture
    , _in<float      > in_X
    , _in<float      > in_Y
    , _in<float      > in_U
    , _in<float      > in_V
    , _in<float      > in_UW
    , _in<float      > in_VH
    , _in<float      > in_Z
    , _in<RectColor4P> in_color
    , _in<float      > in_offs_cx
    , _in<float      > in_offs_cy
    , _in<float      > in_scale_x
    , _in<float      > in_scale_y
    , _in<float      > in_R
    , pin<float4     > in_ptr_rect_clip
    ) const
{
  // 頂点変換用マトリクスの作成。
  Mtx2D m;
  m.Identity();
  m.Scaling( in_UW, in_VH );
  m.Translate( -in_offs_cx, -in_offs_cy );
  m.RotZrad( in_R );
  m.Translate( in_offs_cx, in_offs_cy );
  m.Scaling( in_scale_x, in_scale_y );
  m.Translate( in_X, in_Y );

  m_sp_entity->Draw
    ( in_ptr_texture
    , m
    , float4( in_U, in_V, in_U+in_UW, in_V+in_VH )
    , in_Z
    , in_color
    , in_ptr_rect_clip
    );
}

// _____________________________________________________________________________
/// @brief 描画登録
/// 
/// @param[in] in_ptr_texture : テクスチャリソースへのポインタ。
/// @param[in] in_pos         : 描画する左上隅の座標（ターゲットのピクセル単位）
/// @param[in] in_rect_uv
///   : テクスチャの対角のＵＶ座標が格納されたfloat4型への参照（ピクセル単位）
/// @param[in] in_Z           : ｚ深度。
/// @param[in] in_color       : ４点カラー。
/// @param[in] in_offs_center : in_posを基点とする回転中心座標。
/// @param[in] in_scale       : ｘ方向倍率。
/// @param[in] in_R           : 回転角度（ラジアン単位）
/// @param[in] in_ptr_rect_clip
///   : クリップ矩形(float4型)のポインタを指定。\n
///   : nullptrでクリップしない。
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void
  SpriteDrawManager::Draw
    ( _in<DxSRV*     > in_ptr_texture
    , _in<float2     > in_pos
    , _in<float4     > in_rect_uv
    , _in<float      > in_Z
    , _in<RectColor4P> in_color
    , _in<float2     > in_offs_center
    , _in<float2     > in_scale
    , _in<float      > in_R
    , pin<float4     > in_ptr_rect_clip
    ) const
{
  // 頂点変換用マトリクスの作成。
  Mtx2D m;
  m.Identity();
  m.Scaling( in_rect_uv.right - in_rect_uv.left, in_rect_uv.bottom - in_rect_uv.top );
  m.Translate( -in_offs_center.x, -in_offs_center.y );
  m.RotZrad( in_R );
  m.Translate( in_offs_center.x, in_offs_center.y );
  m.Scaling( in_scale.x, in_scale.y );
  m.Translate( in_pos.x, in_pos.y );

  m_sp_entity->Draw
    ( in_ptr_texture
    , m
    , in_rect_uv
    , in_Z
    , in_color
    , in_ptr_rect_clip
    );
}

// _____________________________________________________________________________
/// @brief 描画登録　２Ｄマトリクス・カラー、拡張版。
/// 
/// @param[in] in_ptr_texture : テクスチャリソースへのポインタ。
/// @param[in] in_mtx
///   : 描画座標変換用の２Ｄマトリクス。\n
///   : 座標（0,0 - 1,1）のスプライト座標を変換する値となる。
/// @param[in] in_rect_uv
///   : テクスチャの対角のＵＶ座標が格納されたfloat4型への参照（ピクセル単位）
/// @param[in] in_Z       : ｚ深度。
/// @param[in] in_color   : ４点カラー。
/// @param[in] in_ptr_rect_clip
///   : クリップ矩形(float4型)のポインタを指定。\n
///   : nullptrでクリップしない。
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void
  SpriteDrawManager::Draw
    ( _in<DxSRV*     > in_ptr_texture
    , _in<Mtx2D      > in_mtx
    , _in<float4     > in_rect_uv
    , _in<float      > in_Z
    , _in<RectColor4P> in_color
    , pin<float4     > in_ptr_rect_clip
    ) const
{
  m_sp_entity->Draw
    ( in_ptr_texture
    , in_mtx
    , in_rect_uv
    , in_Z
    , in_color
    , in_ptr_rect_clip
    );
}


// _____________________________________________________________________________
/// @brief 登録スプライトのプリミティブ転送
/// 
/// @param[in] in_flag_order : false（昇順）　true（降順）
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void SpriteDrawManager::Transrate( _in<bool> in_flag_order ) const
{
  m_sp_entity->Transrate( in_flag_order );
}


} // namespace DX


// _____________________________________________________________________________
/// @brief DX::ColorTypeからタグ形式へ変換
/// 
/// @param[in] in_color4p : DX::RectColor4Pへの参照
/// 
/// @return タグオブジェクトを返す。
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
TBTag ToTag( _in<DX::RectColor4P> in_color4p )
{
  return
    TBTag
    { "Color4p"
    , ToTag( in_color4p.color[0] )
    , ToTag( in_color4p.color[1] )
    , ToTag( in_color4p.color[2] )
    , ToTag( in_color4p.color[3] )
    };
}

// _____________________________________________________________________________
/// @brief タグ読み込み
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
DX::RectColor4P& operator << ( rout<DX::RectColor4P> c4p, _in<TBTag> in_tag )
{
  auto sp_item = in_tag.GetTagChild();
  if( sp_item ) c4p.color[0] << *sp_item, sp_item = sp_item->GetTagChild();
  if( sp_item ) c4p.color[1] << *sp_item, sp_item = sp_item->GetTagChild();
  if( sp_item ) c4p.color[1] << *sp_item, sp_item = sp_item->GetTagChild();
  if( sp_item ) c4p.color[3] << *sp_item;
  return c4p;
}


// _____________________________________________________________________________
/// @brief タグへ書き込み
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
TBTag& operator << ( rout<TBTag> tag, _in<DX::RectColor4P> in_color4p )
{
  tag = ToTag( in_color4p );
  return tag;
}


} // namespace CPL
