Пример #1
0
        public override void PresentStep(int index, PresentationViewController presentationViewController)
        {
            switch (index)
            {
            case (int)ParticleSteps.Fire:
                TextManager.FlipOutText(SlideTextManager.TextType.Bullet);

                TextManager.AddEmptyLine();
                TextManager.AddBulletAtLevel("Particle Image", 0);
                TextManager.AddBulletAtLevel("Color over life duration", 0);
                TextManager.AddBulletAtLevel("Size over life duration", 0);
                TextManager.AddBulletAtLevel("Several blend modes", 0);

                TextManager.FlipInText(SlideTextManager.TextType.Bullet);

                var hole = SCNNode.Create();
                hole.Geometry = SCNTube.Create(1.7f, 1.9f, 1.5f);
                hole.Position = new SCNVector3(0, 0, HOLE_Z);
                hole.Scale    = new SCNVector3(1, 0, 1);

                GroundNode.AddChildNode(hole);

                SCNTransaction.Begin();
                SCNTransaction.AnimationDuration = 0.5f;

                hole.Scale = new SCNVector3(1, 1, 1);

                SCNTransaction.Commit();

                var ps = SCNParticleSystem.Create("fire", "Particles");
                hole.AddParticleSystem(ps);

                Hole = hole;
                break;

            case (int)ParticleSteps.FireScreen:
                ps           = Hole.ParticleSystems [0];
                ps.BlendMode = SCNParticleBlendMode.Screen;
                break;

            case (int)ParticleSteps.Local:
                TextManager.FlipOutText(SlideTextManager.TextType.Bullet);

                TextManager.AddBulletAtLevel("Local vs Global", 0);
                TextManager.FlipInText(SlideTextManager.TextType.Bullet);

                Hole.RemoveAllParticleSystems();
                Hole2          = Hole.Clone();
                Hole2.Geometry = (SCNGeometry)Hole.Geometry.Copy();
                Hole2.Position = new SCNVector3(0, -2, HOLE_Z - 4);
                GroundNode.AddChildNode(Hole2);
                SCNTransaction.Begin();
                SCNTransaction.AnimationDuration = 0.5;
                Hole2.Position = new SCNVector3(0, 0, HOLE_Z - 4);
                SCNTransaction.Commit();

                ps = SCNParticleSystem.Create("reactor", "Particles");
                ps.ParticleColorVariation = new SCNVector4(0, 0, 0.5f, 0);
                Hole.AddParticleSystem(ps);

                var localPs = (SCNParticleSystem)ps.Copy();
                localPs.ParticleImage = ps.ParticleImage;
                localPs.Local         = true;
                Hole2.AddParticleSystem(localPs);

                var animation = CABasicAnimation.FromKeyPath("position");
                animation.From           = NSValue.FromVector(new SCNVector3(7, 0, HOLE_Z));
                animation.To             = NSValue.FromVector(new SCNVector3(-7, 0, HOLE_Z));
                animation.BeginTime      = CAAnimation.CurrentMediaTime() + 0.75;
                animation.Duration       = 8;
                animation.AutoReverses   = true;
                animation.RepeatCount    = float.MaxValue;
                animation.TimingFunction = CAMediaTimingFunction.FromName(CAMediaTimingFunction.EaseInEaseOut);
                animation.TimeOffset     = animation.Duration / 2;
                Hole.AddAnimation(animation, new NSString("animateHole"));

                animation                = CABasicAnimation.FromKeyPath("position");
                animation.From           = NSValue.FromVector(new SCNVector3(-7, 0, HOLE_Z - 4));
                animation.To             = NSValue.FromVector(new SCNVector3(7, 0, HOLE_Z - 4));
                animation.BeginTime      = CAAnimation.CurrentMediaTime() + 0.75;
                animation.Duration       = 8;
                animation.AutoReverses   = true;
                animation.RepeatCount    = float.MaxValue;
                animation.TimingFunction = CAMediaTimingFunction.FromName(CAMediaTimingFunction.EaseInEaseOut);
                animation.TimeOffset     = animation.Duration / 2;
                Hole2.AddAnimation(animation, new NSString("animateHole"));
                break;

            case (int)ParticleSteps.Gravity:
                TextManager.FlipOutText(SlideTextManager.TextType.Bullet);

                TextManager.AddBulletAtLevel("Affected by gravity", 0);
                TextManager.FlipInText(SlideTextManager.TextType.Bullet);

                Hole2.RemoveAllParticleSystems();
                Hole2.RunAction(SCNAction.Sequence(new SCNAction[] {
                    SCNAction.ScaleTo(0, 0.5),
                    SCNAction.RemoveFromParentNode()
                }));
                Hole.RemoveAllParticleSystems();
                Hole.RemoveAnimation(new NSString("animateHole"), 0.5f);

                SCNTransaction.Begin();
                SCNTransaction.AnimationDuration = 0.5;

                var tube = (SCNTube)Hole.Geometry;
                tube.InnerRadius = 0.3f;
                tube.OuterRadius = 0.4f;
                tube.Height      = 1.0f;

                SCNTransaction.Commit();

                ps = SCNParticleSystem.Create("sparks", "Particles");
                Hole.RemoveAllParticleSystems();
                Hole.AddParticleSystem(ps);

                foreach (var child in ((SCNView)presentationViewController.View).Scene.RootNode.ChildNodes)
                {
                    if (child.Geometry != null)
                    {
                        if (child.Geometry.GetType() == typeof(SCNFloor))
                        {
                            FloorNode = child;
                        }
                    }
                }

                /*FloorNode = ((SCNView)presentationViewController.View).Scene.RootNode.FindNodes ((SCNNode child, out bool stop) => {
                 *      stop = false;
                 *      if (child.Geometry != null)
                 *              stop = (child.Geometry.GetType () == typeof(SCNFloor));
                 *      return stop;
                 * });*/

                /*FloorNode = [presentationViewController.view.scene.rootNode childNodesPassingTest:^BOOL(SCNNode *child, BOOL *stop) {
                 *      return [child.geometry isKindOfClass:[SCNFloor class]];
                 * }][0];*/

                ps.ColliderNodes = new SCNNode[] { FloorNode };

                break;

            case (int)ParticleSteps.Collider:
                TextManager.FlipOutText(SlideTextManager.TextType.Bullet);

                TextManager.AddBulletAtLevel("Affected by colliders", 0);
                TextManager.FlipInText(SlideTextManager.TextType.Bullet);

                var boxNode = SCNNode.Create();
                boxNode.Geometry = SCNBox.Create(5, 0.2f, 5, 0);
                boxNode.Position = new SCNVector3(0, 7, HOLE_Z);
                boxNode.Geometry.FirstMaterial.Emission.Contents = NSColor.DarkGray;

                GroundNode.AddChildNode(boxNode);

                ps = Hole.ParticleSystems [0];
                ps.ColliderNodes = new SCNNode[] { FloorNode, boxNode };

                animation                = CABasicAnimation.FromKeyPath("eulerAngles");
                animation.From           = NSValue.FromVector(new SCNVector3(0, 0, NMath.PI / 4 * 1.7f));
                animation.To             = NSValue.FromVector(new SCNVector3(0, 0, -NMath.PI / 4 * 1.7f));
                animation.BeginTime      = CAAnimation.CurrentMediaTime() + 0.5;
                animation.Duration       = 2;
                animation.AutoReverses   = true;
                animation.RepeatCount    = float.MaxValue;
                animation.TimingFunction = CAMediaTimingFunction.FromName(CAMediaTimingFunction.EaseInEaseOut);
                animation.TimeOffset     = animation.Duration / 2;
                boxNode.AddAnimation(animation, new NSString("animateHole"));

                BoxNode = boxNode;
                break;

            case (int)ParticleSteps.Fields:
                Hole.RemoveAllParticleSystems();

                Hole.RunAction(SCNAction.Sequence(new SCNAction[] {
                    SCNAction.ScaleTo(0, 0.75),
                    SCNAction.RemoveFromParentNode()
                }));

                BoxNode.RunAction(SCNAction.Sequence(new SCNAction[] {
                    SCNAction.MoveBy(0, 15, 0, 1.0),
                    SCNAction.RemoveFromParentNode()
                }));

                var particleHolder = SCNNode.Create();
                particleHolder.Position = new SCNVector3(0, 20, HOLE_Z);
                GroundNode.AddChildNode(particleHolder);

                ParticleHolder = particleHolder;

                TextManager.FlipOutText(SlideTextManager.TextType.Bullet);
                TextManager.AddBulletAtLevel("Affected by physics fields", 0);
                TextManager.FlipInText(SlideTextManager.TextType.Bullet);

                ps = SCNParticleSystem.Create("snow", "Particles");
                ps.AffectedByPhysicsFields = true;
                ParticleHolder.AddParticleSystem(ps);
                Snow = ps;

                //physics field
                var field = SCNPhysicsField.CreateTurbulenceField(50, 1);
                field.HalfExtent = new SCNVector3(20, 20, 20);
                field.Strength   = 4.0f;

                var fieldOwner = SCNNode.Create();
                fieldOwner.Position = new SCNVector3(0, 5, HOLE_Z);

                GroundNode.AddChildNode(fieldOwner);
                fieldOwner.PhysicsField = field;
                FieldOwner = fieldOwner;

                ps.ColliderNodes = new SCNNode[] { FloorNode };
                break;

            case (int)ParticleSteps.FieldsVortex:
                VortexFieldOwner          = SCNNode.Create();
                VortexFieldOwner.Position = new SCNVector3(0, 5, HOLE_Z);

                GroundNode.AddChildNode(VortexFieldOwner);

                //tornado
                var worldOrigin = new SCNVector3(FieldOwner.WorldTransform.M41, FieldOwner.WorldTransform.M42, FieldOwner.WorldTransform.M43);
                var worldAxis   = new SCNVector3(0, 1, 0);

                var vortex = SCNPhysicsField.CustomField((SCNVector3 position, SCNVector3 velocity, float mass, float charge, double timeInSeconds) => {
                    var l        = new SCNVector3();
                    l.X          = worldOrigin.X - position.X;
                    l.Z          = worldOrigin.Z - position.Z;
                    SCNVector3 t = Cross(worldAxis, l);
                    var d2       = (l.X * l.X + l.Z * l.Z);
                    var vs       = (nfloat)(VS / Math.Sqrt(d2));
                    var fy       = (nfloat)(1.0 - (Math.Min(1.0, (position.Y / 15.0))));
                    return(new SCNVector3(t.X * vs + l.X * (nfloat)VW * fy, 0, t.Z * vs + l.Z * (nfloat)VW * fy));
                });
                vortex.HalfExtent             = new SCNVector3(100, 100, 100);
                VortexFieldOwner.PhysicsField = vortex;
                break;

            case (int)ParticleSteps.SubSystems:
                FieldOwner.RemoveFromParentNode();
                ParticleHolder.RemoveAllParticleSystems();
                Snow.DampingFactor = -1;

                TextManager.FlipOutText(SlideTextManager.TextType.Bullet);
                TextManager.AddBulletAtLevel("Sub-particle system on collision", 0);
                TextManager.FlipInText(SlideTextManager.TextType.Bullet);

                ps = SCNParticleSystem.Create("rain", "Particles");
                var pss = SCNParticleSystem.Create("plok", "Particles");
                pss.IdleDuration = 0;
                pss.Loops        = false;

                ps.SystemSpawnedOnCollision = pss;

                ParticleHolder.AddParticleSystem(ps);
                ps.ColliderNodes = new SCNNode[] { FloorNode };
                break;

            case (int)ParticleSteps.Confetti:
                ParticleHolder.RemoveAllParticleSystems();

                TextManager.FlipOutText(SlideTextManager.TextType.Bullet);
                TextManager.AddBulletAtLevel("Custom blocks", 0);
                TextManager.FlipInText(SlideTextManager.TextType.Bullet);

                ps = SCNParticleSystem.Create();
                ps.EmitterShape                     = SCNBox.Create(20, 9, 5, 0);
                ps.BirthRate                        = 100;
                ps.ParticleLifeSpan                 = 10;
                ps.ParticleLifeSpanVariation        = 0;
                ps.SpreadingAngle                   = 20;
                ps.ParticleSize                     = 0.25f;
                ps.ParticleVelocity                 = 10;
                ps.ParticleVelocityVariation        = 19;
                ps.BirthDirection                   = SCNParticleBirthDirection.Constant;
                ps.EmittingDirection                = new SCNVector3(0, -1, 0);
                ps.BirthLocation                    = SCNParticleBirthLocation.Volume;
                ps.ParticleImage                    = new NSImage(NSBundle.MainBundle.PathForResource("Particles/confetti", "png"));
                ps.LightingEnabled                  = true;
                ps.OrientationMode                  = SCNParticleOrientationMode.Free;
                ps.SortingMode                      = SCNParticleSortingMode.Distance;
                ps.ParticleAngleVariation           = 180;
                ps.ParticleAngularVelocity          = 200;
                ps.ParticleAngularVelocityVariation = 400;
                ps.ParticleColor                    = NSColor.Green;
                ps.ParticleColorVariation           = new SCNVector4(0.2f, 0.1f, 0.1f, 0);
                ps.ParticleBounce                   = 0;
                ps.ParticleFriction                 = 0.6f;
                ps.ColliderNodes                    = new SCNNode[] { FloorNode };
                ps.BlendMode                        = SCNParticleBlendMode.Alpha;

                var floatAnimation = CAKeyFrameAnimation.FromKeyPath("");
                floatAnimation.Values   = new NSNumber[] { 1, 1, 0 };
                floatAnimation.KeyTimes = new NSNumber[] { 0, 0.9f, 1 };
                floatAnimation.Duration = 1.0f;
                floatAnimation.Additive = false;

                //ps.PropertyControllers = @{ SCNParticlePropertyOpacity: [SCNParticlePropertyController controllerWithAnimation:floatAnimation] };
                //ps.HandleEvent (SCNParticleEvent.Birth,

                /*[ps handleEvent:SCNParticleEventBirth forProperties:@[SCNParticlePropertyColor] withBlock:^(void **data, size_t *dataStride, uint32_t *indices , NSInteger count) {
                 *
                 *      for (int i = 0; i < count; ++i) {
                 *              var col = (float *)((char *)data[0] + dataStride[0] * i);
                 *              if (rand() & 0x1) { // swith green for red
                 *                      col[0] = col[1];
                 *                      col[1] = 0;
                 *              }
                 *
                 *      }
                 * }];*/

                /*[ps handleEvent:SCNParticleEventCollision forProperties:@[SCNParticlePropertyAngle, SCNParticlePropertyRotationAxis, SCNParticlePropertyAngularVelocity, SCNParticlePropertyVelocity, SCNParticlePropertyContactNormal] withBlock:^(void **data, size_t *dataStride, uint32_t *indices , NSInteger count) {
                 *
                 *      for (NSInteger i = 0; i < count; ++i) {
                 *              // fix orientation
                 *              float *angle = (float *)((char *)data[0] + dataStride[0] * indices[i]);
                 *              float *axis = (float *)((char *)data[1] + dataStride[1] * indices[i]);
                 *
                 *              float *colNrm = (float *)((char *)data[4] + dataStride[4] * indices[i]);
                 *              SCNVector3 collisionNormal = {colNrm[0], colNrm[1], colNrm[2]};
                 *              SCNVector3 cp = SCNVector3CrossProduct(collisionNormal, SCNVector3Make(0, 0, 1));
                 *              CGFloat cpLen = SCNVector3Length(cp);
                 *              angle[0] = asin(cpLen);
                 *
                 *              axis[0] = cp.x / cpLen;
                 *              axis[1] = cp.y / cpLen;
                 *              axis[2] = cp.z / cpLen;
                 *
                 *              // kill angular rotation
                 *              float *angVel = (float *)((char *)data[2] + dataStride[2] * indices[i]);
                 *              angVel[0] = 0;
                 *
                 *              if (colNrm[1] > 0.4) {
                 *                      float *vel = (float *)((char *)data[3] + dataStride[3] * indices[i]);
                 *                      vel[0] = 0;
                 *                      vel[1] = 0;
                 *                      vel[2] = 0;
                 *              }
                 *      }
                 * }];*/

                ParticleHolder.AddParticleSystem(ps);
                break;

            case (int)ParticleSteps.EmitterCube:
                ParticleHolder.RemoveAllParticleSystems();

                TextManager.FlipOutText(SlideTextManager.TextType.Bullet);
                TextManager.AddBulletAtLevel("Emitter shape", 0);
                TextManager.FlipInText(SlideTextManager.TextType.Bullet);

                ParticleHolder.RemoveFromParentNode();

                ps       = SCNParticleSystem.Create("emitters", "Particles");
                ps.Local = true;
                ParticleHolder.AddParticleSystem(ps);

                var node = SCNNode.Create();
                node.Position = new SCNVector3(3, 6, HOLE_Z);
                node.RunAction(SCNAction.RepeatActionForever(SCNAction.RotateBy(NMath.PI * 2, new SCNVector3(0.3f, 1, 0), 8)));
                GroundNode.AddChildNode(node);
                Bokeh = ps;

                node.AddParticleSystem(ps);
                break;

            case (int)ParticleSteps.EmitterSphere:
                Bokeh.EmitterShape = SCNSphere.Create(5);
                break;

            case (int)ParticleSteps.EmitterTorus:
                Bokeh.EmitterShape = SCNTorus.Create(5, 1);
                break;
            }
        }