//------------------------------------------------------------------------------
// 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
 * テクスチャヘッダ
 * @author Junpee
 */

#ifndef TEXTURE_H_
#define TEXTURE_H_

#include <Graphics/Scene/SceneObject.h>
#include <Core/Container/ArrayList.h>

namespace Lamp{

class Picture;
class SurfaceTexture;

//------------------------------------------------------------------------------
/**
 * テクスチャ
 */
class Texture : public SceneObject{
friend class SceneObjectManagerTemplate<Texture>;
friend class TextureManager;
friend class Material;
friend class RenderingDevice;
public:
	/**
	 * リファレンスカウントの取得
	 * @return リファレンスカウント
	 */
	virtual int getReferenceCount() const{ return parents_.getCount(); }

	//--------------------------------------------------------------------------
	/**
	 * コピー
	 * @param copyMask コピーマスク
	 * @return コピーされたテクスチャ
	 */
	virtual Texture* copy(u_int copyMask = 0) const = 0;

	/**
	 * 再帰的破棄
	 * @param texture 破棄するテクスチャ
	 * @return 破棄したオブジェクト数
	 */
	static int recursiveDestroy(Texture* texture);

	//--------------------------------------------------------------------------
	/**
	 * ステート変更フラグを立てる
	 */
	virtual void stateChanged();

	//--------------------------------------------------------------------------
	/**
	 * 親のサイズ取得
	 * @return 親のサイズ
	 */
	virtual int getParentCount() const{ return parents_.getCount(); }

	/**
	 * 親の取得
	 * @param index 親のインデックス
	 * @return 親
	 */
	virtual Material* getParent(int index) const{
		Assert(index >= 0);
		Assert(index < getParentCount());
		return parents_.get(index);
	}

	//--------------------------------------------------------------------------
	// アドレスモード
	//--------------------------------------------------------------------------
	/// アドレスモード
	enum AddressMode{
		addressModeWrap = 0,
		addressModeClamp,
		addressModeMirror,
		addressModeMax,
	};

	/**
	 * アドレスモードから文字列への変換
	 * @param addressMode アドレスモード
	 * @return アドレスモード文字列
	 */
	static const String& addressModeToString(AddressMode addressMode);

	/**
	 * 文字列からアドレスモードへの変換
	 * @param addressModeString アドレスモード文字列
	 * @return アドレスモード
	 */
	static AddressMode addressModeFromString(const String& addressModeString);

	//--------------------------------------------------------------------------
	// ピクチャインターフェース
	//--------------------------------------------------------------------------
	/**
	 * ピクチャの追加
	 * @param picture 追加するピクチャ
	 */
	virtual void addPicture(Picture* picture) = 0;

	/**
	 * ピクチャの削除
	 * @param picture 削除するピクチャ
	 */
	virtual void removePicture(Picture* picture) = 0;

	/**
	 * ピクチャ数の取得
	 * @return ピクチャ数
	 */
	virtual int getPictureCount() const = 0;

	/**
	 * ピクチャの取得
	 * @param index インデックス
	 * @return ピクチャ
	 */
	virtual Picture* getPicture(int index) const = 0;

	//--------------------------------------------------------------------------
	// RTTI
	//--------------------------------------------------------------------------
	/**
	 * テクスチャかどうか
	 * @return テクスチャならtrue
	 */
	virtual bool isTexture() const{ return true; }

	//--------------------------------------------------------------------------
	/**
	 * サーフェーステクスチャかどうか
	 * @return サーフェーステクスチャならtrue
	 */
	virtual bool isSurfaceTexture() const{ return false; }

	/**
	 * サーフェーステクスチャへのキャスト
	 * @return サーフェーステクスチャ。型が違えばNULLを返す。
	 */
	virtual SurfaceTexture* castSurfaceTexture() const{
		if(isSurfaceTexture()){ return (SurfaceTexture*)this; }
		return NULL;
	}

	//--------------------------------------------------------------------------
protected:
	/**
	 * コンストラクタ
	 * @param name 名前
	 * @param scene シーン
	 */
	Texture(const String& name, Scene* scene);

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

	/**
	 * テクスチャの値コピー
	 * @param destination コピー先テクスチャ
	 * @param copyMask コピーマスク
	 */
	virtual void copyTextureValue(Texture* destination, u_int copyMask) const;

	/**
	 * 参照の追加
	 * @param parent 親
	 * @return 参照カウント
	 */
	virtual int addReference(Material* parent){
		parents_.add(parent);
		return getParentCount();
	}

	/**
	 * 参照の削除
	 * @param parent 親
	 * @return 参照カウント
	 */
	virtual int removeReference(Material* parent){
		parents_.removeByValue(parent);
		return getParentCount();
	}

	/**
	 * ピクチャリファレンスの追加
	 * @param picture リファレンスを追加するピクチャ
	 */
	virtual void addPictureReference(Picture* picture);

	/**
	 * ピクチャリファレンスの削除
	 * @param picture リファレンスを削除するピクチャ
	 */
	virtual void removePictureReference(Picture* picture);

	/**
	 * D3Dテクスチャの取得
	 * @return D3Dテクスチャの取得
	 */
	virtual Direct3DTexture* getD3DTexture() = 0;

	//--------------------------------------------------------------------------
private:
	// 親配列
	ArrayList<Material*> parents_;

	// アドレスモード文字列テーブル
	static const String addressModeStringTable[];

};

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

