public void RestartExperience(NSObject sender)
        {
            if (!RestartExperienceButton.Enabled || IsLoadingObject)
            {
                return;
            }

            RestartExperienceButton.Enabled = false;

            UserFeedback.CancelAllScheduledMessages();
            UserFeedback.DismissPresentedAlert();
            UserFeedback.ShowMessage("STARTING A NEW SESSION");

            virtualObjectManager.RemoveAllVirtualObjects();
            AddObjectButton.SetImage(UIImage.FromBundle("add"), UIControlState.Normal);
            AddObjectButton.SetImage(UIImage.FromBundle("addPressed"), UIControlState.Highlighted);
            if (FocusSquare != null)
            {
                FocusSquare.Hidden = true;
            }
            ResetTracking();

            RestartExperienceButton.SetImage(UIImage.FromBundle("restart"), UIControlState.Normal);

            // Disable Restart button for a second in order to give the session enough time to restart.
            var when = new DispatchTime(DispatchTime.Now, new TimeSpan(0, 0, 1));

            DispatchQueue.MainQueue.DispatchAfter(when, () => SetupFocusSquare());
        }
예제 #2
0
        public override int GetHashCode()
        {
            int hash = 1;

            if (scheduleTime_ != null)
            {
                hash ^= ScheduleTime.GetHashCode();
            }
            if (dispatchTime_ != null)
            {
                hash ^= DispatchTime.GetHashCode();
            }
            if (responseTime_ != null)
            {
                hash ^= ResponseTime.GetHashCode();
            }
            if (responseStatus_ != null)
            {
                hash ^= ResponseStatus.GetHashCode();
            }
            if (_unknownFields != null)
            {
                hash ^= _unknownFields.GetHashCode();
            }
            return(hash);
        }
예제 #3
0
        public override void PresentStep(int index, PresentationViewController presentationViewController)
        {
            // Set the slide's title
            TextManager.SetTitle ("Labs");

            // Add two labs
            var lab1TitleNode = Utils.SCBoxNode ("Scene Kit Lab", new CGRect (-375, -35, 750, 70), NSColor.FromCalibratedWhite (0.15f, 1.0f), 0.0f, false);
            lab1TitleNode.Scale = new SCNVector3 (0.02f, 0.02f, 0.02f);
            lab1TitleNode.Position = new SCNVector3 (-2.8f, 30.7f, 10.0f);
            lab1TitleNode.Rotation = new SCNVector4 (1, 0, 0, (float)(Math.PI));
            lab1TitleNode.Opacity = 0.0f;

            var lab2TitleNode = (SCNNode)lab1TitleNode.Copy ();
            lab2TitleNode.Position = new SCNVector3 (-2.8f, 29.2f, 10.0f);

            ContentNode.AddChildNode (lab1TitleNode);
            ContentNode.AddChildNode (lab2TitleNode);

            var lab1InfoNode = AddLabInfoNode ("\nGraphics and Games Lab A\nTuesday 4:00PM", 30.7f);
            var lab2InfoNode = AddLabInfoNode ("\nGraphics and Games Lab A\nWednesday 9:00AM", 29.2f);

            var delayInSeconds = 0.75;
            var popTime = new DispatchTime (DispatchTime.Now, (long)(delayInSeconds * Utils.NSEC_PER_SEC));
            DispatchQueue.MainQueue.DispatchAfter (popTime, () => {
                SCNTransaction.Begin ();
                SCNTransaction.AnimationDuration = 1;
                lab1TitleNode.Opacity = lab2TitleNode.Opacity = 1.0f;
                lab1TitleNode.Rotation = lab2TitleNode.Rotation = new SCNVector4 (1, 0, 0, 0);
                lab1InfoNode.Opacity = lab2InfoNode.Opacity = 1.0f;
                lab1InfoNode.Rotation = lab2InfoNode.Rotation = new SCNVector4 (0, 1, 0, 0);
                SCNTransaction.Commit ();
            });
        }
예제 #4
0
 private void ShowResult(IList <Barcode> barcodes, Action completion)
 {
     DispatchQueue.MainQueue.DispatchAsync(() =>
     {
         var result = new ScanResult(barcodes);
         var alert  = UIAlertController.Create("Scan Results", result.Text, UIAlertControllerStyle.Alert);
         alert.AddAction(UIAlertAction.Create("Ok", UIAlertActionStyle.Default, action =>
         {
             DismissViewController(true, null);
             completion.Invoke();
         }));
         this.PresentViewController(alert, true, () =>
         {
             if (!SettingsManager.Instance.ContinuousModeEnabled)
             {
                 return;
             }
             var delta        = new TimeSpan(0, 0, 0, 0, ShownDurationInContinuousModeInMilliSecs);
             var dispatchTime = new DispatchTime(DispatchTime.Now, delta);
             DispatchQueue.MainQueue.DispatchAfter(dispatchTime, () =>
             {
                 this.DismissViewController(true, completion);
             });
         });
     });
 }
예제 #5
0
        public void ButtonFinished(ButtonView button, UIView trackingView, UITouch location)
        {
            double delayInSeconds;

            buttonDraggedToPad            = false;
            miniPadView.Layer.BorderWidth = 0;

            CGPoint point = location.LocationInView(miniPadView);

            if (miniPadView.PointInside(point, null))
            {
                UpdateScoreForDroppedButton(button);
                UIView.Animate(.1f, () => trackingView.Transform = CGAffineTransform.MakeRotation(10f * (float)Math.PI / 180), async() => {
                    await UIView.AnimateAsync(.1f, () => trackingView.Transform = CGAffineTransform.MakeRotation(-10f * (float)Math.PI / 180));
                    await UIView.AnimateAsync(.1f, () => trackingView.Transform = CGAffineTransform.MakeRotation(10f * (float)Math.PI / 180));
                    await UIView.AnimateAsync(.1f, () => trackingView.Transform = CGAffineTransform.MakeRotation(-10f * (float)Math.PI / 180));
                    await UIView.AnimateAsync(.1f, () => trackingView.Transform = CGAffineTransform.MakeRotation(0));
                });
            }

            delayInSeconds = 0.5;

            var popTime = new DispatchTime(DispatchTime.Now, (long)(delayInSeconds * NSEC_PER_SEC));

            DispatchQueue.MainQueue.DispatchAfter(popTime, async() => {
                await UIView.AnimateAsync(0.35f, () => {
                    CGRect bounds       = trackingView.Bounds;
                    bounds.Size         = new CGSize(10, 10);
                    trackingView.Bounds = bounds;
                });
                trackingView.RemoveFromSuperview();
            });
        }
예제 #6
0
		public override void PresentStep (int index, PresentationViewController presentationViewController)
		{
			// Set the slide's title
			TextManager.SetTitle ("Labs");

			// Add two labs
			var lab1TitleNode = Utils.SCBoxNode ("Scene Kit Lab", new CGRect (-375, -35, 750, 70), NSColor.FromCalibratedWhite (0.15f, 1.0f), 0.0f, false);
			lab1TitleNode.Scale = new SCNVector3 (0.02f, 0.02f, 0.02f);
			lab1TitleNode.Position = new SCNVector3 (-2.8f, 30.7f, 10.0f);
			lab1TitleNode.Rotation = new SCNVector4 (1, 0, 0, (float)(Math.PI));
			lab1TitleNode.Opacity = 0.0f;

			var lab2TitleNode = (SCNNode)lab1TitleNode.Copy ();
			lab2TitleNode.Position = new SCNVector3 (-2.8f, 29.2f, 10.0f);

			ContentNode.AddChildNode (lab1TitleNode);
			ContentNode.AddChildNode (lab2TitleNode);

			var lab1InfoNode = AddLabInfoNode ("\nGraphics and Games Lab A\nTuesday 4:00PM", 30.7f);
			var lab2InfoNode = AddLabInfoNode ("\nGraphics and Games Lab A\nWednesday 9:00AM", 29.2f);

			var delayInSeconds = 0.75;
			var popTime = new DispatchTime (DispatchTime.Now, (long)(delayInSeconds * Utils.NSEC_PER_SEC));
			DispatchQueue.MainQueue.DispatchAfter (popTime, () => {
				SCNTransaction.Begin ();
				SCNTransaction.AnimationDuration = 1;
				lab1TitleNode.Opacity = lab2TitleNode.Opacity = 1.0f;
				lab1TitleNode.Rotation = lab2TitleNode.Rotation = new SCNVector4 (1, 0, 0, 0);
				lab1InfoNode.Opacity = lab2InfoNode.Opacity = 1.0f;
				lab1InfoNode.Rotation = lab2InfoNode.Rotation = new SCNVector4 (0, 1, 0, 0);
				SCNTransaction.Commit ();
			});
		}
예제 #7
0
        private void FailIfSimulator()
        {
            if (Runtime.Arch != Arch.SIMULATOR)
            {
                return;
            }

            Console.WriteLine("You will not be able to receive push notifications in the simulator.");

            if (NSUserDefaults.StandardUserDefaults.BoolForKey("ua-simulator-warning-disabled"))
            {
                return;
            }

            UIAlertController alertController = UIAlertController.Create(title: "Notice", message: "You will not be able " +
                                                                         "to receive push notifications in the simulator.",
                                                                         preferredStyle: UIAlertControllerStyle.Alert);

            UIAlertAction cancelAction = UIAlertAction.Create(title: "Cancel", style: UIAlertActionStyle.Cancel, handler: null);

            alertController.AddAction(cancelAction);

            DispatchTime delay = new DispatchTime(DispatchTime.Now, 500000000);

            DispatchQueue.MainQueue.DispatchAfter(delay, () =>
            {
                Window.RootViewController.PresentViewController(alertController, true, null);
            });
        }
        private void adjustOffsetForTransition()
        {
            var currentPage = this.CurrentPage;
            var popTime     = new DispatchTime(DispatchTime.Now, (long)(NSEC_PER_SEC * 0.1) / NSEC_PER_SEC);

            DispatchQueue.MainQueue.DispatchAfter(popTime, () => GotoPage(currentPage));
        }
예제 #9
0
        public override void DidSelectPost()
        {
            string shortenedUrl = "";

            try
            {
                foreach (NSItemProvider itemProvider in this.ExtensionContext.InputItems[0].Attachments)
                {
                    if (itemProvider.HasItemConformingTo(MobileCoreServices.UTType.URL))
                    {
                        itemProvider.LoadItem(MobileCoreServices.UTType.URL, null, async(item, error) =>
                        {
                            if (item is NSUrl)
                            {
                                var urlToShorten = ((NSUrl)item).AbsoluteUrl.ToString();

                                var request = new ShortRequest
                                {
                                    TagWt    = false,
                                    TagUtm   = false,
                                    Campaign = ContentText,
                                    Mediums  = new List <string>()
                                    {
                                        "twitter"
                                    },
                                    Input = urlToShorten
                                };

                                var defaults = new NSUserDefaults(Constants.GroupName, NSUserDefaultsType.SuiteName);
                                var url      = defaults.StringForKey(Constants.IOS_SettingsKey);

                                shortenedUrl = await ShorteningService.ShortenUrl(request, url);

                                InvokeOnMainThread(() =>
                                {
                                    UIPasteboard clipboard = UIPasteboard.General;
                                    clipboard.String       = shortenedUrl;

                                    UIAlertController alert = UIAlertController.Create("Share extension", $"https://{shortenedUrl} has been copied!", UIAlertControllerStyle.Alert);
                                    PresentViewController(alert, true, () =>
                                    {
                                        var dt = new DispatchTime(DispatchTime.Now, TimeSpan.FromSeconds(1));
                                        DispatchQueue.MainQueue.DispatchAfter(dt, () =>
                                        {
                                            ExtensionContext.CompleteRequest(null, null);
                                        });
                                    });
                                });
                            }
                        });
                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex);
            }
        }
예제 #10
0
        void StartSingleVariantAsync(int paramIndex)
        {
            var afterTime = new DispatchTime(DispatchTime.Now, (long)250 * NSEC_PER_MILISEC);

            DispatchQueue.MainQueue.DispatchAfter(afterTime, () =>
            {
                StartSingleVariant(paramIndex);
            });
        }
예제 #11
0
        public override void PresentStep(int index, PresentationViewController presentationViewController)
        {
            SCNTransaction.Begin();

            switch (index)
            {
            case 0:
                // Set the slide's title and subtitle and add some text
                TextManager.SetTitle("Skinning");

                TextManager.AddBulletAtLevel("Animate characters", 0);
                TextManager.AddBulletAtLevel("Deform geometries with a skeleton", 0);
                TextManager.AddBulletAtLevel("Joints and bones", 0);

                // Animate the character
                CharacterNode.AddAnimation(IdleAnimationGroup, new NSString("idleAnimation"));

                // The character is hidden. Wait a little longer before showing it
                // otherwise it may slow down the transition from the previous slide
                var delayInSeconds = 1.5;
                var popTime        = new DispatchTime(DispatchTime.Now, (long)(delayInSeconds * Utils.NSEC_PER_SEC));
                DispatchQueue.MainQueue.DispatchAfter(popTime, () => {
                    SCNTransaction.Begin();
                    SCNTransaction.AnimationDuration = 0;
                    CharacterNode.Hidden             = false;
                    CharacterNode.Opacity            = 0;
                    SCNTransaction.Commit();

                    SCNTransaction.Begin();
                    SCNTransaction.AnimationDuration       = 1.5;
                    SCNTransaction.AnimationTimingFunction = CAMediaTimingFunction.FromName(CAMediaTimingFunction.EaseIn);
                    CharacterNode.Opacity = 1;
                    SCNTransaction.Commit();
                });
                break;

            case 1:
                SCNTransaction.AnimationDuration = 1.5f;
                //TODO SetShowsBones (true);
                break;

            case 2:
                CharacterNode.AddAnimation(AnimationGroup1, new NSString("animation"));
                break;

            case 3:
                SCNTransaction.AnimationDuration = 1.5f;
                //TODO SetShowsBones (false);
                break;

            case 4:
                CharacterNode.AddAnimation(AnimationGroup1, new NSString("animation"));
                break;
            }
            SCNTransaction.Commit();
        }
예제 #12
0
        void goForthZombies()
        {
            manageVisibleZombies();
            statusView.Status = "Your program has started. The zombies are massing";

            const double delayInSeconds = 2;
            var          popTime        = new DispatchTime(DispatchTime.Now, (long)(delayInSeconds * NSEC_PER_SEC));

            DispatchQueue.MainQueue.DispatchAfter(popTime, ZombiesOnATimer);
        }
예제 #13
0
		public override void PresentStep (int index, PresentationViewController presentationViewController)
		{
			TextManager.SetTitle ("Creating a Scene");

			TextManager.AddBulletAtLevel ("Creating programmatically", 0);
			TextManager.AddBulletAtLevel ("Loading a scene from a file", 0);

			var delayInSeconds = 1.0;
			var popTime = new DispatchTime (DispatchTime.Now, (long)(delayInSeconds * Utils.NSEC_PER_SEC));
			DispatchQueue.MainQueue.DispatchAfter (popTime, () => {
				TextManager.HighlightBullet (1);
			});
		}
 /// <summary>
 /// Some view controllers that inherit from BaseViewController have UI elements, e.g., close button,
 /// on the top in View stack that leads to it being read first by VO eventhough a UIAccessibility.PostNotification
 /// is being called to indicate another element that should be in focus. This can be addressed by removing the UIView
 /// that is read first to focus on the element that should be targeted by UIAccessibility.PostNotification call, and
 /// put it back into accessibility elements after a short delay (1 sec).
 /// </summary>
 /// <param name="uiViewToDisable">UIView to be removed from VoiceOver reading hierarchy</param>
 protected void PostAccessibilityNotificationAndReenableElement(UIView uiViewToDisable, UIView uiViewPostNotification)
 {
     if (UIAccessibility.IsVoiceOverRunning)
     {
         UIAccessibility.PostNotification(UIAccessibilityPostNotification.LayoutChanged, uiViewPostNotification);
         uiViewToDisable.IsAccessibilityElement = false;
         DispatchTime when = new DispatchTime(DispatchTime.Now, TimeSpan.FromSeconds(1));
         DispatchQueue.MainQueue.DispatchAfter(when, () =>
         {
             uiViewToDisable.IsAccessibilityElement = true;
         });
     }
 }
예제 #15
0
		public override void PresentStep (int index, PresentationViewController presentationViewController)
		{
			SCNTransaction.Begin ();

			switch (index) {
			case 0:
				// Set the slide's title and subtitle and add some text
				TextManager.SetTitle ("Skinning");

				TextManager.AddBulletAtLevel ("Animate characters", 0);
				TextManager.AddBulletAtLevel ("Deform geometries with a skeleton", 0);
				TextManager.AddBulletAtLevel ("Joints and bones", 0);

				// Animate the character
				CharacterNode.AddAnimation (IdleAnimationGroup, new NSString ("idleAnimation"));

				// The character is hidden. Wait a little longer before showing it
				// otherwise it may slow down the transition from the previous slide
				var delayInSeconds = 1.5;
				var popTime = new DispatchTime (DispatchTime.Now, (long)(delayInSeconds * Utils.NSEC_PER_SEC));
				DispatchQueue.MainQueue.DispatchAfter (popTime, () => {
					SCNTransaction.Begin ();
					SCNTransaction.AnimationDuration = 0;
					CharacterNode.Hidden = false;
					CharacterNode.Opacity = 0;
					SCNTransaction.Commit ();

					SCNTransaction.Begin ();
					SCNTransaction.AnimationDuration = 1.5;
					SCNTransaction.AnimationTimingFunction = CAMediaTimingFunction.FromName (CAMediaTimingFunction.EaseIn);
					CharacterNode.Opacity = 1;
					SCNTransaction.Commit ();
				});
				break;
			case 1:
				SCNTransaction.AnimationDuration = 1.5f;
				//TODO SetShowsBones (true);
				break;
			case 2:
				CharacterNode.AddAnimation (AnimationGroup1, new NSString ("animation"));
				break;
			case 3:
				SCNTransaction.AnimationDuration = 1.5f;
				//TODO SetShowsBones (false);
				break;
			case 4:
				CharacterNode.AddAnimation (AnimationGroup1, new NSString ("animation"));
				break;
			}
			SCNTransaction.Commit ();
		}
예제 #16
0
        public override void PresentStep(int index, PresentationViewController presentationViewController)
        {
            TextManager.SetTitle("Creating a Scene");

            TextManager.AddBulletAtLevel("Creating programmatically", 0);
            TextManager.AddBulletAtLevel("Loading a scene from a file", 0);

            var delayInSeconds = 1.0;
            var popTime        = new DispatchTime(DispatchTime.Now, (long)(delayInSeconds * Utils.NSEC_PER_SEC));

            DispatchQueue.MainQueue.DispatchAfter(popTime, () => {
                TextManager.HighlightBullet(1);
            });
        }
예제 #17
0
        public void NeverTooLate()
        {
            Assert.That(DispatchTime.Now.Nanoseconds, Is.EqualTo(0), "Now");
            Assert.That(DispatchTime.Forever.Nanoseconds, Is.EqualTo(unchecked ((ulong)~0)), "Forever");

            var dt = new DispatchTime(1);

            Assert.That(dt.Nanoseconds, Is.EqualTo(1), "1");

            dt = new DispatchTime(DispatchTime.Now, 0);
            Assert.That(dt.Nanoseconds, Is.Not.EqualTo(0), "!0");

            var dt2 = new DispatchTime(dt, Int32.MaxValue);

            Assert.That(dt2.Nanoseconds, Is.GreaterThan(dt.Nanoseconds), "later");
        }
예제 #18
0
        public void Start(Action <NSData, NSError> completionHandler)
        {
            this.completionHandler = completionHandler;
            downloadState.Queue    = new DispatchQueue("download_queue");
            downloadState.Queue.DispatchAsync(() => {
                try {
                    var data = NSData.FromUrl(downloadURL);

                    downloadState.DownloadTimer = new DispatchSource.Timer(downloadState.Queue);
                    int downloadedBytes         = 0;
                    int randomMilliseconds      = new Random().Next(0, 500);
                    var delay = new DispatchTime(DispatchTime.Now, (long)(TimerInterval * NanosecondsPerSecond - randomMilliseconds * NanosecondsPerMillisecond));
                    downloadState.DownloadTimer.SetTimer(delay, (long)TimerInterval * NanosecondsPerSecond, 0);

                    downloadState.DownloadTimer.SetEventHandler(() => {
                        downloadedBytes += (int)(BatchSize * TimerInterval);

                        if (downloadedBytes >= (int)data.Length)
                        {
                            downloadState.DownloadTimer.Cancel();
                            return;
                        }

                        DidDownloadData(downloadedBytes);
                    });

                    downloadState.DownloadTimer.SetCancelHandler(() => {
                        if (downloadedBytes >= (int)data.Length)
                        {
                            DidFinishDownload(data);
                        }
                        else
                        {
                            DidFailDownloadWithError(downloadState.DownloadError);
                        }

                        downloadState.DownloadTimer = null;
                    });

                    WillBeginDownload((int)data.Length);
                    downloadState.DownloadTimer.Resume();
                } catch (Exception) {
                    var error = new NSError(NSError.CocoaErrorDomain, 0, null);
                    DidFailDownloadWithError(error);
                }
            });
        }
예제 #19
0
        bool TryLoadFirstBatch()
        {
            bool haveNoPost = PostCells.Count == 0 || lastPostSeenOnServer == null;

            if (haveNoPost)
            {
                // We dispatch it after two seconds to give the server time to index the new post
                // TODO: https://trello.com/c/cWWQXKYY
                var dispatchTime = new DispatchTime(DispatchTime.Now, 2 * 1000000000);
                DispatchQueue.MainQueue.DispatchAfter(dispatchTime, () => {
                    // If we get here, we must have no posts. That must mean that last time we tried loading a batch nothing came through so we locked the method. Let's unlock it
                    haveOldestPost = false;
                    LoadBatch();
                });
            }

            return(haveNoPost);
        }
예제 #20
0
        partial void SaveButton_TouchUpInside(UIButton sender)
        {
            var s = new NSUserDefaults(Constants.GroupName, NSUserDefaultsType.SuiteName);

            s.SetString(shortenedUrlLocation.Text, Constants.IOS_SettingsKey);
            s.Synchronize();

            UIAlertController alert = UIAlertController.Create("Share extension", "Shortening URL has been saved!", UIAlertControllerStyle.Alert);

            PresentViewController(alert, true, () =>
            {
                var dt = new DispatchTime(DispatchTime.Now, TimeSpan.FromSeconds(1));
                DispatchQueue.MainQueue.DispatchAfter(dt, () =>
                {
                    alert.DismissViewController(true, null);
                });
            });
        }
예제 #21
0
        public void OpenToast(string text)
        {
            var rootViewController = UIApplication.SharedApplication.KeyWindow.RootViewController;

            var alertController = UIAlertController.Create(string.Empty,
                                                           text,
                                                           UIAlertControllerStyle.Alert);

            alertController.AddAction(UIAlertAction.Create("OK", UIAlertActionStyle.Default, null));

            rootViewController.PresentViewController(alertController, true, () =>
            {
                var delayTime = new DispatchTime(DispatchTime.Now, 3000000000);
                DispatchQueue.MainQueue.DispatchAlert(delayTime, () =>
                {
                    alertController.DismissViewController(true, null);
                });
            });
        }
예제 #22
0
        void ZombiesOnATimer()
        {
            if (paused)
            {
                return;
            }

            TimerEvent eventType = nextZombieEvent();

            statusView.Status     = StringForZombieEvent(eventType);
            meterView.ZombieLevel = meterView.ZombieLevel + ZombieFactorForEvent(eventType);

            MonitorZombiePressure();
            manageVisibleZombies();

            var popTime = new DispatchTime(DispatchTime.Now, (long)6 * NSEC_PER_SEC);

            DispatchQueue.MainQueue.DispatchAfter(popTime, ZombiesOnATimer);
        }
예제 #23
0
		public void Start (Action<NSData, NSError> completionHandler)
		{
			this.completionHandler = completionHandler;
			downloadState.Queue = new DispatchQueue ("download_queue");
			downloadState.Queue.DispatchAsync (() => {
				try {
					var data = NSData.FromUrl (downloadURL);

					downloadState.DownloadTimer = new DispatchSource.Timer (downloadState.Queue);
					int downloadedBytes = 0;
					int randomMilliseconds = new Random ().Next (0, 500);
					var delay = new DispatchTime (DispatchTime.Now, (long)(TimerInterval * NanosecondsPerSecond - randomMilliseconds * NanosecondsPerMillisecond));
					downloadState.DownloadTimer.SetTimer (delay, (long)TimerInterval * NanosecondsPerSecond, 0);

					downloadState.DownloadTimer.SetEventHandler (() => {
						downloadedBytes += (int)(BatchSize * TimerInterval);

						if (downloadedBytes >= (int)data.Length) {
							downloadState.DownloadTimer.Cancel ();
							return;
						}

						DidDownloadData (downloadedBytes);
					});

					downloadState.DownloadTimer.SetCancelHandler (() => {
						if (downloadedBytes >= (int)data.Length)
							DidFinishDownload (data);
						else
							DidFailDownloadWithError (downloadState.DownloadError);

						downloadState.DownloadTimer = null;
					});

					WillBeginDownload ((int)data.Length);
					downloadState.DownloadTimer.Resume ();
				} catch (Exception) {
					var error = new NSError (NSError.CocoaErrorDomain, 0, null);
					DidFailDownloadWithError (error);
				}
			});
		}
예제 #24
0
 public void MergeFrom(Attempt other)
 {
     if (other == null)
     {
         return;
     }
     if (other.scheduleTime_ != null)
     {
         if (scheduleTime_ == null)
         {
             scheduleTime_ = new global::Google.Protobuf.WellKnownTypes.Timestamp();
         }
         ScheduleTime.MergeFrom(other.ScheduleTime);
     }
     if (other.dispatchTime_ != null)
     {
         if (dispatchTime_ == null)
         {
             dispatchTime_ = new global::Google.Protobuf.WellKnownTypes.Timestamp();
         }
         DispatchTime.MergeFrom(other.DispatchTime);
     }
     if (other.responseTime_ != null)
     {
         if (responseTime_ == null)
         {
             responseTime_ = new global::Google.Protobuf.WellKnownTypes.Timestamp();
         }
         ResponseTime.MergeFrom(other.ResponseTime);
     }
     if (other.responseStatus_ != null)
     {
         if (responseStatus_ == null)
         {
             responseStatus_ = new global::Google.Rpc.Status();
         }
         ResponseStatus.MergeFrom(other.ResponseStatus);
     }
     _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
 }
예제 #25
0
		public override void PresentStep (int index, PresentationViewController presentationViewController)
		{
			switch (index) {
			case 0:
				// Set the slide's title and subtitle and add some text
				TextManager.SetTitle ("Constraints");
				TextManager.SetSubtitle ("SCNConstraint");

				TextManager.AddBulletAtLevel ("Applied sequentially at render time", 0);
				TextManager.AddBulletAtLevel ("Only affect presentation values", 0);

				TextManager.AddCode ("#aNode.#Constraints# = new SCNConstraint[] { aConstraint, anotherConstraint, ... };#");

				// Tweak the near clipping plane of the spot light to get a precise shadow map
				presentationViewController.SpotLight.Light.SetAttribute (new NSNumber (10), SCNLightAttribute.ShadowNearClippingKey);
				break;
			case 1:
				// Remove previous text
				TextManager.FlipOutText (SlideTextManager.TextType.Subtitle);
				TextManager.FlipOutText (SlideTextManager.TextType.Bullet);
				TextManager.FlipOutText (SlideTextManager.TextType.Code);

				// Add new text
				TextManager.SetSubtitle ("SCNLookAtConstraint");
				TextManager.AddBulletAtLevel ("Makes a node to look at another node", 0);
				TextManager.AddCode ("#nodeA.Constraints = new SCNConstraint[] { #SCNLookAtConstraint.Create# (nodeB) };#");

				TextManager.FlipInText (SlideTextManager.TextType.Subtitle);
				TextManager.FlipInText (SlideTextManager.TextType.Bullet);
				TextManager.FlipInText (SlideTextManager.TextType.Code);
				break;
			case 2:
				// Setup the scene
				SetupLookAtScene ();

				SCNTransaction.Begin ();
				SCNTransaction.AnimationDuration = 1;
					// Dim the text and move back a little bit
				TextManager.TextNode.Opacity = 0.5f;
				presentationViewController.CameraHandle.Position = presentationViewController.CameraNode.ConvertPositionToNode (new SCNVector3 (0, 0, 5.0f), presentationViewController.CameraHandle.ParentNode);
				SCNTransaction.Commit ();
				break;
			case 3:
				// Add constraints to the arrows
				var container = ContentNode.FindChildNode ("arrowContainer", true);

				// "Look at" constraint
				var constraint = SCNLookAtConstraint.Create (BallNode);

				var i = 0;
				foreach (var arrow in container.ChildNodes) {
					var delayInSeconds = 0.1 * i++;
					var popTime = new DispatchTime (DispatchTime.Now, (long)(delayInSeconds * Utils.NSEC_PER_SEC));
					DispatchQueue.MainQueue.DispatchAfter (popTime, () => {
						SCNTransaction.Begin ();
						SCNTransaction.AnimationDuration = 1;
						// Animate to the result of applying the constraint
						((SCNNode)arrow.ChildNodes [0]).Rotation = new SCNVector4 (0, 1, 0, (float)(Math.PI / 2));
						arrow.Constraints = new SCNConstraint[] { constraint };
						SCNTransaction.Commit ();
					});
				}
				break;
			case 4:
				// Create a keyframe animation to move the ball
				var animation = CAKeyFrameAnimation.GetFromKeyPath ("position");
				animation.KeyTimes = new NSNumber[] {
					0.0f,
					(1.0f / 8.0f),
					(2.0f / 8.0f),
					(3.0f / 8.0f),
					(4.0f / 8.0f),
					(5.0f / 8.0f),
					(6.0f / 8.0f),
					(7.0f / 8.0f),
					1.0f
				};

				animation.Values = new NSObject[] { 
					NSValue.FromVector (new SCNVector3 (0, 0.0f, 0)),
					NSValue.FromVector (new SCNVector3 (20.0f, 0.0f, 20.0f)),
					NSValue.FromVector (new SCNVector3 (40.0f, 0.0f, 0)),
					NSValue.FromVector (new SCNVector3 (20.0f, 0.0f, -20.0f)),
					NSValue.FromVector (new SCNVector3 (0, 0.0f, 0)),
					NSValue.FromVector (new SCNVector3 (-20.0f, 0.0f, 20.0f)),
					NSValue.FromVector (new SCNVector3 (-40.0f, 0.0f, 0)),
					NSValue.FromVector (new SCNVector3 (-20.0f, 0.0f, -20.0f)),
					NSValue.FromVector (new SCNVector3 (0, 0.0f, 0))
				};

				animation.CalculationMode = CAKeyFrameAnimation.AnimationCubicPaced; // smooth the movement between keyframes
				animation.RepeatCount = float.MaxValue;
				animation.Duration = 10.0f;
				animation.TimingFunction = CAMediaTimingFunction.FromName (CAMediaTimingFunction.Linear);
				BallNode.AddAnimation (animation, new NSString ("ballNodeAnimation"));

				// Rotate the ball to give the illusion of a rolling ball
				// We need two animations to do that:
				// - one rotation to orient the ball in the right direction
				// - one rotation to spin the ball
				animation = CAKeyFrameAnimation.GetFromKeyPath ("rotation");
				animation.KeyTimes = new NSNumber[] { 
					0.0f, 
					(0.7f / 8.0f), 
					(1.0f / 8.0f), 
					(2.0f / 8.0f), 
					(3.0f / 8.0f), 
					(3.3f / 8.0f), 
					(4.7f / 8.0f),
					(5.0f / 8.0f),
					(6.0f / 8.0f),
					(7.0f / 8.0f),
					(7.3f / 8.0f),
					1.0f
				};

				animation.Values = new NSObject[] {
					NSValue.FromVector (new SCNVector4 (0, 1, 0, (float)(Math.PI / 4))),
					NSValue.FromVector (new SCNVector4 (0, 1, 0, (float)(Math.PI / 4))),
					NSValue.FromVector (new SCNVector4 (0, 1, 0, (float)(Math.PI / 2))),
					NSValue.FromVector (new SCNVector4 (0, 1, 0, (float)(Math.PI))),
					NSValue.FromVector (new SCNVector4 (0, 1, 0, (float)(Math.PI + Math.PI / 2))),
					NSValue.FromVector (new SCNVector4 (0, 1, 0, (float)(Math.PI * 2 - Math.PI / 4))),
					NSValue.FromVector (new SCNVector4 (0, 1, 0, (float)(Math.PI * 2 - Math.PI / 4))),
					NSValue.FromVector (new SCNVector4 (0, 1, 0, (float)(Math.PI * 2 - Math.PI / 2))),
					NSValue.FromVector (new SCNVector4 (0, 1, 0, (float)(Math.PI))),
					NSValue.FromVector (new SCNVector4 (0, 1, 0, (float)(Math.PI - Math.PI / 2))),
					NSValue.FromVector (new SCNVector4 (0, 1, 0, (float)(Math.PI / 4))),
					NSValue.FromVector (new SCNVector4 (0, 1, 0, (float)(Math.PI / 4))) 
				};

				animation.RepeatCount = float.MaxValue;
				animation.Duration = 10.0f;
				animation.TimingFunction = CAMediaTimingFunction.FromName (CAMediaTimingFunction.Linear);
				BallNode.AddAnimation (animation, new NSString ("ballNodeAnimation2"));

				var rotationAnimation = CABasicAnimation.FromKeyPath ("rotation");
				rotationAnimation.Duration = 1.0f;
				rotationAnimation.RepeatCount = float.MaxValue;
				rotationAnimation.To = NSValue.FromVector (new SCNVector4 (1, 0, 0, (float)(Math.PI * 2)));
				BallNode.ChildNodes [1].AddAnimation (rotationAnimation, new NSString ("ballNodeRotation"));
				break;
			case 5:
				// Add a constraint to the camera
				SCNTransaction.Begin ();
				SCNTransaction.AnimationDuration = 1;
				constraint = SCNLookAtConstraint.Create (BallNode);
				presentationViewController.CameraNode.Constraints = new SCNConstraint[] { constraint };
				SCNTransaction.Commit ();
				break;
			case 6:
				// Add a constraint to the light
				SCNTransaction.Begin ();
				SCNTransaction.AnimationDuration = 1;
				var cameraTarget = ContentNode.FindChildNode ("cameraTarget", true);
				constraint = SCNLookAtConstraint.Create (cameraTarget);
				presentationViewController.SpotLight.Constraints = new SCNConstraint[] { constraint };
				SCNTransaction.Commit ();
				break;
			}
		}
예제 #26
0
		public override void PresentStep (int switchIndex, PresentationViewController presentationViewController)
		{
			switch (switchIndex) {
			case 0:
				// Set the slide's title and subtitle and add some text
				TextManager.SetTitle ("Core Image");
				TextManager.SetSubtitle ("CI Filters");

				TextManager.AddBulletAtLevel ("Screen-space effects", 0);
				TextManager.AddBulletAtLevel ("Applies to a node hierarchy", 0);
				TextManager.AddBulletAtLevel ("Filter parameters are animatable", 0);
				TextManager.AddCode ("#aNode.#Filters# = new CIFilter[] { filter1, filter2 };#");
				break;
			case 1:
				SCNTransaction.Begin ();
				SCNTransaction.AnimationDuration = 1.0f;
				// Dim the text and move back a little
				TextManager.TextNode.Opacity = 0.0f;
				presentationViewController.CameraHandle.Position = presentationViewController.CameraNode.ConvertPositionToNode (new SCNVector3 (0, 0, 5.0f), presentationViewController.CameraHandle.ParentNode);
				SCNTransaction.Commit ();

				// Reveal the grid
				GroupNode.Opacity = 1;
				break;
			case 2:
				SCNTransaction.Begin ();
				SCNTransaction.AnimationDuration = 1;
				// Highlight an item
				HighlightContact (13, presentationViewController);
				SCNTransaction.Commit ();
				break;
			case 3:
				var index = 13;
				var subStep = 0;

				// Successively select items
				for (var i = 0; i < 5; ++i) {
					var popTime = new DispatchTime (DispatchTime.Now, (Int64)(i * 0.2 * Utils.NSEC_PER_SEC));
					DispatchQueue.MainQueue.DispatchAfter (popTime, () => {
						SCNTransaction.Begin ();
						SCNTransaction.AnimationDuration = 0.2f;
						UnhighlightContact (index);

						if (subStep++ == 3)
							index += ColumnCount;
						else
							index++;

						HighlightContact (index, presentationViewController);
						SCNTransaction.Commit ();
					});
				}
				break;
			case 4:
				// BLUR+DESATURATE in the background, GLOW in the foreground

				// Here we will change the node hierarchy in order to group all the nodes in the background under a single node.
				// This way we can use a single Core Image filter and apply it on the whole grid, and have another CI filter for the node in the foreground.

				var selectionParent = HeroNode.ParentNode;

				SCNTransaction.Begin ();
				SCNTransaction.AnimationDuration = 0;
				// Stop the animations of the selected node
				HeroNode.Transform = HeroNode.PresentationNode.Transform; // set the current rotation to the current presentation value
				HeroNode.RemoveAllAnimations ();

				// Re-parent the node by preserving its world tranform
				var wantedWorldTransform = selectionParent.WorldTransform;
				GroupNode.ParentNode.AddChildNode (selectionParent);
				selectionParent.Transform = selectionParent.ParentNode.ConvertTransformFromNode (wantedWorldTransform, null);
				SCNTransaction.Commit ();

				// Add CIFilters

				SCNTransaction.Begin ();
				SCNTransaction.AnimationDuration = 1;
				// A negative 'centerX' value means no scaling.
				//TODO HeroNode.Filters [0].SetValueForKey (new NSNumber (-1), new NSString ("centerX"));

				// Move the selection to the foreground
				selectionParent.Rotation = new SCNVector4 (0, 1, 0, 0);
				HeroNode.Transform = ContentNode.ConvertTransformToNode (SCNMatrix4.CreateTranslation (0, Altitude, 29), selectionParent);
				HeroNode.Scale = new SCNVector3 (1, 1, 1);
				HeroNode.Rotation = new SCNVector4 (1, 0, 0, -(float)(Math.PI / 4) * 0.25f);

				// Upon completion, rotate the selection forever
				SCNTransaction.SetCompletionBlock (() => {
					var animation = CABasicAnimation.FromKeyPath ("rotation");
					animation.Duration = 4.0f;
					animation.From = NSValue.FromVector (new SCNVector4 (0, 1, 0, 0));
					animation.To = NSValue.FromVector (new SCNVector4 (0, 1, 0, NMath.PI * 2));
					animation.TimingFunction = CAMediaTimingFunction.FromName (CAMediaTimingFunction.EaseInEaseOut);
					animation.RepeatCount = float.MaxValue;

					HeroNode.ChildNodes [0].AddAnimation (animation, new NSString ("heroNodeAnimation"));
				});

				// Add the filters
				var blurFilter = CIFilter.FromName ("CIGaussianBlur");
				blurFilter.SetDefaults ();
				blurFilter.Name = "blur";
				blurFilter.SetValueForKey (new NSNumber (0), CIFilterInputKey.Radius);

				var desaturateFilter = CIFilter.FromName ("CIColorControls");
				desaturateFilter.SetDefaults ();
				desaturateFilter.Name = "desaturate";
				GroupNode.Filters = new CIFilter[] { blurFilter, desaturateFilter };
				SCNTransaction.Commit ();

				// Increate the blur radius and desaturate progressively
				SCNTransaction.Begin ();
				SCNTransaction.AnimationDuration = 2;
				GroupNode.SetValueForKey (new NSNumber (10), new NSString ("filters.blur.inputRadius"));
				GroupNode.SetValueForKey (new NSNumber (0.1), new NSString ("filters.desaturate.inputSaturation"));
				SCNTransaction.Commit ();

				break;
			}
		}
예제 #27
0
        void PerformRandomUpdate()
        {
            if (WifiEnabled && ScanForNetworks)
            {
                var updatedNetworks = new List <Network> ();

                if (AvailableNetworks != null)
                {
                    updatedNetworks.AddRange(AvailableNetworks);
                }

                if (updatedNetworks.Count == 0)
                {
                    AvailableNetworks = allNetworks;
                }
                else
                {
                    var random = new Random(DateTime.Now.Millisecond);

                    var shouldRemove = random.Next(0, 3) == 0;
                    if (shouldRemove)
                    {
                        var removeCount = random.Next(0, updatedNetworks.Count);
                        for (int i = 0; i < removeCount; i++)
                        {
                            var removeIndex = random.Next(0, updatedNetworks.Count);
                            updatedNetworks.RemoveAt(removeIndex);
                        }
                    }

                    var shouldAdd = random.Next(0, 3) == 0;
                    if (shouldAdd)
                    {
                        var allNetworksSet        = new List <Network> (allNetworks);
                        var updatedNetworksSet    = new List <Network> (updatedNetworks);
                        var notPresentNetworksSet = new List <Network> (allNetworksSet);

                        foreach (var network in updatedNetworksSet)
                        {
                            notPresentNetworksSet.Remove(network);
                        }

                        if (notPresentNetworksSet.Count > 0)
                        {
                            var addCount = random.Next(0, notPresentNetworksSet.Count);

                            for (int i = 0; i < addCount; i++)
                            {
                                var removeIndex  = random.Next(0, notPresentNetworksSet.Count);
                                var networkToAdd = notPresentNetworksSet [removeIndex];
                                notPresentNetworksSet.Remove(networkToAdd);
                                updatedNetworksSet.Add(networkToAdd);
                            }
                        }
                        updatedNetworks = updatedNetworksSet;
                    }
                    UpdateAvailableNetworks(updatedNetworks.ToArray());
                }

                // notify
                updateHandler(this);
            }

            var deadline = new DispatchTime(DispatchTime.Now, new TimeSpan(0, 0, 4));

            DispatchQueue.MainQueue.DispatchAfter(deadline, () => PerformRandomUpdate());
        }
예제 #28
0
		void zombiesOnATimer ()
		{
			if (paused)
				return;

			TimerEvent eventType = nextZombieEvent ();
			statusView.Status = stringForZombieEvent (eventType);
			meterView.ZombieLevel = meterView.ZombieLevel + zombieFactorForEvent (eventType);

			monitorZombiePressure ();
			manageVisibleZombies ();

			var popTime = new DispatchTime (DispatchTime.Now, (long)6 * NSEC_PER_SEC);
			DispatchQueue.MainQueue.DispatchAfter (popTime, () => zombiesOnATimer ());
		}
        public override string ToString()
        {
            var str = Message + " DispatchTime: " + DispatchTime.ToString("hh:mm:ss.fffffff");

            return(str);
        }
예제 #30
0
        public override void PresentStep(int switchIndex, PresentationViewController presentationViewController)
        {
            switch (switchIndex)
            {
            case 0:
                // Set the slide's title and subtitle and add some text
                TextManager.SetTitle("Core Image");
                TextManager.SetSubtitle("CI Filters");

                TextManager.AddBulletAtLevel("Screen-space effects", 0);
                TextManager.AddBulletAtLevel("Applies to a node hierarchy", 0);
                TextManager.AddBulletAtLevel("Filter parameters are animatable", 0);
                TextManager.AddCode("#aNode.#Filters# = new CIFilter[] { filter1, filter2 };#");
                break;

            case 1:
                SCNTransaction.Begin();
                SCNTransaction.AnimationDuration = 1.0f;
                // Dim the text and move back a little
                TextManager.TextNode.Opacity = 0.0f;
                presentationViewController.CameraHandle.Position = presentationViewController.CameraNode.ConvertPositionToNode(new SCNVector3(0, 0, 5.0f), presentationViewController.CameraHandle.ParentNode);
                SCNTransaction.Commit();

                // Reveal the grid
                GroupNode.Opacity = 1;
                break;

            case 2:
                SCNTransaction.Begin();
                SCNTransaction.AnimationDuration = 1;
                // Highlight an item
                HighlightContact(13, presentationViewController);
                SCNTransaction.Commit();
                break;

            case 3:
                var index   = 13;
                var subStep = 0;

                // Successively select items
                for (var i = 0; i < 5; ++i)
                {
                    var popTime = new DispatchTime(DispatchTime.Now, (long)(i * 0.2 * Utils.NSEC_PER_SEC));
                    DispatchQueue.MainQueue.DispatchAfter(popTime, () => {
                        SCNTransaction.Begin();
                        SCNTransaction.AnimationDuration = 0.2f;
                        UnhighlightContact(index);

                        if (subStep++ == 3)
                        {
                            index += ColumnCount;
                        }
                        else
                        {
                            index++;
                        }

                        HighlightContact(index, presentationViewController);
                        SCNTransaction.Commit();
                    });
                }
                break;

            case 4:
                // BLUR+DESATURATE in the background, GLOW in the foreground

                // Here we will change the node hierarchy in order to group all the nodes in the background under a single node.
                // This way we can use a single Core Image filter and apply it on the whole grid, and have another CI filter for the node in the foreground.

                var selectionParent = HeroNode.ParentNode;

                SCNTransaction.Begin();
                SCNTransaction.AnimationDuration = 0;
                // Stop the animations of the selected node
                HeroNode.Transform = HeroNode.PresentationNode.Transform;                 // set the current rotation to the current presentation value
                HeroNode.RemoveAllAnimations();

                // Re-parent the node by preserving its world tranform
                var wantedWorldTransform = selectionParent.WorldTransform;
                GroupNode.ParentNode.AddChildNode(selectionParent);
                selectionParent.Transform = selectionParent.ParentNode.ConvertTransformFromNode(wantedWorldTransform, null);
                SCNTransaction.Commit();

                // Add CIFilters

                SCNTransaction.Begin();
                SCNTransaction.AnimationDuration = 1;
                // A negative 'centerX' value means no scaling.
                //TODO HeroNode.Filters [0].SetValueForKey (new NSNumber (-1), new NSString ("centerX"));

                // Move the selection to the foreground
                selectionParent.Rotation = new SCNVector4(0, 1, 0, 0);
                HeroNode.Transform       = ContentNode.ConvertTransformToNode(SCNMatrix4.CreateTranslation(0, Altitude, 29), selectionParent);
                HeroNode.Scale           = new SCNVector3(1, 1, 1);
                HeroNode.Rotation        = new SCNVector4(1, 0, 0, -(float)(Math.PI / 4) * 0.25f);

                // Upon completion, rotate the selection forever
                SCNTransaction.SetCompletionBlock(() => {
                    var animation            = CABasicAnimation.FromKeyPath("rotation");
                    animation.Duration       = 4.0f;
                    animation.From           = NSValue.FromVector(new SCNVector4(0, 1, 0, 0));
                    animation.To             = NSValue.FromVector(new SCNVector4(0, 1, 0, NMath.PI * 2));
                    animation.TimingFunction = CAMediaTimingFunction.FromName(CAMediaTimingFunction.EaseInEaseOut);
                    animation.RepeatCount    = float.MaxValue;

                    HeroNode.ChildNodes [0].AddAnimation(animation, new NSString("heroNodeAnimation"));
                });

                // Add the filters
                var blurFilter = CIFilter.FromName("CIGaussianBlur");
                blurFilter.SetDefaults();
                blurFilter.Name = "blur";
                blurFilter.SetValueForKey(new NSNumber(0), CIFilterInputKey.Radius);

                var desaturateFilter = CIFilter.FromName("CIColorControls");
                desaturateFilter.SetDefaults();
                desaturateFilter.Name = "desaturate";
                GroupNode.Filters     = new CIFilter[] { blurFilter, desaturateFilter };
                SCNTransaction.Commit();

                // Increate the blur radius and desaturate progressively
                SCNTransaction.Begin();
                SCNTransaction.AnimationDuration = 2;
                GroupNode.SetValueForKey(new NSNumber(10), new NSString("filters.blur.inputRadius"));
                GroupNode.SetValueForKey(new NSNumber(0.1), new NSString("filters.desaturate.inputSaturation"));
                SCNTransaction.Commit();

                break;
            }
        }
예제 #31
0
		void goForthZombies ()
		{
			manageVisibleZombies ();
			statusView.Status = "Your program has started. The zombies are massing";

			double delayInSeconds = 2;
			var popTime = new DispatchTime (DispatchTime.Now, (long)(delayInSeconds * NSEC_PER_SEC));
			DispatchQueue.MainQueue.DispatchAfter (popTime, () => zombiesOnATimer ());
		}
예제 #32
0
		void PresentStep (nint step)
		{
			var overlay = (SpriteKitOverlayScene)((SCNView)View).OverlayScene;

			if (CameraHandleTransforms [(int)step].M11 == 0) {
				CameraHandleTransforms [(int)step] = CameraHandle.Transform;
				CameraOrientationTransforms [(int)step] = CameraOrientation.Transform;
			}

			switch (step) {
			case 1:
				overlay.ShowLabel ("Physics");
				overlay.RunAction (SKAction.Sequence (new [] { SKAction.WaitForDuration (2), SKAction.Run (() => {
						if (Step == 1)
							overlay.ShowLabel (null);
					})
				}));

				var popTime = new DispatchTime (DispatchTime.Now, (long)(0.0 * NSEC_PER_SEC));
				DispatchQueue.MainQueue.DispatchAfter (popTime, ShowPhysicsSlide);
				break;
			case 2:
				overlay.ShowLabel ("Particles");
				overlay.RunAction (SKAction.Sequence (new [] { SKAction.WaitForDuration (4), SKAction.Run (() => {
						if (Step == 2)
							overlay.ShowLabel (null);
					})
				}));

				ShowParticlesSlide ();
				break;
			case 3:
				overlay.ShowLabel ("Physics Fields");
				overlay.RunAction (SKAction.Sequence (new [] { SKAction.WaitForDuration (2), SKAction.Run (() => {
						if (Step == 3)
							overlay.ShowLabel (null);
					})
				}));

				ShowPhysicsFields ();
				break;
			case 4:
				overlay.ShowLabel ("SceneKit + SpriteKit");
				overlay.RunAction (SKAction.Sequence (new [] { SKAction.WaitForDuration (4), SKAction.Run (() => {
						if (Step == 4)
							overlay.ShowLabel (null);
					})
				}));

				ShowSpriteKitSlide ();
				break;
			case 5:
				overlay.ShowLabel ("SceneKit + Shaders");
				ShowShadersSlide ();
				break;
			}
		}
예제 #33
0
        public override void PresentStep(int index, PresentationViewController presentationViewController)
        {
            Step = index;

            switch (index)
            {
            case 0:
                break;

            case 1:
                TextManager.FlipOutText(SlideTextManager.TextType.Bullet);

                TextManager.SetSubtitle("SCNPhysicsBody");

                TextManager.FlipInText(SlideTextManager.TextType.Subtitle);

                TextManager.AddBulletAtLevel("Dynamic Bodies", 0);

                // Add some code
                TextManager.AddCode("#// Make a node dynamic\n"
                                    + "aNode.#physicsBody# = [SCNPhysicsBody #dynamicBody#];#");

                TextManager.FlipInText(SlideTextManager.TextType.Bullet);
                TextManager.FlipInText(SlideTextManager.TextType.Code);
                break;

            case 2:
                //add a cube
                var worldPos = GroundNode.ConvertPositionToNode(new SCNVector3(0, 12, 2), null);
                var dice     = CreateBlock(worldPos, new SCNVector3(1.5f, 1.5f, 1.5f));
                dice.PhysicsBody = null;                 //wait!
                dice.Rotation    = new SCNVector4(0, 0, 1, (float)(Math.PI / 4) * 0.5f);
                dice.Scale       = new SCNVector3(0.001f, 0.001f, 0.001f);

                ((SCNView)presentationViewController.View).Scene.RootNode.AddChildNode(dice);
                SCNTransaction.Begin();
                SCNTransaction.AnimationDuration = 0.75f;
                dice.Scale = new SCNVector3(2, 2, 2);
                SCNTransaction.Commit();

                Dices.Add(dice);
                break;

            case 3:
                foreach (var node in Dices)
                {
                    node.PhysicsBody = SCNPhysicsBody.CreateDynamicBody();
                }
                break;

            case 4:
                PresentDices(presentationViewController);
                break;

            case 5:
                TextManager.FlipOutText(SlideTextManager.TextType.Bullet);
                TextManager.FlipOutText(SlideTextManager.TextType.Code);

                TextManager.AddBulletAtLevel("Manipulate with forces", 0);

                // Add some code
                TextManager.AddCode("#// Apply an impulse\n"
                                    + "[aNode.physicsBody #applyForce:#aVector3 #atPosition:#aVector3 #impulse:#YES];#");

                TextManager.FlipInText(SlideTextManager.TextType.Bullet);
                TextManager.FlipInText(SlideTextManager.TextType.Code);
                break;

            case 6:
                // remove dices
                var center = new SCNVector3(0, -5, 20);
                center = GroundNode.ConvertPositionToNode(center, null);

                Explosion(center, Dices);

                var popTime = new DispatchTime(DispatchTime.Now, (long)(1 * Utils.NSEC_PER_SEC));
                DispatchQueue.MainQueue.DispatchAfter(popTime, () => {
                    TextManager.FlipOutText(SlideTextManager.TextType.Code);
                    TextManager.FlipOutText(SlideTextManager.TextType.Bullet);

                    TextManager.AddBulletAtLevel("Static Bodies", 0);
                    TextManager.AddCode("#// Make a node static\n"
                                        + "aNode.#physicsBody# = [SCNPhysicsBody #staticBody#];#");
                    TextManager.FlipInText(SlideTextManager.TextType.Bullet);
                    TextManager.FlipInText(SlideTextManager.TextType.Code);
                });
                break;

            case 7:
                PresentWalls(presentationViewController);
                break;

            case 8:
                PresentBalls(presentationViewController);
                break;

            case 9:
                //remove walls
                var walls = new List <SCNNode> ();
                GroundNode.EnumerateChildNodes(delegate(SCNNode node, out bool stop) {
                    stop = false;
                    if (node.Name == "container-wall")
                    {
                        node.RunAction(SCNAction.Sequence(new SCNAction [] {
                            SCNAction.MoveBy(new SCNVector3(0, -2, 0), 0.5),
                            SCNAction.RemoveFromParentNode()
                        }));
                        walls.Add(node);
                    }
                    return(stop);
                });
                break;

            case 10:
                // remove balls
                center = new SCNVector3(0, -5, 5);
                center = GroundNode.ConvertPositionToNode(center, null);
                Explosion(center, Balls);

                popTime = new DispatchTime(DispatchTime.Now, (long)(0.5 * Utils.NSEC_PER_SEC));
                DispatchQueue.MainQueue.DispatchAfter(popTime, () => {
                    TextManager.FlipOutText(SlideTextManager.TextType.Code);
                    TextManager.FlipOutText(SlideTextManager.TextType.Bullet);

                    TextManager.AddBulletAtLevel("Kinematic Bodies", 0);
                    TextManager.AddCode("#// Make a node kinematic\n"
                                        + "aNode.#physicsBody# = [SCNPhysicsBody #kinematicBody#];#");
                    TextManager.FlipInText(SlideTextManager.TextType.Bullet);
                    TextManager.FlipInText(SlideTextManager.TextType.Code);
                });
                break;

            case 11:
                var boxNode = SCNNode.Create();
                boxNode.Geometry = SCNBox.Create(10, 0.2f, 10, 0);
                boxNode.Position = new SCNVector3(0, 5, MIDDLE_Z);
                boxNode.Geometry.FirstMaterial.Emission.Contents = NSColor.DarkGray;
                boxNode.PhysicsBody = SCNPhysicsBody.CreateKinematicBody();
                boxNode.RunAction(SCNAction.RepeatActionForever(SCNAction.RotateBy(0, 0, NMath.PI * 2, 2.0)));
                GroundNode.AddChildNode(boxNode);
                KinematicItems.Add(boxNode);

                var invisibleWall = SCNNode.Create();
                invisibleWall.Geometry = SCNBox.Create(4, 40, 10, 0);
                invisibleWall.Position = new SCNVector3(-7, 0, MIDDLE_Z);
                invisibleWall.Geometry.FirstMaterial.Transparency = 0;
                invisibleWall.PhysicsBody = SCNPhysicsBody.CreateStaticBody();
                GroundNode.AddChildNode(invisibleWall);
                KinematicItems.Add(invisibleWall);

                invisibleWall          = (SCNNode)invisibleWall.Copy();
                invisibleWall.Position = new SCNVector3(7, 0, MIDDLE_Z);
                GroundNode.AddChildNode(invisibleWall);
                KinematicItems.Add(invisibleWall);

                invisibleWall          = (SCNNode)invisibleWall.Copy();
                invisibleWall.Geometry = SCNBox.Create(10, 40, 4, 0);
                invisibleWall.Geometry.FirstMaterial.Transparency = 0;
                invisibleWall.Position    = new SCNVector3(0, 0, MIDDLE_Z - 7);
                invisibleWall.PhysicsBody = SCNPhysicsBody.CreateStaticBody();
                GroundNode.AddChildNode(invisibleWall);
                KinematicItems.Add(invisibleWall);

                invisibleWall          = (SCNNode)invisibleWall.Copy();
                invisibleWall.Position = new SCNVector3(0, 0, MIDDLE_Z + 7);
                GroundNode.AddChildNode(invisibleWall);
                KinematicItems.Add(invisibleWall);


                for (int i = 0; i < 100; i++)
                {
                    var ball = SCNNode.Create();
                    worldPos      = boxNode.ConvertPositionToNode(new SCNVector3(RandFloat(-4, 4), RandFloat(10, 30), RandFloat(-1, 4)), null);
                    ball.Position = worldPos;
                    ball.Geometry = SCNSphere.Create(0.5f);
                    ball.Geometry.FirstMaterial.Diffuse.Contents = NSColor.Cyan;
                    ball.PhysicsBody = SCNPhysicsBody.CreateDynamicBody();
                    ((SCNView)presentationViewController.View).Scene.RootNode.AddChildNode(ball);

                    KinematicItems.Add(ball);
                }
                break;

            case 12:
                TextManager.FlipOutText(SlideTextManager.TextType.Code);
                TextManager.FlipOutText(SlideTextManager.TextType.Bullet);
                TextManager.FlipOutText(SlideTextManager.TextType.Subtitle);
                TextManager.SetSubtitle("SCNPhysicsShape");
                TextManager.AddCode("#// Configure the physics shape\n\n"
                                    + "aNode.physicsBody.#physicsShape# = \n\t[#SCNPhysicsShape# shapeWithGeometry:aGeometry options:options];#");
                TextManager.FlipInText(SlideTextManager.TextType.Bullet);
                TextManager.FlipInText(SlideTextManager.TextType.Code);

                KinematicItems[0].RunAction(SCNAction.Sequence(new SCNAction[] {
                    SCNAction.FadeOut(0.5),
                    SCNAction.RemoveFromParentNode()
                }));
                for (int i = 1; i < 5; i++)
                {
                    KinematicItems[i].RemoveFromParentNode();
                }

                KinematicItems = null;
                break;

            case 13:
                //add meshes
                PresentMeshes(presentationViewController);
                break;

            case 14:
                // remove meshes
                center = new SCNVector3(0, -5, 20);
                center = GroundNode.ConvertPositionToNode(center, null);
                Explosion(center, Meshes);
                break;

            case 15:
                // add shapes
                PresentPrimitives(presentationViewController);
                break;

            case 16:
                // remove shapes
                center = new SCNVector3(0, -5, 20);
                center = GroundNode.ConvertPositionToNode(center, null);
                Explosion(center, Shapes);

                popTime = new DispatchTime(DispatchTime.Now, (long)(0.5 * Utils.NSEC_PER_SEC));
                DispatchQueue.MainQueue.DispatchAfter(popTime, () => {
                    TextManager.FlipOutText(SlideTextManager.TextType.Code);
                    TextManager.FlipOutText(SlideTextManager.TextType.Bullet);
                    TextManager.FlipOutText(SlideTextManager.TextType.Subtitle);

                    TextManager.SetSubtitle("SCNPhysicsBehavior");
                    TextManager.AddCode("#// setup a physics behavior\n\n"
                                        + "#SCNPhysicsHingeJoint# *joint = [SCNPhysicsHingeJoint\n\n"
                                        + "jointWithBodyA:#nodeA.physicsBody# axisA:[...] anchorA:[...]\n\n"
                                        + "bodyB:#nodeB.physicsBody# axisB:[...] anchorB:[...]];\n\n\n"
                                        + "[scene.#physicsWorld# addBehavior:joint];#");

                    TextManager.FlipInText(SlideTextManager.TextType.Bullet);
                    TextManager.FlipInText(SlideTextManager.TextType.Subtitle);
                    TextManager.FlipInText(SlideTextManager.TextType.Code);
                });
                break;

            case 17:
                //add meshes
                PresentHinge(presentationViewController);
                break;

            case 18:
                //remove constraints
                ((SCNView)presentationViewController.View).Scene.PhysicsWorld.RemoveAllBehaviors();

                foreach (var node in Hinges)
                {
                    node.RunAction(SCNAction.Sequence(new SCNAction[] { SCNAction.Wait(3.0), SCNAction.FadeOut(0.5), SCNAction.RemoveFromParentNode() }));
                }

                break;

            case 19:
                TextManager.FlipOutText(SlideTextManager.TextType.Bullet);
                TextManager.FlipOutText(SlideTextManager.TextType.Subtitle);
                TextManager.FlipOutText(SlideTextManager.TextType.Code);

                TextManager.SetSubtitle("More...");

                TextManager.FlipInText(SlideTextManager.TextType.Subtitle);

                TextManager.AddBulletAtLevel("SCNPhysicsField", 0);
                TextManager.AddBulletAtLevel("SCNPhysicsVehicle", 0);

                TextManager.FlipInText(SlideTextManager.TextType.Bullet);
                TextManager.FlipInText(SlideTextManager.TextType.Code);
                break;
            }
        }
예제 #34
0
		void PreventAccidentalNext (nfloat delay)
		{
			PreventNext = true;

			//disable the next button for "delay" seconds to prevent accidental tap
			var overlay = (SpriteKitOverlayScene)((SCNView)View).OverlayScene;
			overlay.NextButton.RunAction (SKAction.FadeAlphaBy (-0.5f, 0.5f));
			overlay.PreviousButton.RunAction (SKAction.FadeAlphaBy (-0.5f, 0.5f));
			var popTime = new DispatchTime (DispatchTime.Now, (long)(delay * NSEC_PER_SEC));
			DispatchQueue.MainQueue.DispatchAfter (popTime, () => {
				PreventNext = false;
				overlay.PreviousButton.RunAction (SKAction.FadeAlphaTo (Step > 1 ? 1 : 0, 0.75f));
				overlay.NextButton.RunAction (SKAction.FadeAlphaTo (IntroductionStep == 0 && Step < 5 ? 1 : 0, 0.75f));
			});
		}
예제 #35
0
		public void HandlePan (CGPoint p)
		{
			var scnView = (SCNView)this.View;

			if (Step == 2) {
				//particles
				var pTmp = scnView.ProjectPoint (new SCNVector3 (0, 0, 0));
				var p3d = scnView.UnprojectPoint (new SCNVector3 (p.X, p.Y, pTmp.Z));
				var handlePos = Handle.WorldTransform;


				var dy = (float)Math.Max (0, p3d.Y - handlePos.M42);
				var dx = handlePos.M41 - p3d.X;
				var angle = (float)Math.Atan2 (dy, dx);


				angle -= 35.0f * (float)Math.PI / 180.0f; //handle is 35 degree by default

				//clamp
				if (angle < MIN_ANGLE)
					angle = MIN_ANGLE;
				if (angle > MAX_ANGLE)
					angle = MAX_ANGLE;


				var popTime = new DispatchTime (DispatchTime.Now, (long)(HIT_DELAY * NSEC_PER_SEC));
				if (angle <= 0.66 && angle >= 0.48) {
					DispatchQueue.MainQueue.DispatchAfter (popTime, () => {
						//hit the fire!
						HitFire = true;
					});
				} else {
					DispatchQueue.MainQueue.DispatchAfter (popTime, () => {
						//hit the fire!
						HitFire = false;
					});
				}

				Handle.Rotation = new SCNVector4 (1, 0, 0, angle);
			}

			if (Step == 3) {
				//bubbles
				MoveEmitter (p);
			}
		}
        public static void DispatchAfter(this DispatchQueue self, TimeSpan delay, Action action)
        {
            var time = new DispatchTime(DispatchTime.Now, delay.Ticks * 100);

            self.DispatchAfter(time, action);
        }
예제 #37
0
		// switch to the next introduction step
		void NextIntroductionStep ()
		{
			IntroductionStep++;

			SCNTransaction.Begin ();
			SCNTransaction.AnimationDuration = 1;
			SCNTransaction.SetCompletionBlock (() => {
				if (IntroductionStep >= 4) {
					//We did finish introduction step 4
					//free some memory
					if (ShipHandle != null)
						ShipHandle.RemoveFromParentNode ();
					ShipHandle = null;
					ShipPivot = null;
					ShipNode = null;

				}
				if (IntroductionStep == 0) {
					//We did finish the whole introduction
					IntroNodeGroup.RemoveFromParentNode ();
					IntroNodeGroup = null;

					Next ();
				}
			});

			if (IntroductionStep == 2) {
				var popTime = new DispatchTime (DispatchTime.Now, (long)(1 * NSEC_PER_SEC));
				DispatchQueue.MainQueue.DispatchAfter (popTime, () => {
					SCNTransaction.Begin ();
					SCNTransaction.AnimationDuration = 1.0f;
					ShipNode.Opacity = 1.0f;
					ShipNode.RunAction (SCNAction.RepeatActionForever (SCNAction.RotateBy (0, NMath.PI, 0, 1.0)));
					SCNTransaction.Commit ();
				});
			}

			if (IntroductionStep == 3) {
				//animate ship
				ShipNode.RemoveAllActions ();
				ShipNode.Rotation = new SCNVector4 (0, 0, 1, (float)(Math.PI / 4) * 0.5f);

				//make spotlight relative to the ship
				var newPosition = new SCNVector3 (50, 100, 0);
				var oldTransform = ShipPivot.ConvertTransformFromNode (SCNMatrix4.Identity, SpotLightNode);

				OldSpotTransform = SpotLightNode.Transform;

				SpotLightNode.RemoveFromParentNode ();
				SpotLightNode.Transform = oldTransform;

				ShipPivot.AddChildNode (SpotLightNode);

				SpotLightNode.Position = newPosition; // will animate implicitly
				SpotLightNode.EulerAngles = new SCNVector3 (-(float)Math.PI / 2, 0, 0);
				SpotLightNode.Light.SpotOuterAngle = 120;

				var action = SCNAction.Sequence (new [] {
					SCNAction.Wait (1),
					SCNAction.RepeatActionForever (SCNAction.RotateBy (0, NMath.PI, 0, 2))
				});
				ShipPivot.RunAction (action);

				var animation = CABasicAnimation.FromKeyPath ("position.x");
				animation.From = new NSNumber (-50);
				animation.To = new NSNumber (50);
				animation.TimingFunction = CAMediaTimingFunction.FromName (CAMediaTimingFunction.EaseInEaseOut);
				animation.AutoReverses = true;
				animation.Duration = 2;
				animation.RepeatCount = float.MaxValue;
				animation.TimeOffset = animation.Duration * 0.5f;
				ShipPivot.ParentNode.AddAnimation (animation, null);

				var emitter = ShipNode.FindChildNode ("emitter", true);
				var ps = SCNParticleSystem.Create ("reactor.scnp", "assets.scnassets/particles");
				ps.ParticleImage = new NSString ("assets.scnassets/textures/tspark.png");
				emitter.AddParticleSystem (ps);

				ShipHandle.Position = new SCNVector3 (ShipHandle.Position.X, ShipHandle.Position.Y, ShipHandle.Position.Z - TEXT_Z_SPACING - 50);
			}


			if (IntroductionStep == 4) {
				//restore spot light config
				SpotLightNode.Light.SpotOuterAngle = 70;
				var oldTransform = SpotLightParentNode.ConvertTransformFromNode (SCNMatrix4.Identity, SpotLightNode);
				SpotLightNode.RemoveFromParentNode ();
				SpotLightNode.Transform = oldTransform;

				SpotLightParentNode.AddChildNode (SpotLightNode);
				SpotLightNode.Transform = OldSpotTransform;

				CameraNode.Position = new SCNVector3 (CameraNode.Position.X, CameraNode.Position.Y, CameraNode.Position.Z - TEXT_Z_SPACING);
			}


			if (IntroductionStep == 5) {
				IntroductionStep = 0;//introduction is over
				// jiterring is now useless since the screen will never be static again.
				var scnView = (SCNView)this.View;
				scnView.JitteringEnabled = false;

				AmbientLightNode.Light.Color = SKColorHelper.FromCommonWhiteAlpha (0.3f, 1.0f);
				SpotLightNode.Position = new SCNVector3 (0, 0, 0);
				SpotLightNode.EulerAngles = new SCNVector3 (-(float)(Math.PI / 4), 0, 0);
				CameraNode.Position = new SCNVector3 (0, 0, 120);
				CameraNode.EulerAngles = new SCNVector3 (0, 0, 0);
			} else {
				CameraNode.Position = new SCNVector3 (CameraNode.Position.X, CameraNode.Position.Y, CameraNode.Position.Z - TEXT_Z_SPACING);
			}

			SCNTransaction.Commit ();
		}
예제 #38
0
		bool TryLoadFirstBatch()
		{
			bool haveNoPost = PostCells.Count == 0 || lastPostSeenOnServer == null;

			if(haveNoPost) {
				// We dispatch it after two seconds to give the server time to index the new post
				// TODO: https://trello.com/c/cWWQXKYY
				var dispatchTime = new DispatchTime (DispatchTime.Now, 2 * 1000000000);
				DispatchQueue.MainQueue.DispatchAfter (dispatchTime, () => {
					// If we get here, we must have no posts. That must mean that last time we tried loading a batch nothing came through so we locked the method. Let's unlock it
					haveOldestPost = false;
					LoadBatch ();
				});
			}

			return haveNoPost;
		}
예제 #39
0
        public override void PresentStep(int index, PresentationViewController presentationViewController)
        {
            float delay = 0;

            switch (index)
            {
            case 0:
                break;

            case 1:
                TextManager.FlipOutText(SlideTextManager.TextType.Bullet);
                TextManager.AddEmptyLine();
                TextManager.AddBulletAtLevel("Available on OS X 10.8+ and iOS 8.0", 0);
                TextManager.FlipInText(SlideTextManager.TextType.Bullet);

                //show some nice icons
                Icon1          = Utils.SCPlaneNode(NSBundle.MainBundle.PathForResource("Images/Badge_X", "png"), 7, false);
                Icon1.Position = new SCNVector3(-20, 3.5f, 5);
                GroundNode.AddChildNode(Icon1);

                Icon2          = Utils.SCPlaneNode(NSBundle.MainBundle.PathForResource("Images/Badge_iOS", "png"), 7, false);
                Icon2.Position = new SCNVector3(20, 3.5f, 5);
                GroundNode.AddChildNode(Icon2);

                SCNTransaction.Begin();
                SCNTransaction.AnimationDuration = 0.75f;
                Icon1.Position = new SCNVector3(-6, 3.5f, 5);
                Icon2.Position = new SCNVector3(6, 3.5f, 5);
                SCNTransaction.Commit();
                break;

            case 2:
                SCNTransaction.Begin();
                SCNTransaction.AnimationDuration = 0.75f;
                Icon1.Position = new SCNVector3(-6, 3.5f, -5);
                Icon2.Position = new SCNVector3(6, 3.5f, -5);
                Icon1.Opacity  = 0.0f;
                Icon2.Opacity  = 0.0f;
                SCNTransaction.Commit();

                foreach (var node in Boxes)
                {
                    var popTime = new DispatchTime(DispatchTime.Now, (Int64)(delay * Utils.NSEC_PER_SEC));
                    DispatchQueue.MainQueue.DispatchAfter(popTime, () => {
                        SCNTransaction.Begin();
                        SCNTransaction.AnimationDuration = 0.5f;

                        node.Rotation = new SCNVector4(1, 0, 0, 0);
                        node.Scale    = new SCNVector3(0.02f, 0.02f, 0.02f);
                        node.Opacity  = 1.0f;

                        SCNTransaction.Commit();
                    });

                    delay += 0.05f;
                }


                TextManager.FlipOutText(SlideTextManager.TextType.Bullet);
                TextManager.FlipOutText(SlideTextManager.TextType.Subtitle);

                TextManager.SetSubtitle("Graphic Frameworks");

                TextManager.FlipInText(SlideTextManager.TextType.Bullet);
                TextManager.FlipInText(SlideTextManager.TextType.Subtitle);

                break;
            }
        }
예제 #40
0
		public void ButtonFinished (ButtonView button, UIView trackingView, UITouch location)
		{
			double delayInSeconds = 0;

			buttonDraggedToPad = false;
			miniPadView.Layer.BorderWidth = 0;

			CGPoint point = location.LocationInView (miniPadView);
			if (miniPadView.PointInside (point, null)) {
				updateScoreForDroppedButton (button);
				UIView.Animate (.1f, () => trackingView.Transform = CGAffineTransform.MakeRotation (10f * (float)Math.PI / 180), async () => {
					await UIView.AnimateAsync (.1f, () => trackingView.Transform = CGAffineTransform.MakeRotation (-10f * (float)Math.PI / 180));
					await UIView.AnimateAsync (.1f, () => trackingView.Transform = CGAffineTransform.MakeRotation (10f * (float)Math.PI / 180));
					await UIView.AnimateAsync (.1f, () => trackingView.Transform = CGAffineTransform.MakeRotation (-10f * (float)Math.PI / 180));
					await UIView.AnimateAsync (.1f, () => trackingView.Transform = CGAffineTransform.MakeRotation (0));
				});
			}

			delayInSeconds = 0.5;

			var popTime = new DispatchTime (DispatchTime.Now, (long)(delayInSeconds * NSEC_PER_SEC));
			DispatchQueue.MainQueue.DispatchAfter (popTime, async () => {
				await UIView.AnimateAsync (0.35f, () => {
					CGRect bounds = trackingView.Bounds;
					bounds.Size = new CGSize (10, 10);
					trackingView.Bounds = bounds;
				});
				trackingView.RemoveFromSuperview ();
			});
		}
        public void GoToSlide(int slideIndex)
        {
            int oldIndex = CurrentSlideIndex;

            // Load the slide at the specified index
            var slide = GetSlide(slideIndex, true);

            if (slide == null)
            {
                return;
            }

            // Compute the playback direction (did the user select next or previous?)
            var direction = slideIndex >= CurrentSlideIndex ? 1 : -1;

            // Update badge
            ShowsNewInSceneKitBadge(slide.IsNewIn10_10);

            // If we are playing backward, we need to use the slide we come from to play the correct transition (backward)
            int transitionSlideIndex = direction == 1 ? slideIndex : CurrentSlideIndex;
            var transitionSlide      = GetSlide(transitionSlideIndex, true);

            // Make sure that the next operations are synchronized by using a transaction
            SCNTransaction.Begin();
            SCNTransaction.AnimationDuration = 0;

            var rootNode      = slide.ContentNode;
            var textContainer = slide.TextManager.TextNode;

            var offset = new SCNVector3(transitionSlide.TransitionOffsetX, 0.0f, transitionSlide.TransitionOffsetZ);

            offset.X *= direction;
            offset.Z *= direction;

            // Rotate offset based on current yaw
            var cosa = Math.Cos(-CameraHandle.Rotation.W);
            var sina = Math.Sin(-CameraHandle.Rotation.W);

            var tmpX = offset.X * cosa - offset.Z * sina;

            offset.Z = (float)(offset.X * sina + offset.Z * cosa);
            offset.X = (float)tmpX;

            // If we don't move, fade in
            if (offset.X == 0 && offset.Y == 0 && offset.Z == 0 && transitionSlide.TransitionRotation == 0)
            {
                rootNode.Opacity = 0;
            }

            // Don't animate the first slide
            bool shouldAnimate = !(slideIndex == 0 && CurrentSlideIndex == 0);

            // Update current slide index
            CurrentSlideIndex = slideIndex;

            // Go to step 0
            GoToSlideStep(0);

            // Add the slide to the scene graph
            ((SCNView)View).Scene.RootNode.AddChildNode(rootNode);

            // Fade in, update paramters and notify on completion
            SCNTransaction.Begin();
            SCNTransaction.AnimationDuration = (shouldAnimate ? slide.TransitionDuration : 0);
            SCNTransaction.SetCompletionBlock(() => DidOrderInSlide(slideIndex));
            rootNode.Opacity = 1;

            CameraHandle.Position = new SCNVector3(CameraHandle.Position.X + offset.X, slide.Altitude, CameraHandle.Position.Z + offset.Z);
            CameraHandle.Rotation = new SCNVector4(0, 1, 0, (float)(CameraHandle.Rotation.W + transitionSlide.TransitionRotation * (Math.PI / 180.0f) * direction));
            CameraPitch.Rotation  = new SCNVector4(1, 0, 0, (float)(slide.Pitch * (Math.PI / 180.0f)));

            UpdateLightingForSlide(slideIndex);

            Floor.Reflectivity         = slide.FloorReflectivity;
            Floor.ReflectionFalloffEnd = slide.FloorFalloff;
            SCNTransaction.Commit();

            // Compute the position of the text (in world space, relative to the camera)
            var textWorldTransform = SCNMatrix4.Mult(SCNMatrix4.CreateTranslation(0, -3.3f, -28), CameraNode.WorldTransform);

            // Place the rest of the slide
            rootNode.Transform = textWorldTransform;
            rootNode.Position  = new SCNVector3(rootNode.Position.X, 0, rootNode.Position.Z);  // clear altitude
            rootNode.Rotation  = new SCNVector4(0, 1, 0, CameraHandle.Rotation.W);             // use same rotation as the camera to simplify the placement of the elements in slides

            // Place the text
            textContainer.Transform = textContainer.ParentNode.ConvertTransformFromNode(textWorldTransform, null);

            // Place the ground node
            var localPosition = new SCNVector3(0, 0, 0);
            var worldPosition = slide.GroundNode.ParentNode.ConvertPositionToNode(localPosition, null);

            worldPosition.Y = 0;             // make it touch the ground

            localPosition             = slide.GroundNode.ParentNode.ConvertPositionFromNode(worldPosition, null);
            slide.GroundNode.Position = localPosition;

            // Update the floor image if needed
            string  floorImagePath = null;
            NSImage floorImage     = null;

            if (slide.FloorImageName != null)
            {
                floorImagePath = NSBundle.MainBundle.PathForResource("SharedTextures/" + slide.FloorImageName, slide.FloorImageExtension);
                floorImage     = new NSImage(floorImagePath);
            }
            UpdateFloorImage(floorImage, slide);

            SCNTransaction.Commit();

            // Preload the next slide after some delay
            var delayInSeconds = 1.5;
            var popTime        = new DispatchTime(DispatchTime.Now, (long)(delayInSeconds * Utils.NSEC_PER_SEC));

            DispatchQueue.MainQueue.DispatchAfter(popTime, () => {
                PrepareSlide(slideIndex + 1);
            });

            // Order out previous slide if any
            if (oldIndex != CurrentSlideIndex)
            {
                WillOrderOutSlide(oldIndex);
            }
        }
예제 #42
0
		public override void PresentStep (int index, PresentationViewController presentationViewController)
		{
			Step = index;

			switch (index) {
			case 0:
				break;
			case 1:
				TextManager.FlipOutText (SlideTextManager.TextType.Bullet);

				TextManager.SetSubtitle ("SCNPhysicsBody");

				TextManager.FlipInText (SlideTextManager.TextType.Subtitle);

				TextManager.AddBulletAtLevel ("Dynamic Bodies", 0);

					// Add some code
				TextManager.AddCode ("#// Make a node dynamic\n"
				+ "aNode.#physicsBody# = [SCNPhysicsBody #dynamicBody#];#");

				TextManager.FlipInText (SlideTextManager.TextType.Bullet);
				TextManager.FlipInText (SlideTextManager.TextType.Code);
				break;
			case 2:
				//add a cube
				var worldPos = GroundNode.ConvertPositionToNode (new SCNVector3 (0, 12, 2), null);
				var dice = CreateBlock (worldPos, new SCNVector3 (1.5f, 1.5f, 1.5f));
				dice.PhysicsBody = null; //wait!
				dice.Rotation = new SCNVector4 (0, 0, 1, (float)(Math.PI / 4) * 0.5f);
				dice.Scale = new SCNVector3 (0.001f, 0.001f, 0.001f);

				((SCNView)presentationViewController.View).Scene.RootNode.AddChildNode (dice);
				SCNTransaction.Begin (); 
				SCNTransaction.AnimationDuration = 0.75f;
				dice.Scale = new SCNVector3 (2, 2, 2);
				SCNTransaction.Commit ();

				Dices.Add (dice);
				break;
			case 3:
				foreach (var node in Dices)
					node.PhysicsBody = SCNPhysicsBody.CreateDynamicBody ();
				break;
			case 4:
				PresentDices (presentationViewController);
				break;
			case 5:
				TextManager.FlipOutText (SlideTextManager.TextType.Bullet);
				TextManager.FlipOutText (SlideTextManager.TextType.Code);

				TextManager.AddBulletAtLevel ("Manipulate with forces", 0);

				// Add some code
				TextManager.AddCode ("#// Apply an impulse\n"
				+ "[aNode.physicsBody #applyForce:#aVector3 #atPosition:#aVector3 #impulse:#YES];#");

				TextManager.FlipInText (SlideTextManager.TextType.Bullet);
				TextManager.FlipInText (SlideTextManager.TextType.Code);
				break;
			case 6:
				// remove dices
				var center = new SCNVector3 (0, -5, 20);
				center = GroundNode.ConvertPositionToNode (center, null);

				Explosion (center, Dices);

				var popTime = new DispatchTime (DispatchTime.Now, (long)(1 * Utils.NSEC_PER_SEC));
				DispatchQueue.MainQueue.DispatchAfter (popTime, () => {
					TextManager.FlipOutText (SlideTextManager.TextType.Code);
					TextManager.FlipOutText (SlideTextManager.TextType.Bullet);

					TextManager.AddBulletAtLevel ("Static Bodies", 0);
					TextManager.AddCode ("#// Make a node static\n"
					+ "aNode.#physicsBody# = [SCNPhysicsBody #staticBody#];#");
					TextManager.FlipInText (SlideTextManager.TextType.Bullet);
					TextManager.FlipInText (SlideTextManager.TextType.Code);
				});
				break;
			case 7:
				PresentWalls (presentationViewController);
				break;
			case 8:
				PresentBalls (presentationViewController);
				break;
			case 9:
				//remove walls
				var walls = new List<SCNNode> ();
				GroundNode.EnumerateChildNodes (delegate(SCNNode node, out bool stop) {
					stop = false;
					if (node.Name == "container-wall") {
						node.RunAction (SCNAction.Sequence (new SCNAction [] {
							SCNAction.MoveBy (new SCNVector3 (0, -2, 0), 0.5),
							SCNAction.RemoveFromParentNode ()
						}));
						walls.Add (node);
					}
					return stop;
				});
				break;
			case 10:
				// remove balls
				center = new SCNVector3 (0, -5, 5);
				center = GroundNode.ConvertPositionToNode (center, null);
				Explosion (center, Balls);

				popTime = new DispatchTime (DispatchTime.Now, (long)(0.5 * Utils.NSEC_PER_SEC));
				DispatchQueue.MainQueue.DispatchAfter (popTime, () => {
					TextManager.FlipOutText (SlideTextManager.TextType.Code);
					TextManager.FlipOutText (SlideTextManager.TextType.Bullet);

					TextManager.AddBulletAtLevel ("Kinematic Bodies", 0);
					TextManager.AddCode ("#// Make a node kinematic\n"
					+ "aNode.#physicsBody# = [SCNPhysicsBody #kinematicBody#];#");
					TextManager.FlipInText (SlideTextManager.TextType.Bullet);
					TextManager.FlipInText (SlideTextManager.TextType.Code);
				});
				break;
			case 11:
				var boxNode = SCNNode.Create ();
				boxNode.Geometry = SCNBox.Create (10, 0.2f, 10, 0);
				boxNode.Position = new SCNVector3 (0, 5, MIDDLE_Z);
				boxNode.Geometry.FirstMaterial.Emission.Contents = NSColor.DarkGray;
				boxNode.PhysicsBody = SCNPhysicsBody.CreateKinematicBody ();
				boxNode.RunAction (SCNAction.RepeatActionForever (SCNAction.RotateBy (0, 0, NMath.PI * 2, 2.0)));
				GroundNode.AddChildNode (boxNode);
				KinematicItems.Add (boxNode);

				var invisibleWall = SCNNode.Create ();
				invisibleWall.Geometry = SCNBox.Create (4, 40, 10, 0);
				invisibleWall.Position = new SCNVector3 (-7, 0, MIDDLE_Z);
				invisibleWall.Geometry.FirstMaterial.Transparency = 0;
				invisibleWall.PhysicsBody = SCNPhysicsBody.CreateStaticBody ();
				GroundNode.AddChildNode (invisibleWall);
				KinematicItems.Add (invisibleWall);

				invisibleWall = (SCNNode)invisibleWall.Copy ();
				invisibleWall.Position = new SCNVector3 (7, 0, MIDDLE_Z);
				GroundNode.AddChildNode (invisibleWall);
				KinematicItems.Add (invisibleWall);

				invisibleWall = (SCNNode)invisibleWall.Copy ();
				invisibleWall.Geometry = SCNBox.Create (10, 40, 4, 0);
				invisibleWall.Geometry.FirstMaterial.Transparency = 0;
				invisibleWall.Position = new SCNVector3 (0, 0, MIDDLE_Z - 7);
				invisibleWall.PhysicsBody = SCNPhysicsBody.CreateStaticBody ();
				GroundNode.AddChildNode (invisibleWall);
				KinematicItems.Add (invisibleWall);

				invisibleWall = (SCNNode)invisibleWall.Copy ();
				invisibleWall.Position = new SCNVector3 (0, 0, MIDDLE_Z + 7);
				GroundNode.AddChildNode (invisibleWall);
				KinematicItems.Add (invisibleWall);


				for (int i = 0; i < 100; i++) {
					var ball = SCNNode.Create ();
					worldPos = boxNode.ConvertPositionToNode (new SCNVector3 (RandFloat (-4, 4), RandFloat (10, 30), RandFloat (-1, 4)), null);
					ball.Position = worldPos;
					ball.Geometry = SCNSphere.Create (0.5f);
					ball.Geometry.FirstMaterial.Diffuse.Contents = NSColor.Cyan;
					ball.PhysicsBody = SCNPhysicsBody.CreateDynamicBody ();
					((SCNView)presentationViewController.View).Scene.RootNode.AddChildNode (ball);

					KinematicItems.Add (ball);
				}
				break;
			case 12:
				TextManager.FlipOutText (SlideTextManager.TextType.Code);
				TextManager.FlipOutText (SlideTextManager.TextType.Bullet);
				TextManager.FlipOutText (SlideTextManager.TextType.Subtitle);
				TextManager.SetSubtitle ("SCNPhysicsShape");
				TextManager.AddCode ("#// Configure the physics shape\n\n"
				+ "aNode.physicsBody.#physicsShape# = \n\t[#SCNPhysicsShape# shapeWithGeometry:aGeometry options:options];#");
				TextManager.FlipInText (SlideTextManager.TextType.Bullet);
				TextManager.FlipInText (SlideTextManager.TextType.Code);

				KinematicItems[0].RunAction (SCNAction.Sequence (new SCNAction[] {
					SCNAction.FadeOut (0.5),
					SCNAction.RemoveFromParentNode ()
				}));
				for (int i = 1; i < 5; i++)
					KinematicItems[i].RemoveFromParentNode ();

				KinematicItems = null;
				break;
			case 13:
				//add meshes
				PresentMeshes (presentationViewController);
				break;
			case 14:
				// remove meshes
				center = new SCNVector3 (0, -5, 20);
				center = GroundNode.ConvertPositionToNode (center, null);
				Explosion (center, Meshes);
				break;
			case 15:
				// add shapes
				PresentPrimitives (presentationViewController);
				break;
			case 16:
				// remove shapes
				center = new SCNVector3 (0, -5, 20);
				center = GroundNode.ConvertPositionToNode (center, null);
				Explosion (center, Shapes);

				popTime = new DispatchTime (DispatchTime.Now, (long)(0.5 * Utils.NSEC_PER_SEC));
				DispatchQueue.MainQueue.DispatchAfter (popTime, () => {
					TextManager.FlipOutText (SlideTextManager.TextType.Code);
					TextManager.FlipOutText (SlideTextManager.TextType.Bullet);
					TextManager.FlipOutText (SlideTextManager.TextType.Subtitle);

					TextManager.SetSubtitle ("SCNPhysicsBehavior");
					TextManager.AddCode ("#// setup a physics behavior\n\n"
						+ "#SCNPhysicsHingeJoint# *joint = [SCNPhysicsHingeJoint\n\n" 
						+ "jointWithBodyA:#nodeA.physicsBody# axisA:[...] anchorA:[...]\n\n"
						+ "bodyB:#nodeB.physicsBody# axisB:[...] anchorB:[...]];\n\n\n"
						+ "[scene.#physicsWorld# addBehavior:joint];#");

					TextManager.FlipInText (SlideTextManager.TextType.Bullet);
					TextManager.FlipInText (SlideTextManager.TextType.Subtitle);
					TextManager.FlipInText (SlideTextManager.TextType.Code);
				});
				break;
			case 17:
				//add meshes
				PresentHinge (presentationViewController);
				break;
			case 18:
				//remove constraints
				((SCNView)presentationViewController.View).Scene.PhysicsWorld.RemoveAllBehaviors ();

				foreach (var node in Hinges)
					node.RunAction (SCNAction.Sequence (new SCNAction[] { SCNAction.Wait (3.0), SCNAction.FadeOut (0.5), SCNAction.RemoveFromParentNode () }));

				break;
			case 19:
				TextManager.FlipOutText (SlideTextManager.TextType.Bullet);
				TextManager.FlipOutText (SlideTextManager.TextType.Subtitle);
				TextManager.FlipOutText (SlideTextManager.TextType.Code);

				TextManager.SetSubtitle ("More...");

				TextManager.FlipInText (SlideTextManager.TextType.Subtitle);

				TextManager.AddBulletAtLevel ("SCNPhysicsField", 0);
				TextManager.AddBulletAtLevel ("SCNPhysicsVehicle", 0);

				TextManager.FlipInText (SlideTextManager.TextType.Bullet);
				TextManager.FlipInText (SlideTextManager.TextType.Code);
				break;
			}
		}
		public void GoToSlide (int slideIndex)
		{
			int oldIndex = CurrentSlideIndex;

			// Load the slide at the specified index
			var slide = GetSlide (slideIndex, true);

			if (slide == null)
				return;

			// Compute the playback direction (did the user select next or previous?)
			var direction = slideIndex >= CurrentSlideIndex ? 1 : -1;

			// Update badge
			ShowsNewInSceneKitBadge (slide.IsNewIn10_9);

			// If we are playing backward, we need to use the slide we come from to play the correct transition (backward)
			int transitionSlideIndex = direction == 1 ? slideIndex : CurrentSlideIndex;
			var transitionSlide = GetSlide (transitionSlideIndex, true);

			// Make sure that the next operations are synchronized by using a transaction
			SCNTransaction.Begin ();
			SCNTransaction.AnimationDuration = 0;

			var rootNode = slide.ContentNode;
			var textContainer = slide.TextManager.TextNode;

			var offset = new SCNVector3 (transitionSlide.TransitionOffsetX, 0.0f, transitionSlide.TransitionOffsetZ);
			offset.X *= direction;
			offset.Z *= direction;

			// Rotate offset based on current yaw
			var cosa = Math.Cos (-CameraHandle.Rotation.W);
			var sina = Math.Sin (-CameraHandle.Rotation.W);

			var tmpX = offset.X * cosa - offset.Z * sina;
			offset.Z = (float)(offset.X * sina + offset.Z * cosa);
			offset.X = (float)tmpX;

			// If we don't move, fade in
			if (offset.X == 0 && offset.Y == 0 && offset.Z == 0 && transitionSlide.TransitionRotation == 0)
				rootNode.Opacity = 0;

			// Don't animate the first slide
			bool shouldAnimate = !(slideIndex == 0 && CurrentSlideIndex == 0);

			// Update current slide index
			CurrentSlideIndex = slideIndex;

			// Go to step 0
			GoToSlideStep (0);

			// Add the slide to the scene graph
			((SCNView)View).Scene.RootNode.AddChildNode (rootNode);

			// Fade in, update paramters and notify on completion
			SCNTransaction.Begin ();
			SCNTransaction.AnimationDuration = (shouldAnimate ? slide.TransitionDuration : 0);
			SCNTransaction.SetCompletionBlock (() => DidOrderInSlide (slideIndex));
			rootNode.Opacity = 1;

			CameraHandle.Position = new SCNVector3 (CameraHandle.Position.X + offset.X, slide.Altitude, CameraHandle.Position.Z + offset.Z);
			CameraHandle.Rotation = new SCNVector4 (0, 1, 0, (float)(CameraHandle.Rotation.W + transitionSlide.TransitionRotation * (Math.PI / 180.0f) * direction));
			CameraPitch.Rotation = new SCNVector4 (1, 0, 0, (float)(slide.Pitch * (Math.PI / 180.0f)));

			UpdateLightingForSlide (slideIndex);

			Floor.Reflectivity = slide.FloorReflectivity;
			Floor.ReflectionFalloffEnd = slide.FloorFalloff;
			SCNTransaction.Commit ();

			// Compute the position of the text (in world space, relative to the camera)
			var textWorldTransform = SCNMatrix4.Mult (SCNMatrix4.CreateTranslation (0, -3.3f, -28), CameraNode.WorldTransform);

			// Place the rest of the slide
			rootNode.Transform = textWorldTransform;
			rootNode.Position = new SCNVector3 (rootNode.Position.X, 0, rootNode.Position.Z); // clear altitude
			rootNode.Rotation = new SCNVector4 (0, 1, 0, CameraHandle.Rotation.W); // use same rotation as the camera to simplify the placement of the elements in slides

			// Place the text
			textContainer.Transform = textContainer.ParentNode.ConvertTransformFromNode (textWorldTransform, null);

			// Place the ground node
			var localPosition = new SCNVector3 (0, 0, 0);
			var worldPosition = slide.GroundNode.ParentNode.ConvertPositionToNode (localPosition, null);
			worldPosition.Y = 0; // make it touch the ground

			localPosition = slide.GroundNode.ParentNode.ConvertPositionFromNode (worldPosition, null);
			slide.GroundNode.Position = localPosition;

			// Update the floor image if needed
			string floorImagePath = null;
			NSImage floorImage = null;
			if (slide.FloorImageName != null) {
				floorImagePath = NSBundle.MainBundle.PathForResource ("SharedTextures/" + slide.FloorImageName, slide.FloorImageExtension);
				floorImage = new NSImage (floorImagePath);
			}
			UpdateFloorImage (floorImage, slide);

			SCNTransaction.Commit ();

			// Preload the next slide after some delay
			var delayInSeconds = 1.5;
			var popTime = new DispatchTime (DispatchTime.Now, (long)(delayInSeconds * Utils.NSEC_PER_SEC));
			DispatchQueue.MainQueue.DispatchAfter (popTime, () => {
				PrepareSlide (slideIndex + 1);
			});

			// Order out previous slide if any
			if (oldIndex != CurrentSlideIndex)
				WillOrderOutSlide (oldIndex);
		}
예제 #44
0
		public override void PresentStep (int index, PresentationViewController presentationViewController)
		{
			float delay = 0;

			switch (index) {
			case 0:
				break;
			case 1:
				TextManager.FlipOutText (SlideTextManager.TextType.Bullet);
				TextManager.AddEmptyLine ();
				TextManager.AddBulletAtLevel ("Available on OS X 10.8+ and iOS 8.0", 0);
				TextManager.FlipInText (SlideTextManager.TextType.Bullet);

					//show some nice icons
				Icon1 = Utils.SCPlaneNode (NSBundle.MainBundle.PathForResource ("Images/Badge_X", "png"), 7, false);
				Icon1.Position = new SCNVector3 (-20, 3.5f, 5);
				GroundNode.AddChildNode (Icon1);

				Icon2 = Utils.SCPlaneNode (NSBundle.MainBundle.PathForResource ("Images/Badge_iOS", "png"), 7, false);
				Icon2.Position = new SCNVector3 (20, 3.5f, 5);
				GroundNode.AddChildNode (Icon2);

				SCNTransaction.Begin ();
				SCNTransaction.AnimationDuration = 0.75f;
				Icon1.Position = new SCNVector3 (-6, 3.5f, 5);
				Icon2.Position = new SCNVector3 (6, 3.5f, 5);
				SCNTransaction.Commit ();
				break;
			case 2:
				SCNTransaction.Begin ();
				SCNTransaction.AnimationDuration = 0.75f;
				Icon1.Position = new SCNVector3 (-6, 3.5f, -5);
				Icon2.Position = new SCNVector3 (6, 3.5f, -5);
				Icon1.Opacity = 0.0f;
				Icon2.Opacity = 0.0f;
				SCNTransaction.Commit ();

				foreach (var node in Boxes) {
					var popTime = new DispatchTime (DispatchTime.Now, (Int64)(delay * Utils.NSEC_PER_SEC));
					DispatchQueue.MainQueue.DispatchAfter (popTime, () => {
						SCNTransaction.Begin ();
						SCNTransaction.AnimationDuration = 0.5f;

						node.Rotation = new SCNVector4 (1, 0, 0, 0);
						node.Scale = new SCNVector3 (0.02f, 0.02f, 0.02f);
						node.Opacity = 1.0f;

						SCNTransaction.Commit ();
					});

					delay += 0.05f;
				}


				TextManager.FlipOutText (SlideTextManager.TextType.Bullet);
				TextManager.FlipOutText (SlideTextManager.TextType.Subtitle);
			
				TextManager.SetSubtitle ("Graphic Frameworks");

				TextManager.FlipInText (SlideTextManager.TextType.Bullet);
				TextManager.FlipInText (SlideTextManager.TextType.Subtitle);

				break;
			}
		}
예제 #45
0
        public override void PresentStep(int index, PresentationViewController presentationViewController)
        {
            switch (index)
            {
            case 0:
                // Set the slide's title and subtitle and add some text
                TextManager.SetTitle("Constraints");
                TextManager.SetSubtitle("SCNConstraint");

                TextManager.AddBulletAtLevel("Applied sequentially at render time", 0);
                TextManager.AddBulletAtLevel("Only affect presentation values", 0);

                TextManager.AddCode("#aNode.#Constraints# = new SCNConstraint[] { aConstraint, anotherConstraint, ... };#");

                // Tweak the near clipping plane of the spot light to get a precise shadow map
                presentationViewController.SpotLight.Light.SetAttribute(new NSNumber(10), SCNLightAttribute.ShadowNearClippingKey);
                break;

            case 1:
                // Remove previous text
                TextManager.FlipOutText(SlideTextManager.TextType.Subtitle);
                TextManager.FlipOutText(SlideTextManager.TextType.Bullet);
                TextManager.FlipOutText(SlideTextManager.TextType.Code);

                // Add new text
                TextManager.SetSubtitle("SCNLookAtConstraint");
                TextManager.AddBulletAtLevel("Makes a node to look at another node", 0);
                TextManager.AddCode("#nodeA.Constraints = new SCNConstraint[] { #SCNLookAtConstraint.Create# (nodeB) };#");

                TextManager.FlipInText(SlideTextManager.TextType.Subtitle);
                TextManager.FlipInText(SlideTextManager.TextType.Bullet);
                TextManager.FlipInText(SlideTextManager.TextType.Code);
                break;

            case 2:
                // Setup the scene
                SetupLookAtScene();

                SCNTransaction.Begin();
                SCNTransaction.AnimationDuration = 1;
                // Dim the text and move back a little bit
                TextManager.TextNode.Opacity = 0.5f;
                presentationViewController.CameraHandle.Position = presentationViewController.CameraNode.ConvertPositionToNode(new SCNVector3(0, 0, 5.0f), presentationViewController.CameraHandle.ParentNode);
                SCNTransaction.Commit();
                break;

            case 3:
                // Add constraints to the arrows
                var container = ContentNode.FindChildNode("arrowContainer", true);

                // "Look at" constraint
                var constraint = SCNLookAtConstraint.Create(BallNode);

                var i = 0;
                foreach (var arrow in container.ChildNodes)
                {
                    var delayInSeconds = 0.1 * i++;
                    var popTime        = new DispatchTime(DispatchTime.Now, (long)(delayInSeconds * Utils.NSEC_PER_SEC));
                    DispatchQueue.MainQueue.DispatchAfter(popTime, () => {
                        SCNTransaction.Begin();
                        SCNTransaction.AnimationDuration = 1;
                        // Animate to the result of applying the constraint
                        ((SCNNode)arrow.ChildNodes [0]).Rotation = new SCNVector4(0, 1, 0, (float)(Math.PI / 2));
                        arrow.Constraints = new SCNConstraint[] { constraint };
                        SCNTransaction.Commit();
                    });
                }
                break;

            case 4:
                // Create a keyframe animation to move the ball
                var animation = CAKeyFrameAnimation.FromKeyPath("position");
                animation.KeyTimes = new NSNumber[] {
                    0.0f,
                    (1.0f / 8.0f),
                    (2.0f / 8.0f),
                    (3.0f / 8.0f),
                    (4.0f / 8.0f),
                    (5.0f / 8.0f),
                    (6.0f / 8.0f),
                    (7.0f / 8.0f),
                    1.0f
                };

                animation.Values = new NSObject[] {
                    NSValue.FromVector(new SCNVector3(0, 0.0f, 0)),
                    NSValue.FromVector(new SCNVector3(20.0f, 0.0f, 20.0f)),
                    NSValue.FromVector(new SCNVector3(40.0f, 0.0f, 0)),
                    NSValue.FromVector(new SCNVector3(20.0f, 0.0f, -20.0f)),
                    NSValue.FromVector(new SCNVector3(0, 0.0f, 0)),
                    NSValue.FromVector(new SCNVector3(-20.0f, 0.0f, 20.0f)),
                    NSValue.FromVector(new SCNVector3(-40.0f, 0.0f, 0)),
                    NSValue.FromVector(new SCNVector3(-20.0f, 0.0f, -20.0f)),
                    NSValue.FromVector(new SCNVector3(0, 0.0f, 0))
                };

                animation.CalculationMode = CAAnimation.AnimationCubicPaced;                 // smooth the movement between keyframes
                animation.RepeatCount     = float.MaxValue;
                animation.Duration        = 10.0f;
                animation.TimingFunction  = CAMediaTimingFunction.FromName(CAMediaTimingFunction.Linear);
                BallNode.AddAnimation(animation, new NSString("ballNodeAnimation"));

                // Rotate the ball to give the illusion of a rolling ball
                // We need two animations to do that:
                // - one rotation to orient the ball in the right direction
                // - one rotation to spin the ball
                animation          = CAKeyFrameAnimation.FromKeyPath("rotation");
                animation.KeyTimes = new NSNumber[] {
                    0.0f,
                    (0.7f / 8.0f),
                    (1.0f / 8.0f),
                    (2.0f / 8.0f),
                    (3.0f / 8.0f),
                    (3.3f / 8.0f),
                    (4.7f / 8.0f),
                    (5.0f / 8.0f),
                    (6.0f / 8.0f),
                    (7.0f / 8.0f),
                    (7.3f / 8.0f),
                    1.0f
                };

                animation.Values = new NSObject[] {
                    NSValue.FromVector(new SCNVector4(0, 1, 0, (float)(Math.PI / 4))),
                    NSValue.FromVector(new SCNVector4(0, 1, 0, (float)(Math.PI / 4))),
                    NSValue.FromVector(new SCNVector4(0, 1, 0, (float)(Math.PI / 2))),
                    NSValue.FromVector(new SCNVector4(0, 1, 0, (float)(Math.PI))),
                    NSValue.FromVector(new SCNVector4(0, 1, 0, (float)(Math.PI + Math.PI / 2))),
                    NSValue.FromVector(new SCNVector4(0, 1, 0, (float)(Math.PI * 2 - Math.PI / 4))),
                    NSValue.FromVector(new SCNVector4(0, 1, 0, (float)(Math.PI * 2 - Math.PI / 4))),
                    NSValue.FromVector(new SCNVector4(0, 1, 0, (float)(Math.PI * 2 - Math.PI / 2))),
                    NSValue.FromVector(new SCNVector4(0, 1, 0, (float)(Math.PI))),
                    NSValue.FromVector(new SCNVector4(0, 1, 0, (float)(Math.PI - Math.PI / 2))),
                    NSValue.FromVector(new SCNVector4(0, 1, 0, (float)(Math.PI / 4))),
                    NSValue.FromVector(new SCNVector4(0, 1, 0, (float)(Math.PI / 4)))
                };

                animation.RepeatCount    = float.MaxValue;
                animation.Duration       = 10.0f;
                animation.TimingFunction = CAMediaTimingFunction.FromName(CAMediaTimingFunction.Linear);
                BallNode.AddAnimation(animation, new NSString("ballNodeAnimation2"));

                var rotationAnimation = CABasicAnimation.FromKeyPath("rotation");
                rotationAnimation.Duration    = 1.0f;
                rotationAnimation.RepeatCount = float.MaxValue;
                rotationAnimation.To          = NSValue.FromVector(new SCNVector4(1, 0, 0, (float)(Math.PI * 2)));
                BallNode.ChildNodes [1].AddAnimation(rotationAnimation, new NSString("ballNodeRotation"));
                break;

            case 5:
                // Add a constraint to the camera
                SCNTransaction.Begin();
                SCNTransaction.AnimationDuration = 1;
                constraint = SCNLookAtConstraint.Create(BallNode);
                presentationViewController.CameraNode.Constraints = new SCNConstraint[] { constraint };
                SCNTransaction.Commit();
                break;

            case 6:
                // Add a constraint to the light
                SCNTransaction.Begin();
                SCNTransaction.AnimationDuration = 1;
                var cameraTarget = ContentNode.FindChildNode("cameraTarget", true);
                constraint = SCNLookAtConstraint.Create(cameraTarget);
                presentationViewController.SpotLight.Constraints = new SCNConstraint[] { constraint };
                SCNTransaction.Commit();
                break;
            }
        }
 public static void DispatchAfter (this DispatchQueue self, TimeSpan delay, Action action)
 {
     var time = new DispatchTime (DispatchTime.Now, delay.Ticks * 100);
     self.DispatchAfter (time, action);
 }