public override Element Copy()
        {
            List <Point3D> copiedPoints;

            lock (SourcePoints)
                copiedPoints = SourcePoints.ConvertAll(v => v?.Copy());

            return(new PointList(copiedPoints, Position.Copy(), Color, Name)
            {
                Orientation = Orientation.Copy(),
                Type = Type
            });
        }
Exemple #2
0
        protected override void UpdateSourcePoints(Vector2 position, float rotation)
        {
            SourcePoints.Clear();
            float delta = Util.TwoPI / Count;

            for (int i = 0; i < Count; i++)
            {
                float       currentRotation = Mathf.Deg2Rad * rotation + i * delta;
                SourcePoint sourcePoint     = new SourcePoint(position + Radius * Util.OnUnitCircleRadians(currentRotation),
                                                              ((Normal) ? Mathf.Rad2Deg * currentRotation - 90f : rotation));
                SourcePoints.Add(sourcePoint);
            }
        }
Exemple #3
0
        protected override void UpdateSourcePoints(Vector2 position, float rotation)
        {
            SourcePoints.Clear();
            int     edge      = 0;
            float   edgeRot   = 90f + rotation;
            float   edgeDelta = 360f / EdgeCount;
            Vector2 current   = position + Size * Util.OnUnitCircle(edgeRot);
            Vector2 next      = position + Size * Util.OnUnitCircle(edgeRot + edgeDelta);

            edgeRot += edgeDelta;
            while (edge <= edgeCount)
            {
                Vector2 diff = (next - current) / (pointsPerEdge);
                float   rot  = rotation;
                switch (type)
                {
                case RotationType.None:
                case RotationType.Radial:
                    break;

                case RotationType.Tangential:
                    rot = edgeRot - 0.5f * edgeDelta;
                    break;

                case RotationType.Normal:
                    rot = edgeRot - 90f - 0.5f * edgeDelta;
                    break;
                }
                for (int i = 0; i < PointsPerEdge; i++)
                {
                    Vector2 currentPos = current + i * diff;
                    if (Type == RotationType.Radial)
                    {
                        rot = DanmakuUtil.AngleBetween2D(position, currentPos);
                    }
                    SourcePoints.Add(new SourcePoint(currentPos, rot));
                }
                edge++;
                edgeRot += edgeDelta;
                current  = next;
                next     = position + Size * Util.OnUnitCircle(edgeRot);
            }
        }
Exemple #4
0
        private void Update(EvaluationContext context)
        {
            var sourcePoints      = SourcePoints.GetValue(context) as StructuredList <Point>;
            var destinationPoints = DestinationsPoints.GetValue(context) as StructuredList <Point>;

            if (sourcePoints == null || destinationPoints == null ||
                sourcePoints.NumElements == 0 || destinationPoints.NumElements == 0)
            {
                _pointList.SetLength(0);
                ResultList.Value = _pointList;
                return;
            }

            var count = sourcePoints.NumElements * destinationPoints.NumElements;

            if (_pointList.NumElements != count)
            {
                _pointList.SetLength(count);
            }

            for (var destinationIndex = 0; destinationIndex < destinationPoints.NumElements; destinationIndex++)
            {
                var destination = destinationPoints.TypedElements[destinationIndex];

                for (var sourceIndex = 0; sourceIndex < sourcePoints.NumElements; sourceIndex++)
                {
                    var source = sourcePoints.TypedElements[sourceIndex];
                    _pointList.TypedElements[destinationIndex * sourcePoints.NumElements + sourceIndex]
                        = new Point()
                        {
                        Position    = destination.Position + Vector3.Transform(source.Position, destination.Orientation),
                        W           = source.W,
                        Orientation = Quaternion.Multiply(destination.Orientation, source.Orientation),
                        };
                }
            }

            ResultList.Value = _pointList;
        }
Exemple #5
0
        private void Update(EvaluationContext context)
        {
            if (!(SourcePoints.GetValue(context) is StructuredList <Point> sourcePoints))
            {
                return;
            }

            if (sourcePoints.NumElements == 0)
            {
                sourcePoints.SetLength(0);
                ResultList.Value = sourcePoints;
                return;
            }

            var spread     = Spread.GetValue(context);
            var spreadMode = (SpreadModes)SpreadMode.GetValue(context);

            var indexWithinSegment = 0;
            var lineSegmentLength  = 0f;
            var totalLength        = 0f;
            var maxLength          = float.NegativeInfinity;

            var randomizeStart    = RandomizeStart.GetValue(context);
            var randomizeDuration = RandomizeDuration.GetValue(context);

            // Measure...
            segments.Clear();
            for (var pointIndex = 0; pointIndex < sourcePoints.NumElements; pointIndex++)
            {
                if (float.IsNaN(sourcePoints.TypedElements[pointIndex].W))
                {
                    var hasAtLeastTwoPoints = indexWithinSegment > 1;
                    if (hasAtLeastTwoPoints)
                    {
                        if (lineSegmentLength > maxLength)
                        {
                            maxLength = lineSegmentLength;
                        }

                        totalLength += lineSegmentLength;
                        segments.Add(new Segment
                        {
                            PointIndex        = pointIndex - indexWithinSegment,
                            PointCount        = indexWithinSegment,
                            AccumulatedLength = totalLength,
                            SegmentLength     = lineSegmentLength
                        });
                    }

                    lineSegmentLength  = 0;
                    indexWithinSegment = 0;
                }
                else
                {
                    if (indexWithinSegment > 0)
                    {
                        lineSegmentLength += Vector3.Distance(sourcePoints.TypedElements[pointIndex - 1].Position,
                                                              sourcePoints.TypedElements[pointIndex].Position);
                    }

                    indexWithinSegment++;
                }
            }

            if (totalLength < 0.0001f || segments.Count < 2)
            {
                Log.Warning("Stroke animation requires at least two segments with of some length");
                return;
            }

            // Write offsets...
            float dist = maxLength / (segments.Count - 1);

            _random = new Random(42);

            for (var segmentIndex = 0; segmentIndex < segments.Count; segmentIndex++)
            {
                var segmentOffset = ComputeOverlappingProgress(0, segmentIndex, segments.Count, spread);
                var lengthProgressWithingSegment = 0f;
                var segment = segments[segmentIndex];

                // see https://www.figma.com/file/V5k13NMMIsnAnbWH651clI/Untitled?node-id=205%3A96
                var stackedRange = TimeRange.FromStartAndDuration(segment.AccumulatedLength - segment.SegmentLength, segment.SegmentLength) * (1 / totalLength);

                var anchor      = segmentIndex * segment.SegmentLength / (segments.Count - 1);
                var pGrid       = segmentIndex * dist;
                var packedRange = TimeRange.FromStartAndDuration(pGrid - anchor, segment.SegmentLength) * (1 / maxLength);
                var range       = TimeRange.Lerp(packedRange, stackedRange, spread);

                if (Math.Abs(randomizeStart) > 0.0001f)
                {
                    var randomStart = (float)_random.NextDouble() * (1 - range.Duration);
                    range.Start = MathUtils.Lerp(range.Start, randomStart, randomizeStart);
                }

                if (Math.Abs(randomizeDuration) > 0.0001f)
                {
                    var randomDuration = (float)_random.NextDouble() * (1 - range.Start);
                    range.Duration = MathUtils.Lerp(range.Duration, randomDuration, randomizeDuration);
                }

                for (var pointIndexInSegment = 0; pointIndexInSegment < segment.PointCount; pointIndexInSegment++)
                {
                    var pi = segment.PointIndex + pointIndexInSegment;
                    if (pointIndexInSegment > 0)
                    {
                        lengthProgressWithingSegment += Vector3.Distance(sourcePoints.TypedElements[pi - 1].Position,
                                                                         sourcePoints.TypedElements[pi].Position);
                    }

                    var   normalizedSegmentPosition = pointIndexInSegment / (segment.PointCount - 1);
                    float w = 0;
                    switch (spreadMode)
                    {
                    case SpreadModes.IgnoreStrokeLengths:
                        var f = lengthProgressWithingSegment / segment.SegmentLength.Clamp(0.001f, 999999f);
                        w = (f - segmentOffset) / (segments.Count + 1);
                        break;

                    case SpreadModes.UseStrokeLength:
                        w = MathUtils.Lerp(range.Start, range.End, normalizedSegmentPosition);
                        break;

                    case SpreadModes.Weird:
                        w = segmentOffset * 0.2f + pointIndexInSegment / segment.PointCount / 2;
                        break;
                    }

                    sourcePoints.TypedElements[pi].W = w;
                }
            }

            StrokeCount.Value = segments.Count;
            ResultList.Value  = sourcePoints;
            StrokeCount.DirtyFlag.Clear();
            ResultList.DirtyFlag.Clear();
        }