public override void Dispose()
 {
     if (ManiaStage != null)
     {
         ManiaStage.Dispose();
     }
     base.Dispose();
 }
Example #2
0
        private ScrollingTestContainer createStage(ScrollingDirection direction, ManiaAction action)
        {
            var specialAction = ManiaAction.Special1;

            var stage = new ManiaStage(0, new StageDefinition {
                Columns = 2
            }, ref action, ref specialAction);

            stages.Add(stage);

            return(new ScrollingTestContainer(direction)
            {
                Anchor = Anchor.Centre,
                Origin = Anchor.Centre,
                RelativeSizeAxes = Axes.Y,
                AutoSizeAxes = Axes.X,
                TimeRange = 2000,
                Child = stage
            });
        }
        internal void ReCalculate(int audioTime)
        {
            bool paused     = false;
            bool upsideDown = ManiaStage.Skin.UpsideDown;

            if (audioTime > LastNoteTime)
            {
                return;
            }

            if (AudioEngine.AudioState == AudioStates.Playing)
            {
                AudioEngine.TogglePause();
                paused = true;
            }

            //Clear anything from a previous ReCalculate
            if (barLines != null)
            {
                barLines.ForEach(b => b.Transformations.Clear());
                barLines.Clear();
            }
            else
            {
                barLines = new List <pSprite>();
            }

            foreach (HitObject h in hitObjects)
            {
                if (((HitCircleMania)h).IsFinished)
                {
                    continue;
                }
                h.SpriteCollection.ForEach(s => s.Transformations.RemoveAll(t => (t.Type & transformationsToClear) > 0));
            }

            //Start a fresh forward play queue
            foreach (StageMania stage in ManiaStage)
            {
                stage.SpriteManagerNotes.Clear(false);
                stage.SpriteManagerNotes.ForwardPlayOptimisedAdd = true;
            }

            //Mania-specific maps use all control points while autoconverts only use BPM changes
            List <ControlPoint> beatmapControlPoints = Beatmap.PlayMode != PlayModes.OsuMania ? Beatmap.TimingPoints : Beatmap.ControlPoints;

            if (beatmapControlPoints.Count == 0 || hitObjects.Count == 0)
            {
                return;
            }

            //For moving things on the play field at the correct speed. It is "collapsed" so you can iterate it in both directions
            speedChanges = new List <ControlPoint>();
            //For placing bar lines
            timingChanges = new List <ControlPoint>();

            double lastBeatLength = beatmapControlPoints[0].BeatLength;

            foreach (ControlPoint p in beatmapControlPoints)
            {
                ControlPoint t = new ControlPoint();
                t.TimingChange  = false; //So that we can guarantee the ordering when searching
                t.BeatLength    = p.BeatLength < 0 ? lastBeatLength * p.BpmMultiplier : p.BeatLength;
                t.TimeSignature = p.TimeSignature;
                t.Offset        = p.Offset;

                //If an SV change right after the initial BPM is before the first note, apply it from the start of time just like the initial BPM
                if (speedChanges.Count == 1 && p.BeatLength < 0 && t.Offset < FirstNoteTime)
                {
                    t.Offset = speedChanges[0].Offset;
                }

                //Collapse changes at the same offset
                if (speedChanges.Count > 0 && t.Offset <= speedChanges[speedChanges.Count - 1].Offset)
                {
                    speedChanges.RemoveAt(speedChanges.Count - 1);
                }

                //Collapse changes that leave us at the same beat length
                if (speedChanges.Count == 0 || t.BeatLength != speedChanges[speedChanges.Count - 1].BeatLength)
                {
                    speedChanges.Add(t);
                }

                //Uncollapsed timing changes
                if (p.BeatLength >= 0)
                {
                    timingChanges.Add(t);
                    lastBeatLength = t.BeatLength;
                }
            }

            //Move the first offset of the control points to before the song starts
            //Doing this after collapsing speed changes makes it so that SV changes to the opening BPM apply from the very start of the song
            double preTimeStart = beatmapControlPoints[0].Offset;

            while (preTimeStart >= 0)
            {
                preTimeStart -= beatmapControlPoints[0].BeatLength * (int)beatmapControlPoints[0].TimeSignature;
            }
            preTimeStart -= beatmapControlPoints[0].BeatLength * (int)beatmapControlPoints[0].TimeSignature;

            speedChanges[0].Offset  = preTimeStart;
            timingChanges[0].Offset = preTimeStart;

            //Add a final control point to speed changes which is useful as an endpoint
            speedChanges.Add(new ControlPoint()
            {
                Offset = Double.PositiveInfinity
            });

            //Add notes
            for (int i = 0; i < hitObjects.Count; i++)
            {
                HitCircleMania     note     = (HitCircleMania)hitObjects[i];
                HitCircleManiaLong noteLong = hitObjects[i] as HitCircleManiaLong;
                if (note.IsFinished)
                {
                    continue;
                }

                float headHeight = SpriteHeight(note.s_note);
                addTransformations(note.s_note, note.StartTime, headHeight);
                if (noteLong != null)
                {
                    float rearHeight = SpriteHeight(noteLong.s_rear);
                    addTransformations(noteLong.s_rear, note.EndTime, rearHeight);
                    addTransformations(noteLong.s_body, note.StartTime, headHeight / 2f, -headHeight / 2f, note.EndTime - note.StartTime);

                    //addTransformations very deliberately breaks up the transformations into three parts
                    //From offscreen to the StartTime -> from the StartTime to the EndTime -> from the end time to offscreen
                    //Using these StartTime and EndTime endpoints, we can find the distance between the head and rear sprites
                    float start = 0, end = 0;
                    if (noteLong.Length > 0)
                    {
                        start = noteLong.s_body.Transformations.Find(t => t.Type == TransformationType.MovementY && t.TagNumeric == TransformationTag.BetweenStartEndTime).StartFloat;
                        end   = noteLong.s_body.Transformations.FindLast(t => t.Type == TransformationType.MovementY && t.TagNumeric == TransformationTag.BetweenStartEndTime).EndFloat;
                    }

                    float length = Math.Abs(end - start) * 1.6f;

                    noteLong.s_body.VectorScale.Y = noteLong.s_body.FlipVertical ? -1f : 1f;

                    if (noteLong.s_body.DrawDimensionsManualOverride)
                    {
                        noteLong.s_body.WrapTexture = false;
                        noteLong.s_body.DrawDimensionsManualOverride = false;
                        noteLong.s_body.UpdateTextureSize();
                    }

                    ManiaNoteBodyStyle style = ManiaStage.Skin.GetNoteBodyStyle(note.Column);
                    if (style == ManiaNoteBodyStyle.Stretch)
                    {
                        noteLong.s_body.VectorScale.Y *= length / noteLong.s_body.DrawHeight;
                    }
                    else
                    {
                        noteLong.s_body.WrapTexture    = true;
                        noteLong.s_body.VectorScale.Y *= ManiaStage.HeightRatio;
                        float height = noteLong.s_body.DrawHeight / ManiaStage.HeightRatio;
                        noteLong.s_body.DrawHeight = noteLong.s_body.Height = (int)(length / ManiaStage.HeightRatio);
                        noteLong.s_body.DrawDimensionsManualOverride = true;

                        switch (style)
                        {
                        case ManiaNoteBodyStyle.RepeatBottom:
                        default:
                            noteLong.s_body.DrawTop = 0;
                            break;

                        case ManiaNoteBodyStyle.RepeatTop:
                            noteLong.s_body.DrawTop = (int)(height - length);
                            break;

                        case ManiaNoteBodyStyle.RepeatTopAndBottom:
                            noteLong.s_body.DrawTop = (int)((height - length) / 2f);
                            break;
                        }
                    }

                    noteLong.s_body.UpdateTextureAlignment();

                    if (noteLong.IsFrozen || noteLong.IsUnfrozen)
                    {
                        FreezeNote(noteLong);
                    }
                    if (noteLong.IsUnfrozen)
                    {
                        UnfreezeNote(noteLong);
                    }
                }

                note.Column.Host.SpriteManagerNotes.Add(note.SpriteCollection);
            }

            //Add barlines
            if (!Configuration.ConfigManager.sIgnoreBarline)
            {
                Color c = ManiaStage.Skin.GetColour(@"Barline");

                for (int i = 0; i < timingChanges.Count; i++)
                {
                    double beatTime = timingChanges[i].Offset;
                    double timeEnd  = LastNoteTime + 1;

                    if (i + 1 < timingChanges.Count)
                    {
                        timeEnd = timingChanges[i + 1].Offset - 1;
                    }

                    if (timeEnd < audioTime - 1000)
                    {
                        continue;
                    }

                    while (beatTime < timeEnd)
                    {
                        foreach (StageMania stage in ManiaStage)
                        {
                            pSprite p = new pSprite(GameBase.WhitePixel, Fields.TopLeft, Origins.CentreLeft, Clocks.Audio, new Vector2(0, -100), 0.62F, false, c);
                            p.VectorScale = new Vector2(stage.Width * 1.6f, ManiaStage.Skin.BarlineHeight);

                            addTransformations(p, beatTime, ManiaStage.Skin.BarlineHeight);

                            barLines.Add(p);
                            stage.SpriteManagerNotes.Add(p);
                        }
                        beatTime += timingChanges[i].BeatLength * (int)timingChanges[i].TimeSignature;
                    }
                }
            }

            //Add arrows
            int arrowTime = FirstNoteTime - 1000;

            for (int arrowCount = 0; arrowTime > speedChanges[0].Offset && arrowCount < 3; arrowCount++)
            {
                foreach (StageMania stage in ManiaStage)
                {
                    pSprite arrow = new pSprite(ManiaStage.Skin.Load(@"WarningArrow", @"mania-warningarrow", ManiaStage.SkinSource), Fields.TopLeft, ManiaStage.FlipOrigin(Origins.TopCentre), Clocks.Audio,
                                                new Vector2(stage.Width / 2, 0), 0.63F, false, Color.White);
                    if (SkinManager.Current.Version >= 2.4 || stage.HeightRatio < 1f)
                    {
                        arrow.Scale = stage.MinimumRatio;
                    }
                    arrow.FlipVertical = upsideDown;

                    //The origin of the arrow is the end of its tail. This is because the tail needs to be 1 second before the first note
                    addTransformations(arrow, arrowTime, -SpriteHeight(arrow));

                    barLines.Add(arrow);
                    stage.SpriteManagerNotes.Add(arrow);
                }
                arrowTime -= 1000;
            }

            //Stop adding to the forward play queue
            foreach (StageMania stage in ManiaStage)
            {
                stage.SpriteManagerNotes.ForwardPlayOptimisedAdd = false;
            }

            if (paused)
            {
                AudioEngine.TogglePause();
            }
        }
Example #4
0
 private bool notesInStageAreAnchored(ManiaStage stage, Anchor anchor) => stage.Columns.SelectMany(c => c.AllHitObjects).All(o => o.Anchor == anchor);
 private bool barsInStageAreAnchored(ManiaStage stage, Anchor anchor) => stage.AllHitObjects.Where(obj => obj is DrawableBarLine).All(o => o.Anchor == anchor);