#include "Mix/Tool/Win32/Core/Graphics/Material.h"

#include <vector>
#include <sstream>

#include "Mix/Tool/Win32/Core/Directory.h"

#include "Mix/Tool/Win32/Core/Graphics/Manager.h"
#include "Mix/Tool/Win32/Core/Graphics/FileTexture.h"
#include "Mix/Tool/Win32/Core/Graphics/DrawObject.h"
#include "Mix/Tool/Win32/Core/Graphics/MaterialSlot.h"
#include "Mix/Tool/Win32/Core/Graphics/MaterialShader.h"

namespace Mix{ namespace Tool{ namespace Win32{ namespace Graphics{

////////////////////////////////////////////////////////////////////////////////////////////////////
// 定数
////////////////////////////////////////////////////////////////////////////////////////////////////

const wchar_t* Material::FILE_EXT = L".mtl";

const Mix::Tool::Win32::Graphics::SHADER_TYPE Material::DEF_SHADER_TYPE = Mix::Tool::Win32::Graphics::SHADER_NORMAL;

const D3DXVECTOR4 Material::DEF_AMBIENT_COLOR = D3DXVECTOR4( 1.0f, 1.0f, 1.0f, 1.0f );
const bool Material::DEF_BOTH_LIGHTING = false;

const Mix::Tool::Win32::Graphics::BLEND_MODE Material::DEF_BLEND_MODE = Mix::Tool::Win32::Graphics::BLEND_COPY;

const bool Material::DEF_TRANSPARENCY = false;
const Mix::Tool::Win32::Graphics::TRANSPARENCY_METHOD Material::DEF_TRANSPARENCY_DRAW = Mix::Tool::Win32::Graphics::TRANSPARENCY_LUMP;
const bool Material::DEF_ZWRITE = false;
const bool Material::DEF_SOFTEDGE = false;
const float Material::DEF_SOFTEDGE_THICKNESS = 0.1f;

const bool Material::DEF_BACKCULLING = true;

const D3DTEXTUREFILTERTYPE Material::DEF_TEXFILTER_TYPE = D3DTEXF_LINEAR;
const D3DTEXTUREADDRESS Material::DEF_TEXADDRES_TYPE = D3DTADDRESS_CLAMP;

const bool Material::DEF_SHADOW_RECEIVE = true;
const bool Material::DEF_SHADOW_CAST = true;

const Mix::Tool::Win32::Graphics::DIFFUSE_TYPE Material::DEF_DIFFUSE_TYPE = Mix::Tool::Win32::Graphics::DIFFUSE_HALF_LAMBERT;
const D3DXVECTOR4 Material::DEF_DIFFUSE_COLOR = D3DXVECTOR4( 1.0f, 1.0f, 1.0f, 1.0f );
const bool Material::DEF_DIFFUSE_FRESNEL = false;
const float Material::DEF_DIFFUSE_FRESNEL_RATIO = 0.5f;
const bool Material::DEF_DIFFUSE_RL = false;
const float Material::DEF_DIFFUSE_RL_HARDNESS = 2.0f;
const float Material::DEF_DIFFUSE_RL_SCALE = 1.0f;

const Mix::Tool::Win32::Graphics::SPECULAR_TYPE Material::DEF_SPECULAR_TYPE = Mix::Tool::Win32::Graphics::SPECULAR_NONE;
const D3DXVECTOR4 Material::DEF_SPECULAR_COLOR = D3DXVECTOR4( 0.0f, 0.0f, 0.0f, 0.0f );
const float Material::DEF_SPECULAR_HARDNESS = 4.0f;
const float Material::DEF_SPECULAR_SCALE = 1.0f;
const float Material::DEF_SPECULAR_CT_FRESNEL = 0.2f;
const float Material::DEF_SPECULAR_CT_ROUGHNESS = 0.5f;

const Mix::Tool::Win32::Graphics::REFLECT_TYPE Material::DEF_REFLECT_TYPE = Mix::Tool::Win32::Graphics::REFLECT_NONE;
const float Material::DEF_REFLECT_INTENSITY = 0.5f;
const float Material::DEF_REFLECT_SCALE = 0.5f;
const float Material::DEF_REFLECT_BIAS = 0.1f;
const float Material::DEF_REFLECT_EXPROSURE = 4.0f;
const float Material::DEF_REFLECT_BUMP_RATIO = 0.02f;

const D3DXVECTOR4 Material::DEF_EMISSIVE_COLOR = D3DXVECTOR4( 0.0f, 0.0f, 0.0f, 0.0f );
const float Material::DEF_EMISSIVE_SCALE = 1.0f;

const Mix::Tool::Win32::Graphics::BUMP_TYPE Material::DEF_BUMP_TYPE = Mix::Tool::Win32::Graphics::BUMP_NORMAL_MAPPING;
const float Material::DEF_PARALLAX_HEIGHT_SCALE = 0.03f;
const int Material::DEF_PARALLAX_SAMPLE = 3;
const Mix::Tool::Win32::Graphics::WAVE_TYPE Material::DEF_WAVE_TYPE = Mix::Tool::Win32::Graphics::WAVE_NORMAL;
const Mix::Tool::Win32::Graphics::WAVE_DIR Material::DEF_WAVE_DIR = Mix::Tool::Win32::Graphics::WAVE_POSITIVE_V;
const D3DXVECTOR2 Material::DEF_WAVE_DIR_VEC = D3DXVECTOR2( 1.0f, 0.0f );
const float Material::DEF_WAVE_VELOCITY = 0.1f;
const float Material::DEF_WAVE_UV_OFFSET = 0.5f;
const float Material::DEF_WAVE_GAP = 3.0f;
const float Material::DEF_WAVE_REFRACT_RATIO = 0.01f;

const D3DTEXTUREFILTERTYPE Material::D3D_TEXF_TABLE[Material::MTL_TEXF_MAX] =
{
	D3DTEXF_POINT,
	D3DTEXF_LINEAR,
	D3DTEXF_ANISOTROPIC,
};

const D3DTEXTUREADDRESS Material::D3D_TEXA_TABLE[Material::MTL_TEXA_MAX] =
{
	D3DTADDRESS_WRAP,
	D3DTADDRESS_CLAMP,
};

////////////////////////////////////////////////////////////////////////////////////////////////////
// クラス
////////////////////////////////////////////////////////////////////////////////////////////////////

Material::Material( Mix::Tool::Win32::Graphics::MaterialSlot* pSlot, bool bDefault ) :
m_pSlot( pSlot ),
m_bAutoUpdate( true ),
m_pShader( new Mix::Tool::Win32::Graphics::MaterialShader() ),
m_bDefault( bDefault ),
m_bActive( false ),
m_DefaultName( L"" ),
m_Name( L"" ),
m_ShaderType( Material::DEF_SHADER_TYPE ),
m_AmbientColor( Material::DEF_AMBIENT_COLOR ),
m_bBothLighting( Material::DEF_BOTH_LIGHTING ),
m_BlendMode( Material::DEF_BLEND_MODE ),
m_bTransparency( Material::DEF_TRANSPARENCY ),
m_TransparencyMethod( Material::DEF_TRANSPARENCY_DRAW ),
m_bZWrite( Material::DEF_ZWRITE ),
m_bSoftEdge( Material::DEF_SOFTEDGE ),
m_SoftEdgeThickness( Material::DEF_SOFTEDGE_THICKNESS ),
m_bBackculling( Material::DEF_BACKCULLING ),
m_TextureFilterType( Material::DEF_TEXFILTER_TYPE ),
m_TextureAddressType( Material::DEF_TEXADDRES_TYPE ),
m_bShadowReceive( Material::DEF_SHADOW_RECEIVE ),
m_bShadowCast( Material::DEF_SHADOW_CAST ),
m_DiffuseType( Material::DEF_DIFFUSE_TYPE ),
m_DiffuseColor( Material::DEF_DIFFUSE_COLOR ),
m_bDiffuseFresnel( Material::DEF_DIFFUSE_FRESNEL ),
m_DiffuseFresnelRatio( Material::DEF_DIFFUSE_FRESNEL_RATIO ),
m_bDiffuseRL( Material::DEF_DIFFUSE_RL ),
m_DiffuseRLHardness( Material::DEF_DIFFUSE_RL_HARDNESS ),
m_DiffuseRLScale( Material::DEF_DIFFUSE_RL_SCALE ),
m_DiffuseTextureFileName( L"" ),
m_pDiffuseTexture( NULL ),
m_SpecularType( Material::DEF_SPECULAR_TYPE ),
m_SpecularColor( Material::DEF_SPECULAR_COLOR ),
m_SpecularHardness( Material::DEF_SPECULAR_HARDNESS ),
m_SpecularScale( Material::DEF_SPECULAR_SCALE ),
m_SpecularCTFresnel( Material::DEF_SPECULAR_CT_FRESNEL ),
m_SpecularCTRoughness( Material::DEF_SPECULAR_CT_ROUGHNESS ),
m_SpecularTextureFileName( L"" ),
m_pSpecularTexture( NULL ),
m_ReflectType( Material::DEF_REFLECT_TYPE ),
m_ReflectScale( Material::DEF_REFLECT_SCALE ),
m_ReflectIntensity( Material::DEF_REFLECT_INTENSITY ),
m_ReflectBias( Material::DEF_REFLECT_BIAS ),
m_ReflectExprosure( Material::DEF_REFLECT_EXPROSURE ),
m_ReflectBumpRatio( Material::DEF_REFLECT_BUMP_RATIO ),
m_EmissiveColor( Material::DEF_EMISSIVE_COLOR ),
m_EmissiveScale( Material::DEF_EMISSIVE_SCALE ),
m_EmissiveTextureFileName( L"" ),
m_pEmissiveTexture( NULL ),
m_BumpTextureFileName( L"" ),
m_pBumpTexture( NULL ),
m_BumpType( Material::DEF_BUMP_TYPE ),
m_BumpHeightScale( Material::DEF_PARALLAX_HEIGHT_SCALE ),
m_BumpSample( Material::DEF_PARALLAX_SAMPLE ),
m_WaveType( Material::DEF_WAVE_TYPE ),
m_WaveDir( Material::DEF_WAVE_DIR ),
m_WaveDirVec( Material::DEF_WAVE_DIR_VEC ),
m_WaveVelocity( Material::DEF_WAVE_VELOCITY ),
m_WaveUVOffset( Material::DEF_WAVE_UV_OFFSET ),
m_WaveGap( Material::DEF_WAVE_GAP ),
m_bWaveInvert( false ),
m_WaveRefractRatio( Material::DEF_WAVE_REFRACT_RATIO ),
m_WavePos( 0.0f ),
m_WaveUV( 0.0f, 0.0f ),
m_SaveFilePath( L"" )
{
}

Material::~Material( void )
{
	Mix::Tool::Win32::Graphics::Manager* pManager = Manager::GetInstance();

	if( pManager != NULL )
	{
		pManager->RemoveWaveMaterial( this );
	}

	MIX_RELEASE( m_pDiffuseTexture );
	MIX_RELEASE( m_pSpecularTexture );
	MIX_RELEASE( m_pEmissiveTexture );
	MIX_RELEASE( m_pBumpTexture );

	MIX_DELETE( m_pShader );
}

Mix::Tool::Win32::Graphics::VertexLayout* Material::GetVertexLayout( Mix::Tool::Win32::Graphics::VERTEX_TYPE vertexType ) const
{
	if( m_pShader == NULL )
	{
		return NULL;
	}

	return m_pShader->GetVertexLayoutPtr( vertexType );
}

Mix::Tool::Win32::Graphics::VertexShader* Material::GetVertexShader( Mix::Tool::Win32::Graphics::VERTEX_TYPE vertexType, Mix::Tool::Win32::Graphics::MAPPING_TYPE mappingType ) const
{
	if( m_pShader == NULL )
	{
		return NULL;
	}

	return m_pShader->GetVertexShaderPtr( vertexType, mappingType );
}

Mix::Tool::Win32::Graphics::PixelShader* Material::GetPixelShader( Mix::Tool::Win32::Graphics::MAPPING_TYPE mappingType ) const
{
	if( m_pShader == NULL )
	{
		return NULL;
	}

	return m_pShader->GetPixelShaderPtr( mappingType );
}

Mix::Tool::Win32::Graphics::VertexShader* Material::GetSelectVertexShader( Mix::Tool::Win32::Graphics::VERTEX_TYPE vertexType ) const
{
	if( m_pShader == NULL )
	{
		return NULL;
	}

	return m_pShader->GetSelectVertexShaderPtr( vertexType );
}

Mix::Tool::Win32::Graphics::PixelShader* Material::GetSelectPixelShader( void ) const
{
	if( m_pShader == NULL )
	{
		return NULL;
	}

	return m_pShader->GetSelectPixelShaderPtr();
}

void Material::Destroy( void )
{
	m_pSlot = NULL;
}

void Material::SetDefaultName( const wchar_t* pName )
{
	m_DefaultName = pName;
}

const wchar_t* Material::GetDefaultName( void ) const
{
	return m_DefaultName.c_str();
}

void Material::SetName( const wchar_t* pName )
{
	if( ( m_pSlot == NULL ) ||
		( pName == NULL ) ||
		( ::wcslen( pName ) == 0 ) )
	{
		return;
	}

	m_pSlot->CreateMaterialName( this, pName, m_Name );
}

const wchar_t* Material::GetName( void ) const
{
	return m_Name.c_str();
}

////////////////////////////////////////////////////////////////////////////////////////////////////
// 全般
////////////////////////////////////////////////////////////////////////////////////////////////////

Mix::Tool::Win32::Graphics::SHADER_TYPE Material::GetShaderType( void ) const
{
	return m_ShaderType;
}

void Material::SetShaderType( Mix::Tool::Win32::Graphics::SHADER_TYPE type )
{
	if( m_ShaderType != type )
	{
		Mix::Tool::Win32::Graphics::Manager* pManager = Manager::GetInstance();

		if( ( m_ShaderType != Mix::Tool::Win32::Graphics::SHADER_WATER ) &&
			( type == Mix::Tool::Win32::Graphics::SHADER_WATER ) )
		{
			pManager->AddWaveMaterial( this );
		}
		else if( ( m_ShaderType == Mix::Tool::Win32::Graphics::SHADER_WATER ) &&
				( type != Mix::Tool::Win32::Graphics::SHADER_WATER ) )
		{
			pManager->RemoveWaveMaterial( this );
		}

		m_ShaderType = type;
		AutoUpdate();
	}
}

const D3DXVECTOR4& Material::GetAmbientColor( void ) const
{
	return m_AmbientColor;
}

void Material::SetAmbientColor( const D3DXVECTOR4& color )
{
	m_AmbientColor = color;
}

bool Material::GetBothLighting( void ) const
{
	return m_bBothLighting;
}

void Material::SetBothLighting( bool state )
{
	if( m_bBothLighting != state )
	{
		m_bBothLighting = state;
		AutoUpdate();
	}
}

Mix::Tool::Win32::Graphics::BLEND_MODE Material::GetBlendMode( void ) const
{
	return m_BlendMode;
}

void Material::SetBlendMode( Mix::Tool::Win32::Graphics::BLEND_MODE blendMode )
{
	m_BlendMode = blendMode;
}

bool Material::GetTransparency( void ) const
{
	return m_bTransparency;
}

void Material::SetTransparency( bool state )
{
	if( m_bTransparency != state )
	{
		m_bTransparency = state;
		AutoUpdate();
	}
}

Mix::Tool::Win32::Graphics::TRANSPARENCY_METHOD Material::GetTransparencyMethod( void ) const
{
	return m_TransparencyMethod;
}

void Material::SetTransparencyMethod( Mix::Tool::Win32::Graphics::TRANSPARENCY_METHOD draw )
{
	m_TransparencyMethod = draw;
}

bool Material::GetZWrite( void ) const
{
	return m_bZWrite;
}

void Material::SetZWrite( bool state )
{
	m_bZWrite = state;
}

bool Material::GetSoftEdge( void ) const
{
	return m_bSoftEdge;
}

void Material::SetSoftEdge( bool state )
{
	if( m_bSoftEdge != state )
	{
		m_bSoftEdge = state;
		AutoUpdate();
	}
}

float Material::GetSoftEdgeThickness( void ) const
{
	return m_SoftEdgeThickness;
}

void Material::SetSoftEdgeThickness( float thickness )
{
	m_SoftEdgeThickness = max( 0.0f, thickness );
}

D3DXVECTOR4 Material::GetTransparencyParam( void )
{
	return D3DXVECTOR4( m_SoftEdgeThickness, 0.0f, 0.0f, 0.0f );
}

bool Material::GetBackculling( void ) const
{
	return m_bBackculling;
}

void Material::SetBackculling( bool state )
{
	m_bBackculling = state;
}

////////////////////////////////////////////////////////////////////////////////////////////////////
// テクスチャマッピング
////////////////////////////////////////////////////////////////////////////////////////////////////

D3DTEXTUREFILTERTYPE Material::GetTextureFilterType( void ) const
{
	return m_TextureFilterType;
}

void Material::SetTextureFilterType( D3DTEXTUREFILTERTYPE type )
{
	MIX_ASSERT( ( type == D3DTEXF_POINT ) || ( type == D3DTEXF_LINEAR ) || ( type == D3DTEXF_ANISOTROPIC ) );

	m_TextureFilterType = type;
}

D3DTEXTUREADDRESS Material::GetTextureAddressType( void ) const
{
	return m_TextureAddressType;
}

void Material::SetTextureAddressType( D3DTEXTUREADDRESS type )
{
	MIX_ASSERT( ( type == D3DTADDRESS_WRAP ) || ( type == D3DTADDRESS_CLAMP ) );

	m_TextureAddressType = type;
}

////////////////////////////////////////////////////////////////////////////////////////////////////
// シャドウマッピング
////////////////////////////////////////////////////////////////////////////////////////////////////

bool Material::GetShadowReceive( void ) const
{
	return m_bShadowReceive;
}

void Material::SetShadowReceive( bool state )
{
	m_bShadowReceive = state;
}

bool Material::GetShadowCast( void ) const
{
	return m_bShadowCast;
}

void Material::SetShadowCast( bool state )
{
	m_bShadowCast = state;
}

////////////////////////////////////////////////////////////////////////////////////////////////////
// ディフューズ
////////////////////////////////////////////////////////////////////////////////////////////////////

// タイプ //

Mix::Tool::Win32::Graphics::DIFFUSE_TYPE Material::GetDiffuseType( void ) const
{
	return m_DiffuseType;
}

void Material::SetDiffuseType( Mix::Tool::Win32::Graphics::DIFFUSE_TYPE type )
{
	if( m_DiffuseType != type )
	{
		m_DiffuseType = type;
		AutoUpdate();
	}
}

// カラー //

const D3DXVECTOR4& Material::GetDiffuseColor( void ) const
{
	return m_DiffuseColor;
}

void Material::SetDiffuseColor( const D3DXVECTOR4& color )
{
	m_DiffuseColor = color;
}

// フレネル //

bool Material::GetDiffuseFresnel( void ) const
{
	return m_bDiffuseFresnel;
}

void Material::SetDiffuseFresnel( bool state )
{
	if( m_bDiffuseFresnel != state )
	{
		m_bDiffuseFresnel = state;
		AutoUpdate();
	}
}

float Material::GetDiffuseFresnelRatio( void ) const
{
	return m_DiffuseFresnelRatio;
}

void Material::SetDiffuseFresnelRatio( float ratio )
{
	m_DiffuseFresnelRatio = ratio;
}

// リムライティング //

bool Material::GetDiffuseRL( void ) const
{
	return m_bDiffuseRL;
}

void Material::SetDiffuseRL( bool state )
{
	if( m_bDiffuseRL != state )
	{
		m_bDiffuseRL = state;
		AutoUpdate();
	}
}

float Material::GetDiffuseRLHardness( void ) const
{
	return m_DiffuseRLHardness;
}

void Material::SetDiffuseRLHardness( float hardness )
{
	m_DiffuseRLHardness = hardness;
}

float Material::GetDiffuseRLScale( void ) const
{
	return m_DiffuseRLScale;
}

void Material::SetDiffuseRLScale( float scale )
{
	m_DiffuseRLScale = scale;
}

// テクスチャ //

const wchar_t* Material::GetDiffuseTextureFileName( void ) const
{
	return m_DiffuseTextureFileName.c_str();
}

void Material::SetDiffuseTextureFileName( const wchar_t* pFileName )
{
	if( ( pFileName != NULL ) &&
		( ::wcslen( pFileName ) > 0 ) )
	{
		m_DiffuseTextureFileName = pFileName;
	}
	else
	{
		m_DiffuseTextureFileName = L"";
	}
}

Mix::Tool::Win32::Graphics::Texture* Material::GetDiffuseTexture( void )
{
	return m_pDiffuseTexture;
}

bool Material::LoadDiffuseTexture( void )
{
	Mix::Tool::Win32::Graphics::Manager* pManager = Manager::GetInstance();
	if( pManager == NULL )
	{
		return false;
	}

	MIX_RELEASE( m_pDiffuseTexture );

	if( m_DiffuseTextureFileName.size() > 0 )
	{
		m_pDiffuseTexture = pManager->CreateTexture( m_DiffuseTextureFileName.c_str() );
		if( m_pDiffuseTexture == NULL )
		{
			return false;
		}
	}

	AutoUpdate();

	return true;
}

bool Material::LoadDiffuseTexture( const wchar_t* pFileName )
{
	SetDiffuseTextureFileName( pFileName );

	return LoadDiffuseTexture();
}

// パラメータ //

D3DXVECTOR4 Material::GetDiffuseParam( void )
{
	return D3DXVECTOR4( m_DiffuseFresnelRatio, m_DiffuseRLHardness, m_DiffuseRLScale, 0.0f );
}

////////////////////////////////////////////////////////////////////////////////////////////////////
// スペキュラー
////////////////////////////////////////////////////////////////////////////////////////////////////

Mix::Tool::Win32::Graphics::SPECULAR_TYPE Material::GetSpecularType( void ) const
{
	return m_SpecularType;
}

void Material::SetSpecularType( Mix::Tool::Win32::Graphics::SPECULAR_TYPE type )
{
	if( m_SpecularType != type )
	{
		m_SpecularType = type;
		AutoUpdate();
	}
}

const D3DXVECTOR4& Material::GetSpecularColor( void ) const
{
	return m_SpecularColor;
}

void Material::SetSpecularColor( const D3DXVECTOR4& color )
{
	m_SpecularColor = color;
}

float Material::GetSpecularHardness( void ) const
{
	return m_SpecularHardness;
}

void Material::SetSpecularHardness( float hardness )
{
	m_SpecularHardness = hardness;
}

float Material::GetSpecularScale( void ) const
{
	return m_SpecularScale;
}

void Material::SetSpecularScale( float scale )
{
	m_SpecularScale = scale;
}

float Material::GetSpecularCTFresnel( void ) const
{
	return m_SpecularCTFresnel;
}

void Material::SetSpecularCTFresnel( float fresnel )
{
	m_SpecularCTFresnel = fresnel;
}

float Material::GetSpecularCTRoughness( void ) const
{
	return m_SpecularCTRoughness;
}

void Material::SetSpecularCTRoughness( float roughness )
{
	m_SpecularCTRoughness = roughness;
}

const wchar_t* Material::GetSpecularTextureFileName( void ) const
{
	return m_SpecularTextureFileName.c_str();
}

void Material::SetSpecularTextureFileName( void )
{
	Mix::Tool::Win32::Graphics::Manager* pManager = Manager::GetInstance();
	if( pManager != NULL )
	{
		if( pManager->GetSpecularTextureFileName( GetDiffuseTextureFileName(), m_SpecularTextureFileName ) == false )
		{
			m_SpecularTextureFileName = L"";
		}
	}
	else
	{
		m_SpecularTextureFileName = L"";
	}
}

void Material::SetSpecularTextureFileName( const wchar_t* pFileName )
{
	if( ( pFileName != NULL ) &&
		( ::wcslen( pFileName ) > 0 ) )
	{
		m_SpecularTextureFileName = pFileName;
	}
	else
	{
		m_SpecularTextureFileName = L"";
	}
}

Mix::Tool::Win32::Graphics::Texture* Material::GetSpecularTexture( void )
{
	return m_pSpecularTexture;
}

bool Material::LoadSpecularTexture( void )
{
	Mix::Tool::Win32::Graphics::Manager* pManager = Manager::GetInstance();
	if( pManager == NULL )
	{
		return false;
	}

	MIX_RELEASE( m_pSpecularTexture );

	if( m_SpecularTextureFileName.size() > 0 )
	{
		m_pSpecularTexture = pManager->CreateTexture( m_SpecularTextureFileName.c_str() );
		if( m_pSpecularTexture == NULL )
		{
			return false;
		}
	}

	AutoUpdate();

	return true;
}

bool Material::LoadSpecularTexture( const wchar_t* pFileName )
{
	SetSpecularTextureFileName( pFileName );

	return LoadSpecularTexture();
}

D3DXVECTOR4 Material::GetSpecularParam0( void )
{
	return D3DXVECTOR4( m_SpecularHardness, m_SpecularScale, 0.0f, 0.0f );
}

D3DXVECTOR4 Material::GetSpecularParam1( void )
{
	return D3DXVECTOR4( m_SpecularCTFresnel, MIX_FLOAT_RCP( m_SpecularCTRoughness ), m_SpecularCTRoughness * m_SpecularCTRoughness, 0.0f );
}

////////////////////////////////////////////////////////////////////////////////////////////////////
// スペキュラー : 反射
////////////////////////////////////////////////////////////////////////////////////////////////////

Mix::Tool::Win32::Graphics::REFLECT_TYPE Material::GetReflectType( void ) const
{
	return m_ReflectType;
}

void Material::SetReflectType( Mix::Tool::Win32::Graphics::REFLECT_TYPE type )
{
	if( m_ReflectType != type )
	{
		m_ReflectType = type;
		AutoUpdate();
	}
}

float Material::GetReflectScale( void ) const
{
	return m_ReflectScale;
}

void Material::SetReflectScale( float scale )
{
	m_ReflectScale = scale;
}

float Material::GetReflectIntensity( void ) const
{
	return m_ReflectIntensity;
}

void Material::SetReflectIntensity( float intensity )
{
	m_ReflectIntensity = intensity;
}

float Material::GetReflectBias( void ) const
{
	return m_ReflectBias;
}

void Material::SetReflectBias( float bias )
{
	m_ReflectBias = bias;
}

float Material::GetReflectExprosure( void ) const
{
	return m_ReflectExprosure;
}

void Material::SetReflectExprosure( float exprosure )
{
	m_ReflectExprosure = exprosure;
}

float Material::GetReflectBumpRatio( void ) const
{
	return m_ReflectBumpRatio;
}

void Material::SetReflectBumpRatio( float ratio )
{
	m_ReflectBumpRatio = ratio;
}

D3DXVECTOR4 Material::GetReflectParam( void )
{
	return D3DXVECTOR4( m_ReflectScale, m_ReflectIntensity, m_ReflectBias, m_ReflectExprosure );
}

////////////////////////////////////////////////////////////////////////////////////////////////////
// エミッシブ
////////////////////////////////////////////////////////////////////////////////////////////////////

const D3DXVECTOR4& Material::GetEmissiveColor( void ) const
{
	return m_EmissiveColor;
}

void Material::SetEmissiveColor( const D3DXVECTOR4& color )
{
	m_EmissiveColor = color;
}

float Material::GetEmissiveScale( void ) const
{
	return m_EmissiveScale;
}

void Material::SetEmissiveScale( float scale )
{
	m_EmissiveScale = scale;
}

const wchar_t* Material::GetEmissiveTextureFileName( void ) const
{
	return m_EmissiveTextureFileName.c_str();
}

void Material::SetEmissiveTextureFileName( void )
{
	Mix::Tool::Win32::Graphics::Manager* pManager = Manager::GetInstance();
	if( pManager != NULL )
	{
		if( pManager->GetEmissiveTextureFileName( GetDiffuseTextureFileName(), m_EmissiveTextureFileName ) == false )
		{
			m_EmissiveTextureFileName = L"";
		}
	}
	else
	{
		m_EmissiveTextureFileName = L"";
	}
}

void Material::SetEmissiveTextureFileName( const wchar_t* pFileName )
{
	if( ( pFileName != NULL ) &&
		( ::wcslen( pFileName ) > 0 ) )
	{
		m_EmissiveTextureFileName = pFileName;
	}
	else
	{
		m_EmissiveTextureFileName = L"";
	}
}

Mix::Tool::Win32::Graphics::Texture* Material::GetEmissiveTexture( void )
{
	return m_pEmissiveTexture;
}

bool Material::LoadEmissiveTexture( void )
{
	Mix::Tool::Win32::Graphics::Manager* pManager = Manager::GetInstance();
	if( pManager == NULL )
	{
		return false;
	}

	MIX_RELEASE( m_pEmissiveTexture );

	if( m_EmissiveTextureFileName.size() > 0 )
	{
		m_pEmissiveTexture = pManager->CreateTexture( m_EmissiveTextureFileName.c_str() );
		if( m_pEmissiveTexture == NULL )
		{
			return false;
		}
	}

	AutoUpdate();

	return true;
}

bool Material::LoadEmissiveTexture( const wchar_t* pFileName )
{
	SetEmissiveTextureFileName( pFileName );

	return LoadEmissiveTexture();
}

D3DXVECTOR4 Material::GetEmissiveParam( void )
{
	return D3DXVECTOR4( m_EmissiveScale, 0.0f, 0.0f, 0.0f );
}

////////////////////////////////////////////////////////////////////////////////////////////////////
// バンプ
////////////////////////////////////////////////////////////////////////////////////////////////////

const wchar_t* Material::GetBumpTextureFileName( void ) const
{
	return m_BumpTextureFileName.c_str();
}

void Material::SetBumpTextureFileName( void )
{
	Mix::Tool::Win32::Graphics::Manager* pManager = Manager::GetInstance();
	if( pManager != NULL )
	{
		if( pManager->GetBumpTextureFileName( GetDiffuseTextureFileName(), m_BumpTextureFileName ) == false )
		{
			m_BumpTextureFileName = L"";
		}
	}
	else
	{
		m_BumpTextureFileName = L"";
	}
}

void Material::SetBumpTextureFileName( const wchar_t* pFileName )
{
	if( ( pFileName != NULL ) &&
		( ::wcslen( pFileName ) > 0 ) )
	{
		m_BumpTextureFileName = pFileName;
	}
	else
	{
		m_BumpTextureFileName = L"";
	}
}

Mix::Tool::Win32::Graphics::Texture* Material::GetBumpTexture( void )
{
	return m_pBumpTexture;
}

bool Material::LoadBumpTexture( void )
{
	Mix::Tool::Win32::Graphics::Manager* pManager = Manager::GetInstance();
	if( pManager == NULL )
	{
		return false;
	}

	MIX_RELEASE( m_pBumpTexture );

	if( m_BumpTextureFileName.size() > 0 )
	{
		m_pBumpTexture = pManager->CreateTexture( m_BumpTextureFileName.c_str() );
		if( m_pBumpTexture == NULL )
		{
			return false;
		}
	}

	AutoUpdate();

	return true;
}

bool Material::LoadBumpTexture( const wchar_t* pFileName )
{
	SetBumpTextureFileName( pFileName );

	return LoadBumpTexture();
}

Mix::Tool::Win32::Graphics::BUMP_TYPE Material::GetBumpType( void ) const
{
	return m_BumpType;
}

void Material::SetBumpType( Mix::Tool::Win32::Graphics::BUMP_TYPE type )
{
	if( m_BumpType != type )
	{
		m_BumpType = type;
		AutoUpdate();
	}
}

float Material::GetBumpHeightScale( void ) const
{
	return m_BumpHeightScale;
}

void Material::SetBumpHeightScale( float scale )
{
	m_BumpHeightScale = scale;
}

int Material::GetBumpSample( void ) const
{
	return m_BumpSample;
}

void Material::SetBumpSample( int sample )
{
	m_BumpSample = sample;
}

////////////////////////////////////////////////////////////////////////////////////////////////////
// バンプ : ウェーブアニメーション
////////////////////////////////////////////////////////////////////////////////////////////////////

Mix::Tool::Win32::Graphics::WAVE_TYPE Material::GetBumpWaveType( void ) const
{
	return m_WaveType;
}

void Material::SetBumpWaveType( Mix::Tool::Win32::Graphics::WAVE_TYPE type )
{
	if( m_WaveType != type )
	{
		m_WaveType = type;
		AutoUpdate();
	}
}

Mix::Tool::Win32::Graphics::WAVE_DIR Material::GetBumpWaveDir( void ) const
{
	return m_WaveDir;
}

void Material::SetBumpWaveDir( Mix::Tool::Win32::Graphics::WAVE_DIR dir )
{
	if( m_WaveDir != dir )
	{
		switch( dir )
		{
		case Mix::Tool::Win32::Graphics::WAVE_POSITIVE_U:
			m_WaveDirVec = D3DXVECTOR2( 1.0f, 0.0f );
			break;
		case Mix::Tool::Win32::Graphics::WAVE_NEGATIVE_U:
			m_WaveDirVec = D3DXVECTOR2( -1.0f, 0.0f );
			break;
		case Mix::Tool::Win32::Graphics::WAVE_POSITIVE_V:
			m_WaveDirVec = D3DXVECTOR2( 0.0f, 1.0f );
			break;
		case Mix::Tool::Win32::Graphics::WAVE_NEGATIVE_V:
			m_WaveDirVec = D3DXVECTOR2( 0.0f, -1.0f );
			break;
		}

		m_WaveDir = dir;
		AutoUpdate();
	}
}

float Material::GetBumpWaveVelocity( void ) const
{
	return m_WaveVelocity;
}

void Material::SetBumpWaveVelocity( float vel )
{
	m_WaveVelocity = vel;
}

float Material::GetBumpWaveUVOffset( void ) const
{
	return m_WaveUVOffset;
}

void Material::SetBumpWaveUVOffset( float offset )
{
	m_WaveUVOffset = offset;
}

float Material::GetBumpWaveGap( void ) const
{
	return m_WaveGap;
}

void Material::SetBumpWaveGap( float gap )
{
	m_WaveGap = gap;
}

bool Material::GetBumpWaveInvert( void ) const
{
	return m_bWaveInvert;
}

void Material::SetBumpWaveInvert( bool state )
{
	m_bWaveInvert = state;
	AutoUpdate();
}

float Material::GetBumpRefractRatio( void ) const
{
	return m_WaveRefractRatio;
}

void Material::SetBumpRefractRatio( float ratio )
{
	m_WaveRefractRatio = ratio;
}

D3DXVECTOR4 Material::GetBumpParam0( void )
{
	return D3DXVECTOR4( m_BumpHeightScale, static_cast<float>( m_BumpSample ), m_ReflectBumpRatio, m_WaveUVOffset );
}

D3DXVECTOR4 Material::GetBumpParam1( void )
{
	return D3DXVECTOR4( m_WaveUV.x, m_WaveUV.y, m_WaveGap, m_WaveRefractRatio );
}

////////////////////////////////////////////////////////////////////////////////////////////////////

bool Material::GetAutoUpdate( void ) const
{
	return m_bAutoUpdate;
}

void Material::SetAutoUpdate( bool state )
{
	m_bAutoUpdate = state;
}

void Material::Update( bool bNotifyDrawObject )
{
	if( m_pSlot == NULL )
	{
		return;
	}

	m_pSlot->Update( this, bNotifyDrawObject );
}

bool Material::GetDefault( void ) const
{
	return m_bDefault;
}

bool Material::GetActive( void ) const
{
	return m_bActive;
}

void Material::SetActive( void )
{
	if( m_pSlot == NULL )
	{
		return;
	}

	m_pSlot->SetActiveMaterial( this );
}

const wchar_t* Material::GetSaveFilePath( void ) const
{
	return m_SaveFilePath.c_str();
}

void Material::SetSaveFilePath( const wchar_t* pFilePath )
{
	m_SaveFilePath = ( pFilePath != NULL )? pFilePath : L"";
}

Mix::Tool::Win32::Object::TYPE Material::GetType( void ) const
{
	return Mix::Tool::Win32::Object::GRAPHICS__MATERIAL;
}

bool Material::Save( void )
{
	LogPrint( LT_INFO, L"----------------------------------------------------------------------------------------------------" );

	if( m_SaveFilePath.size() == 0 )
	{
		LogPrint( LT_WARNING, L"  マテリアルを保存できませんでした : ファイルパスが指定されていません : Location[%s/%s]", m_pSlot->GetName(), m_Name.c_str() );
		return true;
	}

	Mix::Tool::Win32::File::OutputStream output;

	////////////////////////////////////////////////////////////////////////////////////////////////////
	// ファイルを作成
	////////////////////////////////////////////////////////////////////////////////////////////////////

	//ディレクトリを作成
	if( Mix::Tool::Win32::Directory::Create( m_SaveFilePath.c_str(), true ) == false )
	{
		LogPrint(	LT_ERROR, L"  マテリアルの保存に失敗しました : ディレクトリの作成中にエラーが発生 : Location[%s/%s] FilePath[%s]",
					m_pSlot->GetName(),
					m_Name.c_str(),
					m_SaveFilePath.c_str() );

		return false;
	}

	//開く
	if( output.Open( m_SaveFilePath.c_str() ) == false )
	{
		LogPrint(	LT_ERROR, L"  マテリアルの保存に失敗しました : ファイルの作成中にエラーが発生 : Location[%s/%s] FilePath[%s]",
					m_pSlot->GetName(),
					m_Name.c_str(),
					m_SaveFilePath.c_str() );

		return false;
	}

	////////////////////////////////////////////////////////////////////////////////////////////////////
	// ファイルヘッダ : マジックナンバー
	////////////////////////////////////////////////////////////////////////////////////////////////////

	{
		unsigned int magicNumber = Material::MTL_MAGIC_NUMBER;

		if( output.Write( &magicNumber, sizeof( magicNumber ) ) == false )
		{
			LogPrint(	LT_ERROR, L"  マテリアルの保存に失敗しました : 書き込み中にエラーが発生 : Location[%s/%s] FilePath[%s]",
						m_pSlot->GetName(),
						m_Name.c_str(),
						m_SaveFilePath.c_str() );

			return false;
		}
	}

	////////////////////////////////////////////////////////////////////////////////////////////////////
	// データ
	////////////////////////////////////////////////////////////////////////////////////////////////////

	if( Write( m_SaveFilePath.c_str(), output ) == false )
	{
		return false;
	}

	////////////////////////////////////////////////////////////////////////////////////////////////////
	// ファイルを閉じる
	////////////////////////////////////////////////////////////////////////////////////////////////////

	output.Close();

	////////////////////////////////////////////////////////////////////////////////////////////////////
	// ログ
	////////////////////////////////////////////////////////////////////////////////////////////////////
	
	LogPrint(	LT_INFO, L"  マテリアルを保存しました : Location[%s/%s] FilePath[%s]",
				m_pSlot->GetName(),
				m_Name.c_str(),
				m_SaveFilePath.c_str() );

	return true;
}

bool Material::Write( const wchar_t* pFilePath, Mix::Tool::Win32::File::OutputStream& output )
{
	Mix::Tool::Win32::Graphics::Manager* pManager;
	unsigned int procFlags;

	unsigned int version;
	Material::MTL_INFO_HEADER_1_1_0_0 infoHeader;
	Material::MTL_DATA_HEADER_1_1_0_0 dataHeader;

	////////////////////////////////////////////////////////////////////////////////////////////////////
	// マネージャを取得
	////////////////////////////////////////////////////////////////////////////////////////////////////

	pManager = Manager::GetInstance();
	if( pManager == NULL )
	{
		return false;
	}

	////////////////////////////////////////////////////////////////////////////////////////////////////
	// エフェクトパッケージのプロセスフラグを取得
	////////////////////////////////////////////////////////////////////////////////////////////////////

	procFlags = pManager->MEP_GetProcessFlags();

	////////////////////////////////////////////////////////////////////////////////////////////////////
	// ファイルヘッダ
	////////////////////////////////////////////////////////////////////////////////////////////////////

	// バージョン //

	version = Material::MTL_VERSION_CUR;

	if( output.Write( &version, sizeof( version ) ) == false )
	{
		LogPrint(	LT_ERROR, L"マテリアルの保存に失敗しました : 書き込み中にエラーが発生 : Location[%s/%s] FilePath[%s]",
					m_pSlot->GetName(),
					m_Name.c_str(),
					pFilePath );

		return false;
	}

	////////////////////////////////////////////////////////////////////////////////////////////////////
	// インフォヘッダ
	////////////////////////////////////////////////////////////////////////////////////////////////////

	// 名前 //

	if( m_Name.size() < Mix::Tool::Win32::Graphics::MAX_NAME_SIZE )
	{
		::wcscpy_s( infoHeader.name, sizeof( infoHeader.name ) >> 1, m_Name.c_str() );
	}
	else
	{
		LogPrint(	LT_ERROR, L"マテリアルの保存に失敗しました : 名前は%d文字以下にしてください : Location[%s/%s] FilePath[%s]",
					_MAX_NAME_SIZE,
					m_pSlot->GetName(),
					m_Name.c_str(),
					pFilePath );

		return false;
	}

	// シェーダーID //

	infoHeader.vertexShaderID[Mix::Tool::Win32::Graphics::VERTEX_SIMPLE] = m_pShader->GetVertexShaderID( Mix::Tool::Win32::Graphics::VERTEX_SIMPLE );
	infoHeader.vertexShaderID[Mix::Tool::Win32::Graphics::VERTEX_BLEND] = m_pShader->GetVertexShaderID( Mix::Tool::Win32::Graphics::VERTEX_BLEND );
	infoHeader.pixelShaderID = m_pShader->GetPixelShaderID();

	// デフォルト //

	infoHeader.type = Material::MTL_DEFAULT;

	if( output.Write( &infoHeader, sizeof( infoHeader ) ) == false )
	{
		LogPrint(	LT_ERROR, L"マテリアルの保存に失敗しました : 書き込み中にエラーが発生 : Location[%s/%s] FilePath[%s]",
					m_pSlot->GetName(),
					m_Name.c_str(),
					pFilePath );

		return false;
	}

	////////////////////////////////////////////////////////////////////////////////////////////////////
	// データヘッダ : デフォルト
	////////////////////////////////////////////////////////////////////////////////////////////////////

	dataHeader.shaderType = m_ShaderType;
	dataHeader.blendMode = m_BlendMode;

	switch( m_TextureFilterType )
	{
	case D3DTEXF_LINEAR:
		dataHeader.texFilterType = Material::MTL_TEXF_LINEAR;
		break;
	case D3DTEXF_ANISOTROPIC:
		dataHeader.texFilterType = Material::MTL_TEXF_ANISOTROPIC;
		break;
	default:
		dataHeader.texFilterType = Material::MTL_TEXF_POINT;
		break;
	}

	switch( m_TextureAddressType )
	{
	case D3DTADDRESS_CLAMP:
		dataHeader.texAddressType = Material::MTL_TEXA_CLAMP;
		break;
	default:
		dataHeader.texAddressType = Material::MTL_TEXA_WRAP;
		break;
	}

	dataHeader.flags = 0;

	if( m_bBackculling == true ) { dataHeader.flags |= Material::MTL_BACKCULLING; }
	if( m_bBothLighting == true ) { dataHeader.flags |= Material::MTL_BOTH_LIGHTING; }

	if( m_bTransparency == true )
	{
		dataHeader.flags |= Material::MTL_TRANSPARENCY;

		if( m_bZWrite == true ) { dataHeader.flags |= Material::MTL_ZWRITE; }
		if( m_bSoftEdge == true ) { dataHeader.flags |= Material::MTL_SOFTPARTICLE; }
	}
	else
	{
		dataHeader.flags |= Material::MTL_ZWRITE;
	}

	if( m_bDiffuseFresnel == true ) { dataHeader.flags |= Material::MTL_DIFFUSE_FRESNEL; }
	if( m_bDiffuseRL == true ) { dataHeader.flags |= Material::MTL_DIFFUSE_RIMLIGHTING; }

	if( MIX_TEST_BIT( procFlags, SHADER_PROCESS_SHADOW ) == SHADER_PROCESS_SHADOW )
	{
		if( this->m_bShadowReceive == true ) { dataHeader.flags |= Material::MTL_SHADOW_RECEIVE; }
		if( this->m_bShadowCast == true ) { dataHeader.flags |= Material::MTL_SHADOW_CAST; }
	}

	if( ( m_ShaderType != Mix::Tool::Win32::Graphics::SHADER_WATER ) &&
		( m_pDiffuseTexture != NULL ) )
	{
		dataHeader.flags |= Material::MTL_DIFFUSE_TEXTURE;
	}

	if( ( m_ShaderType != SHADER_SHADELESS ) &&
		( m_ShaderType != Mix::Tool::Win32::Graphics::SHADER_WATER ) &&
		( m_SpecularType != Mix::Tool::Win32::Graphics::SPECULAR_NONE ) &&
		( m_pSpecularTexture != NULL ) )
	{
		dataHeader.flags |= Material::MTL_SPECULAR_TEXTURE;
	}

	if( ( m_ShaderType != Mix::Tool::Win32::Graphics::SHADER_WATER ) &&
		( m_pEmissiveTexture != NULL ) )
	{
		dataHeader.flags |= Material::MTL_EMISSIVE_TEXTURE;
	}

	if( ( m_ShaderType != SHADER_SHADELESS ) &&
		( m_pBumpTexture != NULL ) )
	{
		dataHeader.flags |= Material::MTL_BUMP_TEXTURE;
	}

	dataHeader.transparencyMethod = m_TransparencyMethod;

	dataHeader.ambientColor = m_AmbientColor;

	dataHeader.diffuseType = m_DiffuseType;
	dataHeader.diffuseColor = m_DiffuseColor;
	dataHeader.diffuseFresnelRatio = m_DiffuseFresnelRatio;
	dataHeader.diffuseRLHardness = m_DiffuseRLScale;
	dataHeader.diffuseRLScale = m_DiffuseRLScale;

	dataHeader.specularType = m_SpecularType;
	dataHeader.specularColor = m_SpecularColor;
	dataHeader.specularHardness = m_SpecularHardness;
	dataHeader.specularScale = m_SpecularScale;
	dataHeader.specularCTFresnel = m_SpecularCTFresnel;
	dataHeader.specularCTRoughness = m_SpecularCTRoughness;

	dataHeader.reflectType = m_ReflectType;
	dataHeader.reflectScale = m_ReflectScale;
	dataHeader.reflectIntensity = m_ReflectIntensity;
	dataHeader.reflectBias = m_ReflectBias;
	dataHeader.reflectExprosure = m_ReflectExprosure;

	dataHeader.emissiveColor = m_EmissiveColor;
	dataHeader.emissiveScale = m_EmissiveScale;

	dataHeader.bumpType = m_BumpType;
	dataHeader.bumpHeightScale = m_BumpHeightScale;
	dataHeader.bumpSample = m_BumpSample;
	dataHeader.bumpReflectRatio = m_ReflectBumpRatio;

	dataHeader.waveType = m_WaveType;
	dataHeader.waveDir = m_WaveDir;
	dataHeader.waveVelocity = m_WaveVelocity;
	dataHeader.waveUVOffset = m_WaveUVOffset;
	dataHeader.waveGap = m_WaveGap;

	dataHeader.refractRatio = m_WaveRefractRatio;

	dataHeader.particleThickness = m_SoftEdgeThickness;

	if( output.Write( &dataHeader, sizeof( dataHeader ) ) == false )
	{
		LogPrint(	LT_ERROR, L"マテリアルの保存に失敗しました : 書き込み中にエラーが発生 : Location[%s/%s] FilePath[%s]",
					m_pSlot->GetName(),
					m_Name.c_str(),
					pFilePath );

		return false;
	}

	////////////////////////////////////////////////////////////////////////////////////////////////////
	// ディフューズテクスチャ
	////////////////////////////////////////////////////////////////////////////////////////////////////

	if( MIX_TEST_BIT( dataHeader.flags, Material::MTL_DIFFUSE_TEXTURE ) == Material::MTL_DIFFUSE_TEXTURE )
	{
		if( Material::SaveTexture( m_pDiffuseTexture, output ) == false )
		{
			LogPrint(	LT_ERROR, L"マテリアルの保存に失敗しました : 書き込み中にエラーが発生 : Location[%s/%s] FilePath[%s]",
						m_pSlot->GetName(),
						m_Name.c_str(),
						pFilePath );

			return false;
		}
	}

	////////////////////////////////////////////////////////////////////////////////////////////////////
	// スペキュラテクスチャ
	////////////////////////////////////////////////////////////////////////////////////////////////////

	if( MIX_TEST_BIT( dataHeader.flags, Material::MTL_SPECULAR_TEXTURE ) == Material::MTL_SPECULAR_TEXTURE )
	{
		if( Material::SaveTexture( m_pSpecularTexture, output ) == false )
		{
			LogPrint(	LT_ERROR, L"マテリアルの保存に失敗しました : 書き込み中にエラーが発生 : Location[%s/%s] FilePath[%s]",
						m_pSlot->GetName(),
						m_Name.c_str(),
						pFilePath );

			return false;
		}
	}

	////////////////////////////////////////////////////////////////////////////////////////////////////
	// エミッシブテクスチャ
	////////////////////////////////////////////////////////////////////////////////////////////////////

	if( MIX_TEST_BIT( dataHeader.flags, Material::MTL_EMISSIVE_TEXTURE ) == Material::MTL_EMISSIVE_TEXTURE )
	{
		if( Material::SaveTexture( m_pEmissiveTexture, output ) == false )
		{
			LogPrint(	LT_ERROR, L"マテリアルの保存に失敗しました : 書き込み中にエラーが発生 : Location[%s/%s] FilePath[%s]",
						m_pSlot->GetName(),
						m_Name.c_str(),
						pFilePath );

			return false;
		}
	}

	////////////////////////////////////////////////////////////////////////////////////////////////////
	// バンプテクスチャ
	////////////////////////////////////////////////////////////////////////////////////////////////////

	if( MIX_TEST_BIT( dataHeader.flags, Material::MTL_BUMP_TEXTURE ) == Material::MTL_BUMP_TEXTURE )
	{
		if( Material::SaveTexture( m_pBumpTexture, output ) == false )
		{
			LogPrint(	LT_ERROR, L"マテリアルの保存に失敗しました : 書き込み中にエラーが発生 : Location[%s/%s] FilePath[%s]",
						m_pSlot->GetName(),
						m_Name.c_str(),
						pFilePath );

			return false;
		}
	}

	////////////////////////////////////////////////////////////////////////////////////////////////////
	// シェーダーを登録
	////////////////////////////////////////////////////////////////////////////////////////////////////

	m_pShader->Register();

	return true;
}

void Material::OnActivate( bool bActive )
{
	m_bActive = bActive;
}

void Material::OnUpdate( int baseFrameRate, float mag )
{
	m_WaveUV = m_WaveDirVec * m_WavePos;

	m_WavePos += m_WaveVelocity / static_cast<float>( baseFrameRate ) * mag;
	if( m_WavePos >= 1.0f )
	{
		m_WavePos -= 1.0f;
	}
}

void Material::OnUpdateShader( unsigned int flags )
{
	////////////////////////////////////////////////////////////////////////////////////////////////////
	// マネージャを取得
	////////////////////////////////////////////////////////////////////////////////////////////////////

	Mix::Tool::Win32::Graphics::Manager* pManager = Manager::GetInstance();
	if( pManager == NULL )
	{
		return;
	}

	////////////////////////////////////////////////////////////////////////////////////////////////////
	// コンパイルフラグを準備
	////////////////////////////////////////////////////////////////////////////////////////////////////

	unsigned int procFlags = pManager->MEP_GetProcessFlags();
	unsigned int compileFlags = flags;

	//ライティング
	if( m_ShaderType != Mix::Tool::Win32::Graphics::SHADER_SHADELESS )
	{
		MIX_SET_BIT( compileFlags, MCF_LIGHTING );

		if( m_bBothLighting == true )
		{
			MIX_SET_BIT( compileFlags, MCF_BOTH_LIGHTING );
		}
	}

	//半透明の屈折クリップ
	if( ( MIX_TEST_BIT( procFlags, SHADER_PROCESS_REFRACT ) == SHADER_PROCESS_REFRACT ) &&
		( m_ShaderType != Mix::Tool::Win32::Graphics::SHADER_WATER ) &&
		( m_bTransparency == true ) )
	{
		MIX_SET_BIT( compileFlags, MCF_REFRACT_CLIP );
	}

	//ディフューズ
	{
		if( m_ShaderType != Mix::Tool::Win32::Graphics::SHADER_SHADELESS )
		{
			if( m_DiffuseType == Mix::Tool::Win32::Graphics::DIFFUSE_HALF_LAMBERT )
			{
				MIX_SET_BIT( compileFlags, MCF_DIFFUSE_HALF_LAMBERT );
			}

			if( m_bDiffuseFresnel == true )
			{
				MIX_SET_BIT( compileFlags, MCF_DIFFUSE_FRESNEL );
			}

			if( m_bDiffuseRL == true )
			{
				MIX_SET_BIT( compileFlags, MCF_DIFFUSE_RIM_LIGHTING );
			}
		}

		if( ( m_ShaderType != Mix::Tool::Win32::Graphics::SHADER_WATER ) &&
			( m_pDiffuseTexture != NULL ) )
		{
			MIX_SET_BIT( compileFlags, MCF_DIFFUSE_MAPPING );
		}
	}

	//スペキュラー
	if( ( m_ShaderType != Mix::Tool::Win32::Graphics::SHADER_SHADELESS ) &&
		( m_SpecularType != Mix::Tool::Win32::Graphics::SPECULAR_NONE ) )
	{
		switch( m_SpecularType )
		{
		case Mix::Tool::Win32::Graphics::SPECULAR_PHONG:
			MIX_SET_BIT( compileFlags, MCF_SPECULAR_PHONG );
			break;
		case Mix::Tool::Win32::Graphics::SPECULAR_BLINN_PHONG:
			MIX_SET_BIT( compileFlags, MCF_SPECULAR_BLINN_PHONG );
			break;
		case Mix::Tool::Win32::Graphics::SPECULAR_COOK_TORRANCE:
			MIX_SET_BIT( compileFlags, MCF_SPECULAR_COOK_TORRANCE );
			break;
		}

		if( ( m_ShaderType != Mix::Tool::Win32::Graphics::SHADER_WATER ) &&
			( m_pSpecularTexture != NULL ) )
		{
			MIX_SET_BIT( compileFlags, MCF_SPECULAR_MAPPING );
		}

		switch( m_ReflectType )
		{
		case Mix::Tool::Win32::Graphics::REFLECT_NORMAL:
			MIX_SET_BIT( compileFlags, MCF_REFLECT_MAPPING );
			break;
		case Mix::Tool::Win32::Graphics::REFLECT_FRESNEL:
			MIX_SET_BIT( compileFlags, MCF_REFLECT_MAPPING );
			MIX_SET_BIT( compileFlags, MCF_REFLECT_FRESNEL );
			break;
		}
	}

	//エミッシブ
	if( ( m_ShaderType != Mix::Tool::Win32::Graphics::SHADER_WATER ) &&
		( m_pEmissiveTexture != NULL ) )
	{
		MIX_SET_BIT( compileFlags, MCF_EMISSIVE_MAPPING );
	}

	//バンプ
	if( ( m_ShaderType != Mix::Tool::Win32::Graphics::SHADER_SHADELESS ) &&
		( m_pBumpTexture != NULL ) )
	{
		MIX_SET_BIT( compileFlags, MCF_BUMP_MAPPING );

		if( m_BumpType == Mix::Tool::Win32::Graphics::BUMP_PARALLAX_MAPPING )
		{
			MIX_SET_BIT( compileFlags, MCF_PARALLAX );
		}
	}

	//ウォーター
	if( m_ShaderType == Mix::Tool::Win32::Graphics::SHADER_WATER )
	{
		MIX_SET_BIT( compileFlags, MCF_WATER );
/*
		if( ( MIX_TEST_BIT( procFlags, SHADER_PROCESS_REFRACT ) == SHADER_PROCESS_REFRACT ) &&
			( m_ShaderType != Mix::Tool::Win32::Graphics::SHADER_SHADELESS ) &&
			( m_bTransparency == true ) &&
			( m_pBumpTexture != NULL ) &&
			( m_WaveType == Mix::Tool::Win32::Graphics::WAVE_REFRACT ) )
		{
			MIX_SET_BIT( compileFlags, MCF_REFRACT_MAPPING );
		}
*/
		if( m_pBumpTexture != NULL )
		{
			if( ( MIX_TEST_BIT( procFlags, SHADER_PROCESS_REFRACT ) == SHADER_PROCESS_REFRACT ) &&
				( m_bTransparency == true ) &&
				( m_WaveType == Mix::Tool::Win32::Graphics::WAVE_REFRACT ) )
			{
				MIX_SET_BIT( compileFlags, MCF_REFRACT_MAPPING );
			}

			if( m_bWaveInvert == true )
			{
				MIX_SET_BIT( compileFlags, MCF_WAVE_INVERT );
			}
		}
	}

	//ソフトエッジ
//	if( ( MIX_TEST_BIT( procFlags, SHADER_PROCESS_SOFTPARTICLE ) == SHADER_PROCESS_SOFTPARTICLE ) &&
//		( m_bTransparency == true ) &&
//		( m_bSoftEdge == true ) )
	if( ( m_bTransparency == true ) && ( m_bSoftEdge == true ) )
	{
		MIX_SET_BIT( compileFlags, MCF_SOFTPARTICLE );
	}

	//フォグ
	if( MIX_TEST_BIT( procFlags, SHADER_PROCESS_FOG ) == SHADER_PROCESS_FOG )
	{
		MIX_SET_BIT( compileFlags, MCF_FOG );
	}

	//シャドウ
	if( MIX_TEST_BIT( procFlags, SHADER_PROCESS_SHADOW ) == SHADER_PROCESS_SHADOW )
	{
		MIX_SET_BIT( compileFlags, MCF_SHADOW ); //出力することを意味する

		if( ( m_ShaderType != Mix::Tool::Win32::Graphics::SHADER_SHADELESS ) &&
			( m_bShadowReceive == true ) )
		{
			//レシーブはバイアスを適用する際に法線を使用するので、ライティングが有効な場合に限る
			MIX_SET_BIT( compileFlags, MCF_SHADOW_RECEIVE );
		}
	}

	//大気散乱シミュレーション
	if( MIX_TEST_BIT( procFlags, SHADER_PROCESS_ATMOSPHERE ) == SHADER_PROCESS_ATMOSPHERE )
	{
		MIX_SET_BIT( compileFlags, MCF_ATMOSPHERE );
	}

	//SSAO
	if( MIX_TEST_BIT( procFlags, SHADER_PROCESS_SSAO ) == SHADER_PROCESS_SSAO )
	{
		MIX_SET_BIT( compileFlags, MCF_SSAO );
	}

	////////////////////////////////////////////////////////////////////////////////////////////////////
	// シェーダーをコンパイル
	////////////////////////////////////////////////////////////////////////////////////////////////////

	m_pShader->Compile( compileFlags );
}

void Material::AutoUpdate( void )
{
	if( m_bAutoUpdate == true )
	{
		Update();
	}
}
/*
Mix::Tool::Win32::Graphics::FileTexture* Material::LoadTexture( const wchar_t* pFileName, const wchar_t* pTypeName, Mix::Tool::Win32::Graphics::Manager* pMgr, Mix::Tool::Win32::File::InputStream& input )
{
	std::wstringstream registerName;
	std::vector<unsigned char> buffer;
	unsigned int bufferSize = 0;

	////////////////////////////////////////////////////////////////////////////////////////////////////
	// テクスチャの登録名を作成
	////////////////////////////////////////////////////////////////////////////////////////////////////

	registerName << pFileName << L"\\" << pTypeName;

	////////////////////////////////////////////////////////////////////////////////////////////////////
	// バッファサイズを読み込む
	////////////////////////////////////////////////////////////////////////////////////////////////////

	if( input.Read( &bufferSize, sizeof( bufferSize ) ) == false )
	{
		return NULL;
	}

	////////////////////////////////////////////////////////////////////////////////////////////////////
	// バッファを読み込む
	////////////////////////////////////////////////////////////////////////////////////////////////////

	buffer.resize( bufferSize );
	if( buffer.size() != bufferSize )
	{
		return false;
	}

	if( input.Read( &( buffer[0] ), buffer.size() ) == false )
	{
		return false;
	}

	////////////////////////////////////////////////////////////////////////////////////////////////////
	// テクスチャを作成
	////////////////////////////////////////////////////////////////////////////////////////////////////

	return pMgr->CreateTexture( registerName.str().c_str(), &( buffer[0] ), buffer.size() );
}
*/
bool Material::SaveTexture( Mix::Tool::Win32::Graphics::FileTexture* pTexture, Mix::Tool::Win32::File::OutputStream& output )
{
	////////////////////////////////////////////////////////////////////////////////////////////////////
	// テクスチャを書き込む
	////////////////////////////////////////////////////////////////////////////////////////////////////

	unsigned int bufferSize = pTexture->GetBufferSize();

	if( output.Write( &bufferSize, sizeof( bufferSize ) ) == false )
	{
		return false;
	}

	if( output.Write( pTexture->GetBuffer(), bufferSize ) == false )
	{
		return false;
	}

	return true;
}

}}}}
