Inheritance: MonoBehaviour
        public void ShowsNewInSceneKitBadge(bool showsBadge)
        {
            if (NewBadgeNode != null && showsBadge)
            {
                return;                 // already visible
            }
            if (NewBadgeNode == null && !showsBadge)
            {
                return;                 // already invisible
            }
            // Load the model and the animation
            if (NewBadgeNode == null)
            {
                NewBadgeNode = SCNNode.Create();

                var badgeNode = Utils.SCAddChildNode(NewBadgeNode, "newBadge", "Scenes.scnassets/newBadge", 1);
                NewBadgeNode.Scale    = new SCNVector3(0.03f, 0.03f, 0.03f);
                NewBadgeNode.Opacity  = 0;
                NewBadgeNode.Position = new SCNVector3(50, 20, -10);
                NewBadgeNode.Rotation = new SCNVector4(1, 0, 0, -(float)(Math.PI / 2));

                var imageNode = NewBadgeNode.FindChildNode("badgeImage", true);
                imageNode.Geometry.FirstMaterial.Emission.Intensity = 0.0f;

                CameraPitch.AddChildNode(NewBadgeNode);

                NewBadgeAnimation = badgeNode.GetAnimation(badgeNode.GetAnimationKeys() [0]);
                badgeNode.RemoveAllAnimations();

                NewBadgeAnimation.Speed               = 1.5f;
                NewBadgeAnimation.FillMode            = CAFillMode.Both;
                NewBadgeAnimation.UsesSceneTimeBase   = false;
                NewBadgeAnimation.RemovedOnCompletion = false;
                NewBadgeAnimation.RepeatCount         = 0;
            }

            // Play
            if (showsBadge)
            {
                NewBadgeNode.AddAnimation(NewBadgeAnimation, new NSString("badgeAnimation"));

                SCNTransaction.Begin();
                SCNTransaction.AnimationDuration = 2;
                NewBadgeNode.Position            = new SCNVector3(14, 8, -20);

                SCNTransaction.SetCompletionBlock(() => {
                    SCNTransaction.Begin();
                    SCNTransaction.AnimationDuration = 3;
                    if (NewBadgeNode != null)
                    {
                        SCNNode ropeNode = NewBadgeNode.FindChildNode("rope02", true);
                        ropeNode.Opacity = 0.0f;
                    }
                    SCNTransaction.Commit();
                });

                NewBadgeNode.Opacity = 1.0f;
                SCNNode imageNode = NewBadgeNode.FindChildNode("badgeImage", true);
                imageNode.Geometry.FirstMaterial.Emission.Intensity = 0.4f;
                SCNTransaction.Commit();
            }

            // Or hide
            else
            {
                SCNTransaction.Begin();
                SCNTransaction.AnimationDuration = 1.5f;
                SCNTransaction.SetCompletionBlock(() => {
                    if (NewBadgeNode != null)
                    {
                        NewBadgeNode.RemoveFromParentNode();
                        NewBadgeNode = null;
                    }
                });
                NewBadgeNode.Position = new SCNVector3(14, 50, -20);
                NewBadgeNode.Opacity  = 0.0f;
                SCNTransaction.Commit();
            }
        }
        public PresentationViewController(string path)
        {
            // Load the presentation settings from the plist file
            var settingsPath = NSBundle.MainBundle.PathForResource(path, "xml");

            SlideSettings = JsonConvert.DeserializeObject <Settings> (File.ReadAllText(settingsPath));

            SlideCache = new Dictionary <string, Slide> ();

            // Create a new empty scene
            Scene = new SCNScene();

            // Create and add a camera to the scene
            // We create three separate nodes to ease the manipulation of the global position, pitch (ie. orientation around the x axis) and relative position
            // - cameraHandle is used to control the global position in world space
            // - cameraPitch  is used to rotate the position around the x axis
            // - cameraNode   is sometimes manipulated by slides to move the camera relatively to the global position (cameraHandle). But this node is supposed to always be repositioned at (0, 0, 0) in the end of a slide.

            CameraHandle      = SCNNode.Create();
            CameraHandle.Name = "cameraHandle";
            Scene.RootNode.AddChildNode(CameraHandle);

            CameraPitch      = SCNNode.Create();
            CameraPitch.Name = "cameraPitch";
            CameraHandle.AddChildNode(CameraPitch);

            CameraNode        = SCNNode.Create();
            CameraNode.Name   = "cameraNode";
            CameraNode.Camera = new SCNCamera();

            // Set the default field of view to 70 degrees (a relatively strong perspective)
            CameraNode.Camera.XFov = 70.0;
            CameraNode.Camera.YFov = 42.0;
            CameraPitch.AddChildNode(CameraNode);

            // Setup the different lights
            InitLighting();

            // Create and add a reflective floor to the scene
            var floorMaterial = new SCNMaterial();

            floorMaterial.Ambient.Contents          = NSColor.Black;
            floorMaterial.Diffuse.Contents          = new NSImage(NSBundle.MainBundle.PathForResource("SharedTextures/floor", "png"));
            floorMaterial.Diffuse.ContentsTransform = SCNMatrix4.CreateFromAxisAngle(new SCNVector3(0, 0, 1), NMath.PI / 4);
            floorMaterial.Specular.WrapS            =
                floorMaterial.Specular.WrapT        =
                    floorMaterial.Diffuse.WrapS     =
                        floorMaterial.Diffuse.WrapT = SCNWrapMode.Mirror;

            Floor = SCNFloor.Create();
            Floor.ReflectionFalloffEnd = 3.0f;
            Floor.FirstMaterial        = floorMaterial;

            var floorNode = SCNNode.Create();

            floorNode.Geometry = Floor;
            Scene.RootNode.AddChildNode(floorNode);

            floorNode.PhysicsBody    = SCNPhysicsBody.CreateStaticBody(); //make floor dynamic for physics slides
            Scene.PhysicsWorld.Speed = 0;                                 //pause physics to avoid continuous drawing

            // Use a shader modifier to support a secondary texture for some slides
            var shaderFile      = NSBundle.MainBundle.PathForResource("Shaders/floor", "shader");
            var surfaceModifier = File.ReadAllText(shaderFile);

            floorMaterial.ShaderModifiers = new SCNShaderModifiers {
                EntryPointSurface = surfaceModifier
            };

            // Set the scene to the view
            View = new SCNView(CGRect.Empty);
            ((SCNView)View).Scene           = Scene;
            ((SCNView)View).BackgroundColor = NSColor.Black;

            // black fog
            Scene.FogColor         = NSColor.FromCalibratedWhite(0, 1);
            Scene.FogEndDistance   = 45;
            Scene.FogStartDistance = 40;

            // Turn on jittering for better anti-aliasing when the scene is still
            ((SCNView)View).JitteringEnabled = true;

            // Start the presentation
            GoToSlide(0);
        }