public FpsCounterViewModel() { MouseDownUnit = new ReactivePropertySlim <Unit>(mode: ReactivePropertyMode.None).AddTo(CompositeDisposable); // http://reactivex.io/documentation/operators/buffer.html // Buffer(count, skip) : count個のデータが溜まったら、skip個ごとに count個をまとめた List<T> を流します // Buffer(count) : countの倍数で、count個をまとめた List<T> を流します。 FpsCounter1 = MouseDownUnit .Select(_ => DateTime.Now) .Pairwise() .Select(dateTime => dateTime.NewItem - dateTime.OldItem) .Buffer(count: _bufferLength, skip: 1) .Select(tss => 1000d / tss.Select(ts => ts.TotalMilliseconds).Average()) .ToReadOnlyReactivePropertySlim() .AddTo(CompositeDisposable); FpsCounter2 = MouseDownUnit .TimeInterval() .Buffer(count: _bufferLength, skip: 1) .Select(xs => 1000d / xs.Select(x => x.Interval.Milliseconds).Average()) .ToReadOnlyReactivePropertySlim() .AddTo(CompositeDisposable); FpsCounter3 = MouseDownUnit .Framerate(_bufferLength) .ToReadOnlyReactivePropertySlim() .AddTo(CompositeDisposable); }
public SelectPointViewModel() { MouseLeftDownPoint = new ReactivePropertySlim <RoixBorderPoint>(mode: ReactivePropertyMode.None); MouseMovePoint = new ReactivePropertySlim <RoixBorderPoint>(); ViewBorderSize = new ReactivePropertySlim <RoixSize>(mode: ReactivePropertyMode.DistinctUntilChanged); var imageSourceSize = MyImage.ToRoixIntSize(); #region CursorPoint CursorBorderPoint = MouseMovePoint.ToReadOnlyReactivePropertySlim(); CursorPointToModel = CursorBorderPoint .Where(borderPoint => borderPoint.IsNotZero) .Select(borderPoint => borderPoint.ConvertToNewBorderInt(imageSourceSize).Point) .ToReadOnlyReactivePropertySlim(); #endregion #region DoubleClickPoint var eventAcceptedTime = DateTime.Now; var mouseDoubleClickPoint = MouseLeftDownPoint .TimeInterval() .Skip(1) .Where(ti => { // 前回の MouseDown から一定時間が経過していればダブクリと言わない if (ti.Interval > TimeSpan.FromMilliseconds(500)) { return(false); } var now = DateTime.Now; // 前回のダブクリ受付から一定時間が経過するまでは、次のダブクリを受け付けない if (now - eventAcceptedTime < TimeSpan.FromMilliseconds(500)) { return(false); } eventAcceptedTime = now; // ダブクリ受付時間の更新 return(true); }) .Select(x => x.Value) .ToReadOnlyReactivePropertySlim(mode: ReactivePropertyMode.None); // 画像座標系の点(これを基準に管理する) var selectedPointOnImage = mouseDoubleClickPoint .Select(borderPoint => { var borderInt = borderPoint.ConvertToNewBorderInt(imageSourceSize); return(borderInt.ClipToSize(borderInt.Border - 1)); }) .ToReadOnlyReactivePropertySlim(); SinglePoint = selectedPointOnImage .CombineLatest(ViewBorderSize, (intPoint, viewSize) => { var leftTop = intPoint.ConvertToNewBorder(viewSize).Point; var halfPixelSize = new RoixIntSize(1).ToRoixBorder(imageSourceSize).ConvertToNewBorder(viewSize).Size / 2d; return(leftTop + (RoixVector)halfPixelSize); // 画素の中央部に点を打つためシフト }) .ToReadOnlyReactivePropertySlim(); SinglePointToModel = selectedPointOnImage .Where(borderPoint => borderPoint.Border.IsNotZero) .Select(borderRectOnView => borderRectOnView.Point) .ToReadOnlyReactivePropertySlim(); #endregion }