//------------------------------------------------------------------------------
// Lamp : Open source game middleware
// Copyright (C) 2004  Junpei Ohtani ( Email : junpee@users.sourceforge.jp )
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
//------------------------------------------------------------------------------

/** @file
 * 3Dサウンドヘッダ
 * @author Junpee
 */

#ifndef SOUND_3D_H_
#define SOUND_3D_H_

#include <Sound/System/SoundBuffer.h>

namespace Lamp{

//------------------------------------------------------------------------------
/**
 * 3Dサウンド
 */
class Sound3D : public SoundBuffer{
public:
	//--------------------------------------------------------------------------
	// 再生
	//--------------------------------------------------------------------------
	/**
	 * 再生
	 * @return 正常に再生されればtrue
	 */
	virtual bool play(){
		apply3DSettings();
		return SoundBuffer::play();
	}

	//--------------------------------------------------------------------------
	// 3Dパラメータ
	//--------------------------------------------------------------------------
	/**
	 * 位置の設定
	 * @param position 位置
	 */
	virtual void setPosition(const Vector3& position);

	/**
	 * 位置の取得
	 * @return 位置
	 */
	virtual const Vector3& getPosition() const{ return position_; }

	/**
	 * 速度の設定
	 * @param velocity 速度
	 */
	virtual void setVelocity(const Vector3& velocity);

	/**
	 * 速度の取得
	 * @return 速度
	 */
	virtual const Vector3& getVelocity() const{ return velocity_; }

	/**
	 * 位置と速度の設定
	 * @param position 位置
	 * @param millisecond 前回からの時間をミリ秒で設定
	 */
	virtual void setPositionAndVelocity(
		const Vector3& position, float millisecond);

	//--------------------------------------------------------------------------
	/**
	 * 最小距離の設定
	 * @param minimumDistance 最小距離
	 */
	virtual void setMinimumDistance(float minimumDistance);

	/**
	 * 最小距離の取得
	 * @return 最小距離
	 */
	virtual float getMinimumDistance() const{ return minimumDistance_; }

	/**
	 * 最大距離の設定
	 * @param maximumDistance 最大距離
	 */
	virtual void setMaximumDistance(float maximumDistance);

	/**
	 * 最大距離の取得
	 * @return 最大距離
	 */
	virtual float getMaximumDistance() const{ return maximumDistance_; }

	/**
	 * 距離の設定
	 * @param minimumDistance 最小距離
	 * @param maximumDistance 最大距離
	 */
	virtual void setDistance(float minimumDistance, float maximumDistance){
		Assert(minimumDistance <= maximumDistance);
		setMinimumDistance(minimumDistance);
		setMaximumDistance(maximumDistance);
	}

	//--------------------------------------------------------------------------
	/**
	 * コーンの向きの設定
	 * @param coneDirection コーンの向き
	 */
	virtual void setConeDirection(const Vector3& coneDirection);

	/**
	 * コーンの向きの取得
	 * @return コーンの向き
	 */
	virtual const Vector3& getConeDirection() const{ return coneDirection_; }

	//--------------------------------------------------------------------------
	/**
	 * コーン角度の設定
	 * @param insideConeAngle 内側コーン角度をラジアンで指定
	 * @param outsideConeAngle 外側コーン角度をラジアンで指定
	 */
	virtual void setConeAngle(float insideConeAngle, float outsideConeAngle);

	/**
	 * 内側コーン角度の取得
	 * @return ラジアンによる内側コーン角度
	 */
	virtual float getInsideConeAngle() const{ return insideConeAngle_; }

	/**
	 * 外側コーン角度の取得
	 * @return ラジアンによる外側コーン角度
	 */
	virtual float getOutsideConeAngle() const{ return outsideConeAngle_; }

	//--------------------------------------------------------------------------
	/**
	 * コーン外側ボリュームの設定
	 * @param coneOutsideVolume コーン外側ボリュームを0.fから1.fの間で指定
	 */
	virtual void setConeOutsideVolume(float coneOutsideVolume);

	/**
	 * コーン外側ボリュームの取得
	 * @return コーン外側ボリューム
	 */
	virtual float getConeOutsideVolume() const{ return coneOutsideVolume_; }

	//--------------------------------------------------------------------------
	/**
	 * 3Dの有効、無効設定
	 * @param enabled 3Dが有効ならtrue
	 */
	virtual void set3DEnabled(bool enabled);

	/**
	 * 3Dが有効か
	 * @return 3Dが有効ならtrue
	 */
	virtual bool is3DEnabled() const{ return is3DEnabled_; }

	//--------------------------------------------------------------------------
	/**
	 * 3D設定の適用
	 *
	 * 通常はLampSound::presentation()から呼ばれます。
	 */
	virtual void apply3DSettings();

	//--------------------------------------------------------------------------
	// その他
	//--------------------------------------------------------------------------
	/**
	 * リセット
	 * @param flags リセットフラグ
	 */
	virtual void reset(Reset flags);

	//--------------------------------------------------------------------------
	/**
	 * 文字列への変換
	 * @return 文字列
	 */
	virtual String toString() const;

	//--------------------------------------------------------------------------
	// RTTI
	//--------------------------------------------------------------------------
	/**
	 * 3Dサウンドかどうか
	 * @return 3Dサウンドならtrue
	 */
	virtual bool isSound3D() const{ return true; }

protected:
	//--------------------------------------------------------------------------
	/**
	 * コンストラクタ
	 * @param soundBuffer サウンドバッファ
	 */
	Sound3D(DirectSoundBuffer* soundBuffer);

	/**
	 * デストラクタ
	 */
	virtual ~Sound3D();

	/**
	 * 3Dサウンドデータのコピー
	 * @param destination コピー先3Dサウンド
	 */
	virtual void copySound3DData(Sound3D* destination);

private:
	//--------------------------------------------------------------------------
	// 3Dバッファ
	DirectSound3DBuffer* sound3DBuffer_;
	// 位置
	Vector3 position_;
	// 速度
	Vector3 velocity_;
	// コーンの向き
	Vector3 coneDirection_;
	// 最小距離
	float minimumDistance_;
	// 最大距離
	float maximumDistance_;
	// 内側コーン角度
	float insideConeAngle_;
	// 外側コーン角度
	float outsideConeAngle_;
	// コーン外側ボリューム
	float coneOutsideVolume_;
	// 3Dが有効か
	bool is3DEnabled_;

};

//------------------------------------------------------------------------------
} // End of namespace Lamp
#endif // End of SOUND_3D_H_
//------------------------------------------------------------------------------
