#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 scene; // シーン
};
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 _Scene; // シーン
int _SceneMax; // シーン最大値
// 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 _Scene; }
// 最大ステージ取得
int GetStageMax() { return _SceneMax; }
// 刺激のシーン番号を取得
int GetScene(int stimNo) { return _StimInfoSet[stimNo].scene; };
};