public static IDisposable Bind <T>( IReactiveProperty <T> propertyA, IReactiveProperty <T> propertyB, BindingTypes bindingTypes = BindingTypes.Default) { var propertyBBinding = propertyB .DistinctUntilChanged() .Subscribe(x => propertyA.Value = x); if (bindingTypes == BindingTypes.OneWay) { return(propertyBBinding); } var propertyABinding = propertyA .DistinctUntilChanged() .Subscribe(x => propertyB.Value = x); return(new CompositeDisposable(propertyABinding, propertyBBinding)); }
// Start is called before the first frame update protected override void Start() { m_CategoryPagerView.items.Value = m_Categories; var categoryObservable = category as IObservable <CategoryEnum>; var isDragAndDropping = new BoolReactiveProperty(false); // If we have at least one category, start with it if (m_Categories.Length > 0) { categoryObservable = categoryObservable.StartWith(m_Categories[0].category); } // Change the catalogue pager whenever the category button is pressed or the color changes. Observable.Merge( categoryObservable .DistinctUntilChanged() .AsUnitObservable(), flipped.DistinctUntilChanged() .AsUnitObservable(), color.DistinctUntilChanged() .AsUnitObservable() ) .Subscribe(ignored => { var catalogueItems = m_Asset[category.Value, color.Value] .Select(item => new CatalogueItem() { flipped = flipped.Value, asset = item }) .ToArray(); m_CataloguePagerView.items.Value = catalogueItems; if (m_Brush.Value != null) { var index = Array.FindIndex(catalogueItems, item => item.asset.name == m_Brush.Value.catalogueItem.asset.name); if (index >= 0) { // If the color or flip state changed, it now changed here var brush = new BrushItem() { catalogueItem = catalogueItems[index] }; m_Brush.SetValueAndForceNotify(brush); } } var hit = new EventHitBuilder() .SetEventCategory("profile creator") .SetEventAction("brush") .SetEventLabel($"category={category.Value}, color={color.Value}, flipped={flipped.Value}") .SetEventValue(drawingView.stampItems.Count); GoogleAnalyticsV4.getInstance().LogEvent(hit); }) .AddTo(this); category.Value = m_Categories[0].category; // Whenever we click on a catalogue item, set that image as the current brush, then stamp its pixels onto // the drawing image with our brush when it is clicked m_CataloguePagerView.OnCatalogueItemPointerClickAsObservable() .Subscribe(tuple => { // If we clicked instead of dragged the item, we're definitely not dragging isDragAndDropping.Value = false; brush.Value = new BrushItem() { catalogueItem = tuple.Item2 }; }) .AddTo(this); // If we switch into the screen view that contains the editing profile text, copy in the image to it m_UiScreenView.onScreenBeginTransition.AsObservable() .Where(targetScreen => targetScreen == m_EditingProfileTextScreen.screenIndex) .Subscribe(ignored => { Drawing.PostDrawing(drawingView, m_EditingProfileTextDrawingView); }) .AddTo(this); // Drawing code var opaque = new Color(1f, 1f, 1f, 1f); var transparent = new Color(1f, 1f, 1f, m_PreviewBrushTransparency); // Draw a preview of the brush var previewBrush = new GameObject("Preview Brush"); var previewImage = previewBrush.AddComponent <Image>(); // The preview image brush naturally should not receive raycasts / should not block previewImage.raycastTarget = false; var previewBrushTransform = previewBrush.transform as RectTransform; Debug.Assert(previewBrushTransform != null, nameof(previewBrushTransform) + " != null"); // Changes the preview's sprite as long as the brush is not null. The brush is actually set inactive later. // Also reacts to when the flipping setting changes. brush .Where(b => brush.Value != null && brush.Value.sprite != null) .Subscribe(b => { previewImage.sprite = b.sprite; previewImage.rectTransform.localScale = new Vector3(b.flipped ? -1.0f : 1f, 1f, 1f); previewImage.SetNativeSize(); }) .AddTo(this); // Move the preview brush along with the mouse as long as there is a brush selected // Whether or not it will be visible depends on which layer it's on and whether or not we're on a mobile // device. Mobile devices do not show the preview when the item was just clicked. The layer is changed later. Observable.EveryUpdate() .Where(ignored => isActiveAndEnabled) .Subscribe(ignored => { if (brush.Value == null || Application.isMobilePlatform && !isDragAndDropping.Value) { previewBrush.SetActive(false); return; } previewBrush.SetActive(true); var pointer = ContinuousStandaloneInputModule.instance.pointerEventData; var isOverDrawingView = pointer.pointerCurrentRaycast.gameObject == m_DrawingView.raycastTarget.gameObject; previewImage.color = isDragAndDropping.Value ? isOverDrawingView ? opaque : transparent : opaque; previewBrushTransform.transform.position = BrushPosition(pointer); }) .AddTo(this); // When we are drag and dropping, put the preview brush on the root canvas layer so that its totally in // the foreground. Otherwise, put it in the preview layer so it only appears when the user's pointer is // hovering over the drawing canvas isDragAndDropping.StartWith(false) .Subscribe(dragging => { previewBrushTransform.SetParent(dragging ? m_ScreenRectTransform : m_DrawingView.previewLayer); }) .AddTo(this); // Draw the brush when it is stamped var foreground = m_DrawingView.stampLayer; m_DrawingView.OnPointerClickAsObservable() .Where(ignored => brush.Value != null) .Subscribe(pointer => { Stamp(pointer, foreground, brush.Value.flipped); }) .AddTo(this); // Enable drag and dropping a specific sprite. Temporarily switches the brush and activates drag and drop mode m_CataloguePagerView .OnCatalogueItemBeginDragAsObservable() .Subscribe(tuple => { isDragAndDropping.Value = true; brush.Value = new BrushItem() { catalogueItem = tuple.Item2 }; }) .AddTo(this); // Stamp when we stop dragging a catalogue item m_CataloguePagerView .OnCatalogueItemEndDragAsObservable() .Subscribe(tuple => { isDragAndDropping.Value = false; // If we're over the drawing view, we should stamp the sprite var isOverDrawingView = tuple.Item1.pointerCurrentRaycast.gameObject == m_DrawingView.raycastTarget.gameObject; if (isOverDrawingView) { Stamp(tuple.Item1, m_DrawingView.stampLayer, tuple.Item2.flipped); } // Then clear the brush no matter what brush.Value = null; }) .AddTo(this); // Toggle the flip automatically if this particular asset is configured to do so stampEvents.Where(stamp => stamp != null && stamp.brush.flipsAfterStamp) .Subscribe(stamp => { flipped.Value = !flipped.Value; }) .AddTo(this); drawingView.stampItems.ObserveCountChanged(true) .Subscribe(count => { m_CanUndo.Value = count > 0; }) .AddTo(this); // Save as the user stamps stampEvents .Subscribe(stampEvent => { // This throttles internally SaveGameController.instance.Save(); if (stampEvent != null) { // Analytics var hit = new EventHitBuilder() .SetEventCategory("profile creator") .SetEventAction("stamp") .SetEventLabel(stampEvent.brush.sprite.name) .SetEventValue(drawingView.stampItems.Count); GoogleAnalyticsV4.getInstance().LogEvent(hit); } }) .AddTo(this); }
public static IDisposable BindTextTo(this Text label, IReactiveProperty <string> textProperty) { return(textProperty.DistinctUntilChanged() .Subscribe(x => label.text = x)); }