public SpinnerRotationTracker(DrawableSpinner drawableSpinner) { this.drawableSpinner = drawableSpinner; drawableSpinner.HitObjectApplied += resetState; RelativeSizeAxes = Axes.Both; }
private void load(DrawableHitObject drawableHitObject, ISkinSource source) { RelativeSizeAxes = Axes.Both; DrawableSpinner = (DrawableSpinner)drawableHitObject; AddRangeInternal(new[] { spin = new Sprite { Anchor = Anchor.Centre, Origin = Anchor.Centre, Depth = float.MinValue, Texture = source.GetTexture("spinner-spin"), Scale = new Vector2(SPRITE_SCALE), Y = 120 - 45 // offset temporarily to avoid overlapping default spin counter }, clear = new Sprite { Anchor = Anchor.Centre, Origin = Anchor.Centre, Depth = float.MinValue, Alpha = 0, Texture = source.GetTexture("spinner-clear"), Scale = new Vector2(SPRITE_SCALE), Y = -60 }, }); }
public void TestApplyNewSpinner() { DrawableSpinner dho = null; AddStep("create spinner", () => Child = dho = new DrawableSpinner(prepareObject(new Spinner { Position = new Vector2(256, 192), IndexInCurrentCombo = 0, Duration = 500, })) { Clock = new FramedClock(new StopwatchClock()) }); AddStep("rotate some", () => dho.RotationTracker.AddRotation(180)); AddAssert("rotation is set", () => dho.Result.RateAdjustedRotation == 180); AddStep("apply new spinner", () => dho.Apply(prepareObject(new Spinner { Position = new Vector2(256, 192), ComboIndex = 1, Duration = 1000, }))); AddAssert("rotation is reset", () => dho.Result.RateAdjustedRotation == 0); }
private void addObjectsStep(Func <OsuHitObject[]> ctorFunc) { AddStep("add hitobjects", () => { var objects = ctorFunc(); for (int i = 0; i < objects.Length; i++) { objects[i].StartTime = Time.Current + 1000 + 500 * (i + 1); objects[i].ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty()); DrawableOsuHitObject drawableObject = null; switch (objects[i]) { case HitCircle circle: drawableObject = new DrawableHitCircle(circle); break; case Slider slider: drawableObject = new DrawableSlider(slider); break; case Spinner spinner: drawableObject = new DrawableSpinner(spinner); break; } hitObjectContainer.Add(drawableObject); followPointRenderer.AddFollowPoints(objects[i]); } }); }
public override void SetUpSteps() { base.SetUpSteps(); AddUntilStep("wait for track to start running", () => track.IsRunning); AddStep("retrieve spinner", () => drawableSpinner = (DrawableSpinner)((TestPlayer)Player).DrawableRuleset.Playfield.AllHitObjects.First()); }
private void load(DrawableHitObject drawableHitObject, ISkinSource source) { Anchor = Anchor.Centre; Origin = Anchor.Centre; // osu!stable positions spinner components in window-space (as opposed to gamefield-space). This is a 640x480 area taking up the entire screen. // In lazer, the gamefield-space positional transformation is applied in OsuPlayfieldAdjustmentContainer, which is inverted here to make this area take up the entire window space. Size = new Vector2(640, 480); Position = new Vector2(0, -8f); DrawableSpinner = (DrawableSpinner)drawableHitObject; AddRangeInternal(new[] { spin = new Sprite { Anchor = Anchor.TopCentre, Origin = Anchor.Centre, Depth = float.MinValue, Texture = source.GetTexture("spinner-spin"), Scale = new Vector2(SPRITE_SCALE), Y = SPINNER_TOP_OFFSET + 335, }, clear = new Sprite { Alpha = 0, Anchor = Anchor.TopCentre, Origin = Anchor.Centre, Depth = float.MinValue, Texture = source.GetTexture("spinner-clear"), Scale = new Vector2(SPRITE_SCALE), Y = SPINNER_TOP_OFFSET + 115, }, }); }
public void TestSpinnerAutoCompleted() { DrawableSpinner spinner = null; JudgementResult lastResult = null; CreateModTest(new ModTestData { Mod = new OsuModSpunOut(), Autoplay = false, Beatmap = singleSpinnerBeatmap, PassCondition = () => { // Bind to the first spinner's results for further tracking. if (spinner == null) { // We only care about the first spinner we encounter for this test. var nextSpinner = Player.ChildrenOfType <DrawableSpinner>().SingleOrDefault(); if (nextSpinner == null) { return(false); } lastResult = null; spinner = nextSpinner; spinner.OnNewResult += (o, result) => lastResult = result; } return(lastResult?.Type == HitResult.Great); } }); }
public TestSceneSpinnerSelectionBlueprint() { var spinner = new Spinner { Position = new Vector2(256, 256), StartTime = -1000, EndTime = 2000 }; spinner.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty { CircleSize = 2 }); DrawableSpinner drawableSpinner; Add(new Container { RelativeSizeAxes = Axes.Both, Size = new Vector2(0.5f), Child = drawableSpinner = new DrawableSpinner(spinner) }); AddBlueprint(new SpinnerSelectionBlueprint(spinner) { Size = new Vector2(0.5f) }, drawableSpinner); }
private void load(ISkinSource source, DrawableHitObject drawableObject) { drawableSpinner = (DrawableSpinner)drawableObject; Scale = new Vector2(final_scale); InternalChildren = new Drawable[] { discBottom = new Sprite { Anchor = Anchor.Centre, Origin = Anchor.Centre, Texture = source.GetTexture("spinner-bottom") }, discTop = new Sprite { Anchor = Anchor.Centre, Origin = Anchor.Centre, Texture = source.GetTexture("spinner-top") }, fixedMiddle = new Sprite { Anchor = Anchor.Centre, Origin = Anchor.Centre, Texture = source.GetTexture("spinner-middle") }, spinningMiddle = new Sprite { Anchor = Anchor.Centre, Origin = Anchor.Centre, Texture = source.GetTexture("spinner-middle2") } }; }
public void TestSpunOut() { DrawableSpinner spinner = null; AddStep("create spinner", () => spinner = createSpinner()); AddUntilStep("wait for end", () => Time.Current > spinner.LifetimeEnd); AddAssert("spinner is completed", () => spinner.Progress >= 1); }
private void load(ISkinSource source, DrawableHitObject drawableObject) { spinnerBlink = source.GetConfig <OsuSkinConfiguration, bool>(OsuSkinConfiguration.SpinnerNoBlink)?.Value != true; drawableSpinner = (DrawableSpinner)drawableObject; RelativeSizeAxes = Axes.Both; InternalChild = new Container { // the old-style spinner relied heavily on absolute screen-space coordinate values. // wrap everything in a container simulating absolute coords to preserve alignment // as there are skins that depend on it. Width = 640, Height = 480, Anchor = Anchor.Centre, Origin = Anchor.Centre, Children = new Drawable[] { new Sprite { Anchor = Anchor.Centre, Origin = Anchor.Centre, Texture = source.GetTexture("spinner-background"), Scale = new Vector2(sprite_scale) }, disc = new Sprite { Anchor = Anchor.Centre, Origin = Anchor.Centre, Texture = source.GetTexture("spinner-circle"), Scale = new Vector2(sprite_scale) }, metre = new Container { AutoSizeAxes = Axes.Both, // this anchor makes no sense, but that's what stable uses. Anchor = Anchor.TopLeft, Origin = Anchor.TopLeft, // adjustment for stable (metre has additional offset) Margin = new MarginPadding { Top = 20 }, Masking = true, Child = metreSprite = new Sprite { Texture = source.GetTexture("spinner-metre"), Anchor = Anchor.TopLeft, Origin = Anchor.TopLeft, Scale = new Vector2(0.625f) } } } }; }
private void load(DrawableHitObject drawableHitObject, ISkinSource source) { Anchor = Anchor.Centre; Origin = Anchor.Centre; // osu!stable positions spinner components in window-space (as opposed to gamefield-space). This is a 640x480 area taking up the entire screen. // In lazer, the gamefield-space positional transformation is applied in OsuPlayfieldAdjustmentContainer, which is inverted here to make this area take up the entire window space. Size = new Vector2(640, 480); Position = new Vector2(0, -8f); DrawableSpinner = (DrawableSpinner)drawableHitObject; Container overlayContainer; AddInternal(overlayContainer = new Container { Depth = float.MinValue, RelativeSizeAxes = Axes.Both, Children = new Drawable[] { spin = new Sprite { Anchor = Anchor.TopCentre, Origin = Anchor.Centre, Texture = source.GetTexture("spinner-spin"), Scale = new Vector2(SPRITE_SCALE), Y = SPINNER_TOP_OFFSET + 335, }, clear = new Sprite { Alpha = 0, Anchor = Anchor.TopCentre, Origin = Anchor.Centre, Texture = source.GetTexture("spinner-clear"), Scale = new Vector2(SPRITE_SCALE), Y = SPINNER_TOP_OFFSET + 115, }, } }); bonusCounter = (source.GetDrawableComponent(new HUDSkinComponent(HUDSkinComponents.ScoreText)) as LegacySpriteText)?.With(c => { c.Alpha = 0f; c.Anchor = Anchor.TopCentre; c.Origin = Anchor.Centre; c.Font = c.Font.With(fixedWidth: false); c.Scale = new Vector2(SPRITE_SCALE); c.Y = SPINNER_TOP_OFFSET + 299; }); if (bonusCounter != null) { overlayContainer.Add(bonusCounter); } }
private void load(DrawableHitObject drawableHitObject) { drawableSpinner = (DrawableSpinner)drawableHitObject; AddRangeInternal(new Drawable[] { new DefaultSpinnerDisc { RelativeSizeAxes = Axes.Both, Anchor = Anchor.Centre, Origin = Anchor.Centre, }, bonusCounter = new OsuSpriteText { Alpha = 0, Anchor = Anchor.Centre, Origin = Anchor.Centre, Font = OsuFont.Numeric.With(size: 24), Y = -120, }, spmContainer = new Container { Alpha = 0f, Anchor = Anchor.Centre, Origin = Anchor.Centre, Y = 120, Children = new[] { spmCounter = new OsuSpriteText { Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, Text = @"0", Font = OsuFont.Numeric.With(size: 24) }, new OsuSpriteText { Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, Text = @"SPINS PER MINUTE", Font = OsuFont.Numeric.With(size: 12), Y = 30 } } } }); }
public void TestSpinnerGetsNoBonusScore() { DrawableSpinner spinner = null; List <JudgementResult> results = new List <JudgementResult>(); CreateModTest(new ModTestData { Mod = new OsuModSpunOut(), Autoplay = false, Beatmap = singleSpinnerBeatmap, PassCondition = () => { // Bind to the first spinner's results for further tracking. if (spinner == null) { // We only care about the first spinner we encounter for this test. var nextSpinner = Player.ChildrenOfType <DrawableSpinner>().SingleOrDefault(); if (nextSpinner == null) { return(false); } spinner = nextSpinner; spinner.OnNewResult += (o, result) => results.Add(result); results.Clear(); } // we should only be checking the bonus/progress after the spinner has fully completed. if (results.OfType <OsuSpinnerJudgementResult>().All(r => r.TimeCompleted == null)) { return(false); } return (results.Any(r => r.Type == HitResult.SmallBonus) && results.All(r => r.Type != HitResult.LargeBonus)); } }); }
public void TestApplyNewCircle() { DrawableSpinner dho = null; AddStep("create spinner", () => Child = dho = new DrawableSpinner(prepareObject(new Spinner { Position = new Vector2(256, 192), IndexInCurrentCombo = 0, Duration = 0, })) { Clock = new FramedClock(new StopwatchClock()) }); AddStep("apply new spinner", () => dho.Apply(prepareObject(new Spinner { Position = new Vector2(256, 192), ComboIndex = 1, Duration = 1000, }))); }
private void load(ISkinSource source, DrawableHitObject drawableObject) { drawableSpinner = (DrawableSpinner)drawableObject; RelativeSizeAxes = Axes.Both; InternalChildren = new Drawable[] { new Sprite { Anchor = Anchor.BottomCentre, Origin = Anchor.BottomCentre, Texture = source.GetTexture("spinner-background"), Y = background_y_offset, Scale = new Vector2(sprite_scale) }, disc = new Sprite { Anchor = Anchor.Centre, Origin = Anchor.Centre, Texture = source.GetTexture("spinner-circle"), Scale = new Vector2(sprite_scale) }, metre = new Container { Anchor = Anchor.BottomCentre, Origin = Anchor.BottomCentre, Y = background_y_offset, Masking = true, Child = new Sprite { Texture = source.GetTexture("spinner-metre"), Anchor = Anchor.BottomCentre, Origin = Anchor.BottomCentre, }, Scale = new Vector2(0.625f) } }; }
private void load(DrawableHitObject drawableHitObject) { drawableSpinner = (DrawableSpinner)drawableHitObject; AddRangeInternal(new Drawable[] { new DefaultSpinnerDisc { RelativeSizeAxes = Axes.Both, Anchor = Anchor.Centre, Origin = Anchor.Centre, }, bonusCounter = new OsuSpriteText { Alpha = 0, Anchor = Anchor.Centre, Origin = Anchor.Centre, Font = OsuFont.Numeric.With(size: 24), Y = -120, } }); }
private void load(OsuColour colours, DrawableHitObject drawableHitObject) { drawableSpinner = (DrawableSpinner)drawableHitObject; spinner = (Spinner)drawableSpinner.HitObject; normalColour = colours.BlueDark; completeColour = colours.YellowLight; InternalChildren = new Drawable[] { mainContainer = new Container { RelativeSizeAxes = Axes.Both, Anchor = Anchor.Centre, Origin = Anchor.Centre, Children = new Drawable[] { background = new SpinnerBackgroundLayer(), fill = new SpinnerFill { Alpha = idle_alpha, AccentColour = normalColour }, ticks = new SpinnerTicks { Anchor = Anchor.Centre, Origin = Anchor.Centre, AccentColour = normalColour }, } }, centre = new SpinnerCentreLayer { Anchor = Anchor.Centre, Origin = Anchor.Centre, }, }; }
private DrawableSpinner createSpinner() { var spinner = new Spinner { StartTime = Time.Current + 500, EndTime = Time.Current + 2500 }; spinner.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty()); var drawableSpinner = new DrawableSpinner(spinner) { Anchor = Anchor.Centre }; foreach (var mod in SelectedMods.Value.OfType <IApplicableToDrawableHitObjects>()) { mod.ApplyToDrawableHitObjects(new[] { drawableSpinner }); } Add(drawableSpinner); return(drawableSpinner); }
private void load(DrawableHitObject drawableHitObject) { spinner = (DrawableSpinner)drawableHitObject; InternalChildren = new Drawable[] { glow = new GlowPiece(), circle = new CirclePiece { Position = Vector2.Zero, Anchor = Anchor.Centre, }, new RingPiece(), symbol = new SpriteIcon { Anchor = Anchor.Centre, Origin = Anchor.Centre, Size = new Vector2(48), Icon = FontAwesome.Solid.Asterisk, Shadow = false, }, }; }
public SpinnerRotationTracker(DrawableSpinner drawableSpinner) { this.drawableSpinner = drawableSpinner; RelativeSizeAxes = Axes.Both; }
private void load(DrawableHitObject drawableHitObject, ISkinSource source) { Anchor = Anchor.Centre; Origin = Anchor.Centre; // osu!stable positions spinner components in window-space (as opposed to gamefield-space). This is a 640x480 area taking up the entire screen. // In lazer, the gamefield-space positional transformation is applied in OsuPlayfieldAdjustmentContainer, which is inverted here to make this area take up the entire window space. Size = new Vector2(640, 480); Position = new Vector2(0, -8f); DrawableSpinner = (DrawableSpinner)drawableHitObject; AddInternal(new Container { Depth = float.MinValue, RelativeSizeAxes = Axes.Both, Children = new Drawable[] { spin = new Sprite { Anchor = Anchor.TopCentre, Origin = Anchor.Centre, Texture = source.GetTexture("spinner-spin"), Scale = new Vector2(SPRITE_SCALE), Y = SPINNER_TOP_OFFSET + 335, }, clear = new Sprite { Alpha = 0, Anchor = Anchor.TopCentre, Origin = Anchor.Centre, Texture = source.GetTexture("spinner-clear"), Scale = new Vector2(SPRITE_SCALE), Y = SPINNER_TOP_OFFSET + 115, }, bonusCounter = new LegacySpriteText(source, LegacyFont.Score) { Alpha = 0f, Anchor = Anchor.TopCentre, Origin = Anchor.Centre, Scale = new Vector2(SPRITE_SCALE), Y = SPINNER_TOP_OFFSET + 299, }.With(s => s.Font = s.Font.With(fixedWidth: false)), spmBackground = new Sprite { Anchor = Anchor.TopCentre, Origin = Anchor.TopLeft, Texture = source.GetTexture("spinner-rpm"), Scale = new Vector2(SPRITE_SCALE), Position = new Vector2(-87, 445 + spm_hide_offset), }, spmCounter = new LegacySpriteText(source, LegacyFont.Score) { Anchor = Anchor.TopCentre, Origin = Anchor.TopRight, Scale = new Vector2(SPRITE_SCALE * 0.9f), Position = new Vector2(80, 448 + spm_hide_offset), }.With(s => s.Font = s.Font.With(fixedWidth: false)), } }); }
public void TestLegacyKiaiParticles() { LegacyCursorParticles cursorParticles = null; DrawableSpinner spinner = null; DrawableSlider slider = null; createLegacyTest(true, () => { var controlPointInfo = new ControlPointInfo(); controlPointInfo.Add(0, new EffectControlPoint { KiaiMode = true }); controlPointInfo.Add(5000, new EffectControlPoint { KiaiMode = false }); return new Beatmap { ControlPointInfo = controlPointInfo, HitObjects = { new Spinner { StartTime = 0, Duration = 1000, Position = OsuPlayfield.BASE_SIZE / 2, }, new Slider { StartTime = 2500, RepeatCount = 0, Position = OsuPlayfield.BASE_SIZE / 2, Path = new SliderPath(new[] { new PathControlPoint(Vector2.Zero), new PathControlPoint(new Vector2(100, 0)), }) }, new HitCircle { StartTime = 4500, Position = OsuPlayfield.BASE_SIZE / 2, }, }, }; } ); AddUntilStep("fetch cursor particles", () => { cursorParticles = this.ChildrenOfType<LegacyCursorParticles>().SingleOrDefault(); return cursorParticles != null; }); AddUntilStep("wait for spinner tracking", () => { spinner = this.ChildrenOfType<DrawableSpinner>().SingleOrDefault(); return spinner?.RotationTracker.Tracking == true; }); AddAssert("particles are being spawned", () => cursorParticles.Active); AddUntilStep("spinner tracking stopped", () => !spinner.RotationTracker.Tracking); AddAssert("particle spawning stopped", () => !cursorParticles.Active); AddUntilStep("wait for slider tracking", () => { slider = this.ChildrenOfType<DrawableSlider>().SingleOrDefault(); return slider?.Tracking.Value == true; }); AddAssert("particles are being spawned", () => cursorParticles.Active); AddUntilStep("slider tracking stopped", () => !slider.Tracking.Value); AddAssert("particle spawning stopped", () => !cursorParticles.Active); }
public SpinnerSelectionBlueprint(DrawableSpinner spinner) : base(spinner) { InternalChild = piece = new SpinnerPiece((Spinner)spinner.HitObject); }