/// <summary> /// インスタンスを生成します。 /// </summary> /// <param name="nextTetrimino">次のテトリミノ</param> public NextFieldViewModel(IReadOnlyReactiveProperty <TetriminoKind> nextTetrimino) { //--- 描画するセルを準備 this.Cells = new CellViewModel[This.RowCount, This.ColumnCount]; foreach (var item in this.Cells.WithIndex()) { this.Cells[item.X, item.Y] = new CellViewModel(); } //--- ブロックに関する変更を処理 nextTetrimino .Select(x => Tetrimino.Create(x).Blocks.ToDictionary2(y => y.Position.Row, y => y.Position.Column)) .Subscribe(x => { //--- ViewPort のオフセット調整 //--- ちゃんと書くのがだいぶ面倒臭くなったから無理やりやる var offset = new Position((-6 - x.Count) / 2, 2); //--- 適用 foreach (var item in this.Cells.WithIndex()) { var color = x.GetValueOrDefault(item.X + offset.Row) ?.GetValueOrDefault(item.Y + offset.Column) ?.Color ?? this.BackgroundColor; item.Element.Color.Value = color; } }); }
public CollectibleViewModel(Collectible item, IReadOnlyReactiveProperty <string> searchtText, IList <Tag> tags) { OriginalTitle = item.Title; Tags = item.Tags.Select(t => new TagViewModel(t, this)).ToReactiveCollection(); TagsCount = Tags.ObserveCountChanged(true).ToReadOnlyReactiveProperty(); AddRandomTag = new ReactiveCommand(TagsCount.Select(t => t < 2)); AddRandomTag.Subscribe(_ => Tags.Add(new TagViewModel(tags[Random.Range(0, tags.Count - 1)], this))); IsSelected = new ReactiveProperty <bool>(); Title = searchtText.Select(searchVal => { if (string.IsNullOrEmpty(searchVal)) { return(OriginalTitle); } try { return(Regex.Replace(OriginalTitle, "(" + searchVal .Replace("[", "\\[") .Replace("]", "\\]") .Replace("(", "\\(") .Replace(")", "\\)") + ")", "<b>$1</b>", RegexOptions.IgnoreCase)); } catch (Exception e) { return(OriginalTitle); } }).ToReadOnlyReactiveProperty(); }
public Robot(RobotTemplate template, Game game) { _template = template; _game = game; MemorySize = MemoryUpgrades .Select(upgradesCount => template.InitialMemorySize + upgradesCount * template.MemoryUpgradeSize) .ToReactiveProperty(); Programs = new ReactiveCollection <Program>(); ProgramBytes = Programs.ObserveCountChanged(true) .SelectMany(_ => Programs .Select(x => x.MemorySize) .CombineLatest() .Select(y => y.Sum())) .ToReactiveProperty(initialValue: 0); TotalUsedBytes = ProgramBytes.CombineLatest(LeakedBytes, ProducedBytes, (programs, leaked, produced) => programs + leaked + produced) .ToReactiveProperty(); FreeSpace = TotalUsedBytes.CombineLatest(MemorySize, (used, memory) => memory - used) .ToReactiveProperty(); Status = Programs.ObserveCountChanged(true).CombineLatest(FreeSpace, (programCount, freeSpace) => freeSpace <= 0 ? RobotStatus.OutOfMemory : programCount == 0 ? RobotStatus.BootError : RobotStatus.Ok) .ToReactiveProperty(); HasSyncProgram = Programs.ObserveCountChanged(true) .Select(_ => Programs.Any(x => x.Template.Type == ProgramType.Sync)) .ToReactiveProperty(); //TODO: stop sync on game over Observable.CombineLatest(HasSyncProgram, Status.Select(x => x == RobotStatus.OutOfMemory), (hasSync, outOfMemory) => hasSync && !outOfMemory) .DistinctUntilChanged() .Select(shouldSync => shouldSync ? Observable.Interval(TimeSpan.FromSeconds(10)) : Observable.Empty <long>()) .Switch() .Subscribe(_ => { _game.GameProgress.DataCollected.Value += ProducedBytes.Value; ProducedBytes.Value = 0; }); }
/// <summary> /// コンストラクタ。 /// </summary> /// <param name="canModify"> /// 再生や音声保存に関わる設定値の変更可否状態値。 /// </param> /// <param name="items">アイテムコレクション。</param> public TalkTextReplaceItemsViewModel( IReadOnlyReactiveProperty <bool> canModify, IReadOnlyReactiveProperty <TalkTextReplaceItemCollection> items) : base(canModify, items) { // 選択中アイテムインデックス this.SelectedIndex = new ReactiveProperty <int>((items.Value.Count > 0) ? 0 : -1) .AddTo(this.CompositeDisposable); // アイテム追加コマンド this.AddCommand = this.MakeCommand( () => { this.Items.Value.Add(new TalkTextReplaceItem()); this.SelectedIndex.Value = this.Items.Value.Count - 1; }, canModify); // プリセットアイテム追加コマンド this.AddPresetCommand = this.MakeCommand <TalkTextReplacePreset>( this.ExecuteAddPresetCommand, canModify); // コレクションまたは選択中インデックスの変更通知 var itemsNotifier = Observable .CombineLatest( items, items .Select(i => i.CollectionChangedAsObservable()) .Switch() .ToUnit() .Merge(Observable.Return(Unit.Default)), this.SelectedIndex, (i, _, index) => new { count = i.Count, index }) .DistinctUntilChanged(); // コレクションが空でなくなったらアイテム選択 Observable .Zip(itemsNotifier, itemsNotifier.Skip(1)) .Where(v => v[0].count <= 0 && v[1].count > 0 && v[1].index < 0) .Subscribe(_ => this.SelectedIndex.Value = 0) .AddTo(this.CompositeDisposable); // アイテム削除コマンド this.RemoveCommand = this.MakeCommand( this.ExecuteRemoveCommand, canModify, itemsNotifier .Select(n => n.index >= 0 && n.index < n.count) .DistinctUntilChanged()); // アイテムクリアコマンド this.ClearCommand = this.MakeCommand( this.Items.Value.Clear, canModify, itemsNotifier.Select(n => n.count > 0).DistinctUntilChanged()); // アイテム上移動コマンド this.UpCommand = this.MakeCommand( () => this.Items.Value.Move( this.SelectedIndex.Value, this.SelectedIndex.Value - 1), canModify, itemsNotifier .Select(n => n.index > 0 && n.index < n.count) .DistinctUntilChanged()); // アイテム下移動コマンド this.DownCommand = this.MakeCommand( () => this.Items.Value.Move( this.SelectedIndex.Value, this.SelectedIndex.Value + 1), canModify, itemsNotifier .Select(n => n.index >= 0 && n.index + 1 < n.count) .DistinctUntilChanged()); }