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); }