protected override void CreateNestedHitObjects() { base.CreateNestedHitObjects(); var tickSamples = Samples.Select(s => new HitSampleInfo { Bank = s.Bank, Name = @"slidertick", Volume = s.Volume }).ToList(); SliderEventDescriptor?lastEvent = null; foreach (var e in SliderEventGenerator.Generate(StartTime, SpanDuration, Velocity, TickDistance, Path.Distance, this.SpanCount(), LegacyLastTickOffset)) { // generate tiny droplets since the last point if (lastEvent != null) { double sinceLastTick = e.Time - lastEvent.Value.Time; if (sinceLastTick > 80) { double timeBetweenTiny = sinceLastTick; while (timeBetweenTiny > 100) { timeBetweenTiny /= 2; } for (double t = timeBetweenTiny; t < sinceLastTick; t += timeBetweenTiny) { AddNested(new TinyDroplet { Samples = tickSamples, StartTime = t + lastEvent.Value.Time, X = X + Path.PositionAt( lastEvent.Value.PathProgress + (t / sinceLastTick) * (e.PathProgress - lastEvent.Value.PathProgress)).X / CatchPlayfield.BASE_WIDTH, }); } } } // this also includes LegacyLastTick and this is used for TinyDroplet generation above. // this means that the final segment of TinyDroplets are increasingly mistimed where LegacyLastTickOffset is being applied. lastEvent = e; switch (e.Type) { case SliderEventType.Tick: AddNested(new Droplet { Samples = tickSamples, StartTime = e.Time, X = X + Path.PositionAt(e.PathProgress).X / CatchPlayfield.BASE_WIDTH, }); break; case SliderEventType.Head: case SliderEventType.Tail: case SliderEventType.Repeat: AddNested(new Fruit { Samples = Samples, StartTime = e.Time, X = X + Path.PositionAt(e.PathProgress).X / CatchPlayfield.BASE_WIDTH, }); break; } } }
protected override void CreateNestedHitObjects(CancellationToken cancellationToken) { base.CreateNestedHitObjects(cancellationToken); var dropletSamples = Samples.Select(s => s.With(@"slidertick")).ToList(); int nodeIndex = 0; SliderEventDescriptor?lastEvent = null; foreach (var e in SliderEventGenerator.Generate(StartTime, SpanDuration, Velocity, TickDistance, Path.Distance, this.SpanCount(), LegacyLastTickOffset, cancellationToken)) { // generate tiny droplets since the last point if (lastEvent != null) { double sinceLastTick = e.Time - lastEvent.Value.Time; if (sinceLastTick > 80) { double timeBetweenTiny = sinceLastTick; while (timeBetweenTiny > 100) { timeBetweenTiny /= 2; } for (double t = timeBetweenTiny; t < sinceLastTick; t += timeBetweenTiny) { cancellationToken.ThrowIfCancellationRequested(); AddNested(new TinyDroplet { StartTime = t + lastEvent.Value.Time, X = X + Path.PositionAt( lastEvent.Value.PathProgress + (t / sinceLastTick) * (e.PathProgress - lastEvent.Value.PathProgress)).X, }); } } } // this also includes LegacyLastTick and this is used for TinyDroplet generation above. // this means that the final segment of TinyDroplets are increasingly mistimed where LegacyLastTickOffset is being applied. lastEvent = e; switch (e.Type) { case SliderEventType.Tick: AddNested(new Droplet { Samples = dropletSamples, StartTime = e.Time, X = X + Path.PositionAt(e.PathProgress).X, }); break; case SliderEventType.Head: case SliderEventType.Tail: case SliderEventType.Repeat: AddNested(new Fruit { Samples = this.GetNodeSamples(nodeIndex++), StartTime = e.Time, X = X + Path.PositionAt(e.PathProgress).X, }); break; } } }