現在、「Reactive Extensions」の勉強として
rxcppを使用して、ダブルクリックのイベント処理を実装しています。
実装途中で、行き詰まり質問することにしました。
ダブルクリックのイベントを定義する際に、
「時間内に2回クリックしたとき」を表現したいのですが、イマイチ実装がわかりません。
とりあえず、bufferメソッドを使用して2個ずつイベントを通知する実装としている為、
「2回クリックしたとき」しか表現できていない状態です。
ここに、制限時間を定義するにはどうしたらよいでしょうか。
可能であれば、具体的な実装例が欲しいです。
宜しくお願い致します。
下記は、再現コードです。
- C++の理解度
C++11入門書レベルの内容であれば、辛うじてわかります。 - 環境
VS2015(Unicodeプロジェクト) / Windows 10
Reactive Extensions for C++ 3.0.1
/*
* ・「Reactive Extensions」の調査
* - RxCppによるダブルクリックの実装
//*/
#include "DxLib.h" // DxLib
// nuget rxcpp 3.0.1
// This software includes the work that is distributed in the Apache License 2.0
#include <rx.hpp>
namespace Rx
{
using namespace rxcpp;
using namespace rxcpp::subjects;
using namespace rxcpp::operators;
using namespace rxcpp::util;
}
// DXライブラリ簡易ラップクラス
template<int windowWidth_ = 640, int windowHeight_ = 480, int colorBitDepth_ = 32>
struct DxLibApp final
{
DxLibApp(const wchar_t* pWindowText = L"無題")
{
DxLib::SetWindowText(pWindowText);
SetGraphMode(windowWidth_, windowHeight_, colorBitDepth_);
ChangeWindowMode(TRUE);
if (DxLib_Init() == -1) {
throw;
}
SetDrawScreen(DX_SCREEN_BACK);
}
~DxLibApp() {
DxLib_End();
}
static bool Update() {
return (ScreenFlip() == 0 && ProcessMessage() == 0 && ClearDrawScreen() == 0);
}
};
// 簡易入力クラス
struct Input final
{
Input()
: mouse_()
{}
~Input() {}
inline int Update() {
mouse_.Update();
return 0;
}
struct Mouse final
{
Mouse()
: keyBuffer_(0)
, backKeyBuffer_(0)
{}
inline int Update() {
backKeyBuffer_ = keyBuffer_;
keyBuffer_ = GetMouseInput();
return 0;
}
inline bool IsPress(const int keyCode) const {
return ((keyBuffer_ & keyCode) != 0);
}
inline bool IsDown(const int keyCode) const {
return ((keyBuffer_ & keyCode) && !(backKeyBuffer_ & keyCode));
}
inline bool IsUp(const int keyCode) const {
return (!(keyBuffer_ & keyCode) && (backKeyBuffer_ & keyCode));
}
private:
int keyBuffer_;
int backKeyBuffer_;
};
Mouse mouse_;
};
static DxLibApp<> app(L"Rxによるイベント処理");
static Input input;
// エントリーポイント
int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
{
// Updateイベント (<int>はダミー)
Rx::subject<int> update_subject;
auto update_subscriber = update_subject.get_subscriber();
auto update_observable = update_subject.get_observable();
auto clickStream = update_observable
.filter([](int) {return input.mouse_.IsDown(MOUSE_INPUT_LEFT);});
// ここのイベント通知の定義に、
// ダブルクリックらしく制限時間を設けたい
auto doubleClickStream = clickStream.buffer(2);
auto send_mousePos = doubleClickStream
.map([](std::vector<int>) {
// とりあえず bool型を送信
return true;
});
auto subscription = send_mousePos.subscribe([](bool) {
printfDx(L"2クリック\n");
});
// メインループ
while (DxLibApp<>::Update() && input.Update() == 0)
{
// Update通知
update_subscriber.on_next(1);
}
// 解除
subscription.unsubscribe();
return 0;
}