Newer
Older
PrismSoftware / ECTrainer2 / Stimulus.h
#pragma once

#include <Windows.h>
#include <tchar.h>
#include <vector>
#include <string>
#include "nkcOpenCV.h"
#include "RingBuffer.h"
#include "MovieObject.h"
#include "HPTimer.h"

class BaseProcess;
class Marker;
class ECTrainer;
enum class STIM_PAGE;

struct StimInfo {
	enum {TYPE_IMAGE = 1, TYPE_MOVIE = 2, TYPE_CALIB = 3};
	int type;				// 1:画像 2:動画
	std::string filepath;	// 提示ファイル名(パス付き)
	std::string filename;	// 提示ファイル名(パスなし)
	std::string smallmovie;	// 縮小動画ファイル名
	float dulation;			// 時間(sec)
	float accTime;			// この刺激までの蓄積時間(ms)
	std::string csvfile;	// ターゲット座標ファイル(無い場合は_アンダーバー)
	int stage;				// 刺激ステージ
};

class Stimulus : public BaseProcess
{
public:
	static const int SMALL_MOVIE_WIDTH = 640;	// 縮小動画の幅(px) 全画面表示抑制の判定に使う
private:
	const std::string STIM_CONFIG_FILE = "../config/visit%02d.txt";
	const cv::String OPENING_FILE = "../images/StartPage.png";
	const cv::String CALIB_FILE = "../images/TobiiCalib.png";
	const cv::String CALIB_COMPLETE_FILE = "../images/CalibOK.png";
	const cv::String CALIB_FAILED_FILE = "../images/CalibFailed.png";
	const cv::String BLACK_FILE = "../images/Black.png";
	const cv::String ERROR_FILE = "../images/SystemError.png";
	const cv::String EXP_STOP_FILE = "../images/ExpStop.png";
	const cv::String EXP_DONE_FILE = "../images/ExpDone.png";

	std::vector<StimInfo> _StimInfoSet;	// 実験設定
	MovieObject* _pMovieObject;			// ターゲット情報
	int _StimNo;						// 刺激データ番号 -1:停止 
	nkc::HPTimer _StimTimer;			// 刺激提示タイマー
	nkc::RingBuffer<cv::Mat> _Display;		// 表示画像
	nkc::RingBuffer<std::wstring> _Movie;	// 動画情報
	cv::VideoCapture _cap;				// 動画オブジェクト
	float _TotalExpTime;				// 合計実験時間
	int _Stage;							// 刺激ステージ
	int _StageMax;						// 刺激ステージ最大値

	// ECTrainerインスタンス取得
	ECTrainer* Ect() { return (ECTrainer*)_pUserdata; }
	// 実験開始
	void StartExp();
	// 刺激を設定
	bool SetStimulus(int newStimNo);
	// 動画オブジェクトの読み込み
	void LoadMovieObject(int stimNo);
	// 基本処理
	bool Routine();
	// イベント処理
	bool EventProc(MSG& msg);
	// 次の刺激へ移動
	bool MoveNext();
	// 画像読み込み
	bool SetImage(cv::String imageFile);
	// FPS表示
	void FPS(double fps);
	// 画像にマーカーを描画
	//void StimWithMarker();

public:
	// コンストラクタ
	Stimulus(ECTrainer* pEct);
	// デストラクタ
	~Stimulus();
	// 初期化
	bool Init();
	// 刺激データ番号を取得
	int GetStimNo() { return _StimNo; }
	// 刺激ファイル名を取得
	std::string GetStimFile() { return _StimInfoSet[_StimNo].filename; }
	// 刺激の種類を取得
	bool IsStimMovie() { return (_StimInfoSet[_StimNo].type == 2); }
	// 刺激提示の経過時間を取得
	double GetStimTime() { return _StimTimer.Elapse(); }
	// 動画情報を返す
	std::wstring GetMovie() { return _Movie.Get(); }
	// 動画情報の更新状態
	bool IsNewMovie() { return _Movie.IsNew(); }
	// 表示画像を返す
	cv::Mat GetDisplay() { return _Display.Get(); }
	// 表示画像の更新状態
	bool IsNewDisplay() { return _Display.IsNew(); }
	// ターゲット情報を取得
	std::vector<Element> GetMovieObject(float eTime = -1.f);
	// 合計実験時間を取得
	float GetTotalExpTime() { return _TotalExpTime; }
	// 実験経過時間を取得
	float GetExpTime() { return _StimNo < 0 ? 0 : _StimInfoSet[_StimNo].accTime + (float)_StimTimer.Elapse(); }
	// ソフトウェアキャリブレーション実行中かどうか
	bool IsSoftCalib() { return _StimNo < 0 ? false : _StimInfoSet[_StimNo].type == StimInfo::TYPE_CALIB; }
	// ステージ取得
	int GetStage() { return _Stage; }
	// 最大ステージ取得
	int GetStageMax() { return _StageMax; }
};