Ejemplo n.º 1
0
        private static ContentSizeComponent ProcessParticleEmitter(ParticleEmitter emitter)
        {
            if (emitter.ParticlesLinkage != ParticlesLinkage.Parent)
            {
                return(null);
            }

            const float EmulationDuration = 15f;
            const float EmulationStep     = (float)AnimationUtils.SecondsPerFrame;
            var         parent            = emitter.ParentWidget;
            var         modifiers         = new List <ParticleModifier>();

            for (var i = 0; i < emitter.Nodes.Count; i++)
            {
                var modifier = emitter.Nodes[i] as ParticleModifier;
                if (modifier != null)
                {
                    modifiers.Add(modifier);
                }
            }
            var corners = new[] {
                Vector2.Zero,
                Vector2.Right,
                Vector2.One,
                Vector2.Down
            };

            // Particles pivot == (0.5, 0.5)
            for (var i = 0; i < corners.Length; i++)
            {
                corners[i] = corners[i] - Vector2.Half;
            }
            var aabb           = new Rectangle(float.MaxValue, float.MaxValue, float.MinValue, float.MinValue);
            var isEmpty        = true;
            var animatedFrames = new SortedSet <int>();

            foreach (var animator in emitter.Animators)
            {
                for (var i = 0; i < animator.ReadonlyKeys.Count; i++)
                {
                    animatedFrames.Add(animator.ReadonlyKeys[i].Frame);
                }
            }
            if (animatedFrames.Count == 0)
            {
                animatedFrames.Add(parent.DefaultAnimation.Frame);
            }

            var grandParent = parent.Parent;
            var parentIndex = grandParent?.Nodes.IndexOf(parent) ?? 0;

            parent.Unlink();
            var animationFrame   = parent.DefaultAnimation.Frame;
            var parentVisibility = parent.Visible;

            parent.Visible = true;

            foreach (var frame in animatedFrames)
            {
                parent.DefaultAnimation.Frame = frame;
                var parentToLocalTransform = emitter.CalcLocalToParentTransform().CalcInversed();

                for (var time = 0f; time < EmulationDuration; time += EmulationStep)
                {
                    foreach (var particle in emitter.particles)
                    {
                        if (particle.ColorCurrent.A <= 0)
                        {
                            continue;
                        }
                        isEmpty = false;
                        var transform = particle.Transform * parentToLocalTransform;
                        for (var i = 0; i < corners.Length; i++)
                        {
                            var corner = transform.TransformVector(corners[i]);
                            aabb = aabb.IncludingPoint(corner);
                        }
                    }
                    emitter.Update(EmulationStep);
                }
                emitter.DeleteAllParticles();
            }

            grandParent?.Nodes.Insert(parentIndex, parent);
            parent.DefaultAnimation.Frame = animationFrame;
            parent.Visible = parentVisibility;

            if (isEmpty)
            {
                return(ProcessEmptyNode(emitter));
            }

            var safeHV = aabb.Size * 0.1f;

            aabb = aabb.ExpandedBy(new Thickness(safeHV.X, safeHV.Y));

            var selfSize = emitter.Components.GetOrAdd <ContentSizeComponent>();

            selfSize.Size = new ContentRectangle(aabb, Vector2.One / emitter.Size);
            return(selfSize);
        }