//******************************************************************************
//
// MIDITrail / MTBackgroundImage
//
// 背景画像描画クラス
//
// Copyright (C) 2017-2021 WADA Masashi. All Rights Reserved.
//
//******************************************************************************

#include "YNBaseLib.h"
#include "MTParam.h"
#include "MTConfFile.h"
#include "MTBackgroundImage.h"


//******************************************************************************
// コンストラクタ
//******************************************************************************
MTBackgroundImage::MTBackgroundImage(void)
{
	m_pView = nil;
	m_isEnable = true;
}

//******************************************************************************
// デストラクタ
//******************************************************************************
MTBackgroundImage::~MTBackgroundImage(void)
{
	Release();
}

//******************************************************************************
// 背景画像生成
//******************************************************************************
int MTBackgroundImage::Create(
		OGLDevice* pOGLDevice,
		UIView* pView
	)
{
	int result = 0;
	unsigned int vertexNum = 0;
	unsigned int indexNum = 0;
	MTBACKGROUNDIMAGE_VERTEX* pVertex = NULL;
	unsigned int* pIndex = NULL;

	Release();

	m_pView = pView;

	//テクスチャ読み込み
	result = _LoadTexture(pOGLDevice);
	if (result != 0) goto EXIT;

	//テクスチャを生成しなかった場合は何もしない
	if (m_Texture.GetWidth() == 0) goto EXIT;

	//プリミティブ初期化
	result = m_Primitive.Initialize(
					sizeof(MTBACKGROUNDIMAGE_VERTEX),	//頂点サイズ
					_GetFVFFormat(),			//頂点FVFフォーマット
					GL_TRIANGLE_STRIP			//プリミティブ種別
				);
	if (result != 0) goto EXIT;

	//頂点バッファ生成
	vertexNum = 4;
	result = m_Primitive.CreateVertexBuffer(pOGLDevice, vertexNum);
	if (result != 0) goto EXIT;

	//インデックスバッファ生成
	indexNum = 4;
	result = m_Primitive.CreateIndexBuffer(pOGLDevice, indexNum);
	if (result != 0) goto EXIT;

	//バッファのロック
	result = m_Primitive.LockVertex((void**)&pVertex);
	if (result != 0) goto EXIT;
	result = m_Primitive.LockIndex(&pIndex);
	if (result != 0) goto EXIT;

	//バッファに頂点とインデックスを書き込む
	result = _CreateVertexOfBackground(
					pOGLDevice,
					pVertex,		//頂点バッファ書き込み位置
					pIndex			//インデックスバッファ書き込み位置
				);
	if (result != 0) goto EXIT;

	//バッファのロック解除
	result = m_Primitive.UnlockVertex();
	if (result != 0) goto EXIT;
	result = m_Primitive.UnlockIndex();
	if (result != 0) goto EXIT;

EXIT:;
	return result;
}

//******************************************************************************
// 描画
//******************************************************************************
int MTBackgroundImage::Draw(
		OGLDevice* pOGLDevice
	)
{
	int result = 0;
	GLboolean isEnableDepthTest = false;
    OGLTransMatrix transMatrix;
    OGLVIEWPORT viewPort;
    GLint depthFunc = 0;
    
	if (!m_isEnable) goto EXIT;
	if (m_Texture.GetWidth() == 0) goto EXIT;
    
	//Zバッファを一時的に無効化する
	glGetBooleanv(GL_DEPTH_TEST, &isEnableDepthTest);
	glDisable(GL_DEPTH_TEST);
	
	//テクスチャステージ設定
	glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
	//  カラー演算：引数1を使用  引数1：テクスチャ
	glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_REPLACE);
	glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_RGB, GL_TEXTURE);
	// アルファ演算：引数1を使用  引数1：テクスチャ
	glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE);
	glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_ALPHA, GL_TEXTURE);
	
	//テクスチャフィルタ
	//OGLTexture::BindTexture()で対応
    
    //正射影
    pOGLDevice->GetViewPort(&viewPort);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glOrthof(0, viewPort.width, viewPort.height, 0, -1, 1);
    
    //深度テストを無効化
    glGetIntegerv(GL_DEPTH_FUNC, &depthFunc);
    glDepthFunc(GL_ALWAYS);
    
	//描画
	result = m_Primitive.Draw(pOGLDevice, &m_Texture);
	if (result != 0) goto EXIT;
    
    //深度テストを戻す
    glDepthFunc(depthFunc);
    
	//Zバッファ有効化状態を戻す
	if (isEnableDepthTest) {
		glEnable(GL_DEPTH_TEST);
	}
    
EXIT:;
	return result;
}

//******************************************************************************
// 解放
//******************************************************************************
void MTBackgroundImage::Release()
{
	m_Primitive.Release();
}

//******************************************************************************
// 背景画像頂点生成
//******************************************************************************
int MTBackgroundImage::_CreateVertexOfBackground(
		OGLDevice* pOGLDevice,
		MTBACKGROUNDIMAGE_VERTEX* pVertex,
		unsigned int* pIndex
	)
{
	int result = 0;
	unsigned int i = 0;
	unsigned int cw = 0;
	unsigned int ch = 0;
	float ratio_cwh = 0.0f;
	float ratio_iwh = 0.0f;
	float x1 = 0.0f;
	float x2 = 0.0f;
	float y1 = 0.0f;
	float y2 = 0.0f;
	OGLVIEWPORT viewPort;
	
	pOGLDevice->GetViewPort(&viewPort);
	
	//クライアント領域のサイズを取得
	cw = viewPort.width;
	ch = viewPort.height;
	
	ratio_cwh = (float)cw / (float)ch;
	ratio_iwh = (float)m_Texture.GetWidth() / (float)m_Texture.GetHeight();

	// クライアント領域より画像の方が横長の場合
	//     |----- cw -----|
	//  ---0--------------+-- +x
	//   | |              |
	//   | +--------------+
	//  ch |    image     |
	//   | +--------------+
	//   | |              |
	//  ---+--------------+
	//     |
	//    +y
	if (ratio_cwh < ratio_iwh) {
		x1 = 0.0f;
		x2 = (float)cw;
		y1 = ((float)ch - ((float)cw / ratio_iwh)) / 2.0f;
		y2 = (float)ch - y1;
	}
	// クライアント領域より画像の方が縦長の場合
	//     |----- cw -----|
	//  ---0--+--------+--+-- +x
	//   | |  |        |  |
	//   | |  |        |  |
	//  ch |  | image  |  |
	//   | |  |        |  |
	//   | |  |        |  |
	//  ---+--+--------+--+
	//     |
	//    +y
	else {
		x1 = ((float)cw - ((float)ch * ratio_iwh)) / 2.0f;
        x2 = (float)cw - x1;
		y1 = 0.0f;
        y2 = (float)ch;
	}
    
	//頂点座標
	pVertex[0].p = OGLVECTOR3(x1, y1, 0.0f);
	pVertex[1].p = OGLVECTOR3(x2, y1, 0.0f);
	pVertex[2].p = OGLVECTOR3(x1, y2, 0.0f);
	pVertex[3].p = OGLVECTOR3(x2, y2, 0.0f);

	//各頂点のディフューズ色
	for (i = 0; i < 4; i++) {
		//各頂点のディフューズ色
		pVertex[i].c = OGLCOLOR(1.0f, 1.0f, 1.0f, 1.0f);
	}

	//各頂点のテクスチャ座標
	pVertex[0].t = OGLVECTOR2(0.0f, 0.0f);
	pVertex[1].t = OGLVECTOR2(1.0f, 0.0f);
	pVertex[2].t = OGLVECTOR2(0.0f, 1.0f);
	pVertex[3].t = OGLVECTOR2(1.0f, 1.0f);

	//インデックス：TRIANGLESTRIP
	pIndex[0] = 0;
	pIndex[1] = 1;
	pIndex[2] = 2;
	pIndex[3] = 3;

EXIT:;
	return result;
}

//******************************************************************************
// テクスチャ画像読み込み
//******************************************************************************
int MTBackgroundImage::_LoadTexture(
		OGLDevice* pOGLDevice
	)
{
	int result = 0;
    YNUserConf* pUserConf = nil;
    NSString* pImgFileSubPath = nil;
    NSString* pImgFilePath = nil;
	NSFileManager* pFileManager = nil;
    NSArray* pPathList = nil;
    NSString* pDocDirPath = nil;
    
    //ユーザ設定初期化
    pUserConf = [[YNUserConf alloc] init];
    if (pUserConf == nil) {
        result = YN_SET_ERR(@"Program error.", 0, 0);
        goto EXIT;
    }
    
	//背景画像の設定を取得
	//  MIDITrail Ver.1.3.3からサブディレクトリ内の画像ファイルの選択に対応するため
	//  "ImageFileName"キーの値はDocumentsディレクトリより後のサブパスを格納する
	//  Ver.1.3.2以前からの互換性を維持するためキーの名前は変更していない
	[pUserConf setCategory:MT_CONF_CATEGORY_GRAPHIC];
	[pUserConf setSection:MT_CONF_SECTION_BGIMG];
	pImgFileSubPath = [pUserConf strValueForKey:@"ImageFileName" defaultValue:@""];
    
	//ファイル未指定なら何もしない
	if ([pImgFileSubPath length] == 0) goto EXIT;
	
	//ファイルパス作成
	pPathList = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
	pDocDirPath = [pPathList objectAtIndex:0];
	pImgFilePath = [pDocDirPath stringByAppendingPathComponent:pImgFileSubPath];
	
	//ファイルが存在しない場合は何もしない
	pFileManager = [NSFileManager defaultManager];
	if (![pFileManager fileExistsAtPath:pImgFilePath]) goto EXIT;
    
	//テクスチャ画像として読み込み
	result = m_Texture.LoadImageFile(pImgFilePath);
	if (result != 0) goto EXIT;
    
EXIT:;
	[pUserConf release];
	return result;
}

//******************************************************************************
// 表示設定
//******************************************************************************
void MTBackgroundImage::SetEnable(
		bool isEnable
	)
{
	m_isEnable = isEnable;
}


