//******************************************************************************
//
// MIDITrail / MTMainViewCtrl
//
// メインビュー制御クラス
//
// Copyright (C) 2012 WADA Masashi. All Rights Reserved.
//
//******************************************************************************

#import "YNBaseLib.h"
#import "MTMainViewCtrl.h"


//******************************************************************************
// プライベートメソッド定義
//******************************************************************************
@interface MTMainViewCtrl ()

// OpneGLコンテキスト初期化
- (int)initializeOpenGLContext;

// OpneGLコンテキスト破棄
- (void)terminateOpenGLContext;

//シーン描画
- (void)drawScene:(NSTimer*)timer;

//シーケンサメッセージ処理
- (int)sequencerMsgProc;

//描画処理
- (int)drawProc;

//演奏状態変更通知受信処理
- (int)postPlayStatus:(NSString*)pNotificationName;

//FPS更新
- (void)updateFPS:(uint64_t)startTime;

//タップ
- (void)onTapped;

//通知送信処理
- (int)postNotificationWithName:(NSString*)pName;

//全アイテム非表示
- (void)hideAllItems;

//ボタン表示状態更新
- (void)updateButtonStatus;

//タッチガイド画像表示状態更新
-(void)updateGuideImageStatus;

@end


@implementation MTMainViewCtrl

//******************************************************************************
// 生成
//******************************************************************************
- (id)initWithNibName:(NSString *)nibNameOrNil
			   bundle:(NSBundle *)nibBundleOrNil
		rendererParam:(OGLRedererParam)rendererParam
{
	int result = 0;
	NSString* pDeviceType = nil;
	NSString* pNibNameHowToView = nil;
	NSString* pPathImgButtonPlayN = nil;
	NSString* pPathImgButtonPlayH = nil;
	NSString* pPathImgButtonPauseN = nil;
	NSString* pPathImgButtonPauseH = nil;
	
	//メンバ初期化
	m_ScreenWidth = 0;
	m_ScreenHeight = 0;
	m_pEAGLContext = nil;
	m_FrameBuffer = 0;
	m_ColorRenderBuffer = 0;
	m_DepthRenderBuffer = 0;
	m_Timer = nil;
	m_pScene = NULL;
	m_pMsgQueue = NULL;
	m_isStopScene = false;
	m_LastTouchTime = 0;
	m_PrevDrawTime = 0;
	m_FPS = 0.0f;
	m_isTap = NO;
	m_isDisplayButtons = YES;
	m_isMonitor = false;
	
	//レンダリングパラメータ
	m_RendererParam = rendererParam;
	
	//バンドル初期化
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
		//OpenGLコンテキスト初期化
		result = [self initializeOpenGLContext];
		if (result != 0) YN_SHOW_ERR();
    }
	
	//デバイス種別
    if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) {
		//iPhone / iPod touch
		pDeviceType = @"iPhone";
    } else {
		//iPad
		pDeviceType = @"iPad";
    }
	
	//Nibファイル名称
	pNibNameHowToView = [NSString stringWithFormat:@"MTHowToView_%@", pDeviceType];
	
	//ビュー制御生成
	m_pHowToViewCtrl = [[MTHowToViewCtrl alloc] initWithNibName:pNibNameHowToView bundle:nil];
	
	//画像ファイルパス
	pPathImgButtonPlayN  = [NSString stringWithFormat:@"img/%@/Button-Play-N", pDeviceType];
	pPathImgButtonPlayH  = [NSString stringWithFormat:@"img/%@/Button-Play-H", pDeviceType];
	pPathImgButtonPauseN = [NSString stringWithFormat:@"img/%@/Button-Pause-N", pDeviceType];
	pPathImgButtonPauseH = [NSString stringWithFormat:@"img/%@/Button-Pause-H", pDeviceType];
	
	//画像読み込み
	m_pImgButtonPlayN  = [[UIImage imageNamed:pPathImgButtonPlayN] retain];
	m_pImgButtonPlayH  = [[UIImage imageNamed:pPathImgButtonPlayH] retain];
	m_pImgButtonPauseN = [[UIImage imageNamed:pPathImgButtonPauseN] retain];
	m_pImgButtonPauseH = [[UIImage imageNamed:pPathImgButtonPauseH] retain];
		
    return self;
}

//******************************************************************************
// 破棄
//******************************************************************************
- (void)dealloc
{
	[m_pImgButtonPlayN release];
	[m_pImgButtonPlayH release];
	[m_pImgButtonPauseN release];
	[m_pImgButtonPauseH release];
	
	//ビュー破棄
	[m_pHowToViewCtrl release];
	
	//OpenGLコンテキスト破棄
	[self terminateOpenGLContext];
	
	[super dealloc];
	
	return;
}

//******************************************************************************
// OpneGLコンテキスト初期化
//******************************************************************************
- (int)initializeOpenGLContext
{
	int result = 0;
	CAEAGLLayer* pEAGLLayer = NULL;
	CGRect frame;
	
	//解像度係数を設定：retinaの場合は2.0
	m_pBaseView.contentScaleFactor = [UIScreen mainScreen].scale;	//retina対応
	
	//現在のビューのサイズを確認する
	frame = self.view.frame;
	frame.origin = CGPointZero;
	
	//CAEAGLレイヤー作成
	pEAGLLayer = [CAEAGLLayer layer];
	pEAGLLayer.frame = frame;
	pEAGLLayer.contentsScale = [UIScreen mainScreen].scale;	//retina対応
	
	//縦横サイズを覚えておく
	m_ScreenWidth = frame.size.width * [UIScreen mainScreen].scale;		//retina対応
	m_ScreenHeight = frame.size.height * [UIScreen mainScreen].scale;	//retina対応
	
	//CAEAGLレイヤー：不透明
	pEAGLLayer.opaque = YES;
	//CAEAGLレイヤー：プロパティ
	pEAGLLayer.drawableProperties =
					[NSDictionary dictionaryWithObjectsAndKeys:
						//描画結果保存：しない
						[NSNumber numberWithBool:NO], kEAGLDrawablePropertyRetainedBacking,
						//描画カラーフォーマット：各色8bit
						kEAGLColorFormatRGBA8, kEAGLDrawablePropertyColorFormat,
					nil];
	
	//EAGLコンテキスト生成：OpenGL ES 1.1
	m_pEAGLContext = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES1];
	[EAGLContext setCurrentContext:m_pEAGLContext];
	
	//フレームバッファ生成
	glGenFramebuffersOES(1, &m_FrameBuffer);
	glBindFramebufferOES(GL_FRAMEBUFFER_OES, m_FrameBuffer);
	
	//深度バッファ作成
	glGenRenderbuffersOES(1, &m_DepthRenderBuffer);
	glBindRenderbufferOES(GL_RENDERBUFFER_OES, m_DepthRenderBuffer);
	glRenderbufferStorageOES(
							 GL_RENDERBUFFER_OES,
							 GL_DEPTH_COMPONENT16_OES,
							 m_ScreenWidth,
							 m_ScreenHeight);
	
	//深度バッファを現在のフレームバッファにつなぐ
	glFramebufferRenderbufferOES(
								 GL_FRAMEBUFFER_OES,
								 GL_DEPTH_ATTACHMENT_OES,
								 GL_RENDERBUFFER_OES,
								 m_DepthRenderBuffer);
	
	//レンダリングバッファ生成
	glGenRenderbuffersOES(1, &m_ColorRenderBuffer);
	glBindRenderbufferOES(GL_RENDERBUFFER_OES, m_ColorRenderBuffer);
	
	//レンダリングバッファを現在のフレームバッファにつなぐ
	glFramebufferRenderbufferOES(
								 GL_FRAMEBUFFER_OES,
								 GL_COLOR_ATTACHMENT0_OES,
								 GL_RENDERBUFFER_OES,
								 m_ColorRenderBuffer);
	
	//EAGLコンテキストにストレージ割り当て
	[m_pEAGLContext renderbufferStorage:GL_RENDERBUFFER_OES fromDrawable:pEAGLLayer];
	
	//CAEAGLレイヤーをビューに追加
	[m_pBaseView.layer addSublayer:pEAGLLayer];
	
EXIT:;
	return result;
}

//******************************************************************************
// OpneGLコンテキスト破棄
//******************************************************************************
- (void)terminateOpenGLContext
{	
	//レンダリングバッファ破棄
	glDeleteRenderbuffersOES(1, &m_ColorRenderBuffer);
	
	//フレームバッファ破棄
	glDeleteRenderbuffersOES(1, &m_FrameBuffer);
	
	//EAGLコンテキスト破棄
	[EAGLContext setCurrentContext:nil];
	[m_pEAGLContext release];
	
	return;
}

//******************************************************************************
// 初期化処理
//******************************************************************************
- (int)initialize:(SMMsgQueue*)pMsgQueue
{
	int result = 0;
	
	//メッセージキュー
	m_pMsgQueue = pMsgQueue;
		
	//レンダラ初期化
	result = m_Renderer.Initialize(m_pBaseView, m_RendererParam);
	if (result != 0) goto EXIT;
	
	//バッファクリア
	result = m_Renderer.RenderScene(NULL);
	if (result != 0) goto EXIT;
	
	//時間初期化
	result = m_MachTime.Initialize();
	if (result != 0) goto EXIT;
	
	//モニタ状態
	m_isMonitor = NO;
	
	//全アイテム非表示
	[self hideAllItems];
	
EXIT:;
	return result;
}

//******************************************************************************
// 終了処理
//******************************************************************************
- (void)terminate
{	
	//レンダラ終了
	m_Renderer.Terminate();
	
	return;
}

//******************************************************************************
// デバイス取得
//******************************************************************************
- (OGLDevice*)getDevice
{
	return m_Renderer.GetDevice();
}

//******************************************************************************
// ビュー取得
//******************************************************************************
- (UIView*)getView
{
	return m_pBaseView;
}

//******************************************************************************
// ビュー登録完了
//******************************************************************************
- (void)viewDidLoad
{	
    [super viewDidLoad];
	// Do any additional setup after loading the view.
	
	return;
}

//******************************************************************************
// ビュー解除完了
//******************************************************************************
- (void)viewDidUnload
{
    [super viewDidUnload];
    // Release any retained subviews of the main view.
	
	return;
}

//******************************************************************************
// インターフェース自動回転確認
//******************************************************************************
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
	BOOL isRotate = NO;
	
	//横長のみに対応する
	if ((interfaceOrientation == UIInterfaceOrientationLandscapeLeft)
	 || (interfaceOrientation == UIInterfaceOrientationLandscapeRight)) {
		isRotate = YES;
	}
	
	return isRotate;
}

//******************************************************************************
// ビュー表示開始
//******************************************************************************
- (void)viewWillAppear:(BOOL)animated
{
	NSString* currSysVer;
	
	//最終タッチ時間
	m_LastTouchTime = m_MachTime.GetCurTimeInNanosec();
	
	//前回描画時間
	m_PrevDrawTime = m_MachTime.GetCurTimeInNanosec();
	
	//描画更新処理間隔設定
	currSysVer = [[UIDevice currentDevice] systemVersion];
	if ([currSysVer compare:@"3.1" options:NSNumericSearch] != NSOrderedAscending) {
		//iOS3.1以降ならDisplayLinkによって描画処理を同期する
		NSLog(@"Use DisplayLink");
		m_Timer = [NSClassFromString(@"CADisplayLink") displayLinkWithTarget:self
																	selector:@selector(drawScene:)];
		[m_Timer addToRunLoop:[NSRunLoop currentRunLoop]
					  forMode:NSDefaultRunLoopMode];
	}
	else {
		//iOS3.1未満なら通常のタイマーを使って描画処理間隔を制御する
		NSLog(@"Use Timer");
		m_Timer = [NSTimer timerWithTimeInterval:(1.0 / 60.0)
										  target:self
										selector:@selector(UpdateProc:)
										userInfo:nil
										 repeats:YES];
		[[NSRunLoop currentRunLoop] addTimer:m_Timer
									 forMode:NSDefaultRunLoopMode];
	}
	
	return;
}

//******************************************************************************
// ビュー表示終了
//******************************************************************************
- (void)viewDidDisappear:(BOOL)animated
{	
	//タイマー破棄
	[m_Timer invalidate];
	m_Timer = nil;
	
	return;
}

//******************************************************************************
// シーン開始
//******************************************************************************
- (int)startScene:(MTScene*)pScene
		isMonitor:(BOOL)isMonitor
{
	int result = 0;
	
	//シーンオブジェクト
	m_pScene = pScene;
	
	//ダミーのクリックイベントを送ることでタッチ操作を有効化する
	m_pScene->OnWindowClicked(WM_LBUTTONDOWN, 0, 0);
	
	//モニタフラグ
	m_isMonitor = isMonitor;
	
	//シーンメッセージキューをクリア
	m_SceneMsgQueue.Clear();
	
	//初回描画処理
	result = [self drawProc];
	if (result != 0) goto EXIT;
	
	//最終タッチ時間
	m_LastTouchTime = m_MachTime.GetCurTimeInNanosec();
	
EXIT:;
	return result;
}

//******************************************************************************
// シーン停止
//******************************************************************************
- (int)stopScene
{
	int result = 0;
	
	//シーンオブジェクト
	m_pScene = NULL;
	
	return result;
}

//******************************************************************************
// シーン操作：演奏開始
//******************************************************************************
- (int)scene_PlayStart
{
	int result = 0;
	
	result = m_pScene->OnPlayStart();
	if (result != 0) goto EXIT;
	
EXIT:;
	return result;
}

//******************************************************************************
// シーン操作：演奏終了
//******************************************************************************
- (int)scene_PlayEnd
{
	int result = 0;
	
	result = m_pScene->OnPlayEnd();
	if (result != 0) goto EXIT;
	
EXIT:;
	return result;
}

//******************************************************************************
// シーン操作：巻き戻し
//******************************************************************************
- (int)scene_Rewind
{
	int result = 0;
	
	result = m_pScene->Rewind();
	if (result != 0) goto EXIT;
	
EXIT:;
	return result;
}

//******************************************************************************
// シーン操作：視点リセット
//******************************************************************************
- (int)scene_ResetViewpoint
{
	int result = 0;
	
	m_pScene->ResetViewpoint();
	
	return result;
}

//******************************************************************************
// シーン操作：視点登録
//******************************************************************************
- (int)scene_SetViewpoint:(MTScene::MTViewParamMap*)pParamMap
{
	int result = 0;
	
	m_pScene->SetViewParam(pParamMap);
	
	return result;
}

//******************************************************************************
// シーン操作：視点取得
//******************************************************************************
- (int)scene_GetViewpoint:(MTScene::MTViewParamMap*)pParamMap
{
	int result = 0;
	
	m_pScene->GetViewParam(pParamMap);
	
	return result;
}

//******************************************************************************
// シーン操作：エフェクト設定
//******************************************************************************
- (int)scene_SetEffect:(MTScene::EffectType)type isEnable:(bool)isEnable
{
	int result = 0;
	
	m_pScene->SetEffect(type, isEnable);
	
	return result;
}

//******************************************************************************
// シーン描画
//******************************************************************************
- (void)drawScene:(NSTimer*)timer
{
	int result = 0;
	
	if (m_pScene == NULL) goto EXIT;
	
	m_isStopScene = NO;
	
	//シーケンサメッセージ処理
	result = [self sequencerMsgProc];
	if (result != 0) goto EXIT;
	
	//描画
	result = [self drawProc];
	if (result != 0) goto EXIT;
	
	//FPS更新
	[self updateFPS:m_PrevDrawTime];

	//描画処理開始時刻
	m_PrevDrawTime = m_MachTime.GetCurTimeInNanosec();
	
	//ボタン表示状態を更新
	[self updateButtonStatus];
	
	//タッチガイド画像表示状態を更新
	[self updateGuideImageStatus];
	
EXIT:;
	if (result != 0) YN_SHOW_ERR();
}

//******************************************************************************
// シーケンサメッセージ処理
//******************************************************************************
- (int)sequencerMsgProc
{
	int result = 0;
	bool isExist = false;
	unsigned long wParam = 0;
	unsigned long lParam = 0;
	SMMsgParser parser;
	
	while (YES) {
		//メッセージ取り出し
		result = m_pMsgQueue->GetMessage(&isExist, &wParam, &lParam);
		if (result != 0) goto EXIT;
		
		//メッセージがなければ終了
		if (!isExist) break;
		
		//メッセージ通知
		result = m_pScene->OnRecvSequencerMsg(wParam, lParam);
		if (result != 0) goto EXIT;	
		
		//演奏状態変更通知への対応
		parser.Parse(wParam, lParam);
		if (parser.GetMsg() == SMMsgParser::MsgPlayStatus) {
			//一時停止
			if (parser.GetPlayStatus() == SMMsgParser::StatusPause) {
				[self postPlayStatus:@"onChangePlayStatusPause"];
			}
			//停止（演奏終了）
			else if (parser.GetPlayStatus() == SMMsgParser::StatusStop) {
				[self postPlayStatus:@"onChangePlayStatusStop"];
			}
		}
	}
	
EXIT:;
	return result;
}

//******************************************************************************
// 描画処理
//******************************************************************************
- (int)drawProc
{
	int result = 0;
	
	//EAGLコンテキストを設定
	[EAGLContext setCurrentContext:m_pEAGLContext];
	
	//フレームバッファを設定
	glBindFramebufferOES(GL_FRAMEBUFFER_OES, m_FrameBuffer);
	
	//レンダリング
	result = m_Renderer.RenderScene((OGLScene*)m_pScene);
	if (result != 0) goto EXIT;
	
	//レンダリングバッファを表示
	glBindRenderbufferOES(GL_RENDERBUFFER_OES, m_ColorRenderBuffer);
	[m_pEAGLContext presentRenderbuffer:GL_RENDERBUFFER_OES];
	
EXIT:;
	return result;
}

//******************************************************************************
// 演奏状態変更通知受信処理
//******************************************************************************
- (int)postPlayStatus:(NSString*)pNotificationName
{
	int result = 0;
	NSNotification* pNotification = nil;
	NSNotificationCenter* pCenter = nil;
	
	//通知オブジェクトを作成
    pNotification = [NSNotification notificationWithName:pNotificationName
												  object:self
												userInfo:nil];
	//通知する
	pCenter = [NSNotificationCenter defaultCenter];
	
	//通知に対応する処理を演奏スレッドで処理させる場合
	//[pCenter postNotification:pNotification];
	
	//通知に対応する処理をメインスレッドに処理させる場合
	[pCenter performSelectorOnMainThread:@selector(postNotification:)
							  withObject:pNotification
						   waitUntilDone:NO];
	
	return result;
}

//******************************************************************************
// FPS更新
//******************************************************************************
- (void)updateFPS:(uint64_t)startTime
{
	uint64_t curTime = 0;
	uint64_t diffTime = 0;
	
	//現在時刻
	curTime = m_MachTime.GetCurTimeInNanosec();
	
	//描画周期（ナノ秒）
	diffTime = curTime - startTime;
	
	//FPS算出
	m_FPS = (float)((double)(1000 * 1000000) / diffTime);
}

//******************************************************************************
// クローズボタン押下
//******************************************************************************
- (IBAction)onCloseButton
{
	//クローズ通知
	[self postNotificationWithName:@"onCloseButton"];
	
	return;
}

//******************************************************************************
// 再生ボタン押下
//******************************************************************************
- (IBAction)onPlayButton
{	
	//再生通知
	[self postNotificationWithName:@"onPlayButton"];
	
	//最終タッチ時間更新
	m_LastTouchTime = m_MachTime.GetCurTimeInNanosec();
	
	return;
}

//******************************************************************************
// 停止ボタン押下
//******************************************************************************
- (IBAction)onStopButton
{
	//停止通知
	[self postNotificationWithName:@"onStopButton"];
	
	//最終タッチ時間更新
	m_LastTouchTime = m_MachTime.GetCurTimeInNanosec();
	
	return;
}

//******************************************************************************
// 後方スキップボタン押下
//******************************************************************************
- (IBAction)onSkipBackwardButton
{
	//後方スキップ通知
	[self postNotificationWithName:@"onSkipBackwardButton"];
	
	//最終タッチ時間更新
	m_LastTouchTime = m_MachTime.GetCurTimeInNanosec();
	
	return;
}

//******************************************************************************
// 前方スキップボタン押下
//******************************************************************************
- (IBAction)onSkipForwardButton
{
	//前方スキップ通知
	[self postNotificationWithName:@"onSkipForwardButton"];
	
	//最終タッチ時間更新
	m_LastTouchTime = m_MachTime.GetCurTimeInNanosec();
	
	return;
}

//******************************************************************************
// 再生スピードダウンボタン押下
//******************************************************************************
- (IBAction)onPlaySpeedDownButton
{
	//再生スピードダウン通知
	[self postNotificationWithName:@"onPlaySpeedDownButton"];	
	
	//最終タッチ時間更新
	m_LastTouchTime = m_MachTime.GetCurTimeInNanosec();
	
	return;
}

//******************************************************************************
// 再生スピードアップボタン押下
//******************************************************************************
- (IBAction)onPlaySpeedUpButton
{
	//再生スピードアップ通知
	[self postNotificationWithName:@"onPlaySpeedUpButton"];
	
	//最終タッチ時間更新
	m_LastTouchTime = m_MachTime.GetCurTimeInNanosec();
	
	return;
}

//******************************************************************************
// リピートボタン押下
//******************************************************************************
- (IBAction)onRepeatButton
{
	//通知
	[self postNotificationWithName:@"onRepeatButton"];
	
	//最終タッチ時間更新
	m_LastTouchTime = m_MachTime.GetCurTimeInNanosec();
	
	return;
}

//******************************************************************************
// ビューボタン押下
//******************************************************************************
- (IBAction)onViewButton
{
	UIActionSheet* pActionSheet = nil;
	
	//最終タッチ時間更新
	m_LastTouchTime = m_MachTime.GetCurTimeInNanosec();
	
	//視点制御アクションシート生成
	pActionSheet = [[UIActionSheet alloc] init];
	pActionSheet.delegate = self;
	pActionSheet.tag = 1;
	
	//視点制御アクションシート設定
	//pActionSheet.title = @"Viewpoint";
	[pActionSheet addButtonWithTitle:@"Reset Viewpoint"];
	[pActionSheet addButtonWithTitle:@"Cancel"];
	pActionSheet.cancelButtonIndex = 1;
	//pActionSheet.destructiveButtonIndex = 0;
	
	//視点制御アクションシート表示
	[pActionSheet showInView:self.view];
	
	return;
}

//******************************************************************************
// ヘルプボタン押下
//******************************************************************************
- (IBAction)onHelpButton
{
	//HowToViewヘルプ表示
	m_pHowToViewCtrl.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
	[self presentModalViewController:m_pHowToViewCtrl animated:YES];
	
	//最終タッチ時間更新
	m_LastTouchTime = m_MachTime.GetCurTimeInNanosec();
	
	return;
}

//******************************************************************************
// アクションシートボタン選択イベント
//******************************************************************************
- (void)actionSheet:(UIActionSheet*)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex
{
	//視点制御アクションシート
	if (actionSheet.tag == 1) {
		switch (buttonIndex) {
			case 0:
				//視点リセット
				[self scene_ResetViewpoint];
				break;
			case 1:
				//キャンセル
				break;
			default:
				break;
		}
	}
	
	return;
}

//******************************************************************************
// タッチイベント：開始
//******************************************************************************
- (void)touchesBegan:(NSSet*)touches withEvent:(UIEvent *)event
{
	//シーンに通知
	if (m_pScene != NULL) {
		//タッチイベント通知
		m_pScene->OnTouchesBegan(touches);
		
		//タップ確認開始
		m_isTap = YES;
	}
	
	return;
}

//******************************************************************************
// タッチイベント：移動
//******************************************************************************
- (void)touchesMoved:(NSSet*)touches withEvent:(UIEvent *)event
{
	//シーンに通知
	if (m_pScene != NULL) {
		//タッチイベント通知
		m_pScene->OnTouchesMoved(touches);
		
		//移動が発生した場合はタップ確認解除
		m_isTap = NO;
	}
	
	return;
}

//******************************************************************************
// タッチイベント：終了
//******************************************************************************
- (void)touchesEnded:(NSSet*)touches withEvent:(UIEvent *)event
{
	//シーンに通知
	if (m_pScene != NULL) {
		//タッチイベント通知
		m_pScene->OnTouchesEnd(touches);
		
		//タップされた場合
		if (m_isTap) {
			[self onTapped];
			m_isTap = NO;
		}
	}
	
	return;
}

//******************************************************************************
// タッチイベント：キャンセル
//******************************************************************************
- (void)touchesCancelled:(NSSet*)touches withEvent:(UIEvent *)event
{
	//シーンに通知
	if (m_pScene != NULL) {
		//タッチイベント通知
		m_pScene->OnTouchesCanceled(touches);
		
		//キャンセルが発生した場合はタップ確認解除
		m_isTap = NO;
	}
	
	return;
}

//******************************************************************************
// タップ
//******************************************************************************
- (void)onTapped
{
	//ボタン表示状態を反転
	m_isDisplayButtons = !m_isDisplayButtons;

	//最終タッチ時間更新
	m_LastTouchTime = m_MachTime.GetCurTimeInNanosec();
	
	return;
}

//******************************************************************************
// 通知送信処理
//******************************************************************************
- (int)postNotificationWithName:(NSString*)pName
{
	int result = 0;
	NSNotification* pNotification = nil;
	NSNotificationCenter* pCenter = nil;
	
	//通知オブジェクトを作成
    pNotification = [NSNotification notificationWithName:pName
												  object:self
												userInfo:nil];
	//通知する
	pCenter = [NSNotificationCenter defaultCenter];
	
	//通知に対応する処理を演奏スレッドで処理させる場合
	//[pCenter postNotification:pNotification];
	
	//通知に対応する処理をメインスレッドに処理させる場合
	[pCenter performSelectorOnMainThread:@selector(postNotification:)
							  withObject:pNotification
						   waitUntilDone:NO];
	
	return result;
}

//******************************************************************************
// 全アイテム非表示
//******************************************************************************
- (void)hideAllItems
{
	//ボタン：上段
	m_pCloseButton.hidden = YES;
	m_pRepeatButton.hidden = YES;
	m_pViewButton.hidden = YES;
	m_pHelpButton.hidden = YES;
	
	//ボタン：下段
	m_pPlayButton.hidden = YES;
	m_pStopButton.hidden = YES;
	m_pSkipBackwardButton.hidden = YES;
	m_pSkipForwardButton.hidden = YES;
	m_pPlaySpeedDownButton.hidden = YES;
	m_pPlaySpeedUpButton.hidden = YES;
	
	//ガイド
	m_pGuideImageUD.hidden = YES;
	m_pGuideImageFB.hidden = YES;
	m_pGuideImageLR.hidden = YES;
	m_pGuideImageRT.hidden = YES;
	
	//インジケータ
	m_pActivityIndicator.hidden = YES;
	m_pLabel.hidden = YES;
	
	return;
}

//******************************************************************************
// ボタン表示状態更新
//******************************************************************************
- (void)updateButtonStatus
{
	uint64_t elapsedTime = 0;
	
	//最終タッチ時刻から5秒経過したらボタンを隠す
	if (m_isDisplayButtons) {
		elapsedTime = m_MachTime.GetCurTimeInNanosec() - m_LastTouchTime;
		if (elapsedTime > (5ULL * 1000ULL * 1000000ULL)) {
			m_isDisplayButtons = NO;
		}
	}
	
	//ボタンの表示更新
	m_pCloseButton.hidden = !m_isDisplayButtons;
	m_pRepeatButton.hidden = !m_isDisplayButtons;
	m_pViewButton.hidden = !m_isDisplayButtons;
	m_pHelpButton.hidden = !m_isDisplayButtons;
	m_pPlayButton.hidden = !m_isDisplayButtons;
	m_pStopButton.hidden = !m_isDisplayButtons;
	m_pSkipBackwardButton.hidden = !m_isDisplayButtons;
	m_pSkipForwardButton.hidden = !m_isDisplayButtons;
	m_pPlaySpeedDownButton.hidden = !m_isDisplayButtons;
	m_pPlaySpeedUpButton.hidden = !m_isDisplayButtons;

	//MIDI IN モニタでは一部のボタンを表示しない
	if (m_isMonitor) {
		m_pRepeatButton.hidden = YES;
		m_pPlayButton.hidden = YES;
		m_pStopButton.hidden = YES;
		m_pSkipBackwardButton.hidden = YES;
		m_pSkipForwardButton.hidden = YES;
		m_pPlaySpeedDownButton.hidden = YES;
		m_pPlaySpeedUpButton.hidden = YES;
	}
	
	//タッチガイド表示中はすべてのボタンを表示しない
	if ((m_pScene->GetCurOperationType() == MTTouchCtrl::OperationMoveUD)
	 || (m_pScene->GetCurOperationType() == MTTouchCtrl::OperationMoveFB)
	 || (m_pScene->GetCurOperationType() == MTTouchCtrl::OperationMoveLR)
	 || (m_pScene->GetCurOperationType() == MTTouchCtrl::OperationRotate)) {
		m_pCloseButton.hidden = YES;
		m_pRepeatButton.hidden = YES;
		m_pViewButton.hidden = YES;
		m_pHelpButton.hidden = YES;
		m_pPlayButton.hidden = YES;
		m_pStopButton.hidden = YES;
		m_pSkipBackwardButton.hidden = YES;
		m_pSkipForwardButton.hidden = YES;
		m_pPlaySpeedDownButton.hidden = YES;
		m_pPlaySpeedUpButton.hidden = YES;
	}
	
	return;
}

//******************************************************************************
// タッチガイド画像表示状態更新
//******************************************************************************
-(void)updateGuideImageStatus
{
	m_pGuideImageUD.hidden = YES;
	m_pGuideImageFB.hidden = YES;
	m_pGuideImageLR.hidden = YES;
	m_pGuideImageRT.hidden = YES;
	
	if (m_pScene == NULL) goto EXIT;
	
	//操作中のガイドのみを表示
	switch (m_pScene->GetCurOperationType()) {
		case (MTTouchCtrl::OperationNone):
			break;
		case (MTTouchCtrl::OperationEyeDir):
			break;
		case (MTTouchCtrl::OperationMoveUD):
			m_pGuideImageUD.hidden = NO;
			break;
		case (MTTouchCtrl::OperationMoveFB):
			m_pGuideImageFB.hidden = NO;
			break;
		case (MTTouchCtrl::OperationMoveLR):
			m_pGuideImageLR.hidden = NO;
			break;
		case (MTTouchCtrl::OperationRotate):
			m_pGuideImageRT.hidden = NO;
			break;
		default:
			break;
	}
	
EXIT:;
	return;
}

//******************************************************************************
// リピート状態設定
//******************************************************************************
- (void)setRepeatStatus:(BOOL)isRepeat
{
	if (isRepeat) {
		[m_pRepeatButton setSelected:YES];
	}
	else {
		[m_pRepeatButton setSelected:NO];
	}
	
	return;
}

//******************************************************************************
// インジケータアニメーション開始
//******************************************************************************
- (void)startActivityIndicator
{
	[self hideAllItems];
	
	m_pActivityIndicator.hidden = NO;
	m_pLabel.hidden = NO;
	
	[m_pActivityIndicator startAnimating];
	
	return;
}

//******************************************************************************
// インジケータアニメーション停止
//******************************************************************************
- (void)stopActivityIndicator
{
	m_pActivityIndicator.hidden = YES;
	m_pLabel.hidden = YES;
	
	[m_pActivityIndicator stopAnimating];
	
	return;
}

//******************************************************************************
// カレントコンテキスト設定
//******************************************************************************
- (void)setCurrentContext
{
	//OpenGLを利用するスレッドを切り替えるときは
	//当該スレッドにて本メソッドを呼ぶこと
	[EAGLContext setCurrentContext:m_pEAGLContext];
	
	return;
}

//******************************************************************************
// 演奏状態設定
//******************************************************************************
- (void)setPlayStatus:(PlayStatus)status
{
	//再生ボタンの画像を初期化
	[m_pPlayButton setImage:m_pImgButtonPlayN forState:UIControlStateNormal];
	[m_pPlayButton setImage:m_pImgButtonPlayH forState:UIControlStateHighlighted];
	
	switch(status) {
		//データなし
		case NoData:
			break;
		//停止状態
		case Stop:
			break;
		//再生中
		case Play:
			//再生ボタンの画像を一時停止アイコンに置き換える
			[m_pPlayButton setImage:m_pImgButtonPauseN forState:UIControlStateNormal];
			[m_pPlayButton setImage:m_pImgButtonPauseH forState:UIControlStateHighlighted];
			break;
		//一時停止
		case Pause:
			break;	
		//モニタ停止
		case MonitorOFF:
			break;
		//モニタ中
		case MonitorON:
			break;
		default:
			break;
	}
	
	return;
}


@end

