├── .editorconfig ├── .github └── FUNDING.yml ├── .gitignore ├── LICENSE ├── README.md ├── osu.Game.Rulesets.Sandbox.Tests ├── FlappyDon │ ├── TestSceneBackground.cs │ └── TestSceneFlappyDonGame.cs ├── Game │ ├── TestSceneOsuGame.cs │ └── TestSceneOsuPlayer.cs ├── Graphics │ ├── TestSceneFake3DContainer.cs │ └── TestSceneInnerShadowContainer.cs ├── NumbersGame │ ├── TestSceneDrawableNumber.cs │ └── TestSceneNumbersPlayfield.cs ├── RulesetTestScene.cs ├── Shooter │ └── TestSceneShooterPlayer.cs ├── TestRulesetTestScene.cs ├── TestRulesets │ ├── TestSceneProjectile.cs │ └── TestSceneRulesetProjectile.cs ├── UI │ ├── TestSceneButtonSystem.cs │ ├── TestSceneInteractiveContainer.cs │ └── TestSceneSandboxOverlay.cs ├── VisualTestRunner.cs ├── Visualizer │ ├── TestSceneLinearRounded.cs │ ├── TestSceneParticles.cs │ ├── TestSceneSettingsTip.cs │ └── TestSceneSmoothRandom.cs └── osu.Game.Rulesets.Sandbox.Tests.csproj ├── osu.Game.Rulesets.Sandbox.sln ├── osu.Game.Rulesets.Sandbox.sln.DotSettings └── osu.Game.Rulesets.Sandbox ├── Beatmaps ├── SandboxBeatmap.cs └── SandboxBeatmapConverter.cs ├── Configuration └── SandboxRulesetConfigManager.cs ├── Difficulty └── SandboxDifficultyCalculator.cs ├── Extensions ├── MathExtensions.cs ├── OpenSimplexNoise.cs ├── OsuGameExtensions.cs └── ProjectileExtensions.cs ├── Graphics ├── ContentFitContainer.cs └── InnerShadowContainer.cs ├── Judgements └── SandboxJudgement.cs ├── Objects ├── Drawables │ └── DrawableSandboxHitObject.cs └── SandboxHitObject.cs ├── Online ├── GetLatestReleaseRequest.cs └── GitHubRelease.cs ├── Resources ├── Samples │ ├── die.wav │ ├── flap.wav │ ├── hit.wav │ └── point.wav ├── Shaders │ ├── sh_InnerShadow.fs │ ├── sh_RoundedBar.fs │ └── sh_RulesetUtils.h └── Textures │ ├── 2048.png │ ├── FlappyDon.png │ ├── FlappyDon │ ├── bg.png │ ├── gameover.png │ ├── ground.png │ ├── message.png │ ├── pipe.png │ ├── redbird-downflap.png │ ├── redbird-midflap.png │ └── redbird-upflap.png │ ├── Icons │ ├── Bosu.png │ ├── Hishigata.png │ ├── Hitokori.png │ ├── Sandbox.png │ ├── Swing.png │ ├── Tau.png │ ├── Touhosu.png │ ├── Yoso.png │ ├── gamebosu.png │ ├── osu!DIVA.png │ ├── sentakki.png │ └── soyokaze!.png │ ├── Ruleset Updates.png │ ├── Visualizer.png │ └── Visualizer │ └── particle.png ├── SandboxInputManager.cs ├── SandboxRuleset.cs ├── Screens ├── FlappyDon │ ├── Components │ │ ├── Backdrop.cs │ │ ├── BackgroundSprite.cs │ │ ├── Bird.cs │ │ ├── FlappyDonGame.cs │ │ ├── FlappyDonScalingContainer.cs │ │ ├── GroundSprite.cs │ │ ├── Obstacles.cs │ │ ├── PipeObstacle.cs │ │ └── PipeSprite.cs │ └── FlappyDonScreen.cs ├── Main │ ├── Components │ │ ├── SandboxButtonSystem.cs │ │ └── SandboxPanel.cs │ └── MainRulesetScreen.cs ├── Numbers │ ├── Components │ │ ├── DrawableNumber.cs │ │ └── NumbersPlayfield.cs │ └── NumbersScreen.cs ├── Rulesets │ ├── Components │ │ ├── DrawableLatestRulesetUpdate.cs │ │ ├── RulesetDownloadType.cs │ │ └── RulesetPanel.cs │ └── RulesetsScreen.cs ├── SandboxScreen.cs ├── SandboxScreenWithSettings.cs ├── Shooter │ └── ShooterPlayer.cs └── Visualizer │ ├── Components │ ├── LayoutController.cs │ ├── Layouts │ │ ├── DrawableVisualizerLayout.cs │ │ ├── EmptyLayout.cs │ │ ├── TypeA │ │ │ ├── CircularBeatmapLogo.cs │ │ │ ├── TypeAVisualizerController.cs │ │ │ └── UpdateableBeatmapBackground.cs │ │ ├── TypeALayout.cs │ │ ├── TypeB │ │ │ └── TypeBVisualizerController.cs │ │ └── TypeBLayout.cs │ ├── MusicHelpers │ │ ├── CurrentBeatmapProvider.cs │ │ ├── CurrentRateContainer.cs │ │ ├── MusicAmplitudesProvider.cs │ │ ├── MusicIntensityController.cs │ │ └── RateAdjustableContainer.cs │ ├── Particles.cs │ ├── ParticlesDrawable.cs │ ├── Settings │ │ ├── BackgroundSection.cs │ │ ├── LayoutSettingsSubsection.cs │ │ ├── ParticleSettings.cs │ │ ├── TrackSection.cs │ │ └── VisualizerSection.cs │ ├── VisualizerSettingsTip.cs │ └── Visualizers │ │ ├── Circular │ │ ├── BasicMusicVisualizerDrawable.cs │ │ ├── DotsMusicVisualizerDrawable.cs │ │ ├── FallMusicVisualizerDrawable.cs │ │ └── RoundedMusicVisualizerDrawable.cs │ │ ├── CircularMusicVisualizerDrawable.cs │ │ ├── Linear │ │ ├── BasicLinearMusicVisualizerDrawable.cs │ │ └── RoundedLinearMusicVisualizerDrawable.cs │ │ ├── LinearMusicVisualizerDrawable.cs │ │ └── MusicVisualizerDrawable.cs │ └── VisualizerScreen.cs ├── UI ├── DrawableSandboxRuleset.cs ├── InteractiveContainer.cs ├── Overlays │ ├── SandboxCheckbox.cs │ └── SandboxOverlay.cs ├── SandboxPlayfield.cs ├── SandboxSettingsSubsection.cs ├── Settings │ ├── ColourPickerDropdown.cs │ ├── SandboxSettings.cs │ ├── SandboxSettingsSection.cs │ └── SettingsDropdownContainer.cs ├── StoryboardContainer.cs └── TrackController.cs └── osu.Game.Rulesets.Sandbox.csproj /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] 4 | patreon: evast 5 | open_collective: # Replace with a single Open Collective username 6 | ko_fi: # Replace with a single Ko-fi username 7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 | liberapay: # Replace with a single Liberapay username 10 | issuehunt: # Replace with a single IssueHunt username 11 | otechie: # Replace with a single Otechie username 12 | custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] 13 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Andrei Zavatski 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # lazer-sandbox 2 | 3 | A custom game mode for osu!lazer project. 4 | 5 | Support: 6 | 7 | https://www.patreon.com/evast 8 | 9 | https://boosty.to/evast 10 | 11 | Follow me: 12 | 13 | https://discord.gg/d2ZCzC42yH 14 | 15 | https://youtube.com/c/evast_osu 16 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Sandbox.Tests/FlappyDon/TestSceneBackground.cs: -------------------------------------------------------------------------------- 1 | using osu.Game.Rulesets.Sandbox.Screens.FlappyDon.Components; 2 | 3 | namespace osu.Game.Rulesets.Sandbox.Tests.FlappyDon 4 | { 5 | public class TestSceneBackground : RulesetTestScene 6 | { 7 | public TestSceneBackground() 8 | { 9 | Backdrop b; 10 | 11 | Add(b = new Backdrop(() => new BackgroundSprite(), 20000)); 12 | b.Start(); 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Sandbox.Tests/FlappyDon/TestSceneFlappyDonGame.cs: -------------------------------------------------------------------------------- 1 | using osu.Game.Rulesets.Sandbox.Screens.FlappyDon.Components; 2 | 3 | namespace osu.Game.Rulesets.Sandbox.Tests.FlappyDon 4 | { 5 | public class TestSceneFlappyDonGame : RulesetTestScene 6 | { 7 | public TestSceneFlappyDonGame() 8 | { 9 | Add(new FlappyDonGame()); 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Sandbox.Tests/Game/TestSceneOsuGame.cs: -------------------------------------------------------------------------------- 1 | using osu.Framework.Allocation; 2 | using osu.Framework.Graphics; 3 | using osu.Framework.Graphics.Shapes; 4 | using osu.Framework.Platform; 5 | using osu.Game.Tests.Visual; 6 | using osuTK.Graphics; 7 | 8 | namespace osu.Game.Rulesets.Sandbox.Tests.Game 9 | { 10 | public class TestSceneOsuGame : OsuTestScene 11 | { 12 | [BackgroundDependencyLoader] 13 | private void load(GameHost host) 14 | { 15 | Children = new Drawable[] 16 | { 17 | new Box 18 | { 19 | RelativeSizeAxes = Axes.Both, 20 | Colour = Color4.Black, 21 | }, 22 | }; 23 | 24 | AddGame(new OsuGame()); 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Sandbox.Tests/Game/TestSceneOsuPlayer.cs: -------------------------------------------------------------------------------- 1 | using NUnit.Framework; 2 | using osu.Game.Tests.Visual; 3 | 4 | namespace osu.Game.Rulesets.Sandbox.Tests.Game 5 | { 6 | [TestFixture] 7 | public class TestSceneOsuPlayer : PlayerTestScene 8 | { 9 | protected override Ruleset CreatePlayerRuleset() => new SandboxRuleset(); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Sandbox.Tests/Graphics/TestSceneFake3DContainer.cs: -------------------------------------------------------------------------------- 1 | using osu.Framework.Bindables; 2 | using osu.Framework.Graphics; 3 | using osu.Framework.Graphics.Containers; 4 | using osu.Framework.Graphics.Shapes; 5 | using osu.Framework.Input.Events; 6 | using osu.Framework.Utils; 7 | using osuTK; 8 | using osuTK.Graphics; 9 | 10 | namespace osu.Game.Rulesets.Sandbox.Tests.Graphics 11 | { 12 | public partial class TestSceneFake3DContainer : RulesetTestScene 13 | { 14 | public TestSceneFake3DContainer() 15 | { 16 | Fake3DContainer container; 17 | 18 | Add(container = new Fake3DContainer 19 | { 20 | RelativeSizeAxes = Axes.Both 21 | }); 22 | 23 | for (int i = 0; i < 500; i++) 24 | { 25 | float depth = RNG.Next(-100, 1000); 26 | container.Add(new Fake3DEntity 27 | { 28 | Origin = Anchor.Centre, 29 | Anchor = Anchor.Centre, 30 | Size = new Vector2(RNG.Next(10, 100)), 31 | PositionInVolume = new Vector3(RNG.Next(-2000, 2000), RNG.Next(-2000, 2000), depth), 32 | Depth = depth, 33 | Colour = getRandomColour() 34 | }); 35 | } 36 | } 37 | 38 | private Color4 getRandomColour() => new Color4(RNG.NextSingle(0.5f, 1f), RNG.NextSingle(0.5f, 1f), RNG.NextSingle(0.5f, 1f), 1f); 39 | 40 | private partial class Fake3DContainer : CompositeDrawable 41 | { 42 | public readonly Bindable CameraPosition = new Bindable(new Vector3(0, 0, -100)); 43 | 44 | protected override void LoadComplete() 45 | { 46 | base.LoadComplete(); 47 | CameraPosition.BindValueChanged(c => updateChildren(c.NewValue), true); 48 | } 49 | 50 | private void updateChildren(Vector3 cameraPosition) 51 | { 52 | foreach (var c in InternalChildren) 53 | { 54 | if (c is not Fake3DEntity e) 55 | continue; 56 | 57 | e.UpdateWithCamera(cameraPosition); 58 | } 59 | } 60 | 61 | public void Add(Fake3DEntity e) 62 | { 63 | e.UpdateWithCamera(CameraPosition.Value); 64 | AddInternal(e); 65 | } 66 | 67 | protected override bool OnScroll(ScrollEvent e) 68 | { 69 | CameraPosition.Value = new Vector3(CameraPosition.Value.X, CameraPosition.Value.Y, CameraPosition.Value.Z + e.ScrollDelta.Y * 10); 70 | return true; 71 | } 72 | 73 | protected override bool OnDragStart(DragStartEvent e) => true; 74 | 75 | protected override void OnDrag(DragEvent e) 76 | { 77 | base.OnDrag(e); 78 | 79 | CameraPosition.Value = new Vector3(CameraPosition.Value.X - e.Delta.X, CameraPosition.Value.Y - e.Delta.Y, CameraPosition.Value.Z); 80 | } 81 | } 82 | 83 | private partial class Fake3DEntity : Container 84 | { 85 | private Vector3 positionInVolume; 86 | 87 | public Vector3 PositionInVolume 88 | { 89 | get => positionInVolume; 90 | set 91 | { 92 | if (positionInVolume == value) 93 | return; 94 | 95 | positionInVolume = value; 96 | 97 | if (lastCameraPosition.HasValue) 98 | UpdateWithCamera(lastCameraPosition.Value); 99 | } 100 | } 101 | 102 | public Fake3DEntity() 103 | { 104 | Child = new Box 105 | { 106 | RelativeSizeAxes = Axes.Both 107 | }; 108 | } 109 | 110 | private Vector3? lastCameraPosition; 111 | 112 | public void UpdateWithCamera(Vector3 cameraPosition) 113 | { 114 | lastCameraPosition = cameraPosition; 115 | 116 | if (positionInVolume.Z <= cameraPosition.Z) 117 | { 118 | Alpha = 0; 119 | return; 120 | } 121 | 122 | var distance = positionInVolume.Z - cameraPosition.Z; 123 | var mappedDepth = 2f / (distance / 100); 124 | 125 | Scale = new Vector2(mappedDepth); 126 | Position = (positionInVolume.Xy - cameraPosition.Xy) * mappedDepth; 127 | Alpha = 1; 128 | } 129 | } 130 | } 131 | } 132 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Sandbox.Tests/Graphics/TestSceneInnerShadowContainer.cs: -------------------------------------------------------------------------------- 1 | using osu.Framework.Graphics; 2 | using osu.Framework.Graphics.Containers; 3 | using osu.Game.Rulesets.Sandbox.Graphics; 4 | using osuTK; 5 | 6 | namespace osu.Game.Rulesets.Sandbox.Tests.Graphics 7 | { 8 | public partial class TestSceneInnerShadowContainer : RulesetTestScene 9 | { 10 | private readonly TestContainer testContainer; 11 | 12 | public TestSceneInnerShadowContainer() 13 | { 14 | AddRange(new Drawable[] 15 | { 16 | testContainer = new TestContainer() 17 | { 18 | Anchor = Anchor.Centre, 19 | Origin = Anchor.Centre, 20 | Size = new Vector2(400) 21 | } 22 | }); 23 | } 24 | 25 | protected override void LoadComplete() 26 | { 27 | base.LoadComplete(); 28 | 29 | AddSliderStep("Corner radius", 0, 200, 10, c => testContainer.CornerRadius = c); 30 | } 31 | 32 | private partial class TestContainer : InnerShadowContainer 33 | { 34 | protected override Container CreateContent() => new Container(); 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Sandbox.Tests/NumbersGame/TestSceneDrawableNumber.cs: -------------------------------------------------------------------------------- 1 | using osu.Framework.Graphics; 2 | using osu.Game.Rulesets.Sandbox.Screens.Numbers.Components; 3 | using osu.Game.Tests.Visual; 4 | 5 | namespace osu.Game.Rulesets.Sandbox.Tests.NumbersGame 6 | { 7 | public class TestSceneDrawableNumber : OsuTestScene 8 | { 9 | private readonly DrawableNumber drawableNumber; 10 | 11 | public TestSceneDrawableNumber() 12 | { 13 | Add(drawableNumber = new DrawableNumber(0, 0) 14 | { 15 | Anchor = Anchor.Centre, 16 | Origin = Anchor.Centre 17 | }); 18 | } 19 | 20 | protected override void LoadComplete() 21 | { 22 | base.LoadComplete(); 23 | AddStep("Increment", () => drawableNumber.Increment()); 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Sandbox.Tests/NumbersGame/TestSceneNumbersPlayfield.cs: -------------------------------------------------------------------------------- 1 | using osu.Game.Rulesets.Sandbox.Screens.Numbers.Components; 2 | using osu.Game.Tests.Visual; 3 | using osu.Framework.Graphics; 4 | 5 | namespace osu.Game.Rulesets.Sandbox.Tests.NumbersGame 6 | { 7 | public class TestSceneNumbersPlayfield : OsuTestScene 8 | { 9 | private readonly NumbersPlayfield playfield; 10 | 11 | public TestSceneNumbersPlayfield() 12 | { 13 | Add(playfield = new NumbersPlayfield 14 | { 15 | Anchor = Anchor.Centre, 16 | Origin = Anchor.Centre 17 | }); 18 | } 19 | 20 | protected override void LoadComplete() 21 | { 22 | base.LoadComplete(); 23 | AddStep("Restart", playfield.Restart); 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Sandbox.Tests/RulesetTestScene.cs: -------------------------------------------------------------------------------- 1 | using osu.Game.Tests.Visual; 2 | 3 | namespace osu.Game.Rulesets.Sandbox.Tests 4 | { 5 | public abstract partial class RulesetTestScene : OsuTestScene 6 | { 7 | protected override Ruleset CreateRuleset() => new SandboxRuleset(); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Sandbox.Tests/Shooter/TestSceneShooterPlayer.cs: -------------------------------------------------------------------------------- 1 | using osu.Game.Rulesets.Sandbox.Screens.Shooter; 2 | using osu.Game.Tests.Visual; 3 | 4 | namespace osu.Game.Rulesets.Sandbox.Tests.Shooter 5 | { 6 | public class TestSceneShooterPlayer : OsuTestScene 7 | { 8 | public TestSceneShooterPlayer() 9 | { 10 | Add(new ShooterPlayer()); 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Sandbox.Tests/TestRulesetTestScene.cs: -------------------------------------------------------------------------------- 1 | using osu.Framework.Graphics; 2 | using osu.Framework.Graphics.Containers; 3 | using osu.Game.Overlays; 4 | using osu.Game.Rulesets.Sandbox.Screens.Visualizer.Components.MusicHelpers; 5 | 6 | namespace osu.Game.Rulesets.Sandbox.Tests 7 | { 8 | public abstract class TestRulesetTestScene : RulesetTestScene 9 | { 10 | private readonly NowPlayingOverlay nowPlayingOverlay; 11 | 12 | public TestRulesetTestScene() 13 | { 14 | AddRange(new Drawable[] 15 | { 16 | CreateTestPlayfield(), 17 | nowPlayingOverlay = new NowPlayingOverlay 18 | { 19 | Origin = Anchor.TopRight, 20 | Anchor = Anchor.TopRight, 21 | State = { Value = Visibility.Visible }, 22 | } 23 | }); 24 | } 25 | 26 | protected override void LoadComplete() 27 | { 28 | base.LoadComplete(); 29 | 30 | AddStep("Snow music controller", () => nowPlayingOverlay.State.Value = Visibility.Visible); 31 | } 32 | 33 | protected abstract TestPlayfield CreateTestPlayfield(); 34 | 35 | protected abstract class TestPlayfield : CurrentBeatmapProvider 36 | { 37 | public TestPlayfield() 38 | { 39 | RelativeSizeAxes = Axes.Both; 40 | } 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Sandbox.Tests/TestRulesets/TestSceneProjectile.cs: -------------------------------------------------------------------------------- 1 | using osu.Framework.Graphics; 2 | using osu.Framework.Graphics.Containers; 3 | using osu.Framework.Graphics.Shapes; 4 | using osu.Game.Rulesets.Sandbox.Extensions; 5 | using osu.Game.Tests.Visual; 6 | using osuTK; 7 | using osuTK.Graphics; 8 | 9 | namespace osu.Game.Rulesets.Sandbox.Tests.TestRulesets 10 | { 11 | public class TestSceneProjectile : OsuTestScene 12 | { 13 | private readonly Container pathContainer; 14 | private readonly Box collisionSurface; 15 | private readonly Box drawableNormal; 16 | private ProjectileInfo infoAtStart; 17 | private float angle; 18 | private float surfaceNormal; 19 | private float speed; 20 | private double duration = 1.0; 21 | private Vector2 startPos = Vector2.Zero; 22 | 23 | public TestSceneProjectile() 24 | { 25 | AddRange(new Drawable[] 26 | { 27 | pathContainer = new Container 28 | { 29 | RelativeSizeAxes = Axes.Both 30 | }, 31 | collisionSurface = new Box 32 | { 33 | Origin = Anchor.Centre, 34 | Height = 60, 35 | Width = 1, 36 | EdgeSmoothness = Vector2.One 37 | }, 38 | drawableNormal = new Box 39 | { 40 | Origin = Anchor.CentreLeft, 41 | Height = 1, 42 | Width = 30, 43 | EdgeSmoothness = Vector2.One, 44 | Colour = Color4.Red 45 | } 46 | }); 47 | } 48 | 49 | protected override void LoadComplete() 50 | { 51 | base.LoadComplete(); 52 | 53 | AddSliderStep("Angle", -270f, 90f, 0f, a => 54 | { 55 | angle = a; 56 | updatePath(); 57 | }); 58 | AddSliderStep("Speed", 0f, 20f, 10f, s => 59 | { 60 | speed = s; 61 | updatePath(); 62 | }); 63 | AddSliderStep("Duration", 1.0, 10000.0, 5000.0, d => 64 | { 65 | duration = d; 66 | updatePath(); 67 | }); 68 | 69 | AddSliderStep("Surface normal", -270f, 90f, -90f, sn => 70 | { 71 | surfaceNormal = sn; 72 | collisionSurface.Rotation = drawableNormal.Rotation = sn; 73 | updatePath(); 74 | }); 75 | 76 | AddSliderStep("Start x", 100f, 1000f, 100f, x => 77 | { 78 | startPos.X = x; 79 | updatePath(); 80 | }); 81 | AddSliderStep("Start y", 100f, 1000f, 200f, y => 82 | { 83 | startPos.Y = y; 84 | updatePath(); 85 | }); 86 | } 87 | 88 | private void updatePath() 89 | { 90 | pathContainer.Clear(); 91 | 92 | infoAtStart = new ProjectileInfo(startPos, speed, angle); 93 | 94 | for (int i = 0; i <= 100; i++) 95 | { 96 | pathContainer.Add(new Circle 97 | { 98 | Size = new Vector2(5), 99 | Colour = Color4.White, 100 | Position = ProjectileExtensions.GetProjectileInfoAt(infoAtStart, (float)duration * i / 200f).Position, 101 | Origin = Anchor.Centre 102 | }); 103 | } 104 | 105 | var infoBeforeCollision = ProjectileExtensions.GetProjectileInfoAt(infoAtStart, (float)duration * 0.5f); 106 | 107 | collisionSurface.Position = drawableNormal.Position = infoBeforeCollision.Position; 108 | 109 | var (info, collided) = ProjectileExtensions.ProcessCollision(infoBeforeCollision, surfaceNormal); 110 | 111 | for (int i = 0; i <= 100; i++) 112 | { 113 | pathContainer.Add(new Circle 114 | { 115 | Size = new Vector2(5), 116 | Colour = collided ? Color4.White : Color4.Gray, 117 | Position = ProjectileExtensions.GetProjectileInfoAt(info, (float)duration * i / 200f).Position, 118 | Origin = Anchor.Centre 119 | }); 120 | } 121 | } 122 | } 123 | } 124 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Sandbox.Tests/UI/TestSceneButtonSystem.cs: -------------------------------------------------------------------------------- 1 | using osu.Game.Rulesets.Sandbox.Screens.Main.Components; 2 | using osu.Game.Tests.Visual; 3 | 4 | namespace osu.Game.Rulesets.Sandbox.Tests.UI 5 | { 6 | public class TestSceneButtonSystem : OsuTestScene 7 | { 8 | private const int button_count = 10; 9 | 10 | public TestSceneButtonSystem() 11 | { 12 | var buttons = new SandboxPanel[button_count]; 13 | 14 | for (int i = 0; i < button_count; i++) 15 | buttons[i] = new SandboxPanel((i + 1).ToString()); 16 | 17 | Add(new SandboxButtonSystem { Buttons = buttons }); 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Sandbox.Tests/UI/TestSceneInteractiveContainer.cs: -------------------------------------------------------------------------------- 1 | using osu.Framework.Graphics.Shapes; 2 | using osu.Game.Rulesets.Sandbox.UI; 3 | using osu.Game.Tests.Visual; 4 | using osuTK; 5 | using osu.Framework.Graphics; 6 | 7 | namespace osu.Game.Rulesets.Sandbox.Tests.UI 8 | { 9 | public class TestSceneInteractiveContainer : OsuTestScene 10 | { 11 | public TestSceneInteractiveContainer() 12 | { 13 | Add(new InteractiveContainer 14 | { 15 | Child = new Box 16 | { 17 | Anchor = Anchor.Centre, 18 | Origin = Anchor.Centre, 19 | Size = new Vector2(100) 20 | } 21 | }); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Sandbox.Tests/UI/TestSceneSandboxOverlay.cs: -------------------------------------------------------------------------------- 1 | using osu.Framework.Graphics; 2 | using osu.Framework.Graphics.Containers; 3 | using osu.Game.Graphics; 4 | using osu.Game.Rulesets.Sandbox.UI.Overlays; 5 | using osuTK; 6 | using osuTK.Graphics; 7 | 8 | namespace osu.Game.Rulesets.Sandbox.Tests.UI 9 | { 10 | public class TestSceneSandboxOverlay : RulesetTestScene 11 | { 12 | private readonly TestOverlay overlay; 13 | 14 | public TestSceneSandboxOverlay() 15 | { 16 | Add(overlay = new TestOverlay()); 17 | } 18 | 19 | protected override void LoadComplete() 20 | { 21 | base.LoadComplete(); 22 | AddStep("visibility", overlay.ToggleVisibility); 23 | } 24 | 25 | private class TestOverlay : SandboxOverlay 26 | { 27 | protected override SandboxOverlayButton[] CreateButtons() => new[] 28 | { 29 | new SandboxOverlayButton("Test1"), 30 | new SandboxOverlayButton("Test2"), 31 | new SandboxOverlayButton("Test3") 32 | }; 33 | 34 | protected override Drawable CreateContent() => new FillFlowContainer 35 | { 36 | Anchor = Anchor.Centre, 37 | Origin = Anchor.Centre, 38 | AutoSizeAxes = Axes.Y, 39 | RelativeSizeAxes = Axes.X, 40 | Direction = FillDirection.Vertical, 41 | Spacing = new Vector2(0, 20), 42 | Children = new Drawable[] 43 | { 44 | new TextFlowContainer(f => 45 | { 46 | f.Colour = Color4.Black; 47 | f.Font = OsuFont.GetFont(size: 30, weight: FontWeight.Regular); 48 | }) 49 | { 50 | Anchor = Anchor.Centre, 51 | Origin = Anchor.Centre, 52 | AutoSizeAxes = Axes.Y, 53 | RelativeSizeAxes = Axes.X, 54 | TextAnchor = Anchor.TopCentre, 55 | Text = "This is a very important tip with useful information, you should read it!" 56 | }, 57 | new SandboxCheckbox("Test") 58 | { 59 | Anchor = Anchor.Centre, 60 | Origin = Anchor.Centre 61 | } 62 | } 63 | }; 64 | } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Sandbox.Tests/VisualTestRunner.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using osu.Framework; 3 | using osu.Framework.Platform; 4 | using osu.Game.Tests; 5 | 6 | namespace osu.Game.Rulesets.Sandbox.Tests 7 | { 8 | public static class VisualTestRunner 9 | { 10 | [STAThread] 11 | public static int Main(string[] args) 12 | { 13 | using (DesktopGameHost host = Host.GetSuitableDesktopHost(@"osu")) 14 | { 15 | host.Run(new OsuTestBrowser()); 16 | return 0; 17 | } 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Sandbox.Tests/Visualizer/TestSceneLinearRounded.cs: -------------------------------------------------------------------------------- 1 | using osu.Framework.Graphics; 2 | using osu.Framework.Graphics.Containers; 3 | using osu.Game.Rulesets.Sandbox.Screens.Visualizer.Components.MusicHelpers; 4 | using osu.Game.Rulesets.Sandbox.Screens.Visualizer.Components.Visualizers; 5 | using osu.Game.Rulesets.Sandbox.Screens.Visualizer.Components.Visualizers.Linear; 6 | using osu.Game.Rulesets.Sandbox.UI; 7 | 8 | namespace osu.Game.Rulesets.Sandbox.Tests.Visualizer 9 | { 10 | public partial class TestSceneLinearRounded : RulesetTestScene 11 | { 12 | private readonly Visualizer visualizer; 13 | private RoundedLinearMusicVisualizerDrawable drawable => visualizer.Drawable; 14 | 15 | public TestSceneLinearRounded() 16 | { 17 | AddRange(new Drawable[] 18 | { 19 | visualizer = new Visualizer(), 20 | new Container 21 | { 22 | Anchor = Anchor.TopRight, 23 | Origin = Anchor.TopRight, 24 | AutoSizeAxes = Axes.Y, 25 | Width = 400, 26 | Child = new TrackController() 27 | } 28 | }); 29 | } 30 | 31 | protected override void LoadComplete() 32 | { 33 | base.LoadComplete(); 34 | AddSliderStep("Anchor", 0, 2, 0, value => drawable.BarAnchorBindable.Value = (BarAnchor)value); 35 | AddSliderStep("Bar count", 0, 3000, 30, value => drawable.BarCount.Value = value); 36 | AddSliderStep("Bar width", 1f, 100f, 15, value => drawable.BarWidth.Value = value); 37 | AddSliderStep("Smoothness", 0, 10, 0, value => drawable.Smoothness.Value = value); 38 | } 39 | 40 | private partial class Visualizer : MusicAmplitudesProvider 41 | { 42 | public readonly RoundedLinearMusicVisualizerDrawable Drawable; 43 | 44 | public Visualizer() 45 | { 46 | Anchor = Anchor.Centre; 47 | Origin = Anchor.Centre; 48 | RelativeSizeAxes = Axes.X; 49 | Height = 200; 50 | Child = Drawable = new RoundedLinearMusicVisualizerDrawable(); 51 | } 52 | 53 | protected override void OnAmplitudesUpdate(float[] amplitudes) 54 | { 55 | Drawable.SetAmplitudes(amplitudes); 56 | } 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Sandbox.Tests/Visualizer/TestSceneParticles.cs: -------------------------------------------------------------------------------- 1 | using osu.Framework.Graphics; 2 | using osu.Framework.Graphics.Containers; 3 | using osu.Framework.Graphics.Shapes; 4 | using osu.Game.Rulesets.Sandbox.Screens.Visualizer.Components; 5 | using osu.Game.Rulesets.Sandbox.Screens.Visualizer.Components.MusicHelpers; 6 | using osu.Game.Rulesets.Sandbox.UI; 7 | using osuTK; 8 | using osuTK.Graphics; 9 | 10 | namespace osu.Game.Rulesets.Sandbox.Tests.Visualizer 11 | { 12 | public partial class TestSceneParticles : RulesetTestScene 13 | { 14 | private readonly ParticlesDrawable particles; 15 | 16 | public TestSceneParticles() 17 | { 18 | AddRange(new Drawable[] 19 | { 20 | new Container 21 | { 22 | Anchor = Anchor.Centre, 23 | Origin = Anchor.Centre, 24 | Size = new Vector2(500), 25 | Children = new Drawable[] 26 | { 27 | new Box 28 | { 29 | RelativeSizeAxes = Axes.Both, 30 | Colour = Color4.Black 31 | }, 32 | new CurrentRateContainer 33 | { 34 | RelativeSizeAxes = Axes.Both, 35 | Child = particles = new ParticlesDrawable() 36 | } 37 | } 38 | }, 39 | new Container 40 | { 41 | Anchor = Anchor.TopRight, 42 | Origin = Anchor.TopRight, 43 | AutoSizeAxes = Axes.Y, 44 | Width = 400, 45 | Child = new TrackController() 46 | } 47 | }); 48 | } 49 | 50 | protected override void LoadComplete() 51 | { 52 | base.LoadComplete(); 53 | AddSliderStep("Restart", 1, 30000, 1000, c => particles.TargetCount = c); 54 | AddSliderStep("Direction", 0, 6, 0, d => particles.Direction.Value = (ParticlesDirection)d); 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Sandbox.Tests/Visualizer/TestSceneSettingsTip.cs: -------------------------------------------------------------------------------- 1 | using osu.Game.Rulesets.Sandbox.Screens.Visualizer.Components; 2 | using osu.Game.Tests.Visual; 3 | 4 | namespace osu.Game.Rulesets.Sandbox.Tests.Visualizer 5 | { 6 | public class TestSceneSettingsTip : OsuTestScene 7 | { 8 | private readonly VisualizerSettingsTip tip; 9 | 10 | public TestSceneSettingsTip() 11 | { 12 | Add(tip = new VisualizerSettingsTip()); 13 | } 14 | 15 | protected override void LoadComplete() 16 | { 17 | base.LoadComplete(); 18 | 19 | AddStep("Toggle visibility", tip.ToggleVisibility); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Sandbox.Tests/Visualizer/TestSceneSmoothRandom.cs: -------------------------------------------------------------------------------- 1 | using osu.Framework.Graphics.Shapes; 2 | using osu.Game.Graphics.Sprites; 3 | using osu.Game.Rulesets.Sandbox.Extensions; 4 | using osu.Game.Tests.Visual; 5 | using osu.Framework.Graphics; 6 | using osuTK; 7 | using System; 8 | using osu.Framework.Graphics.Containers; 9 | 10 | namespace osu.Game.Rulesets.Sandbox.Tests.Visualizer 11 | { 12 | public class TestSceneSmoothRandom : OsuTestScene 13 | { 14 | private readonly OsuSpriteText valueText; 15 | private readonly OsuSpriteText minText; 16 | private readonly OsuSpriteText maxText; 17 | private readonly OpenSimplexNoise noise; 18 | private readonly Circle circle; 19 | 20 | public TestSceneSmoothRandom() 21 | { 22 | noise = new OpenSimplexNoise(); 23 | 24 | Children = new Drawable[] 25 | { 26 | new FillFlowContainer 27 | { 28 | Margin = new MarginPadding(10), 29 | Direction = FillDirection.Vertical, 30 | Spacing = new Vector2(0, 10), 31 | Children = new Drawable[] 32 | { 33 | valueText = new OsuSpriteText(), 34 | minText = new OsuSpriteText(), 35 | maxText = new OsuSpriteText() 36 | } 37 | }, 38 | circle = new Circle 39 | { 40 | Anchor = Anchor.Centre, 41 | Origin = Anchor.Centre, 42 | Size = new Vector2(20) 43 | } 44 | }; 45 | } 46 | 47 | private double min, max; 48 | 49 | protected override void Update() 50 | { 51 | base.Update(); 52 | 53 | var value = noise.Evaluate(Time.Current / 1000, 0.0); 54 | 55 | min = Math.Min(value, min); 56 | max = Math.Max(value, max); 57 | 58 | valueText.Text = $"Current: {value}"; 59 | minText.Text = $"Min: {min}"; 60 | maxText.Text = $"Max: {max}"; 61 | 62 | circle.Y = (float)value * 100; 63 | } 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Sandbox.Tests/osu.Game.Rulesets.Sandbox.Tests.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | osu.Game.Rulesets.Sandbox.Tests.VisualTestRunner 4 | 5 | 6 | 7 | 8 | 9 | WinExe 10 | net8.0 11 | osu.Game.Rulesets.Sandbox.Tests 12 | 13 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Sandbox.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.29123.88 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "osu.Game.Rulesets.Sandbox", "osu.Game.Rulesets.Sandbox\osu.Game.Rulesets.Sandbox.csproj", "{5AE1F0F1-DAFA-46E7-959C-DA233B7C87E9}" 7 | EndProject 8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "osu.Game.Rulesets.Sandbox.Tests", "osu.Game.Rulesets.Sandbox.Tests\osu.Game.Rulesets.Sandbox.Tests.csproj", "{B4577C85-CB83-462A-BCE3-22FFEB16311D}" 9 | EndProject 10 | Global 11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 12 | Debug|Any CPU = Debug|Any CPU 13 | Release|Any CPU = Release|Any CPU 14 | VisualTests|Any CPU = VisualTests|Any CPU 15 | EndGlobalSection 16 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 17 | {5AE1F0F1-DAFA-46E7-959C-DA233B7C87E9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 18 | {5AE1F0F1-DAFA-46E7-959C-DA233B7C87E9}.Debug|Any CPU.Build.0 = Debug|Any CPU 19 | {5AE1F0F1-DAFA-46E7-959C-DA233B7C87E9}.Release|Any CPU.ActiveCfg = Release|Any CPU 20 | {5AE1F0F1-DAFA-46E7-959C-DA233B7C87E9}.Release|Any CPU.Build.0 = Release|Any CPU 21 | {5AE1F0F1-DAFA-46E7-959C-DA233B7C87E9}.VisualTests|Any CPU.ActiveCfg = Release|Any CPU 22 | {5AE1F0F1-DAFA-46E7-959C-DA233B7C87E9}.VisualTests|Any CPU.Build.0 = Release|Any CPU 23 | {B4577C85-CB83-462A-BCE3-22FFEB16311D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 24 | {B4577C85-CB83-462A-BCE3-22FFEB16311D}.Debug|Any CPU.Build.0 = Debug|Any CPU 25 | {B4577C85-CB83-462A-BCE3-22FFEB16311D}.Release|Any CPU.ActiveCfg = Release|Any CPU 26 | {B4577C85-CB83-462A-BCE3-22FFEB16311D}.Release|Any CPU.Build.0 = Release|Any CPU 27 | {B4577C85-CB83-462A-BCE3-22FFEB16311D}.VisualTests|Any CPU.ActiveCfg = Debug|Any CPU 28 | {B4577C85-CB83-462A-BCE3-22FFEB16311D}.VisualTests|Any CPU.Build.0 = Debug|Any CPU 29 | EndGlobalSection 30 | GlobalSection(SolutionProperties) = preSolution 31 | HideSolutionNode = FALSE 32 | EndGlobalSection 33 | GlobalSection(NestedProjects) = preSolution 34 | EndGlobalSection 35 | GlobalSection(ExtensibilityGlobals) = postSolution 36 | SolutionGuid = {671B0BEC-2403-45B0-9357-2C97CC517668} 37 | EndGlobalSection 38 | GlobalSection(MonoDevelopProperties) = preSolution 39 | Policies = $0 40 | $0.TextStylePolicy = $1 41 | $1.EolMarker = Windows 42 | $1.inheritsSet = VisualStudio 43 | $1.inheritsScope = text/plain 44 | $1.scope = text/x-csharp 45 | $0.CSharpFormattingPolicy = $2 46 | $2.IndentSwitchSection = True 47 | $2.NewLinesForBracesInProperties = True 48 | $2.NewLinesForBracesInAccessors = True 49 | $2.NewLinesForBracesInAnonymousMethods = True 50 | $2.NewLinesForBracesInControlBlocks = True 51 | $2.NewLinesForBracesInAnonymousTypes = True 52 | $2.NewLinesForBracesInObjectCollectionArrayInitializers = True 53 | $2.NewLinesForBracesInLambdaExpressionBody = True 54 | $2.NewLineForElse = True 55 | $2.NewLineForCatch = True 56 | $2.NewLineForFinally = True 57 | $2.NewLineForMembersInObjectInit = True 58 | $2.NewLineForMembersInAnonymousTypes = True 59 | $2.NewLineForClausesInQuery = True 60 | $2.SpacingAfterMethodDeclarationName = False 61 | $2.SpaceAfterMethodCallName = False 62 | $2.SpaceBeforeOpenSquareBracket = False 63 | $2.inheritsSet = Mono 64 | $2.inheritsScope = text/x-csharp 65 | $2.scope = text/x-csharp 66 | EndGlobalSection 67 | GlobalSection(MonoDevelopProperties) = preSolution 68 | Policies = $0 69 | $0.TextStylePolicy = $1 70 | $1.EolMarker = Windows 71 | $1.inheritsSet = VisualStudio 72 | $1.inheritsScope = text/plain 73 | $1.scope = text/x-csharp 74 | $0.CSharpFormattingPolicy = $2 75 | $2.IndentSwitchSection = True 76 | $2.NewLinesForBracesInProperties = True 77 | $2.NewLinesForBracesInAccessors = True 78 | $2.NewLinesForBracesInAnonymousMethods = True 79 | $2.NewLinesForBracesInControlBlocks = True 80 | $2.NewLinesForBracesInAnonymousTypes = True 81 | $2.NewLinesForBracesInObjectCollectionArrayInitializers = True 82 | $2.NewLinesForBracesInLambdaExpressionBody = True 83 | $2.NewLineForElse = True 84 | $2.NewLineForCatch = True 85 | $2.NewLineForFinally = True 86 | $2.NewLineForMembersInObjectInit = True 87 | $2.NewLineForMembersInAnonymousTypes = True 88 | $2.NewLineForClausesInQuery = True 89 | $2.SpacingAfterMethodDeclarationName = False 90 | $2.SpaceAfterMethodCallName = False 91 | $2.SpaceBeforeOpenSquareBracket = False 92 | $2.inheritsSet = Mono 93 | $2.inheritsScope = text/x-csharp 94 | $2.scope = text/x-csharp 95 | EndGlobalSection 96 | EndGlobal 97 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Sandbox/Beatmaps/SandboxBeatmap.cs: -------------------------------------------------------------------------------- 1 | using osu.Game.Beatmaps; 2 | using osu.Game.Rulesets.Sandbox.Objects; 3 | 4 | namespace osu.Game.Rulesets.Sandbox.Beatmaps 5 | { 6 | public class SandboxBeatmap : Beatmap 7 | { 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Sandbox/Beatmaps/SandboxBeatmapConverter.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Threading; 3 | using osu.Framework.Extensions.IEnumerableExtensions; 4 | using osu.Game.Beatmaps; 5 | using osu.Game.Rulesets.Sandbox.Objects; 6 | using osu.Game.Rulesets.Objects; 7 | 8 | namespace osu.Game.Rulesets.Sandbox.Beatmaps 9 | { 10 | public class SandboxBeatmapConverter : BeatmapConverter 11 | { 12 | public SandboxBeatmapConverter(IBeatmap beatmap, Ruleset ruleset) 13 | : base(beatmap, ruleset) 14 | { 15 | } 16 | 17 | public override bool CanConvert() => true; 18 | 19 | protected override Beatmap CreateBeatmap() => new SandboxBeatmap(); 20 | 21 | protected override IEnumerable ConvertHitObject(HitObject obj, IBeatmap beatmap, CancellationToken token) 22 | => new SandboxHitObject 23 | { 24 | StartTime = obj.StartTime, 25 | Samples = obj.Samples 26 | }.Yield(); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Sandbox/Configuration/SandboxRulesetConfigManager.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | using osu.Game.Configuration; 3 | using osu.Game.Rulesets.Configuration; 4 | using osu.Game.Rulesets.Sandbox.Screens.Visualizer.Components; 5 | 6 | namespace osu.Game.Rulesets.Sandbox.Configuration 7 | { 8 | public class SandboxRulesetConfigManager : RulesetConfigManager 9 | { 10 | public SandboxRulesetConfigManager(SettingsStore settings, RulesetInfo ruleset, int? variant = null) 11 | : base(settings, ruleset, variant) 12 | { 13 | } 14 | 15 | protected override void InitialiseDefaults() 16 | { 17 | base.InitialiseDefaults(); 18 | 19 | // Best scores 20 | SetDefault(SandboxRulesetSetting.NumbersGameBestScore, 0); 21 | SetDefault(SandboxRulesetSetting.FlappyDonGameBestScore, 0); 22 | 23 | // Visualizer 24 | SetDefault(SandboxRulesetSetting.ShowParticles, true); 25 | SetDefault(SandboxRulesetSetting.ParticleCount, 500, 50, 1000); 26 | SetDefault(SandboxRulesetSetting.ShowStoryboard, false); 27 | SetDefault(SandboxRulesetSetting.VisualizerLayout, VisualizerLayout.TypeA); 28 | SetDefault(SandboxRulesetSetting.ShowSettingsTip, true); 29 | SetDefault(SandboxRulesetSetting.ParticlesColour, "#ffffff"); 30 | SetDefault(SandboxRulesetSetting.ParticlesDirection, ParticlesDirection.Random); 31 | SetDefault(SandboxRulesetSetting.GlobalSpeed, 100, 1, 200); 32 | 33 | // TypeA settings 34 | SetDefault(SandboxRulesetSetting.Radius, 350, 200, 500); 35 | SetDefault(SandboxRulesetSetting.CircularBarType, CircularBarType.Basic); 36 | SetDefault(SandboxRulesetSetting.Rotation, 0, 0, 360); 37 | SetDefault(SandboxRulesetSetting.DecayA, 200, 100, 500); 38 | SetDefault(SandboxRulesetSetting.MultiplierA, 400, 200, 500); 39 | SetDefault(SandboxRulesetSetting.Symmetry, false); 40 | SetDefault(SandboxRulesetSetting.SmoothnessA, 1, 0, 50); 41 | SetDefault(SandboxRulesetSetting.BarWidthA, 3.0, 1, 20); 42 | SetDefault(SandboxRulesetSetting.BarsPerVisual, 120, 10, 3500); 43 | SetDefault(SandboxRulesetSetting.VisualizerAmount, 3, 1, 10); 44 | SetDefault(SandboxRulesetSetting.TypeAColour, "#ffffff"); 45 | SetDefault(SandboxRulesetSetting.TypeAProgressColour, "#ffffff"); 46 | SetDefault(SandboxRulesetSetting.TypeATextColour, "#ffffff"); 47 | 48 | // TypeB settings 49 | SetDefault(SandboxRulesetSetting.DecayB, 200, 100, 500); 50 | SetDefault(SandboxRulesetSetting.MultiplierB, 400, 200, 500); 51 | SetDefault(SandboxRulesetSetting.SmoothnessB, 1, 0, 50); 52 | SetDefault(SandboxRulesetSetting.BarWidthB, 3.0, 1, 20); 53 | SetDefault(SandboxRulesetSetting.BarCountB, 120, 10, 3500); 54 | SetDefault(SandboxRulesetSetting.LinearBarType, LinearBarType.Basic); 55 | SetDefault(SandboxRulesetSetting.TypeBColour, "#ffffff"); 56 | SetDefault(SandboxRulesetSetting.TypeBProgressColour, "#ffffff"); 57 | SetDefault(SandboxRulesetSetting.TypeBTextColour, "#ffffff"); 58 | } 59 | } 60 | 61 | public enum SandboxRulesetSetting 62 | { 63 | NumbersGameBestScore, 64 | FlappyDonGameBestScore, 65 | 66 | // Visualizer 67 | ShowParticles, 68 | ParticleCount, 69 | ShowStoryboard, 70 | VisualizerLayout, 71 | ShowSettingsTip, 72 | ParticlesColour, 73 | ParticlesDirection, 74 | GlobalSpeed, 75 | 76 | // TypeA settings 77 | Radius, 78 | CircularBarType, 79 | Rotation, 80 | DecayA, 81 | MultiplierA, 82 | Symmetry, 83 | SmoothnessA, 84 | BarWidthA, 85 | BarsPerVisual, 86 | VisualizerAmount, 87 | TypeAColour, 88 | TypeAProgressColour, 89 | TypeATextColour, 90 | 91 | // TypeB settings 92 | DecayB, 93 | MultiplierB, 94 | SmoothnessB, 95 | BarWidthB, 96 | BarCountB, 97 | LinearBarType, 98 | TypeBColour, 99 | TypeBProgressColour, 100 | TypeBTextColour 101 | } 102 | 103 | public enum VisualizerLayout 104 | { 105 | [Description("Type A")] 106 | TypeA, 107 | 108 | [Description("Type B")] 109 | TypeB, 110 | Empty 111 | } 112 | 113 | public enum CircularBarType 114 | { 115 | Basic, 116 | Rounded, 117 | Fall, 118 | Dots 119 | } 120 | 121 | public enum LinearBarType 122 | { 123 | Basic, 124 | Rounded 125 | } 126 | } 127 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Sandbox/Difficulty/SandboxDifficultyCalculator.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using osu.Game.Beatmaps; 5 | using osu.Game.Rulesets.Difficulty; 6 | using osu.Game.Rulesets.Difficulty.Preprocessing; 7 | using osu.Game.Rulesets.Difficulty.Skills; 8 | using osu.Game.Rulesets.Mods; 9 | 10 | namespace osu.Game.Rulesets.Sandbox.Difficulty 11 | { 12 | public class SandboxDifficultyCalculator : DifficultyCalculator 13 | { 14 | public SandboxDifficultyCalculator(IRulesetInfo ruleset, IWorkingBeatmap beatmap) 15 | : base(ruleset, beatmap) 16 | { 17 | } 18 | 19 | protected override DifficultyAttributes CreateDifficultyAttributes(IBeatmap beatmap, Mod[] mods, Skill[] skills, double clockRate) 20 | { 21 | return new DifficultyAttributes 22 | { 23 | StarRating = 1 24 | }; 25 | } 26 | 27 | protected override IEnumerable CreateDifficultyHitObjects(IBeatmap beatmap, double clockRate) => Enumerable.Empty(); 28 | 29 | protected override Skill[] CreateSkills(IBeatmap beatmap, Mod[] mods, double clockRate) => Array.Empty(); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Sandbox/Extensions/MathExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using osuTK; 3 | 4 | namespace osu.Game.Rulesets.Sandbox.Extensions 5 | { 6 | public static class MathExtensions 7 | { 8 | public static float Map(float value, float minValue, float maxValue, float minEndValue, float maxEndValue) 9 | { 10 | return (value - minValue) / (maxValue - minValue) * (maxEndValue - minEndValue) + minEndValue; 11 | } 12 | 13 | public static double Map(double value, double minValue, double maxValue, double minEndValue, double maxEndValue) 14 | { 15 | return (value - minValue) / (maxValue - minValue) * (maxEndValue - minEndValue) + minEndValue; 16 | } 17 | 18 | public static Vector2 Map(float value, float minValue, float maxValue, Vector2 minEndValue, Vector2 maxEndValue) 19 | { 20 | return new Vector2(Map(value, minValue, maxValue, minEndValue.X, maxEndValue.X), Map(value, minValue, maxValue, minEndValue.Y, maxEndValue.Y)); 21 | } 22 | 23 | public static void Smooth(this float[] src, int severity = 1) 24 | { 25 | for (int i = 0; i < src.Length; i++) 26 | { 27 | var start = Math.Max(i - severity, 0); 28 | var end = Math.Min(i + severity, src.Length); 29 | 30 | float sum = 0; 31 | 32 | for (int j = start; j < end; j++) 33 | sum += src[j]; 34 | 35 | src[i] = sum / (end - start); 36 | } 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Sandbox/Extensions/OpenSimplexNoise.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.CompilerServices; 2 | 3 | namespace osu.Game.Rulesets.Sandbox.Extensions 4 | { 5 | public class OpenSimplexNoise 6 | { 7 | private const double stretch_2d = -0.211324865405187; //(1/Math.sqrt(2+1)-1)/2; 8 | private const double squish_2d = 0.366025403784439; //(Math.sqrt(2+1)-1)/2; 9 | private const double norm_2d = 1.0 / 47.0; 10 | 11 | private byte[] perm; 12 | private byte[] perm2D; 13 | private byte[] perm3D; 14 | private byte[] perm4D; 15 | 16 | private static double[] gradients2D = new double[] 17 | { 18 | 5, 2, 2, 5, 19 | -5, 2, -2, 5, 20 | 5, -2, 2, -5, 21 | -5, -2, -2, -5, 22 | }; 23 | 24 | private readonly Contribution[] lookup2D = new Contribution[64]; 25 | 26 | public OpenSimplexNoise(long seed = 0) 27 | { 28 | var base2D = new int[][] 29 | { 30 | new int[] { 1, 1, 0, 1, 0, 1, 0, 0, 0 }, 31 | new int[] { 1, 1, 0, 1, 0, 1, 2, 1, 1 } 32 | }; 33 | var p2D = new int[] { 0, 0, 1, -1, 0, 0, -1, 1, 0, 2, 1, 1, 1, 2, 2, 0, 1, 2, 0, 2, 1, 0, 0, 0 }; 34 | var lookupPairs2D = new int[] { 0, 1, 1, 0, 4, 1, 17, 0, 20, 2, 21, 2, 22, 5, 23, 5, 26, 4, 39, 3, 42, 4, 43, 3 }; 35 | 36 | var contributions2D = new Contribution[p2D.Length / 4]; 37 | for (int i = 0; i < p2D.Length; i += 4) 38 | { 39 | var baseSet = base2D[p2D[i]]; 40 | Contribution previous = null, current = null; 41 | for (int k = 0; k < baseSet.Length; k += 3) 42 | { 43 | current = new Contribution(baseSet[k], baseSet[k + 1], baseSet[k + 2]); 44 | if (previous == null) 45 | { 46 | contributions2D[i / 4] = current; 47 | } 48 | else 49 | { 50 | previous.Next = current; 51 | } 52 | previous = current; 53 | } 54 | current.Next = new Contribution(p2D[i + 1], p2D[i + 2], p2D[i + 3]); 55 | } 56 | 57 | for (var i = 0; i < lookupPairs2D.Length; i += 2) 58 | lookup2D[lookupPairs2D[i]] = contributions2D[lookupPairs2D[i + 1]]; 59 | 60 | perm = new byte[256]; 61 | perm2D = new byte[256]; 62 | perm3D = new byte[256]; 63 | perm4D = new byte[256]; 64 | var source = new byte[256]; 65 | for (int i = 0; i < 256; i++) 66 | { 67 | source[i] = (byte)i; 68 | } 69 | seed = seed * 6364136223846793005L + 1442695040888963407L; 70 | seed = seed * 6364136223846793005L + 1442695040888963407L; 71 | seed = seed * 6364136223846793005L + 1442695040888963407L; 72 | for (int i = 255; i >= 0; i--) 73 | { 74 | seed = seed * 6364136223846793005L + 1442695040888963407L; 75 | int r = (int)((seed + 31) % (i + 1)); 76 | if (r < 0) 77 | { 78 | r += (i + 1); 79 | } 80 | perm[i] = source[r]; 81 | perm2D[i] = (byte)(perm[i] & 0x0E); 82 | perm3D[i] = (byte)((perm[i] % 24) * 3); 83 | perm4D[i] = (byte)(perm[i] & 0xFC); 84 | source[r] = source[i]; 85 | } 86 | } 87 | 88 | public double Evaluate(double x, double y) 89 | { 90 | var stretchOffset = (x + y) * stretch_2d; 91 | var xs = x + stretchOffset; 92 | var ys = y + stretchOffset; 93 | 94 | var xsb = fastFloor(xs); 95 | var ysb = fastFloor(ys); 96 | 97 | var squishOffset = (xsb + ysb) * squish_2d; 98 | var dx0 = x - (xsb + squishOffset); 99 | var dy0 = y - (ysb + squishOffset); 100 | 101 | var xins = xs - xsb; 102 | var yins = ys - ysb; 103 | 104 | var inSum = xins + yins; 105 | 106 | var hash = 107 | (int)(xins - yins + 1) | 108 | (int)(inSum) << 1 | 109 | (int)(inSum + yins) << 2 | 110 | (int)(inSum + xins) << 4; 111 | 112 | var c = lookup2D[hash]; 113 | 114 | var value = 0.0; 115 | while (c != null) 116 | { 117 | var dx = dx0 + c.Dx; 118 | var dy = dy0 + c.Dy; 119 | var attn = 2 - dx * dx - dy * dy; 120 | if (attn > 0) 121 | { 122 | var px = xsb + c.Xsb; 123 | var py = ysb + c.Ysb; 124 | 125 | var i = perm2D[(perm[px & 0xFF] + py) & 0xFF]; 126 | var valuePart = gradients2D[i] * dx + gradients2D[i + 1] * dy; 127 | 128 | attn *= attn; 129 | value += attn * attn * valuePart; 130 | } 131 | c = c.Next; 132 | } 133 | return value * norm_2d; 134 | } 135 | 136 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 137 | private static int fastFloor(double x) 138 | { 139 | var xi = (int)x; 140 | return x < xi ? xi - 1 : xi; 141 | } 142 | 143 | private class Contribution 144 | { 145 | public double Dx, Dy; 146 | public int Xsb, Ysb; 147 | public Contribution Next; 148 | 149 | public Contribution(double multiplier, int xsb, int ysb) 150 | { 151 | Dx = -xsb - multiplier * squish_2d; 152 | Dy = -ysb - multiplier * squish_2d; 153 | Xsb = xsb; 154 | Ysb = ysb; 155 | } 156 | } 157 | } 158 | } 159 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Sandbox/Extensions/OsuGameExtensions.cs: -------------------------------------------------------------------------------- 1 | using System.Linq; 2 | using osu.Framework.Allocation; 3 | using osu.Framework.Testing; 4 | using osu.Game.Overlays; 5 | using osu.Game.Screens; 6 | 7 | namespace osu.Game.Rulesets.Sandbox.Extensions 8 | { 9 | public static class OsuGameExtensions 10 | { 11 | public static SandboxRuleset GetRuleset(this DependencyContainer dependencies) 12 | { 13 | var rulesets = dependencies.Get().AvailableRulesets.Select(info => info.CreateInstance()); 14 | return (SandboxRuleset)rulesets.FirstOrDefault(r => r is SandboxRuleset); 15 | } 16 | 17 | public static SandboxRuleset GetThisRuleset(this RulesetStore rulesetStore) 18 | { 19 | var rulesets = rulesetStore.AvailableRulesets.Select(info => info.CreateInstance()); 20 | return (SandboxRuleset)rulesets.FirstOrDefault(r => r is SandboxRuleset); 21 | } 22 | 23 | public static OsuScreenStack GetScreenStack(this OsuGame game) => game.ChildrenOfType().FirstOrDefault(); 24 | 25 | public static SettingsOverlay GetSettingsOverlay(this OsuGame game) => game.ChildrenOfType().FirstOrDefault(); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Sandbox/Extensions/ProjectileExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using osu.Framework.Utils; 3 | using osuTK; 4 | 5 | namespace osu.Game.Rulesets.Sandbox.Extensions 6 | { 7 | public static class ProjectileExtensions 8 | { 9 | public static ProjectileInfo GetProjectileInfoAt(ProjectileInfo startParameters, float timeOffset, float pixelToMeterRatio = 15f) 10 | { 11 | float durationInSeconds = timeOffset / 1000; 12 | 13 | float speedX = startParameters.Speed * (float)Math.Cos(startParameters.Angle * Math.PI / 180f); 14 | float speedY = startParameters.Speed * (float)Math.Sin(startParameters.Angle * Math.PI / 180f); 15 | 16 | float xOffset = speedX * durationInSeconds; 17 | float yOffset = speedY * durationInSeconds + 4.9f * durationInSeconds * durationInSeconds; 18 | 19 | Vector2 position = startParameters.Position + new Vector2(xOffset, yOffset) * pixelToMeterRatio; 20 | 21 | float finalSpeedY = speedY + 9.8f * durationInSeconds; 22 | float finalSpeed = (float)Math.Sqrt(speedX * speedX + finalSpeedY * finalSpeedY); 23 | float sin = speedX / finalSpeed; 24 | float finalAngle = (float)Math.Abs(Math.Asin(sin) * 180f / Math.PI); // from 0 to 90 25 | 26 | if (startParameters.Angle > -90) 27 | finalAngle = finalSpeedY > 0 ? (90 - finalAngle) : finalAngle - 90; 28 | else 29 | finalAngle = finalSpeedY > 0 ? finalAngle - 270 : (-90 - finalAngle); 30 | 31 | return new ProjectileInfo(position, finalSpeed, finalAngle); 32 | } 33 | 34 | public static (ProjectileInfo info, bool collided) ProcessCollision(ProjectileInfo atCollision, float surfaceNormalAngle) 35 | { 36 | var result = hitResultAngle(atCollision.Angle, surfaceNormalAngle); 37 | 38 | if (Precision.AlmostEquals(result, 10000)) 39 | return (atCollision, false); 40 | 41 | return (new ProjectileInfo(atCollision.Position, atCollision.Speed, GetAcceptableAngle(result)), true); 42 | } 43 | 44 | private static float hitResultAngle(float projectileAngle, float surfaceNormalAngle) 45 | { 46 | float offset = offsetBetweenAngles(GetOppositeAngle(projectileAngle), surfaceNormalAngle); 47 | 48 | if (Math.Abs(offset) > 90) 49 | return 10000; 50 | 51 | float x = surfaceNormalAngle - 90; 52 | if (x < -270) 53 | x += 360; 54 | 55 | return 360f + 2 * x - projectileAngle; 56 | } 57 | 58 | private static float offsetBetweenAngles(float a, float b) 59 | { 60 | var radA = a * Math.PI / 180f; 61 | var radB = b * Math.PI / 180f; 62 | 63 | return (float)(Math.Atan2(Math.Sin(radA - radB), Math.Cos(radA - radB)) * 180f / Math.PI); 64 | } 65 | 66 | public static float GetAcceptableAngle(float a) 67 | { 68 | if (a < -270) 69 | { 70 | while (a < 270) 71 | a += 360; 72 | } 73 | 74 | if (a > 90) 75 | { 76 | while (a > 90) 77 | a -= 360; 78 | } 79 | 80 | return a; 81 | } 82 | 83 | public static float GetOppositeAngle(float a) 84 | { 85 | float oppositeAngle = a - 180f; 86 | if (oppositeAngle < -270) 87 | oppositeAngle += 360; 88 | 89 | return oppositeAngle; 90 | } 91 | } 92 | 93 | public class ProjectileInfo 94 | { 95 | public Vector2 Position { get; private set; } 96 | 97 | public float Speed { get; private set; } 98 | 99 | public float Angle { get; private set; } 100 | 101 | public ProjectileInfo(Vector2 position, float speed, float angle) 102 | { 103 | Position = position; 104 | Speed = speed; 105 | Angle = angle; 106 | } 107 | 108 | public override string ToString() => $"Position: {Position}, Speed: {Speed}, Angle: {Angle}"; 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Sandbox/Graphics/ContentFitContainer.cs: -------------------------------------------------------------------------------- 1 | using osu.Framework.Graphics.Containers; 2 | using osu.Framework.Graphics; 3 | 4 | namespace osu.Game.Rulesets.Sandbox.Graphics 5 | { 6 | public partial class ContentFitContainer : Container 7 | { 8 | protected override Container Content => content; 9 | 10 | private readonly Container content; 11 | 12 | public ContentFitContainer() 13 | { 14 | Anchor = Anchor.Centre; 15 | Origin = Anchor.Centre; 16 | RelativeSizeAxes = Axes.Both; 17 | InternalChild = content = new Container 18 | { 19 | Anchor = Anchor.Centre, 20 | Origin = Anchor.Centre, 21 | RelativeSizeAxes = Axes.Both, 22 | FillMode = FillMode.Fit, 23 | }; 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Sandbox/Graphics/InnerShadowContainer.cs: -------------------------------------------------------------------------------- 1 | using osu.Framework.Allocation; 2 | using osu.Framework.Graphics; 3 | using osu.Framework.Graphics.Containers; 4 | using osu.Framework.Graphics.Shaders; 5 | using osu.Framework.Graphics.Shapes; 6 | using osuTK.Graphics; 7 | 8 | namespace osu.Game.Rulesets.Sandbox.Graphics 9 | { 10 | public abstract partial class InnerShadowContainer : Container 11 | { 12 | protected override Container Content => content; 13 | 14 | private readonly Container content; 15 | 16 | protected InnerShadowContainer() 17 | { 18 | Masking = true; 19 | InternalChildren = new Drawable[] 20 | { 21 | new Box 22 | { 23 | RelativeSizeAxes = Axes.Both, 24 | Colour = Color4.Black, 25 | Alpha = 0.1f 26 | }, 27 | content = CreateContent(), 28 | new InnerShadow() 29 | }; 30 | } 31 | 32 | protected abstract Container CreateContent(); 33 | 34 | private partial class InnerShadow : Box 35 | { 36 | [BackgroundDependencyLoader] 37 | private void load(ShaderManager shaders) 38 | { 39 | RelativeSizeAxes = Axes.Both; 40 | Colour = Color4.Black; 41 | TextureShader = shaders.Load(VertexShaderDescriptor.TEXTURE_2, "InnerShadow"); 42 | } 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Sandbox/Judgements/SandboxJudgement.cs: -------------------------------------------------------------------------------- 1 | using osu.Game.Rulesets.Judgements; 2 | using osu.Game.Rulesets.Scoring; 3 | 4 | namespace osu.Game.Rulesets.Sandbox.Judgements 5 | { 6 | public class SandboxJudgement : Judgement 7 | { 8 | public override HitResult MaxResult => HitResult.Perfect; 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Sandbox/Objects/Drawables/DrawableSandboxHitObject.cs: -------------------------------------------------------------------------------- 1 | using osu.Game.Rulesets.Objects.Drawables; 2 | 3 | namespace osu.Game.Rulesets.Sandbox.Objects.Drawables 4 | { 5 | public class DrawableSandboxHitObject : DrawableHitObject 6 | { 7 | protected override double InitialLifetimeOffset => 500; 8 | 9 | public DrawableSandboxHitObject(SandboxHitObject h) 10 | : base(h) 11 | { 12 | } 13 | 14 | protected override void CheckForResult(bool userTriggered, double timeOffset) 15 | { 16 | if (timeOffset > 0) 17 | ApplyResult(r => r.Type = r.Judgement.MaxResult); 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Sandbox/Objects/SandboxHitObject.cs: -------------------------------------------------------------------------------- 1 | using osu.Game.Rulesets.Judgements; 2 | using osu.Game.Rulesets.Sandbox.Judgements; 3 | using osu.Game.Rulesets.Objects; 4 | using osu.Game.Rulesets.Scoring; 5 | 6 | namespace osu.Game.Rulesets.Sandbox.Objects 7 | { 8 | public class SandboxHitObject : HitObject 9 | { 10 | protected override HitWindows CreateHitWindows() => HitWindows.Empty; 11 | 12 | public override Judgement CreateJudgement() => new SandboxJudgement(); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Sandbox/Online/GetLatestReleaseRequest.cs: -------------------------------------------------------------------------------- 1 | using osu.Framework.IO.Network; 2 | 3 | namespace osu.Game.Rulesets.Sandbox.Online 4 | { 5 | public class GetLatestReleaseRequest : JsonWebRequest 6 | { 7 | public GetLatestReleaseRequest(string url) 8 | : base($"https://api.github.com/repos/{url}/releases/latest") 9 | { 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Sandbox/Online/GitHubRelease.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Newtonsoft.Json; 3 | 4 | namespace osu.Game.Rulesets.Sandbox.Online 5 | { 6 | public class GitHubRelease 7 | { 8 | [JsonProperty("tag_name")] 9 | public string TagName { get; set; } 10 | 11 | [JsonProperty("body")] 12 | public string Body { get; set; } 13 | 14 | [JsonProperty("published_at")] 15 | public DateTime PublishedAt { get; set; } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Sandbox/Resources/Samples/die.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EVAST9919/lazer-sandbox/df5c2d1fed98b29b2bb26ff1eee4c18ab8bf7a51/osu.Game.Rulesets.Sandbox/Resources/Samples/die.wav -------------------------------------------------------------------------------- /osu.Game.Rulesets.Sandbox/Resources/Samples/flap.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EVAST9919/lazer-sandbox/df5c2d1fed98b29b2bb26ff1eee4c18ab8bf7a51/osu.Game.Rulesets.Sandbox/Resources/Samples/flap.wav -------------------------------------------------------------------------------- /osu.Game.Rulesets.Sandbox/Resources/Samples/hit.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EVAST9919/lazer-sandbox/df5c2d1fed98b29b2bb26ff1eee4c18ab8bf7a51/osu.Game.Rulesets.Sandbox/Resources/Samples/hit.wav -------------------------------------------------------------------------------- /osu.Game.Rulesets.Sandbox/Resources/Samples/point.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EVAST9919/lazer-sandbox/df5c2d1fed98b29b2bb26ff1eee4c18ab8bf7a51/osu.Game.Rulesets.Sandbox/Resources/Samples/point.wav -------------------------------------------------------------------------------- /osu.Game.Rulesets.Sandbox/Resources/Shaders/sh_InnerShadow.fs: -------------------------------------------------------------------------------- 1 | #ifndef INNER_SHADOW_FS 2 | #define INNER_SHADOW_FS 3 | 4 | #include "sh_Utils.h" 5 | #include "sh_Masking.h" 6 | #include "sh_TextureWrapping.h" 7 | 8 | layout(location = 2) in mediump vec2 v_TexCoord; 9 | 10 | layout(set = 0, binding = 0) uniform lowp texture2D m_Texture; 11 | layout(set = 0, binding = 1) uniform lowp sampler m_Sampler; 12 | 13 | layout(location = 0) out vec4 o_Colour; 14 | 15 | void main(void) 16 | { 17 | highp vec2 topLeftOffset = g_MaskingRect.xy - v_MaskingPosition; 18 | highp vec2 bottomRightOffset = v_MaskingPosition - g_MaskingRect.zw; 19 | 20 | highp vec2 distanceFromShrunkRect = max( 21 | bottomRightOffset + vec2(g_CornerRadius), 22 | topLeftOffset + vec2(g_CornerRadius)); 23 | 24 | highp float maxDist = max(distanceFromShrunkRect.x, distanceFromShrunkRect.y); 25 | highp float minDist = min(distanceFromShrunkRect.x, distanceFromShrunkRect.y); 26 | 27 | lowp float a = 0.0; 28 | const float size = 10.0; 29 | 30 | if (maxDist > 0.0) 31 | { 32 | highp float dst = minDist < 0.0 ? maxDist : distance(vec2(-minDist, 0.0), vec2(0.0, maxDist)); 33 | highp float dstFromEdge = clamp(max(g_CornerRadius, size) - dst, 0.0, size); 34 | a = smoothstep(size, -size, dstFromEdge); 35 | } 36 | 37 | vec2 wrappedCoord = wrap(v_TexCoord, v_TexRect); 38 | vec4 texCol = wrappedSampler(wrappedCoord, v_TexRect, m_Texture, m_Sampler, -0.9); 39 | texCol.a *= a; 40 | o_Colour = getRoundedColor(texCol, wrappedCoord); 41 | } 42 | 43 | #endif -------------------------------------------------------------------------------- /osu.Game.Rulesets.Sandbox/Resources/Shaders/sh_RoundedBar.fs: -------------------------------------------------------------------------------- 1 | #ifndef ROUNDED_BAR_FS 2 | #define ROUNDED_BAR_FS 3 | 4 | #include "sh_Utils.h" 5 | #include "sh_Masking.h" 6 | #include "sh_RulesetUtils.h" 7 | 8 | layout(location = 2) in mediump vec2 v_TexCoord; 9 | 10 | layout(set = 0, binding = 0) uniform lowp texture2D m_Texture; 11 | layout(set = 0, binding = 1) uniform lowp sampler m_Sampler; 12 | 13 | layout(location = 0) out vec4 o_Colour; 14 | 15 | void main(void) 16 | { 17 | const float pixelSize = 0.0000003; 18 | 19 | highp vec2 resolution = v_TexRect.wz - v_TexRect.yx; 20 | 21 | if (resolution.x < pixelSize * 2.0) 22 | { 23 | o_Colour = getRoundedColor(vec4(1.0), v_TexCoord); 24 | return; 25 | } 26 | 27 | highp vec2 coord = v_TexCoord.yx; 28 | highp vec2 halfSize = resolution * 0.5; 29 | 30 | if (coord.y > halfSize.y) 31 | coord.y = resolution.y - coord.y; 32 | 33 | highp float dst = coord.y < halfSize.x ? distance(coord, vec2(halfSize.x)) : abs(coord.x - halfSize.x); 34 | 35 | lowp float a = smoothstep(halfSize.x, halfSize.x - pixelSize, dst); 36 | o_Colour = getRoundedColor(vec4(vec3(1.0), a), v_TexCoord); 37 | } 38 | 39 | #endif 40 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Sandbox/Resources/Shaders/sh_RulesetUtils.h: -------------------------------------------------------------------------------- 1 | #define PI 3.1415926538 2 | 3 | vec4 transparentBlack(vec3 c) 4 | { 5 | float alpha = c.r * c.g * c.b; 6 | return vec4(c, alpha < 0.01 ? 0 : alpha); 7 | } 8 | 9 | vec2 rotate(float length, vec2 origin, float angle) 10 | { 11 | float rad = angle * PI / 180.0; 12 | return vec2(cos(rad), sin(rad)) * length + origin; 13 | } 14 | 15 | vec2 rotateAround(vec2 point, vec2 origin, float angle) 16 | { 17 | float rad = angle * PI / 180.0; 18 | float s = sin(rad); 19 | float c = cos(rad); 20 | 21 | point -= origin; 22 | 23 | return vec2(point.x * c - point.y * s, point.x * s + point.y * c) + origin; 24 | } 25 | 26 | highp float dstToLine(highp vec2 start, highp vec2 end, highp vec2 pixelPos) 27 | { 28 | highp float lineLength = distance(end, start); 29 | 30 | if (lineLength < 0.001) 31 | return distance(pixelPos, start); 32 | 33 | highp vec2 a = (end - start) / lineLength; 34 | highp vec2 closest = clamp(dot(a, pixelPos - start), 0.0, distance(end, start)) * a + start; // closest point on a line from given position 35 | return distance(closest, pixelPos); 36 | } 37 | 38 | float map(float value, float minValue, float maxValue, float minEndValue, float maxEndValue) 39 | { 40 | return (value - minValue) / (maxValue - minValue) * (maxEndValue - minEndValue) + minEndValue; 41 | } 42 | 43 | bool almostEqual(float v1, float v2) 44 | { 45 | return abs(v1.x - v2.x) < 0.00001; 46 | } 47 | 48 | bool almostEqual(vec2 p1, vec2 p2) 49 | { 50 | return almostEqual(p1.x, p2.x) && almostEqual(p1.y, p2.y); 51 | } 52 | 53 | vec2 getShaderTexturePosition(vec2 value, vec2 texRes, vec2 topLeft) 54 | { 55 | return topLeft - fract(value) * texRes; 56 | } 57 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Sandbox/Resources/Textures/2048.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EVAST9919/lazer-sandbox/df5c2d1fed98b29b2bb26ff1eee4c18ab8bf7a51/osu.Game.Rulesets.Sandbox/Resources/Textures/2048.png -------------------------------------------------------------------------------- /osu.Game.Rulesets.Sandbox/Resources/Textures/FlappyDon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EVAST9919/lazer-sandbox/df5c2d1fed98b29b2bb26ff1eee4c18ab8bf7a51/osu.Game.Rulesets.Sandbox/Resources/Textures/FlappyDon.png -------------------------------------------------------------------------------- /osu.Game.Rulesets.Sandbox/Resources/Textures/FlappyDon/bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EVAST9919/lazer-sandbox/df5c2d1fed98b29b2bb26ff1eee4c18ab8bf7a51/osu.Game.Rulesets.Sandbox/Resources/Textures/FlappyDon/bg.png -------------------------------------------------------------------------------- /osu.Game.Rulesets.Sandbox/Resources/Textures/FlappyDon/gameover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EVAST9919/lazer-sandbox/df5c2d1fed98b29b2bb26ff1eee4c18ab8bf7a51/osu.Game.Rulesets.Sandbox/Resources/Textures/FlappyDon/gameover.png -------------------------------------------------------------------------------- /osu.Game.Rulesets.Sandbox/Resources/Textures/FlappyDon/ground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EVAST9919/lazer-sandbox/df5c2d1fed98b29b2bb26ff1eee4c18ab8bf7a51/osu.Game.Rulesets.Sandbox/Resources/Textures/FlappyDon/ground.png -------------------------------------------------------------------------------- /osu.Game.Rulesets.Sandbox/Resources/Textures/FlappyDon/message.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EVAST9919/lazer-sandbox/df5c2d1fed98b29b2bb26ff1eee4c18ab8bf7a51/osu.Game.Rulesets.Sandbox/Resources/Textures/FlappyDon/message.png -------------------------------------------------------------------------------- /osu.Game.Rulesets.Sandbox/Resources/Textures/FlappyDon/pipe.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EVAST9919/lazer-sandbox/df5c2d1fed98b29b2bb26ff1eee4c18ab8bf7a51/osu.Game.Rulesets.Sandbox/Resources/Textures/FlappyDon/pipe.png -------------------------------------------------------------------------------- /osu.Game.Rulesets.Sandbox/Resources/Textures/FlappyDon/redbird-downflap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EVAST9919/lazer-sandbox/df5c2d1fed98b29b2bb26ff1eee4c18ab8bf7a51/osu.Game.Rulesets.Sandbox/Resources/Textures/FlappyDon/redbird-downflap.png -------------------------------------------------------------------------------- /osu.Game.Rulesets.Sandbox/Resources/Textures/FlappyDon/redbird-midflap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EVAST9919/lazer-sandbox/df5c2d1fed98b29b2bb26ff1eee4c18ab8bf7a51/osu.Game.Rulesets.Sandbox/Resources/Textures/FlappyDon/redbird-midflap.png -------------------------------------------------------------------------------- /osu.Game.Rulesets.Sandbox/Resources/Textures/FlappyDon/redbird-upflap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EVAST9919/lazer-sandbox/df5c2d1fed98b29b2bb26ff1eee4c18ab8bf7a51/osu.Game.Rulesets.Sandbox/Resources/Textures/FlappyDon/redbird-upflap.png -------------------------------------------------------------------------------- /osu.Game.Rulesets.Sandbox/Resources/Textures/Icons/Bosu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EVAST9919/lazer-sandbox/df5c2d1fed98b29b2bb26ff1eee4c18ab8bf7a51/osu.Game.Rulesets.Sandbox/Resources/Textures/Icons/Bosu.png -------------------------------------------------------------------------------- /osu.Game.Rulesets.Sandbox/Resources/Textures/Icons/Hishigata.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EVAST9919/lazer-sandbox/df5c2d1fed98b29b2bb26ff1eee4c18ab8bf7a51/osu.Game.Rulesets.Sandbox/Resources/Textures/Icons/Hishigata.png -------------------------------------------------------------------------------- /osu.Game.Rulesets.Sandbox/Resources/Textures/Icons/Hitokori.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EVAST9919/lazer-sandbox/df5c2d1fed98b29b2bb26ff1eee4c18ab8bf7a51/osu.Game.Rulesets.Sandbox/Resources/Textures/Icons/Hitokori.png -------------------------------------------------------------------------------- /osu.Game.Rulesets.Sandbox/Resources/Textures/Icons/Sandbox.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EVAST9919/lazer-sandbox/df5c2d1fed98b29b2bb26ff1eee4c18ab8bf7a51/osu.Game.Rulesets.Sandbox/Resources/Textures/Icons/Sandbox.png -------------------------------------------------------------------------------- /osu.Game.Rulesets.Sandbox/Resources/Textures/Icons/Swing.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EVAST9919/lazer-sandbox/df5c2d1fed98b29b2bb26ff1eee4c18ab8bf7a51/osu.Game.Rulesets.Sandbox/Resources/Textures/Icons/Swing.png -------------------------------------------------------------------------------- /osu.Game.Rulesets.Sandbox/Resources/Textures/Icons/Tau.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EVAST9919/lazer-sandbox/df5c2d1fed98b29b2bb26ff1eee4c18ab8bf7a51/osu.Game.Rulesets.Sandbox/Resources/Textures/Icons/Tau.png -------------------------------------------------------------------------------- /osu.Game.Rulesets.Sandbox/Resources/Textures/Icons/Touhosu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EVAST9919/lazer-sandbox/df5c2d1fed98b29b2bb26ff1eee4c18ab8bf7a51/osu.Game.Rulesets.Sandbox/Resources/Textures/Icons/Touhosu.png -------------------------------------------------------------------------------- /osu.Game.Rulesets.Sandbox/Resources/Textures/Icons/Yoso.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EVAST9919/lazer-sandbox/df5c2d1fed98b29b2bb26ff1eee4c18ab8bf7a51/osu.Game.Rulesets.Sandbox/Resources/Textures/Icons/Yoso.png -------------------------------------------------------------------------------- /osu.Game.Rulesets.Sandbox/Resources/Textures/Icons/gamebosu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EVAST9919/lazer-sandbox/df5c2d1fed98b29b2bb26ff1eee4c18ab8bf7a51/osu.Game.Rulesets.Sandbox/Resources/Textures/Icons/gamebosu.png -------------------------------------------------------------------------------- /osu.Game.Rulesets.Sandbox/Resources/Textures/Icons/osu!DIVA.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EVAST9919/lazer-sandbox/df5c2d1fed98b29b2bb26ff1eee4c18ab8bf7a51/osu.Game.Rulesets.Sandbox/Resources/Textures/Icons/osu!DIVA.png -------------------------------------------------------------------------------- /osu.Game.Rulesets.Sandbox/Resources/Textures/Icons/sentakki.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EVAST9919/lazer-sandbox/df5c2d1fed98b29b2bb26ff1eee4c18ab8bf7a51/osu.Game.Rulesets.Sandbox/Resources/Textures/Icons/sentakki.png -------------------------------------------------------------------------------- /osu.Game.Rulesets.Sandbox/Resources/Textures/Icons/soyokaze!.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EVAST9919/lazer-sandbox/df5c2d1fed98b29b2bb26ff1eee4c18ab8bf7a51/osu.Game.Rulesets.Sandbox/Resources/Textures/Icons/soyokaze!.png -------------------------------------------------------------------------------- /osu.Game.Rulesets.Sandbox/Resources/Textures/Ruleset Updates.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EVAST9919/lazer-sandbox/df5c2d1fed98b29b2bb26ff1eee4c18ab8bf7a51/osu.Game.Rulesets.Sandbox/Resources/Textures/Ruleset Updates.png -------------------------------------------------------------------------------- /osu.Game.Rulesets.Sandbox/Resources/Textures/Visualizer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EVAST9919/lazer-sandbox/df5c2d1fed98b29b2bb26ff1eee4c18ab8bf7a51/osu.Game.Rulesets.Sandbox/Resources/Textures/Visualizer.png -------------------------------------------------------------------------------- /osu.Game.Rulesets.Sandbox/Resources/Textures/Visualizer/particle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EVAST9919/lazer-sandbox/df5c2d1fed98b29b2bb26ff1eee4c18ab8bf7a51/osu.Game.Rulesets.Sandbox/Resources/Textures/Visualizer/particle.png -------------------------------------------------------------------------------- /osu.Game.Rulesets.Sandbox/SandboxInputManager.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | using osu.Framework.Input.Bindings; 3 | using osu.Game.Rulesets.UI; 4 | 5 | namespace osu.Game.Rulesets.Sandbox 6 | { 7 | public partial class SandboxInputManager : RulesetInputManager 8 | { 9 | public SandboxInputManager(RulesetInfo ruleset) 10 | : base(ruleset, 0, SimultaneousBindingMode.Unique) 11 | { 12 | } 13 | } 14 | 15 | public enum SandboxAction 16 | { 17 | [Description("2048 Up")] 18 | NumbersUp, 19 | 20 | [Description("2048 Down")] 21 | NumbersDown, 22 | 23 | [Description("2048 Left")] 24 | NumbersLeft, 25 | 26 | [Description("2048 Right")] 27 | NumbersRight, 28 | 29 | [Description("FlappyDon Jump")] 30 | FlappyJump 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Sandbox/SandboxRuleset.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using osu.Framework.Graphics; 3 | using osu.Framework.Graphics.Sprites; 4 | using osu.Game.Beatmaps; 5 | using osu.Game.Rulesets.Difficulty; 6 | using osu.Game.Rulesets.Mods; 7 | using osu.Game.Rulesets.Scoring; 8 | using osu.Game.Rulesets.UI; 9 | using System; 10 | using osu.Framework.Graphics.Textures; 11 | using osu.Game.Rulesets.Sandbox.UI; 12 | using osu.Game.Rulesets.Sandbox.Beatmaps; 13 | using osu.Game.Rulesets.Sandbox.Difficulty; 14 | using osu.Game.Rulesets.Configuration; 15 | using osu.Game.Configuration; 16 | using osu.Game.Rulesets.Sandbox.Configuration; 17 | using osu.Game.Overlays.Settings; 18 | using osu.Framework.Allocation; 19 | using osu.Framework.Platform; 20 | using osu.Framework.Input.Bindings; 21 | 22 | namespace osu.Game.Rulesets.Sandbox 23 | { 24 | public partial class SandboxRuleset : Ruleset 25 | { 26 | public override DrawableRuleset CreateDrawableRulesetWith(IBeatmap beatmap, IReadOnlyList mods = null) => new DrawableSandboxRuleset(this, beatmap, mods); 27 | 28 | public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => new SandboxBeatmapConverter(beatmap, this); 29 | 30 | public override IRulesetConfigManager CreateConfig(SettingsStore settings) => new SandboxRulesetConfigManager(settings, RulesetInfo); 31 | 32 | public override RulesetSettingsSubsection CreateSettings() => new SandboxSettingsSubsection(this); 33 | 34 | public override string Description => "Sandbox"; 35 | 36 | public override string ShortName => "sandbox"; 37 | 38 | public override string PlayingVerb => "Sandboxing"; 39 | 40 | public override Drawable CreateIcon() => new SandboxIcon(this); 41 | 42 | public override IEnumerable GetModsFor(ModType type) => Array.Empty(); 43 | 44 | public override IEnumerable GetDefaultKeyBindings(int variant = 0) => new[] 45 | { 46 | new KeyBinding(InputKey.Up, SandboxAction.NumbersUp), 47 | new KeyBinding(InputKey.Down, SandboxAction.NumbersDown), 48 | new KeyBinding(InputKey.Left, SandboxAction.NumbersLeft), 49 | new KeyBinding(InputKey.Right, SandboxAction.NumbersRight), 50 | new KeyBinding(InputKey.Z, SandboxAction.FlappyJump), 51 | new KeyBinding(InputKey.X, SandboxAction.FlappyJump) 52 | }; 53 | 54 | protected override IEnumerable GetValidHitResults() => new[] 55 | { 56 | HitResult.Perfect 57 | }; 58 | 59 | public override DifficultyCalculator CreateDifficultyCalculator(IWorkingBeatmap beatmap) => new SandboxDifficultyCalculator(RulesetInfo, beatmap); 60 | 61 | private partial class SandboxIcon : Sprite 62 | { 63 | private readonly SandboxRuleset ruleset; 64 | 65 | public SandboxIcon(SandboxRuleset ruleset) 66 | { 67 | this.ruleset = ruleset; 68 | } 69 | 70 | [BackgroundDependencyLoader] 71 | private void load(GameHost host) 72 | { 73 | Texture = new TextureStore(host.Renderer, new TextureLoaderStore(ruleset.CreateResourceStore()), false).Get("Textures/Icons/Sandbox"); 74 | } 75 | } 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Sandbox/Screens/FlappyDon/Components/Backdrop.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using osu.Framework.Graphics; 3 | using osu.Framework.Graphics.Containers; 4 | using osu.Framework.Graphics.Sprites; 5 | using osuTK; 6 | 7 | namespace osu.Game.Rulesets.Sandbox.Screens.FlappyDon.Components 8 | { 9 | public class Backdrop : Container 10 | { 11 | public bool Running { get; private set; } 12 | 13 | private Vector2 lastSize; 14 | private readonly Func createSprite; 15 | private readonly double duration; 16 | 17 | public Backdrop(Func createSprite, double duration = 2000.0f) 18 | { 19 | this.createSprite = createSprite; 20 | this.duration = duration; 21 | 22 | RelativeSizeAxes = Axes.Both; 23 | Add(createSprite()); 24 | } 25 | 26 | protected override void LoadComplete() 27 | { 28 | base.LoadComplete(); 29 | updateLayout(); 30 | } 31 | 32 | protected override void UpdateAfterChildren() 33 | { 34 | base.UpdateAfterChildren(); 35 | 36 | if (!DrawSize.Equals(lastSize)) 37 | { 38 | updateLayout(); 39 | lastSize = DrawSize; 40 | } 41 | } 42 | 43 | /// 44 | /// Start animating the child sprites across the screen 45 | /// 46 | public void Start() 47 | { 48 | if (Running) 49 | return; 50 | 51 | Running = true; 52 | 53 | if (!IsLoaded) 54 | return; 55 | 56 | updateLayout(); 57 | } 58 | 59 | /// 60 | /// Cancel the animations, but leave all sprites in place. 61 | /// 62 | public void Freeze() 63 | { 64 | if (!Running || !IsLoaded) 65 | return; 66 | 67 | Running = false; 68 | 69 | if (!IsLoaded) 70 | return; 71 | 72 | stopAnimatingChildren(); 73 | } 74 | 75 | private void updateLayout() 76 | { 77 | // Get an initial sprite we can use to derive size 78 | var sprite = Children[0]; 79 | 80 | // Work out how many copies are needed to horizontally fill the screen 81 | var spriteNum = (int)Math.Ceiling(DrawWidth / sprite.DrawWidth) + 1; 82 | 83 | // If the number needed is higher or lower than the current number of child sprites, add/remove the amount needed for them to match 84 | if (spriteNum != Children.Count) 85 | { 86 | // Update the number of sprites in the list to match the number we need to cover the whole container 87 | while (Children.Count > spriteNum) 88 | Remove(Children[Children.Count - 1], true); 89 | 90 | while (Children.Count < spriteNum) 91 | Add(createSprite()); 92 | } 93 | 94 | // Lay out all of the child sprites horizontally, and assign a looping pan animation to create the effect of constant scrolling 95 | var offset = 0f; 96 | 97 | foreach (var childSprite in Children) 98 | { 99 | var width = childSprite.DrawWidth; 100 | childSprite.X = offset; 101 | 102 | if (Running) 103 | childSprite.Loop(b => b.MoveToX(offset).Then().MoveToX(offset - width, duration)); 104 | 105 | offset += width; 106 | } 107 | } 108 | 109 | private void stopAnimatingChildren() => ClearTransforms(true); 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Sandbox/Screens/FlappyDon/Components/BackgroundSprite.cs: -------------------------------------------------------------------------------- 1 | using osu.Framework.Allocation; 2 | using osu.Framework.Graphics; 3 | using osu.Framework.Graphics.Sprites; 4 | using osu.Framework.Graphics.Textures; 5 | using osuTK; 6 | 7 | namespace osu.Game.Rulesets.Sandbox.Screens.FlappyDon.Components 8 | { 9 | public partial class BackgroundSprite : Sprite 10 | { 11 | private Vector2 textureSize; 12 | 13 | [BackgroundDependencyLoader] 14 | private void load(TextureStore textures) 15 | { 16 | Texture = textures.Get("FlappyDon/bg", WrapMode.ClampToBorder, WrapMode.ClampToBorder); 17 | textureSize = Texture.Size; 18 | RelativeSizeAxes = Axes.Y; 19 | Height = 1.0f; 20 | EdgeSmoothness = Vector2.One; 21 | } 22 | 23 | protected override void Update() 24 | { 25 | base.Update(); 26 | Width = DrawHeight * textureSize.X / textureSize.Y; 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Sandbox/Screens/FlappyDon/Components/Bird.cs: -------------------------------------------------------------------------------- 1 | using osu.Framework.Allocation; 2 | using osu.Framework.Audio.Sample; 3 | using osu.Framework.Graphics; 4 | using osu.Framework.Graphics.Animations; 5 | using osu.Framework.Graphics.Containers; 6 | using osu.Framework.Graphics.Primitives; 7 | using osu.Framework.Graphics.Textures; 8 | using osuTK; 9 | 10 | namespace osu.Game.Rulesets.Sandbox.Screens.FlappyDon.Components 11 | { 12 | public class Bird : CompositeDrawable 13 | { 14 | public float GroundY = 0.0f; 15 | 16 | /// 17 | /// Will return true once the bird has passed the GroundY value. 18 | /// 19 | public bool IsTouchingGround { get; private set; } 20 | 21 | /// 22 | /// The quad value representing this sprite for collision purposes. 23 | /// 24 | public Quad CollisionQuad 25 | { 26 | get 27 | { 28 | // Because the quad is rotated 45 degrees during animation and the collision 29 | // event occurs when even the corner touches, shrink the collision box 30 | // so that it more accurately matches the bounds of the character on-screen. 31 | RectangleF rect = ScreenSpaceDrawQuad.AABBFloat; 32 | rect = rect.Shrink(new Vector2(rect.Width * 0.3f, rect.Height * 0.2f)); 33 | return Quad.FromRectangle(rect); 34 | } 35 | } 36 | 37 | private TextureAnimation animation; 38 | 39 | [Resolved] 40 | private TextureStore textures { get; set; } 41 | 42 | private Sample flapSound; 43 | 44 | private bool isIdle; 45 | 46 | private float currentVelocity; 47 | 48 | [BackgroundDependencyLoader] 49 | private void load(ISampleStore samples) 50 | { 51 | Anchor = Anchor.CentreLeft; 52 | Origin = Anchor.Centre; 53 | Position = new Vector2(120.0f, .0f); 54 | 55 | animation = new TextureAnimation 56 | { 57 | Origin = Anchor.Centre, 58 | Anchor = Anchor.Centre, 59 | }; 60 | 61 | animation.AddFrame(textures.Get("FlappyDon/redbird-upflap"), 200.0f); 62 | animation.AddFrame(textures.Get("FlappyDon/redbird-downflap"), 200.0f); 63 | animation.AddFrame(textures.Get("FlappyDon/redbird-midflap"), 200.0f); 64 | 65 | AddInternal(animation); 66 | flapSound = samples.Get("flap"); 67 | 68 | Size = animation.Size; 69 | Scale = new Vector2(0.45f); 70 | } 71 | 72 | protected override void LoadComplete() 73 | { 74 | base.LoadComplete(); 75 | Reset(); 76 | } 77 | 78 | /// 79 | /// Reset the animation and rotation state of the bird. 80 | /// 81 | public void Reset() 82 | { 83 | isIdle = true; 84 | IsTouchingGround = false; 85 | ClearTransforms(); 86 | Rotation = 0.0f; 87 | Y = -60.0f; 88 | animation.IsPlaying = true; 89 | this.Loop(b => b.MoveToOffset(new Vector2(0.0f, -20.0f), 1000.0f, Easing.InOutSine) 90 | .Then() 91 | .MoveToOffset(new Vector2(0.0f, 20.0f), 1000.0f, Easing.InOutSine) 92 | ); 93 | } 94 | 95 | /// 96 | /// Halt all animations and velocity so the bird will promptly start falling. 97 | /// 98 | public void FallDown() 99 | { 100 | currentVelocity = 0.0f; 101 | animation.IsPlaying = false; 102 | animation.GotoFrame(2); 103 | } 104 | 105 | /// 106 | /// Called on each screen tap, increment the velocity slightly to make the bird fly up vertically. 107 | /// 108 | public void FlyUp() 109 | { 110 | if (isIdle) 111 | { 112 | isIdle = false; 113 | ClearTransforms(); 114 | } 115 | 116 | animation.GotoFrame(0); 117 | 118 | currentVelocity = 70.0f; 119 | this.RotateTo(-45.0f).Then(350.0f).RotateTo(90.0f, 500.0f); 120 | flapSound.Play(); 121 | } 122 | 123 | protected override void Update() 124 | { 125 | base.Update(); 126 | 127 | if (isIdle) 128 | return; 129 | 130 | if (IsTouchingGround) 131 | return; 132 | 133 | currentVelocity -= (float)Clock.ElapsedFrameTime * 0.22f; 134 | Y -= currentVelocity * (float)Clock.ElapsedFrameTime * 0.01f; 135 | 136 | if (Y >= GroundY - FlappyDonGame.SIZE.Y / 2) 137 | { 138 | IsTouchingGround = true; 139 | ClearTransforms(); 140 | } 141 | } 142 | } 143 | } 144 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Sandbox/Screens/FlappyDon/Components/FlappyDonScalingContainer.cs: -------------------------------------------------------------------------------- 1 | using osu.Framework.Graphics; 2 | using osu.Framework.Graphics.Containers; 3 | using osuTK; 4 | 5 | namespace osu.Game.Rulesets.Sandbox.Screens.FlappyDon.Components 6 | { 7 | public class FlappyDonScalingContainer : Container 8 | { 9 | protected override Container Content => content; 10 | 11 | private readonly Container content; 12 | private readonly Vector2 size; 13 | 14 | public FlappyDonScalingContainer(Vector2 size) 15 | { 16 | this.size = size; 17 | 18 | RelativeSizeAxes = Axes.Both; 19 | InternalChild = content = new Container 20 | { 21 | Anchor = Anchor.Centre, 22 | Origin = Anchor.Centre, 23 | Masking = true, 24 | Size = size 25 | }; 26 | } 27 | 28 | protected override void Update() 29 | { 30 | base.Update(); 31 | content.Scale = DrawWidth / DrawHeight < size.X / size.Y ? new Vector2(DrawWidth / size.X) : new Vector2(DrawHeight / size.Y); 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Sandbox/Screens/FlappyDon/Components/GroundSprite.cs: -------------------------------------------------------------------------------- 1 | using osu.Framework.Allocation; 2 | using osu.Framework.Graphics; 3 | using osu.Framework.Graphics.Sprites; 4 | using osu.Framework.Graphics.Textures; 5 | using osuTK; 6 | 7 | namespace osu.Game.Rulesets.Sandbox.Screens.FlappyDon.Components 8 | { 9 | public partial class GroundSprite : Sprite 10 | { 11 | private Vector2 textureSize; 12 | 13 | public GroundSprite() 14 | { 15 | Anchor = Anchor.BottomLeft; 16 | Origin = Anchor.BottomLeft; 17 | } 18 | 19 | [BackgroundDependencyLoader] 20 | private void load(TextureStore textures) 21 | { 22 | Texture = textures.Get("FlappyDon/ground", WrapMode.ClampToBorder, WrapMode.ClampToBorder); 23 | textureSize = Texture.Size; 24 | Height = FlappyDonGame.GROUND_HEIGHT; 25 | } 26 | 27 | protected override void Update() 28 | { 29 | base.Update(); 30 | Width = DrawHeight * textureSize.X / textureSize.Y; 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Sandbox/Screens/FlappyDon/Components/PipeObstacle.cs: -------------------------------------------------------------------------------- 1 | using osu.Framework.Allocation; 2 | using osu.Framework.Extensions.PolygonExtensions; 3 | using osu.Framework.Graphics; 4 | using osu.Framework.Graphics.Containers; 5 | using osu.Framework.Graphics.Primitives; 6 | using osuTK; 7 | 8 | namespace osu.Game.Rulesets.Sandbox.Screens.FlappyDon.Components 9 | { 10 | public class PipeObstacle : CompositeDrawable 11 | { 12 | /// 13 | /// The vertical offset from the middle of the screen to denote the default vertical position of the gap in the pipes. 14 | /// 15 | public float VerticalPositionAdjust = -130.0f; 16 | 17 | private PipeSprite topPipe; 18 | private PipeSprite bottomPipe; 19 | 20 | public PipeObstacle() 21 | { 22 | Anchor = Anchor.CentreLeft; 23 | Origin = Anchor.CentreLeft; 24 | 25 | RelativeSizeAxes = Axes.Y; 26 | AutoSizeAxes = Axes.X; 27 | } 28 | 29 | [BackgroundDependencyLoader] 30 | private void load() 31 | { 32 | // Rotate the top pipe 180 degrees and flip it horizontally so the shading matches the bottom pipe. 33 | topPipe = new PipeSprite 34 | { 35 | Anchor = Anchor.Centre, 36 | Origin = Anchor.TopCentre, 37 | Rotation = 180.0f, 38 | Position = new Vector2(0.0f, -110 + VerticalPositionAdjust), 39 | }; 40 | 41 | topPipe.Scale = new Vector2(-topPipe.Scale.X, topPipe.Scale.Y); 42 | 43 | AddInternal(topPipe); 44 | 45 | bottomPipe = new PipeSprite 46 | { 47 | Anchor = Anchor.Centre, 48 | Origin = Anchor.TopCentre, 49 | Position = new Vector2(0.0f, 110 + VerticalPositionAdjust) 50 | }; 51 | 52 | AddInternal(bottomPipe); 53 | } 54 | 55 | public bool CheckCollision(Quad birdQuad) 56 | { 57 | // Extend the top pipe bounds upwards so it's not possible to simply fly over it. 58 | RectangleF topPipeRect = topPipe.ScreenSpaceDrawQuad.AABBFloat; 59 | topPipeRect.Y -= 5000.0f; 60 | topPipeRect.Height += 5000.0f; 61 | Quad topPipeQuad = Quad.FromRectangle(topPipeRect); 62 | 63 | // Bird touched the top pipe 64 | if (birdQuad.Intersects(topPipeQuad)) 65 | return true; 66 | 67 | // Bird touched the bottom pipe 68 | if (birdQuad.Intersects(bottomPipe.ScreenSpaceDrawQuad)) 69 | return true; 70 | 71 | return false; 72 | } 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Sandbox/Screens/FlappyDon/Components/PipeSprite.cs: -------------------------------------------------------------------------------- 1 | using osu.Framework.Allocation; 2 | using osu.Framework.Graphics; 3 | using osu.Framework.Graphics.Sprites; 4 | using osu.Framework.Graphics.Textures; 5 | using osuTK; 6 | 7 | namespace osu.Game.Rulesets.Sandbox.Screens.FlappyDon.Components 8 | { 9 | public class PipeSprite : Sprite 10 | { 11 | public PipeSprite() 12 | { 13 | Anchor = Anchor.BottomCentre; 14 | Origin = Anchor.BottomCentre; 15 | Scale = new Vector2(4.1f); 16 | } 17 | 18 | [BackgroundDependencyLoader] 19 | private void load(TextureStore textures) 20 | { 21 | Texture = textures.Get("FlappyDon/pipe"); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Sandbox/Screens/FlappyDon/FlappyDonScreen.cs: -------------------------------------------------------------------------------- 1 | using osu.Framework.Allocation; 2 | using osu.Framework.Graphics; 3 | using osu.Game.Rulesets.Sandbox.Extensions; 4 | using osu.Game.Rulesets.Sandbox.Screens.FlappyDon.Components; 5 | 6 | namespace osu.Game.Rulesets.Sandbox.Screens.FlappyDon 7 | { 8 | public partial class FlappyDonScreen : SandboxScreen 9 | { 10 | [BackgroundDependencyLoader] 11 | private void load(RulesetStore rulesetStore) 12 | { 13 | AddInternal(new SandboxInputManager(rulesetStore.GetThisRuleset().RulesetInfo) 14 | { 15 | RelativeSizeAxes = Axes.Both, 16 | Child = new FlappyDonGame() 17 | }); 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Sandbox/Screens/Main/Components/SandboxButtonSystem.cs: -------------------------------------------------------------------------------- 1 | using osu.Framework.Graphics; 2 | using osu.Framework.Graphics.Containers; 3 | using osu.Game.Graphics.Containers; 4 | using osuTK; 5 | 6 | namespace osu.Game.Rulesets.Sandbox.Screens.Main.Components 7 | { 8 | public class SandboxButtonSystem : CompositeDrawable 9 | { 10 | public SandboxPanel[] Buttons 11 | { 12 | set => buttonsFlow.Children = value; 13 | } 14 | 15 | private readonly FillFlowContainer buttonsFlow; 16 | 17 | public SandboxButtonSystem() 18 | { 19 | RelativeSizeAxes = Axes.Both; 20 | InternalChild = new OsuScrollContainer(Direction.Horizontal) 21 | { 22 | RelativeSizeAxes = Axes.Both, 23 | Height = 0.7f, 24 | Anchor = Anchor.Centre, 25 | Origin = Anchor.Centre, 26 | ScrollbarVisible = false, 27 | Masking = false, 28 | Child = buttonsFlow = new FillFlowContainer 29 | { 30 | RelativeSizeAxes = Axes.Y, 31 | AutoSizeAxes = Axes.X, 32 | Direction = FillDirection.Horizontal, 33 | Spacing = new Vector2(20, 0) 34 | } 35 | }; 36 | } 37 | 38 | protected override void Update() 39 | { 40 | base.Update(); 41 | buttonsFlow.Margin = new MarginPadding { Horizontal = DrawWidth / 2 - SandboxPanel.WIDTH / 2 }; 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Sandbox/Screens/Main/Components/SandboxPanel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using osu.Framework.Allocation; 3 | using osu.Framework.Extensions.Color4Extensions; 4 | using osu.Framework.Graphics; 5 | using osu.Framework.Graphics.Colour; 6 | using osu.Framework.Graphics.Containers; 7 | using osu.Framework.Graphics.Effects; 8 | using osu.Framework.Graphics.Shapes; 9 | using osu.Framework.Graphics.Sprites; 10 | using osu.Framework.Graphics.Textures; 11 | using osu.Framework.Input.Events; 12 | using osu.Game.Graphics; 13 | using osu.Game.Graphics.Containers; 14 | using osu.Game.Graphics.Sprites; 15 | using osuTK; 16 | using osuTK.Graphics; 17 | 18 | namespace osu.Game.Rulesets.Sandbox.Screens.Main.Components 19 | { 20 | public partial class SandboxPanel : CompositeDrawable 21 | { 22 | public static readonly float WIDTH = 300; 23 | private const float reflection_idle = -120; 24 | private const float reflection_active = 0; 25 | 26 | public Action Action; 27 | 28 | [Resolved] 29 | private OsuColour colours { get; set; } 30 | 31 | private readonly string name; 32 | private readonly Creator? creator; 33 | private Box reflection; 34 | 35 | public SandboxPanel(string name, Creator? creator = null) 36 | { 37 | this.name = name; 38 | this.creator = creator; 39 | } 40 | 41 | private Sprite texture; 42 | 43 | [BackgroundDependencyLoader] 44 | private void load(TextureStore textures) 45 | { 46 | Anchor = Anchor.Centre; 47 | Origin = Anchor.Centre; 48 | RelativeSizeAxes = Axes.Y; 49 | Width = WIDTH; 50 | Masking = true; 51 | CornerRadius = 3; 52 | EdgeEffect = idle_edge_effect; 53 | InternalChildren = new Drawable[] 54 | { 55 | new Box 56 | { 57 | RelativeSizeAxes = Axes.Both, 58 | Colour = Color4.Black, 59 | Alpha = 0.5f 60 | }, 61 | new Container 62 | { 63 | RelativeSizeAxes = Axes.Both, 64 | Child = texture = new Sprite 65 | { 66 | RelativeSizeAxes = Axes.Both, 67 | Anchor = Anchor.Centre, 68 | Origin = Anchor.Centre, 69 | FillMode = FillMode.Fill, 70 | Texture = textures.Get(name), 71 | Colour = Color4.Gray 72 | } 73 | }, 74 | new OsuSpriteText 75 | { 76 | Anchor = Anchor.Centre, 77 | Origin = Anchor.Centre, 78 | Text = name, 79 | Colour = colours.Yellow, 80 | Font = OsuFont.GetFont(size: 40, weight: FontWeight.SemiBold) 81 | }, 82 | reflection = new Box 83 | { 84 | RelativeSizeAxes = Axes.Both, 85 | Width = 0.5f, 86 | Rotation = 80, 87 | Origin = Anchor.Centre, 88 | Anchor = Anchor.TopCentre, 89 | Y = reflection_idle, 90 | Alpha = 0.15f, 91 | EdgeSmoothness = Vector2.One, 92 | Colour = ColourInfo.GradientHorizontal(Color4.White.Opacity(0f), Color4.White) 93 | } 94 | }; 95 | 96 | if (!creator.HasValue) 97 | return; 98 | 99 | var linkFlow = new LinkFlowContainer(t => 100 | { 101 | t.Font = OsuFont.GetFont(size: 20); 102 | }) 103 | { 104 | AutoSizeAxes = Axes.Both, 105 | Anchor = Anchor.BottomCentre, 106 | Origin = Anchor.BottomCentre, 107 | Margin = new MarginPadding { Bottom = 25 } 108 | }; 109 | 110 | linkFlow.AddText("Created by "); 111 | linkFlow.AddLink(creator.Value.Name, creator.Value.URL); 112 | 113 | AddInternal(linkFlow); 114 | } 115 | 116 | protected override bool OnHover(HoverEvent e) 117 | { 118 | texture?.FadeColour(Color4.DarkGray, 250, Easing.OutQuint); 119 | reflection.MoveToY(reflection_active, 250, Easing.OutQuint); 120 | TweenEdgeEffectTo(hover_edge_effect, 250, Easing.OutQuint); 121 | return true; 122 | } 123 | 124 | protected override void OnHoverLost(HoverLostEvent e) 125 | { 126 | texture?.FadeColour(Color4.Gray, 250, Easing.OutQuint); 127 | reflection.MoveToY(reflection_idle, 250, Easing.OutQuint); 128 | TweenEdgeEffectTo(idle_edge_effect, 250, Easing.OutQuint); 129 | } 130 | 131 | protected override bool OnClick(ClickEvent e) 132 | { 133 | Action?.Invoke(); 134 | return true; 135 | } 136 | 137 | private static readonly EdgeEffectParameters idle_edge_effect = new EdgeEffectParameters 138 | { 139 | Radius = 10, 140 | Colour = Color4.Black.Opacity(0.5f), 141 | Type = EdgeEffectType.Shadow, 142 | Offset = Vector2.Zero 143 | }; 144 | 145 | private static readonly EdgeEffectParameters hover_edge_effect = new EdgeEffectParameters 146 | { 147 | Radius = 20, 148 | Colour = Color4.Black.Opacity(0.5f), 149 | Type = EdgeEffectType.Shadow, 150 | Offset = new Vector2(0, 3) 151 | }; 152 | } 153 | 154 | public struct Creator 155 | { 156 | public string URL { get; set; } 157 | 158 | public string Name { get; set; } 159 | } 160 | } 161 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Sandbox/Screens/Main/MainRulesetScreen.cs: -------------------------------------------------------------------------------- 1 | using osu.Framework.Allocation; 2 | using osu.Framework.Screens; 3 | using osu.Game.Rulesets.Sandbox.Extensions; 4 | using osu.Game.Rulesets.Sandbox.Screens.FlappyDon; 5 | using osu.Game.Rulesets.Sandbox.Screens.Main.Components; 6 | using osu.Game.Rulesets.Sandbox.Screens.Numbers; 7 | using osu.Game.Rulesets.Sandbox.Screens.Rulesets; 8 | using osu.Game.Rulesets.Sandbox.Screens.Visualizer; 9 | using osu.Game.Rulesets.UI; 10 | using osu.Game.Screens; 11 | 12 | namespace osu.Game.Rulesets.Sandbox.Screens.Main 13 | { 14 | public partial class MainRulesetScreen : SandboxScreen 15 | { 16 | public MainRulesetScreen() 17 | { 18 | InternalChild = new SandboxButtonSystem 19 | { 20 | Buttons = new[] 21 | { 22 | new SandboxPanel("Visualizer") { Action = () => this.Push(new VisualizerScreen()) }, 23 | new SandboxPanel("2048") { Action = () => this.Push(new NumbersScreen()) }, 24 | new SandboxPanel("FlappyDon", new Creator { Name = "Tim Oliver", URL = "https://github.com/TimOliver"}) { Action = () => this.Push(new FlappyDonScreen()) }, 25 | new SandboxPanel("Ruleset Updates") { Action = () => this.Push(new RulesetsScreen()) } 26 | } 27 | }; 28 | } 29 | 30 | protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) 31 | { 32 | var baseDependencies = new DependencyContainer(base.CreateChildDependencies(parent)); 33 | 34 | return new OsuScreenDependencies(false, new DrawableRulesetDependencies(baseDependencies.GetRuleset(), baseDependencies)); 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Sandbox/Screens/Numbers/Components/DrawableNumber.cs: -------------------------------------------------------------------------------- 1 | using osu.Framework.Graphics.Containers; 2 | using osu.Framework.Graphics; 3 | using osu.Framework.Graphics.Shapes; 4 | using osuTK.Graphics; 5 | using osuTK; 6 | using osu.Game.Graphics.Sprites; 7 | using osu.Game.Graphics; 8 | using System; 9 | using osu.Game.Graphics.Containers; 10 | using osu.Game.Beatmaps.ControlPoints; 11 | using osu.Framework.Audio.Track; 12 | 13 | namespace osu.Game.Rulesets.Sandbox.Screens.Numbers.Components 14 | { 15 | public partial class DrawableNumber : BeatSyncedContainer 16 | { 17 | public const int SIZE = 100; 18 | 19 | public int XIndex; 20 | public int YIndex; 21 | 22 | public int Power { get; private set; } 23 | 24 | public int NumericValue 25 | { 26 | get 27 | { 28 | int result = 2; 29 | 30 | for (int i = 1; i < Power; i++) 31 | result *= 2; 32 | 33 | return result; 34 | } 35 | } 36 | 37 | public bool IsBlocked; 38 | 39 | private readonly Box background; 40 | private readonly Box foreground; 41 | private readonly Container content; 42 | private readonly OsuSpriteText text; 43 | 44 | public DrawableNumber(int xIndex, int yIndex, int startPower = 1) 45 | { 46 | XIndex = xIndex; 47 | YIndex = yIndex; 48 | Power = startPower; 49 | 50 | Size = new Vector2(SIZE); 51 | Add(content = new Container 52 | { 53 | Anchor = Anchor.Centre, 54 | Origin = Anchor.Centre, 55 | RelativeSizeAxes = Axes.Both, 56 | Scale = new Vector2(0), 57 | Masking = true, 58 | CornerRadius = 4, 59 | Children = new Drawable[] 60 | { 61 | background = new Box 62 | { 63 | RelativeSizeAxes = Axes.Both 64 | }, 65 | text = new OsuSpriteText 66 | { 67 | Anchor = Anchor.Centre, 68 | Origin = Anchor.Centre, 69 | Font = OsuFont.GetFont(size: 40, weight: FontWeight.Bold), 70 | Text = NumericValue.ToString(), 71 | Colour = startPower == 3 ? Color4.White : new Color4(119, 110, 101, 255), 72 | Shadow = false, 73 | }, 74 | foreground = new Box 75 | { 76 | RelativeSizeAxes = Axes.Both, 77 | Colour = Color4.White, 78 | Alpha = 0, 79 | } 80 | } 81 | }); 82 | 83 | if (startPower != 1) 84 | background.Colour = getPowerColour(Power); 85 | } 86 | 87 | protected override void LoadComplete() 88 | { 89 | base.LoadComplete(); 90 | content.ScaleTo(1, 200, Easing.OutQuint); 91 | } 92 | 93 | public void Increment() 94 | { 95 | Power++; 96 | animate(); 97 | } 98 | 99 | protected override void OnNewBeat(int beatIndex, TimingControlPoint timingPoint, EffectControlPoint effectPoint, ChannelAmplitudes amplitudes) 100 | { 101 | base.OnNewBeat(beatIndex, timingPoint, effectPoint, amplitudes); 102 | 103 | float amplitudeAdjust = Math.Min(1, 0.4f + amplitudes.Maximum); 104 | 105 | if (beatIndex < 0) return; 106 | 107 | foreground.FadeTo(0.15f * amplitudeAdjust, 20, Easing.Out) 108 | .Then() 109 | .FadeTo(0, timingPoint.BeatLength * 2, Easing.OutQuint); 110 | } 111 | 112 | private void animate() 113 | { 114 | this.ScaleTo(1.2f, 20, Easing.OutQuint).Then().ScaleTo(1, 160, Easing.OutQuint); 115 | background.FadeColour(getPowerColour(Power), 180, Easing.OutQuint); 116 | text.Text = NumericValue.ToString(); 117 | 118 | if (Power == 3) 119 | text.Colour = Color4.White; 120 | } 121 | 122 | private Color4 getPowerColour(int newPower) 123 | { 124 | switch (newPower) 125 | { 126 | case 1: 127 | return Color4.White; 128 | 129 | case 2: 130 | return new Color4(237, 224, 200, 255); 131 | 132 | case 3: 133 | return new Color4(243, 177, 121, 255); 134 | 135 | case 4: 136 | return new Color4(245, 150, 99, 255); 137 | 138 | case 5: 139 | return new Color4(247, 124, 95, 255); 140 | 141 | case 6: 142 | return new Color4(246, 94, 60, 255); 143 | 144 | case 7: 145 | return new Color4(237, 207, 114, 255); 146 | 147 | case 8: 148 | return new Color4(236, 204, 97, 255); 149 | 150 | case 9: 151 | return new Color4(237, 199, 80, 255); 152 | 153 | case 10: 154 | return new Color4(238, 197, 63, 255); 155 | 156 | default: 157 | case 11: 158 | return new Color4(236, 194, 45, 255); 159 | } 160 | } 161 | } 162 | } 163 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Sandbox/Screens/Rulesets/Components/DrawableLatestRulesetUpdate.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using osu.Framework.Graphics; 3 | using osu.Framework.Graphics.Containers; 4 | using osu.Framework.Utils; 5 | using osu.Game.Graphics; 6 | using osu.Game.Graphics.Sprites; 7 | using osu.Game.Overlays.Settings; 8 | using osu.Game.Rulesets.Sandbox.Online; 9 | using osuTK.Graphics; 10 | 11 | namespace osu.Game.Rulesets.Sandbox.Screens.Rulesets.Components 12 | { 13 | public partial class DrawableLatestRulesetUpdate : CompositeDrawable 14 | { 15 | private readonly string url; 16 | 17 | private GetLatestReleaseRequest request; 18 | private readonly FillFlowContainer flow; 19 | private readonly UpdateButton button; 20 | 21 | public DrawableLatestRulesetUpdate(string url) 22 | { 23 | this.url = url; 24 | 25 | AutoSizeAxes = Axes.Y; 26 | RelativeSizeAxes = Axes.X; 27 | AddRangeInternal(new Drawable[] 28 | { 29 | button = new UpdateButton 30 | { 31 | Clicked = checkUpdate, 32 | Text = "Check latest update" 33 | }, 34 | flow = new FillFlowContainer 35 | { 36 | Anchor = Anchor.Centre, 37 | Origin = Anchor.Centre, 38 | AutoSizeAxes = Axes.Both, 39 | Direction = FillDirection.Horizontal, 40 | Alpha = 0f, 41 | Children = new Drawable[] 42 | { 43 | new OsuSpriteText 44 | { 45 | Anchor = Anchor.Centre, 46 | Origin = Anchor.Centre, 47 | Font = OsuFont.GetFont(weight: FontWeight.Bold), 48 | Text = "Latest update: " 49 | } 50 | } 51 | } 52 | }); 53 | } 54 | 55 | private void checkUpdate() 56 | { 57 | button.Enabled.Value = false; 58 | button.Text = "Checking..."; 59 | 60 | request?.Abort(); 61 | 62 | request = new GetLatestReleaseRequest(url); 63 | request.Finished += () => Schedule(() => 64 | { 65 | button.Hide(); 66 | 67 | TimeSpan timeSpan = DateTimeOffset.Now.Subtract(request.ResponseObject.PublishedAt); 68 | 69 | int days = Math.Clamp(timeSpan.Days, 0, 7); 70 | Color4 color = Interpolation.ValueAt(days, Color4.Red, Color4.DeepSkyBlue, 0, 7); 71 | 72 | flow.Add(new DrawableDate(request.ResponseObject.PublishedAt) 73 | { 74 | Anchor = Anchor.Centre, 75 | Origin = Anchor.Centre, 76 | Font = OsuFont.GetFont(weight: FontWeight.Bold), 77 | Colour = color 78 | }); 79 | 80 | flow.Show(); 81 | }); 82 | 83 | request.Failed += (_) => onFail(); 84 | request.PerformAsync(); 85 | } 86 | 87 | private void onFail() 88 | { 89 | Schedule(() => 90 | { 91 | button.Hide(); 92 | 93 | flow.Add(new OsuSpriteText 94 | { 95 | Anchor = Anchor.Centre, 96 | Origin = Anchor.Centre, 97 | Font = OsuFont.GetFont(weight: FontWeight.Bold), 98 | Text = "Check failed." 99 | }); 100 | 101 | flow.Show(); 102 | }); 103 | } 104 | 105 | protected override void Dispose(bool isDisposing) 106 | { 107 | request?.Abort(); 108 | base.Dispose(isDisposing); 109 | } 110 | 111 | private partial class UpdateButton : SettingsButton 112 | { 113 | public Action Clicked; 114 | 115 | public UpdateButton() 116 | { 117 | Padding = new MarginPadding(0); 118 | Action = () => Clicked?.Invoke(); 119 | } 120 | } 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Sandbox/Screens/Rulesets/Components/RulesetDownloadType.cs: -------------------------------------------------------------------------------- 1 | namespace osu.Game.Rulesets.Sandbox.Screens.Rulesets.Components 2 | { 3 | public enum RulesetDownloadType 4 | { 5 | Github, 6 | External 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Sandbox/Screens/Rulesets/Components/RulesetPanel.cs: -------------------------------------------------------------------------------- 1 | using osu.Framework.Allocation; 2 | using osu.Framework.Extensions.Color4Extensions; 3 | using osu.Framework.Graphics; 4 | using osu.Framework.Graphics.Containers; 5 | using osu.Framework.Graphics.Shapes; 6 | using osu.Framework.Graphics.Sprites; 7 | using osu.Framework.Graphics.Textures; 8 | using osu.Framework.Platform; 9 | using osu.Game.Graphics; 10 | using osu.Game.Graphics.Sprites; 11 | using osu.Game.Overlays.Settings; 12 | using osuTK; 13 | using osuTK.Graphics; 14 | 15 | namespace osu.Game.Rulesets.Sandbox.Screens.Rulesets.Components 16 | { 17 | public partial class RulesetPanel : CompositeDrawable 18 | { 19 | public RulesetPanel(string name, string updateURL, string downloadURL = "", RulesetDownloadType type = RulesetDownloadType.Github) 20 | { 21 | RelativeSizeAxes = Axes.X; 22 | Height = 120; 23 | Masking = true; 24 | CornerRadius = 10; 25 | InternalChildren = new Drawable[] 26 | { 27 | new Box 28 | { 29 | RelativeSizeAxes = Axes.Both, 30 | Colour = Color4.Black.Opacity(0.5f) 31 | }, 32 | new Container 33 | { 34 | RelativeSizeAxes = Axes.Both, 35 | Padding = new MarginPadding { Horizontal = 20 }, 36 | Children = new Drawable[] 37 | { 38 | new FillFlowContainer 39 | { 40 | AutoSizeAxes = Axes.Both, 41 | Direction = FillDirection.Horizontal, 42 | Spacing = new Vector2(15), 43 | Anchor = Anchor.CentreLeft, 44 | Origin = Anchor.CentreLeft, 45 | Children = new Drawable[] 46 | { 47 | new RulesetIcon(name) 48 | { 49 | Anchor = Anchor.Centre, 50 | Origin = Anchor.Centre, 51 | Size = new Vector2(50) 52 | }, 53 | new OsuSpriteText 54 | { 55 | Anchor = Anchor.Centre, 56 | Origin = Anchor.Centre, 57 | Text = name, 58 | Font = OsuFont.GetFont(size: 30, weight: FontWeight.Bold) 59 | } 60 | } 61 | }, 62 | new FillFlowContainer 63 | { 64 | AutoSizeAxes = Axes.Y, 65 | Width = 200, 66 | Anchor = Anchor.CentreRight, 67 | Origin = Anchor.CentreRight, 68 | Direction = FillDirection.Vertical, 69 | Spacing = new Vector2(0, 10), 70 | Children = new Drawable[] 71 | { 72 | new DrawableLatestRulesetUpdate(updateURL) 73 | { 74 | Anchor = Anchor.CentreRight, 75 | Origin = Anchor.CentreRight 76 | }, 77 | new RulesetDownloadButton(string.IsNullOrEmpty(downloadURL) ? updateURL : downloadURL, type) 78 | { 79 | Anchor = Anchor.CentreRight, 80 | Origin = Anchor.CentreRight, 81 | Text = "Download" 82 | } 83 | } 84 | } 85 | } 86 | } 87 | }; 88 | } 89 | 90 | private partial class RulesetDownloadButton : SettingsButton 91 | { 92 | private readonly string downloadURL; 93 | private readonly RulesetDownloadType type; 94 | 95 | public RulesetDownloadButton(string downloadURL, RulesetDownloadType type) 96 | { 97 | this.downloadURL = downloadURL; 98 | this.type = type; 99 | 100 | Padding = new MarginPadding(0); 101 | } 102 | 103 | [BackgroundDependencyLoader] 104 | private void load(GameHost host) 105 | { 106 | Action = () => host.OpenUrlExternally(type == RulesetDownloadType.Github ? $"https://github.com/{downloadURL}/releases/latest" : downloadURL); 107 | } 108 | } 109 | 110 | private partial class RulesetIcon : Sprite 111 | { 112 | private readonly string name; 113 | 114 | public RulesetIcon(string name) 115 | { 116 | this.name = name; 117 | } 118 | 119 | [BackgroundDependencyLoader] 120 | private void load(TextureStore textures) 121 | { 122 | Texture = textures.Get($"Icons/{name}"); 123 | if (Texture == null) 124 | Alpha = 0; 125 | } 126 | } 127 | } 128 | } 129 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Sandbox/Screens/Rulesets/RulesetsScreen.cs: -------------------------------------------------------------------------------- 1 | using osu.Framework.Graphics; 2 | using osu.Framework.Graphics.Containers; 3 | using osu.Game.Graphics.Containers; 4 | using osu.Game.Rulesets.Sandbox.Screens.Rulesets.Components; 5 | using osuTK; 6 | 7 | namespace osu.Game.Rulesets.Sandbox.Screens.Rulesets 8 | { 9 | public partial class RulesetsScreen : SandboxScreen 10 | { 11 | public RulesetsScreen() 12 | { 13 | AddInternal(new Container 14 | { 15 | RelativeSizeAxes = Axes.Both, 16 | Padding = new MarginPadding { Vertical = 10 }, 17 | Anchor = Anchor.Centre, 18 | Origin = Anchor.Centre, 19 | Width = 0.5f, 20 | Child = new OsuScrollContainer 21 | { 22 | RelativeSizeAxes = Axes.Both, 23 | Child = new FillFlowContainer 24 | { 25 | RelativeSizeAxes = Axes.X, 26 | AutoSizeAxes = Axes.Y, 27 | Direction = FillDirection.Vertical, 28 | Spacing = new Vector2(0, 10), 29 | Children = new Drawable[] 30 | { 31 | new RulesetPanel("Tau", "taulazer/tau"), 32 | new RulesetPanel("Yoso", "EVAST9919/yoso-version-tracker", "https://www.patreon.com/evast", RulesetDownloadType.External), 33 | new RulesetPanel("Bosu", "EVAST9919/bosu"), 34 | new RulesetPanel("Swing", "EVAST9919/lazer-swing"), 35 | new RulesetPanel("Touhosu", "EVAST9919/touhosu"), 36 | new RulesetPanel("Sandbox", "EVAST9919/lazer-sandbox"), 37 | new RulesetPanel("Karaoke", "karaoke-dev/karaoke"), 38 | new RulesetPanel("soyokaze!", "goodtrailer/soyokaze"), 39 | new RulesetPanel("sentakki", "LumpBloom7/sentakki"), 40 | new RulesetPanel("osu!DIVA", "Artemis-chan/osu-DIVA"), 41 | new RulesetPanel("Hitokori", "Flutterish/Hitokori"), 42 | new RulesetPanel("gamebosu", "Game4all/gamebosu"), 43 | new RulesetPanel("Hishigata", "LumpBloom7/hishigata") 44 | } 45 | } 46 | } 47 | }); 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Sandbox/Screens/SandboxScreen.cs: -------------------------------------------------------------------------------- 1 | using osu.Framework.Graphics; 2 | using osu.Framework.Screens; 3 | using osu.Game.Beatmaps; 4 | using osu.Game.Screens.Play; 5 | 6 | namespace osu.Game.Rulesets.Sandbox.Screens 7 | { 8 | public abstract class SandboxScreen : ScreenWithBeatmapBackground 9 | { 10 | protected override void LoadComplete() 11 | { 12 | base.LoadComplete(); 13 | 14 | Beatmap.BindValueChanged(b => updateComponentFromBeatmap(b.NewValue)); 15 | } 16 | 17 | public override void OnEntering(ScreenTransitionEvent e) 18 | { 19 | base.OnEntering(e); 20 | this.FadeInFromZero(250, Easing.OutQuint); 21 | updateComponentFromBeatmap(Beatmap.Value); 22 | } 23 | 24 | public override bool OnExiting(ScreenExitEvent e) 25 | { 26 | this.FadeOut(250, Easing.OutQuint); 27 | return base.OnExiting(e); 28 | } 29 | 30 | public override void OnResuming(ScreenTransitionEvent e) 31 | { 32 | base.OnResuming(e); 33 | this.FadeIn(250, Easing.OutQuint); 34 | } 35 | 36 | public override void OnSuspending(ScreenTransitionEvent e) 37 | { 38 | base.OnSuspending(e); 39 | this.FadeOut(250, Easing.OutQuint); 40 | } 41 | 42 | private void updateComponentFromBeatmap(WorkingBeatmap beatmap) 43 | { 44 | ApplyToBackground(b => 45 | { 46 | b.IgnoreUserSettings.Value = false; 47 | b.Beatmap = beatmap; 48 | }); 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Sandbox/Screens/SandboxScreenWithSettings.cs: -------------------------------------------------------------------------------- 1 | using osu.Framework.Bindables; 2 | using osu.Framework.Graphics; 3 | using osu.Framework.Graphics.Containers; 4 | using osu.Framework.Input.Events; 5 | using osu.Game.Rulesets.Sandbox.UI.Settings; 6 | 7 | namespace osu.Game.Rulesets.Sandbox.Screens 8 | { 9 | public abstract class SandboxScreenWithSettings : SandboxScreen 10 | { 11 | private readonly SandboxSettings settings; 12 | protected readonly BindableBool SettingsVisible = new BindableBool(); 13 | 14 | public SandboxScreenWithSettings() 15 | { 16 | AddRangeInternal(new Drawable[] 17 | { 18 | CreateBackground(), 19 | new GridContainer 20 | { 21 | RelativeSizeAxes = Axes.Both, 22 | RowDimensions = new[] 23 | { 24 | new Dimension() 25 | }, 26 | ColumnDimensions = new[] 27 | { 28 | new Dimension(), 29 | new Dimension(GridSizeMode.AutoSize) 30 | }, 31 | Content = new[] 32 | { 33 | new Drawable[] 34 | { 35 | new Container 36 | { 37 | RelativeSizeAxes = Axes.Both, 38 | Child = CreateContent() 39 | }, 40 | settings = new SandboxSettings 41 | { 42 | Sections = CreateSettingsSections() 43 | } 44 | } 45 | } 46 | } 47 | }); 48 | 49 | SettingsVisible.BindTo(settings.IsVisible); 50 | } 51 | 52 | protected abstract Drawable CreateContent(); 53 | 54 | protected new abstract Drawable CreateBackground(); 55 | 56 | protected abstract SandboxSettingsSection[] CreateSettingsSections(); 57 | 58 | protected override bool OnMouseMove(MouseMoveEvent e) 59 | { 60 | base.OnMouseMove(e); 61 | 62 | if (SettingsVisible.Value) 63 | return false; 64 | 65 | var cursorPosition = ToLocalSpace(e.CurrentState.Mouse.Position); 66 | 67 | if (cursorPosition.X > DrawWidth - 5) 68 | { 69 | SettingsVisible.Value = true; 70 | return true; 71 | } 72 | 73 | return false; 74 | } 75 | 76 | protected override bool OnClick(ClickEvent e) 77 | { 78 | if (!SettingsVisible.Value) 79 | return false; 80 | 81 | SettingsVisible.Value = false; 82 | return true; 83 | } 84 | 85 | protected override void Dispose(bool isDisposing) 86 | { 87 | SettingsVisible.UnbindFrom(settings.IsVisible); 88 | base.Dispose(isDisposing); 89 | } 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Sandbox/Screens/Shooter/ShooterPlayer.cs: -------------------------------------------------------------------------------- 1 | using osu.Framework.Graphics.Containers; 2 | using osu.Framework.Graphics; 3 | using osuTK; 4 | using osu.Framework.Graphics.Shapes; 5 | using osuTK.Graphics; 6 | 7 | namespace osu.Game.Rulesets.Sandbox.Screens.Shooter 8 | { 9 | public class ShooterPlayer : CompositeDrawable 10 | { 11 | public ShooterPlayer() 12 | { 13 | Anchor = Anchor.Centre; 14 | Origin = Anchor.Centre; 15 | Size = new Vector2(30); 16 | InternalChildren = new Drawable[] 17 | { 18 | new Circle 19 | { 20 | RelativeSizeAxes = Axes.Both, 21 | Colour = Color4.White 22 | }, 23 | new Circle 24 | { 25 | Anchor = Anchor.TopCentre, 26 | Origin = Anchor.TopCentre, 27 | Size = new Vector2(10), 28 | Colour = Color4.Black 29 | } 30 | }; 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Sandbox/Screens/Visualizer/Components/LayoutController.cs: -------------------------------------------------------------------------------- 1 | using osu.Framework.Allocation; 2 | using osu.Framework.Bindables; 3 | using osu.Framework.Graphics.Containers; 4 | using osu.Framework.Graphics; 5 | using osu.Game.Rulesets.Sandbox.Configuration; 6 | using osu.Game.Rulesets.Sandbox.Screens.Visualizer.Components.Layouts; 7 | 8 | namespace osu.Game.Rulesets.Sandbox.Screens.Visualizer.Components 9 | { 10 | public class LayoutController : CompositeDrawable 11 | { 12 | private readonly Bindable layoutBinable = new Bindable(); 13 | 14 | [BackgroundDependencyLoader] 15 | private void load(SandboxRulesetConfigManager config) 16 | { 17 | RelativeSizeAxes = Axes.Both; 18 | config?.BindWith(SandboxRulesetSetting.VisualizerLayout, layoutBinable); 19 | } 20 | 21 | protected override void LoadComplete() 22 | { 23 | base.LoadComplete(); 24 | layoutBinable.BindValueChanged(_ => updateLayout(), true); 25 | } 26 | 27 | private void updateLayout() 28 | { 29 | DrawableVisualizerLayout l; 30 | 31 | switch(layoutBinable.Value) 32 | { 33 | default: 34 | case VisualizerLayout.TypeA: 35 | l = new TypeALayout(); 36 | break; 37 | 38 | case VisualizerLayout.TypeB: 39 | l = new TypeBLayout(); 40 | break; 41 | 42 | case VisualizerLayout.Empty: 43 | l = new EmptyLayout(); 44 | break; 45 | } 46 | 47 | loadLayout(l); 48 | } 49 | 50 | private void loadLayout(DrawableVisualizerLayout layout) 51 | { 52 | InternalChild = layout; 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Sandbox/Screens/Visualizer/Components/Layouts/DrawableVisualizerLayout.cs: -------------------------------------------------------------------------------- 1 | using osu.Framework.Graphics.Containers; 2 | using osu.Framework.Graphics; 3 | 4 | namespace osu.Game.Rulesets.Sandbox.Screens.Visualizer.Components.Layouts 5 | { 6 | public abstract class DrawableVisualizerLayout : CompositeDrawable 7 | { 8 | public DrawableVisualizerLayout() 9 | { 10 | RelativeSizeAxes = Axes.Both; 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Sandbox/Screens/Visualizer/Components/Layouts/EmptyLayout.cs: -------------------------------------------------------------------------------- 1 | namespace osu.Game.Rulesets.Sandbox.Screens.Visualizer.Components.Layouts 2 | { 3 | public class EmptyLayout : DrawableVisualizerLayout 4 | { 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Sandbox/Screens/Visualizer/Components/Layouts/TypeA/CircularBeatmapLogo.cs: -------------------------------------------------------------------------------- 1 | using osu.Framework.Allocation; 2 | using osu.Framework.Bindables; 3 | using osu.Framework.Graphics; 4 | using osu.Framework.Graphics.Containers; 5 | using osu.Framework.Graphics.UserInterface; 6 | using osu.Game.Rulesets.Sandbox.Screens.Visualizer.Components.MusicHelpers; 7 | using osuTK; 8 | using osuTK.Graphics; 9 | 10 | namespace osu.Game.Rulesets.Sandbox.Screens.Visualizer.Components.Layouts.TypeA 11 | { 12 | public partial class CircularBeatmapLogo : CurrentBeatmapProvider 13 | { 14 | private const int base_size = 350; 15 | private const int progress_padding = 10; 16 | 17 | public Color4 ProgressColour 18 | { 19 | get => progress.Colour; 20 | set => progress.Colour = value; 21 | } 22 | 23 | public new Bindable Size = new Bindable(base_size); 24 | 25 | private CircularProgress progress; 26 | private Container progressWrapper; 27 | 28 | [BackgroundDependencyLoader] 29 | private void load() 30 | { 31 | Origin = Anchor.Centre; 32 | RelativePositionAxes = Axes.Both; 33 | 34 | InternalChildren = new Drawable[] 35 | { 36 | new UpdateableBeatmapBackground 37 | { 38 | RelativeSizeAxes = Axes.Both, 39 | Anchor = Anchor.Centre, 40 | Origin = Anchor.Centre, 41 | }, 42 | progressWrapper = new Container 43 | { 44 | RelativeSizeAxes = Axes.Both, 45 | Child = progress = new CircularProgress 46 | { 47 | Anchor = Anchor.Centre, 48 | Origin = Anchor.Centre, 49 | RelativeSizeAxes = Axes.Both, 50 | InnerRadius = 0.03f, 51 | } 52 | } 53 | }; 54 | } 55 | 56 | protected override void LoadComplete() 57 | { 58 | base.LoadComplete(); 59 | 60 | Size.BindValueChanged(s => 61 | { 62 | base.Size = new Vector2(s.NewValue); 63 | progressWrapper.Padding = new MarginPadding(progress_padding * s.NewValue / base_size); 64 | }, true); 65 | } 66 | 67 | protected override void Update() 68 | { 69 | base.Update(); 70 | 71 | var track = Beatmap.Value?.Track; 72 | progress.Progress = (track == null || track.Length == 0) ? 0 : (track.CurrentTime / track.Length); 73 | } 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Sandbox/Screens/Visualizer/Components/Layouts/TypeA/TypeAVisualizerController.cs: -------------------------------------------------------------------------------- 1 | using osu.Framework.Graphics; 2 | using osu.Framework.Bindables; 3 | using osu.Framework.Allocation; 4 | using System; 5 | using osuTK; 6 | using osu.Game.Rulesets.Sandbox.Screens.Visualizer.Components.MusicHelpers; 7 | using osu.Game.Rulesets.Sandbox.Configuration; 8 | using osu.Game.Rulesets.Sandbox.Screens.Visualizer.Components.Visualizers; 9 | using osu.Game.Rulesets.Sandbox.Screens.Visualizer.Components.Visualizers.Circular; 10 | 11 | namespace osu.Game.Rulesets.Sandbox.Screens.Visualizer.Components.Layouts.TypeA 12 | { 13 | public class TypeAVisualizerController : MusicAmplitudesProvider 14 | { 15 | [Resolved(canBeNull: true)] 16 | private SandboxRulesetConfigManager config { get; set; } 17 | 18 | private readonly Bindable visuals = new Bindable(3); 19 | private readonly Bindable barWidth = new Bindable(1.0); 20 | private readonly Bindable totalBarCount = new Bindable(3500); 21 | private readonly Bindable rotation = new Bindable(0); 22 | private readonly Bindable decay = new Bindable(200); 23 | private readonly Bindable multiplier = new Bindable(400); 24 | private readonly Bindable type = new Bindable(CircularBarType.Basic); 25 | private readonly Bindable symmetry = new Bindable(true); 26 | private readonly Bindable smoothness = new Bindable(); 27 | 28 | [BackgroundDependencyLoader] 29 | private void load() 30 | { 31 | Origin = Anchor.Centre; 32 | Size = new Vector2(348); 33 | RelativePositionAxes = Axes.Both; 34 | 35 | config?.BindWith(SandboxRulesetSetting.VisualizerAmount, visuals); 36 | config?.BindWith(SandboxRulesetSetting.BarWidthA, barWidth); 37 | config?.BindWith(SandboxRulesetSetting.BarsPerVisual, totalBarCount); 38 | config?.BindWith(SandboxRulesetSetting.Rotation, rotation); 39 | config?.BindWith(SandboxRulesetSetting.CircularBarType, type); 40 | config?.BindWith(SandboxRulesetSetting.DecayA, decay); 41 | config?.BindWith(SandboxRulesetSetting.MultiplierA, multiplier); 42 | config?.BindWith(SandboxRulesetSetting.Symmetry, symmetry); 43 | config?.BindWith(SandboxRulesetSetting.SmoothnessA, smoothness); 44 | } 45 | 46 | protected override void LoadComplete() 47 | { 48 | base.LoadComplete(); 49 | 50 | rotation.BindValueChanged(e => Rotation = e.NewValue + (symmetry.Value ? 180f / visuals.Value : 0)); 51 | totalBarCount.BindValueChanged(_ => updateBarCount()); 52 | visuals.BindValueChanged(_ => updateVisuals()); 53 | symmetry.BindValueChanged(_ => updateVisuals()); 54 | type.BindValueChanged(_ => updateVisuals(), true); 55 | } 56 | 57 | private void updateVisuals() 58 | { 59 | Clear(); 60 | 61 | var degree = 360f / trueVisualsCount; 62 | 63 | for (int i = 0; i < trueVisualsCount; i++) 64 | { 65 | Add(createVisualizer().With(v => 66 | { 67 | v.Anchor = Anchor.Centre; 68 | v.Origin = Anchor.Centre; 69 | v.RelativeSizeAxes = Axes.Both; 70 | v.Rotation = i * degree; 71 | v.DegreeValue.Value = degree; 72 | v.BarWidth.BindTo(barWidth); 73 | v.Decay.BindTo(decay); 74 | v.HeightMultiplier.BindTo(multiplier); 75 | v.Smoothness.BindTo(smoothness); 76 | 77 | if (symmetry.Value) 78 | v.Reversed.Value = i % 2 == 0; 79 | })); 80 | } 81 | 82 | updateBarCount(); 83 | rotation.TriggerChange(); 84 | } 85 | 86 | private CircularMusicVisualizerDrawable createVisualizer() 87 | { 88 | switch (type.Value) 89 | { 90 | default: 91 | case CircularBarType.Basic: 92 | return new BasicMusicVisualizerDrawable(); 93 | 94 | case CircularBarType.Rounded: 95 | return new RoundedMusicVisualizerDrawable(); 96 | 97 | case CircularBarType.Fall: 98 | return new FallMusicVisualizerDrawable(); 99 | 100 | case CircularBarType.Dots: 101 | return new DotsMusicVisualizerDrawable(); 102 | } 103 | } 104 | 105 | private void updateBarCount() 106 | { 107 | var barsPerVis = (int)Math.Round((float)totalBarCount.Value / trueVisualsCount); 108 | 109 | foreach (var c in Children) 110 | ((MusicVisualizerDrawable)c).BarCount.Value = barsPerVis; 111 | } 112 | 113 | protected override void OnAmplitudesUpdate(float[] amplitudes) 114 | { 115 | foreach (var c in Children) 116 | ((MusicVisualizerDrawable)c).SetAmplitudes(amplitudes); 117 | } 118 | 119 | private int trueVisualsCount => visuals.Value * (symmetry.Value ? 2 : 1); 120 | } 121 | } 122 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Sandbox/Screens/Visualizer/Components/Layouts/TypeALayout.cs: -------------------------------------------------------------------------------- 1 | using osu.Framework.Allocation; 2 | using osu.Framework.Bindables; 3 | using osu.Framework.Graphics; 4 | using osu.Game.Rulesets.Sandbox.Configuration; 5 | using osu.Game.Rulesets.Sandbox.Screens.Visualizer.Components.Layouts.TypeA; 6 | using osuTK; 7 | 8 | namespace osu.Game.Rulesets.Sandbox.Screens.Visualizer.Components.Layouts 9 | { 10 | public partial class TypeALayout : DrawableVisualizerLayout 11 | { 12 | private readonly Bindable radius = new Bindable(350); 13 | private readonly Bindable colour = new Bindable("#ffffff"); 14 | private readonly Bindable progressColour = new Bindable("#ffffff"); 15 | 16 | private TypeAVisualizerController visualizerController; 17 | private CircularBeatmapLogo logo; 18 | 19 | [BackgroundDependencyLoader] 20 | private void load(SandboxRulesetConfigManager config) 21 | { 22 | InternalChildren = new Drawable[] 23 | { 24 | visualizerController = new TypeAVisualizerController 25 | { 26 | Position = new Vector2(0.5f), 27 | }, 28 | logo = new CircularBeatmapLogo 29 | { 30 | Position = new Vector2(0.5f), 31 | Size = { BindTarget = radius } 32 | } 33 | }; 34 | 35 | config?.BindWith(SandboxRulesetSetting.Radius, radius); 36 | config?.BindWith(SandboxRulesetSetting.TypeAColour, colour); 37 | config?.BindWith(SandboxRulesetSetting.TypeAProgressColour, progressColour); 38 | } 39 | 40 | protected override void LoadComplete() 41 | { 42 | base.LoadComplete(); 43 | 44 | radius.BindValueChanged(r => 45 | { 46 | visualizerController.Size = new Vector2(r.NewValue - 2); 47 | }, true); 48 | 49 | colour.BindValueChanged(c => visualizerController.Colour = Colour4.FromHex(c.NewValue), true); 50 | progressColour.BindValueChanged(c => logo.ProgressColour = Colour4.FromHex(c.NewValue), true); 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Sandbox/Screens/Visualizer/Components/Layouts/TypeBLayout.cs: -------------------------------------------------------------------------------- 1 | using osu.Game.Rulesets.Sandbox.Screens.Visualizer.Components.Layouts.TypeB; 2 | 3 | namespace osu.Game.Rulesets.Sandbox.Screens.Visualizer.Components.Layouts 4 | { 5 | public class TypeBLayout : DrawableVisualizerLayout 6 | { 7 | public TypeBLayout() 8 | { 9 | AddInternal(new TypeBVisualizerController()); 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Sandbox/Screens/Visualizer/Components/MusicHelpers/CurrentBeatmapProvider.cs: -------------------------------------------------------------------------------- 1 | using osu.Framework.Allocation; 2 | using osu.Framework.Bindables; 3 | using osu.Framework.Graphics.Containers; 4 | using osu.Game.Beatmaps; 5 | 6 | namespace osu.Game.Rulesets.Sandbox.Screens.Visualizer.Components.MusicHelpers 7 | { 8 | public class CurrentBeatmapProvider : Container 9 | { 10 | protected IBindable Beatmap = new Bindable(); 11 | 12 | [BackgroundDependencyLoader] 13 | private void load(IBindable working) 14 | { 15 | Beatmap.BindTo(working); 16 | } 17 | 18 | protected override void LoadComplete() 19 | { 20 | base.LoadComplete(); 21 | Beatmap.BindValueChanged(OnBeatmapChanged, true); 22 | } 23 | 24 | protected virtual void OnBeatmapChanged(ValueChangedEvent beatmap) 25 | { 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Sandbox/Screens/Visualizer/Components/MusicHelpers/CurrentRateContainer.cs: -------------------------------------------------------------------------------- 1 | using osu.Framework.Bindables; 2 | using osu.Framework.Graphics; 3 | using osu.Framework.Graphics.Containers; 4 | 5 | namespace osu.Game.Rulesets.Sandbox.Screens.Visualizer.Components.MusicHelpers 6 | { 7 | public class CurrentRateContainer : RateAdjustableContainer 8 | { 9 | protected readonly BindableBool IsKiai = new BindableBool(); 10 | 11 | protected override Container Content => content; 12 | 13 | private readonly MusicIntensityController intensityController; 14 | private readonly Container content; 15 | 16 | public CurrentRateContainer() 17 | { 18 | AddRangeInternal(new Drawable[] 19 | { 20 | content = new Container 21 | { 22 | Anchor = Anchor.Centre, 23 | Origin = Anchor.Centre, 24 | RelativeSizeAxes = Axes.Both, 25 | }, 26 | intensityController = new MusicIntensityController() 27 | }); 28 | 29 | IsKiai.BindTo(intensityController.IsKiai); 30 | } 31 | 32 | protected override void LoadComplete() 33 | { 34 | base.LoadComplete(); 35 | intensityController.Intensity.BindValueChanged(rate => Rate = rate.NewValue); 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Sandbox/Screens/Visualizer/Components/MusicHelpers/MusicAmplitudesProvider.cs: -------------------------------------------------------------------------------- 1 | using osu.Framework.Audio.Track; 2 | using osu.Framework.Bindables; 3 | using osu.Game.Beatmaps; 4 | 5 | namespace osu.Game.Rulesets.Sandbox.Screens.Visualizer.Components.MusicHelpers 6 | { 7 | public abstract partial class MusicAmplitudesProvider : CurrentBeatmapProvider 8 | { 9 | public readonly BindableBool IsKiai = new BindableBool(); 10 | 11 | private ITrack track; 12 | 13 | protected override void OnBeatmapChanged(ValueChangedEvent beatmap) 14 | { 15 | base.OnBeatmapChanged(beatmap); 16 | track = beatmap.NewValue?.Track; 17 | } 18 | 19 | protected override void Update() 20 | { 21 | base.Update(); 22 | 23 | OnAmplitudesUpdate(track?.CurrentAmplitudes.FrequencyAmplitudes.Span.ToArray() ?? new float[256]); 24 | IsKiai.Value = Beatmap.Value?.Beatmap.ControlPointInfo.EffectPointAt(track?.CurrentTime ?? 0).KiaiMode ?? false; 25 | } 26 | 27 | protected abstract void OnAmplitudesUpdate(float[] amplitudes); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Sandbox/Screens/Visualizer/Components/MusicHelpers/MusicIntensityController.cs: -------------------------------------------------------------------------------- 1 | using osu.Framework.Bindables; 2 | using osu.Framework.Extensions.IEnumerableExtensions; 3 | 4 | namespace osu.Game.Rulesets.Sandbox.Screens.Visualizer.Components.MusicHelpers 5 | { 6 | public class MusicIntensityController : MusicAmplitudesProvider 7 | { 8 | public readonly BindableFloat Intensity = new BindableFloat(); 9 | 10 | protected override void OnAmplitudesUpdate(float[] amplitudes) 11 | { 12 | float sum = 0; 13 | amplitudes.ForEach(amp => sum += amp); 14 | 15 | if (IsKiai.Value) 16 | sum *= 1.2f; 17 | 18 | Intensity.Value = sum; 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Sandbox/Screens/Visualizer/Components/MusicHelpers/RateAdjustableContainer.cs: -------------------------------------------------------------------------------- 1 | using osu.Framework.Graphics.Containers; 2 | using osu.Framework.Timing; 3 | 4 | namespace osu.Game.Rulesets.Sandbox.Screens.Visualizer.Components.MusicHelpers 5 | { 6 | public class RateAdjustableContainer : Container 7 | { 8 | public double Rate 9 | { 10 | get => clock.Rate; 11 | set => clock.Rate = value; 12 | } 13 | 14 | private readonly StopwatchClock clock; 15 | 16 | public RateAdjustableContainer() 17 | { 18 | ProcessCustomClock = true; 19 | Clock = new FramedClock(clock = new StopwatchClock()); 20 | clock.Start(); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Sandbox/Screens/Visualizer/Components/Particles.cs: -------------------------------------------------------------------------------- 1 | using osu.Framework.Allocation; 2 | using osu.Framework.Bindables; 3 | using osu.Framework.Graphics; 4 | using osu.Game.Rulesets.Sandbox.Configuration; 5 | using osu.Game.Rulesets.Sandbox.Screens.Visualizer.Components.MusicHelpers; 6 | 7 | namespace osu.Game.Rulesets.Sandbox.Screens.Visualizer.Components 8 | { 9 | public class Particles : CurrentRateContainer 10 | { 11 | private readonly Bindable colour = new Bindable("#ffffff"); 12 | private readonly Bindable direction = new Bindable(); 13 | 14 | private ParticlesDrawable particles; 15 | 16 | [Resolved(canBeNull: true)] 17 | private SandboxRulesetConfigManager config { get; set; } 18 | 19 | public Particles() 20 | { 21 | RelativeSizeAxes = Axes.Both; 22 | Add(particles = new ParticlesDrawable()); 23 | } 24 | 25 | [BackgroundDependencyLoader] 26 | private void load() 27 | { 28 | config?.BindWith(SandboxRulesetSetting.ParticlesColour, colour); 29 | config?.BindWith(SandboxRulesetSetting.ParticlesDirection, direction); 30 | } 31 | 32 | protected override void LoadComplete() 33 | { 34 | base.LoadComplete(); 35 | 36 | direction.BindValueChanged(_ => updateDirection()); 37 | IsKiai.BindValueChanged(_ => updateDirection(), true); 38 | 39 | colour.BindValueChanged(c => particles.Colour = Colour4.FromHex(c.NewValue), true); 40 | } 41 | 42 | private void updateDirection() 43 | { 44 | particles.Direction.Value = direction.Value; 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Sandbox/Screens/Visualizer/Components/Settings/BackgroundSection.cs: -------------------------------------------------------------------------------- 1 | using osu.Framework.Allocation; 2 | using osu.Framework.Graphics; 3 | using osu.Game.Configuration; 4 | using osu.Game.Overlays.Settings; 5 | using osu.Game.Rulesets.Sandbox.Configuration; 6 | using osu.Game.Rulesets.Sandbox.UI.Settings; 7 | 8 | namespace osu.Game.Rulesets.Sandbox.Screens.Visualizer.Components.Settings 9 | { 10 | public class BackgroundSection : SandboxSettingsSection 11 | { 12 | protected override string HeaderName => "Background"; 13 | 14 | [BackgroundDependencyLoader] 15 | private void load(OsuConfigManager config, SandboxRulesetConfigManager rulesetConfig) 16 | { 17 | AddRange(new Drawable[] 18 | { 19 | new SettingsCheckbox 20 | { 21 | LabelText = "Show storyboard (if available)", 22 | Current = rulesetConfig.GetBindable(SandboxRulesetSetting.ShowStoryboard) 23 | }, 24 | new SettingsCheckbox 25 | { 26 | LabelText = "Show particles", 27 | Current = rulesetConfig.GetBindable(SandboxRulesetSetting.ShowParticles) 28 | }, 29 | new ParticleSettings(), 30 | new SettingsSlider 31 | { 32 | LabelText = "Background dim", 33 | Current = config.GetBindable(OsuSetting.DimLevel), 34 | KeyboardStep = 0.01f, 35 | DisplayAsPercentage = true 36 | }, 37 | new SettingsSlider 38 | { 39 | LabelText = "Background blur", 40 | Current = config.GetBindable(OsuSetting.BlurLevel), 41 | KeyboardStep = 0.01f, 42 | DisplayAsPercentage = true 43 | } 44 | }); 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Sandbox/Screens/Visualizer/Components/Settings/ParticleSettings.cs: -------------------------------------------------------------------------------- 1 | using osu.Framework.Allocation; 2 | using osu.Framework.Bindables; 3 | using osu.Framework.Graphics.Containers; 4 | using osu.Game.Rulesets.Sandbox.Configuration; 5 | using osu.Framework.Graphics; 6 | using osuTK; 7 | using osu.Game.Overlays.Settings; 8 | using osu.Game.Rulesets.Sandbox.UI.Settings; 9 | 10 | namespace osu.Game.Rulesets.Sandbox.Screens.Visualizer.Components.Settings 11 | { 12 | public partial class ParticleSettings : FillFlowContainer 13 | { 14 | private readonly BindableBool showParticles = new BindableBool(); 15 | 16 | [BackgroundDependencyLoader] 17 | private void load(SandboxRulesetConfigManager rulesetConfig) 18 | { 19 | RelativeSizeAxes = Axes.X; 20 | AutoSizeAxes = Axes.Y; 21 | Direction = FillDirection.Vertical; 22 | Spacing = new Vector2(0, 5); 23 | Children = new Drawable[] 24 | { 25 | new SettingsSlider 26 | { 27 | LabelText = "Particle count", 28 | Current = rulesetConfig.GetBindable(SandboxRulesetSetting.ParticleCount), 29 | KeyboardStep = 1 30 | }, 31 | new SettingsSlider 32 | { 33 | LabelText = "Global Speed", 34 | Current = rulesetConfig.GetBindable(SandboxRulesetSetting.GlobalSpeed), 35 | KeyboardStep = 1 36 | }, 37 | new SettingsEnumDropdown 38 | { 39 | LabelText = "Direction", 40 | Current = rulesetConfig.GetBindable(SandboxRulesetSetting.ParticlesDirection) 41 | }, 42 | new ColourPickerDropdown("Colour", SandboxRulesetSetting.ParticlesColour) 43 | }; 44 | 45 | rulesetConfig.BindWith(SandboxRulesetSetting.ShowParticles, showParticles); 46 | } 47 | 48 | protected override void LoadComplete() 49 | { 50 | base.LoadComplete(); 51 | 52 | showParticles.BindValueChanged(s => Alpha = s.NewValue ? 1 : 0, true); 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Sandbox/Screens/Visualizer/Components/Settings/TrackSection.cs: -------------------------------------------------------------------------------- 1 | using osu.Framework.Allocation; 2 | using osu.Framework.Bindables; 3 | using osu.Framework.Graphics; 4 | using osu.Game.Beatmaps; 5 | using osu.Game.Overlays.Settings; 6 | using osu.Game.Rulesets.Sandbox.UI; 7 | using osu.Game.Rulesets.Sandbox.UI.Settings; 8 | 9 | namespace osu.Game.Rulesets.Sandbox.Screens.Visualizer.Components.Settings 10 | { 11 | public class TrackSection : SandboxSettingsSection 12 | { 13 | protected override string HeaderName => "Track"; 14 | 15 | [Resolved] 16 | private Bindable working { get; set; } 17 | 18 | private readonly BindableBool loopCurrent = new BindableBool(); 19 | 20 | [BackgroundDependencyLoader] 21 | private void load() 22 | { 23 | AddRange(new Drawable[] 24 | { 25 | new TrackController(), 26 | new SettingsCheckbox 27 | { 28 | LabelText = "Loop Current Track", 29 | Current = loopCurrent 30 | } 31 | }); 32 | } 33 | 34 | protected override void LoadComplete() 35 | { 36 | base.LoadComplete(); 37 | 38 | loopCurrent.BindValueChanged(loop => updateLooping(working.Value, loop.NewValue)); 39 | working.BindValueChanged(w => updateLooping(w.NewValue, loopCurrent.Value), true); 40 | } 41 | 42 | private static void updateLooping(WorkingBeatmap beatmap, bool isLooping) 43 | { 44 | if (beatmap != null && beatmap.Track != null) 45 | beatmap.Track.Looping = isLooping; 46 | } 47 | 48 | protected override void Dispose(bool isDisposing) 49 | { 50 | updateLooping(working.Value, false); 51 | base.Dispose(isDisposing); 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Sandbox/Screens/Visualizer/Components/Settings/VisualizerSection.cs: -------------------------------------------------------------------------------- 1 | using osu.Framework.Allocation; 2 | using osu.Framework.Graphics; 3 | using osu.Game.Overlays.Settings; 4 | using osu.Game.Rulesets.Sandbox.Configuration; 5 | using osu.Game.Rulesets.Sandbox.UI.Settings; 6 | 7 | namespace osu.Game.Rulesets.Sandbox.Screens.Visualizer.Components.Settings 8 | { 9 | public class VisualizerSection : SandboxSettingsSection 10 | { 11 | protected override string HeaderName => "Visualizer"; 12 | 13 | [BackgroundDependencyLoader] 14 | private void load(SandboxRulesetConfigManager config) 15 | { 16 | AddRange(new Drawable[] 17 | { 18 | new SettingsEnumDropdown 19 | { 20 | LabelText = "Layout type", 21 | Current = config.GetBindable(SandboxRulesetSetting.VisualizerLayout) 22 | }, 23 | new LayoutSettingsSubsection() 24 | }); 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Sandbox/Screens/Visualizer/Components/VisualizerSettingsTip.cs: -------------------------------------------------------------------------------- 1 | using osu.Framework.Allocation; 2 | using osu.Framework.Bindables; 3 | using osu.Framework.Graphics; 4 | using osu.Framework.Graphics.Containers; 5 | using osu.Game.Graphics; 6 | using osu.Game.Rulesets.Sandbox.Configuration; 7 | using osu.Game.Rulesets.Sandbox.UI.Overlays; 8 | using osuTK.Graphics; 9 | 10 | namespace osu.Game.Rulesets.Sandbox.Screens.Visualizer.Components 11 | { 12 | public class VisualizerSettingsTip : SandboxOverlay 13 | { 14 | private readonly BindableBool showAgain = new BindableBool(); 15 | 16 | protected override SandboxOverlayButton[] CreateButtons() => new[] 17 | { 18 | new SandboxOverlayButton("Got it") 19 | { 20 | ClickAction = onClick 21 | } 22 | }; 23 | 24 | private SandboxCheckbox checkbox; 25 | 26 | protected override Drawable CreateContent() => new Container 27 | { 28 | Anchor = Anchor.Centre, 29 | Origin = Anchor.Centre, 30 | AutoSizeAxes = Axes.Y, 31 | RelativeSizeAxes = Axes.X, 32 | Children = new Drawable[] 33 | { 34 | new TextFlowContainer(f => 35 | { 36 | f.Colour = Color4.Black; 37 | f.Font = OsuFont.GetFont(size: 30, weight: FontWeight.Regular); 38 | }) 39 | { 40 | Anchor = Anchor.Centre, 41 | Origin = Anchor.Centre, 42 | AutoSizeAxes = Axes.Y, 43 | RelativeSizeAxes = Axes.X, 44 | TextAnchor = Anchor.TopCentre, 45 | Text = "To open visualizer settings move your cursor to the right side of the screen." 46 | }, 47 | checkbox = new SandboxCheckbox("Don't show again") 48 | { 49 | Anchor = Anchor.BottomCentre, 50 | Origin = Anchor.TopCentre, 51 | BypassAutoSizeAxes = Axes.Y, 52 | Y = 30 53 | } 54 | } 55 | }; 56 | 57 | [Resolved(canBeNull: true)] 58 | private SandboxRulesetConfigManager config { get; set; } 59 | 60 | [BackgroundDependencyLoader] 61 | private void load() 62 | { 63 | config?.BindWith(SandboxRulesetSetting.ShowSettingsTip, showAgain); 64 | } 65 | 66 | private void onClick() 67 | { 68 | if (checkbox.Current.Value) 69 | showAgain.Value = false; 70 | 71 | Hide(); 72 | } 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Sandbox/Screens/Visualizer/Components/Visualizers/Circular/BasicMusicVisualizerDrawable.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using osu.Framework.Graphics; 3 | using osu.Framework.Graphics.Primitives; 4 | using osu.Framework.Graphics.Rendering; 5 | using osuTK; 6 | 7 | namespace osu.Game.Rulesets.Sandbox.Screens.Visualizer.Components.Visualizers.Circular 8 | { 9 | public partial class BasicMusicVisualizerDrawable : CircularMusicVisualizerDrawable 10 | { 11 | protected override CircularVisualizerDrawNode CreateCircularVisualizerDrawNode() => new BasicVisualizerDrawNode(this); 12 | 13 | private class BasicVisualizerDrawNode : CircularVisualizerDrawNode 14 | { 15 | public BasicVisualizerDrawNode(BasicMusicVisualizerDrawable source) 16 | : base(source) 17 | { 18 | } 19 | 20 | protected override void DrawBar(int index, float data, float spacing, Vector2 inflation, IRenderer renderer) 21 | { 22 | float rotation = MathHelper.DegreesToRadians(index * spacing - 90); 23 | float rotationCos = MathF.Cos(rotation); 24 | float rotationSin = MathF.Sin(rotation); 25 | 26 | var barPosition = new Vector2(rotationCos / 2 + 0.5f, rotationSin / 2 + 0.5f) * Size.X; 27 | var barSize = new Vector2((float)BarWidth, 2 + data); 28 | 29 | var bottomOffset = new Vector2(-rotationSin * barSize.X / 2, rotationCos * barSize.X / 2); 30 | var amplitudeOffset = new Vector2(rotationCos * barSize.Y, rotationSin * barSize.Y); 31 | 32 | var rectangle = new Quad( 33 | Vector2Extensions.Transform(barPosition - bottomOffset, DrawInfo.Matrix), 34 | Vector2Extensions.Transform(barPosition - bottomOffset + amplitudeOffset, DrawInfo.Matrix), 35 | Vector2Extensions.Transform(barPosition + bottomOffset, DrawInfo.Matrix), 36 | Vector2Extensions.Transform(barPosition + bottomOffset + amplitudeOffset, DrawInfo.Matrix) 37 | ); 38 | 39 | renderer.DrawQuad( 40 | Texture, 41 | rectangle, 42 | DrawColourInfo.Colour, 43 | null, 44 | VertexBatch.AddAction, 45 | Vector2.Divide(inflation, barSize.Yx)); 46 | } 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Sandbox/Screens/Visualizer/Components/Visualizers/Circular/DotsMusicVisualizerDrawable.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using osu.Framework.Graphics; 3 | using osu.Framework.Graphics.Primitives; 4 | using osu.Framework.Graphics.Rendering; 5 | using osu.Framework.Graphics.Textures; 6 | using osuTK; 7 | 8 | namespace osu.Game.Rulesets.Sandbox.Screens.Visualizer.Components.Visualizers.Circular 9 | { 10 | public class DotsMusicVisualizerDrawable : CircularMusicVisualizerDrawable 11 | { 12 | protected override Texture GetTexture(IRenderer renderer, TextureStore textures) => textures.Get("Visualizer/particle"); 13 | 14 | protected override CircularVisualizerDrawNode CreateCircularVisualizerDrawNode() => new DotsVisualizerDrawNode(this); 15 | 16 | private class DotsVisualizerDrawNode : CircularVisualizerDrawNode 17 | { 18 | public DotsVisualizerDrawNode(DotsMusicVisualizerDrawable source) 19 | : base(source) 20 | { 21 | } 22 | 23 | private Vector2 dotSize; 24 | 25 | protected override void PreCompute() 26 | { 27 | base.PreCompute(); 28 | dotSize = new Vector2((float)BarWidth); 29 | } 30 | 31 | protected override void DrawBar(int index, float data, float spacing, Vector2 inflation, IRenderer renderer) 32 | { 33 | float rotation = MathHelper.DegreesToRadians(index * spacing - 90); 34 | float rotationCos = MathF.Cos(rotation); 35 | float rotationSin = MathF.Sin(rotation); 36 | 37 | var scale = (data * 2 + Size.X) / Size.X; 38 | var multiplier = 1f / (scale * 2); 39 | 40 | var dotPosition = new Vector2(rotationCos / 2 + multiplier, rotationSin / 2 + multiplier) * Size.X * scale; 41 | 42 | var bottomOffset = new Vector2(-rotationSin * dotSize.X / 2, rotationCos * dotSize.Y / 2); 43 | var amplitudeOffset = new Vector2(rotationCos * dotSize.X, rotationSin * dotSize.Y); 44 | 45 | var rectangle = new Quad( 46 | Vector2Extensions.Transform(dotPosition - bottomOffset, DrawInfo.Matrix), 47 | Vector2Extensions.Transform(dotPosition - bottomOffset + amplitudeOffset, DrawInfo.Matrix), 48 | Vector2Extensions.Transform(dotPosition + bottomOffset, DrawInfo.Matrix), 49 | Vector2Extensions.Transform(dotPosition + bottomOffset + amplitudeOffset, DrawInfo.Matrix) 50 | ); 51 | 52 | renderer.DrawQuad( 53 | Texture, 54 | rectangle, 55 | DrawColourInfo.Colour, 56 | null, 57 | VertexBatch.AddAction); 58 | } 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Sandbox/Screens/Visualizer/Components/Visualizers/Circular/FallMusicVisualizerDrawable.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using osu.Framework.Graphics; 4 | using osu.Framework.Graphics.Primitives; 5 | using osu.Framework.Graphics.Rendering; 6 | using osu.Game.Rulesets.Sandbox.Extensions; 7 | using osuTK; 8 | 9 | namespace osu.Game.Rulesets.Sandbox.Screens.Visualizer.Components.Visualizers.Circular 10 | { 11 | public class FallMusicVisualizerDrawable : CircularMusicVisualizerDrawable 12 | { 13 | private float[] currentRawFallAudioData; 14 | private float[] maxFallBarValues; 15 | private float[] smoothFallAudioData; 16 | 17 | protected override void ResetArrays() 18 | { 19 | base.ResetArrays(); 20 | 21 | currentRawFallAudioData = new float[AdjustedBarCount]; 22 | maxFallBarValues = new float[AdjustedBarCount]; 23 | smoothFallAudioData = new float[AdjustedBarCount]; 24 | } 25 | 26 | protected override void ApplyData(int index, float newRawAudioDataAtIndex) 27 | { 28 | base.ApplyData(index, newRawAudioDataAtIndex); 29 | 30 | if (newRawAudioDataAtIndex > currentRawFallAudioData[index]) 31 | { 32 | currentRawFallAudioData[index] = newRawAudioDataAtIndex; 33 | maxFallBarValues[index] = currentRawFallAudioData[index]; 34 | } 35 | } 36 | 37 | protected override void UpdateData(int index, float timeDifference) 38 | { 39 | base.UpdateData(index, timeDifference); 40 | 41 | currentRawFallAudioData[index] -= maxFallBarValues[index] / (Decay.Value * 4) * timeDifference; 42 | smoothFallAudioData[index] = currentRawFallAudioData[index] * HeightMultiplier.Value; 43 | } 44 | 45 | protected override void PostUpdate() 46 | { 47 | base.PostUpdate(); 48 | 49 | if (Smoothness.Value > 0) 50 | smoothFallAudioData.Smooth(Math.Min(Smoothness.Value, AdjustedBarCount / 2)); 51 | } 52 | 53 | protected override CircularVisualizerDrawNode CreateCircularVisualizerDrawNode() => new FallVisualizerDrawNode(this); 54 | 55 | private class FallVisualizerDrawNode : CircularVisualizerDrawNode 56 | { 57 | protected new FallMusicVisualizerDrawable Source => (FallMusicVisualizerDrawable)base.Source; 58 | 59 | public FallVisualizerDrawNode(FallMusicVisualizerDrawable source) 60 | : base(source) 61 | { 62 | } 63 | 64 | private readonly List fallAudioData = new List(); 65 | 66 | public override void ApplyState() 67 | { 68 | base.ApplyState(); 69 | 70 | fallAudioData.Clear(); 71 | fallAudioData.AddRange(Source.smoothFallAudioData); 72 | } 73 | 74 | protected override void DrawBar(int index, float data, float spacing, Vector2 inflation, IRenderer renderer) 75 | { 76 | float rotation = MathHelper.DegreesToRadians(index * spacing - 90); 77 | float rotationCos = MathF.Cos(rotation); 78 | float rotationSin = MathF.Sin(rotation); 79 | 80 | var barPosition = new Vector2(rotationCos / 2 + 0.5f, rotationSin / 2 + 0.5f) * Size.X; 81 | var barSize = new Vector2((float)BarWidth, 2 + data); 82 | 83 | var bottomOffset = new Vector2(-rotationSin * barSize.X / 2, rotationCos * barSize.X / 2); 84 | var amplitudeOffset = new Vector2(rotationCos * barSize.Y, rotationSin * barSize.Y); 85 | 86 | var rectangle = new Quad( 87 | Vector2Extensions.Transform(barPosition - bottomOffset, DrawInfo.Matrix), 88 | Vector2Extensions.Transform(barPosition - bottomOffset + amplitudeOffset, DrawInfo.Matrix), 89 | Vector2Extensions.Transform(barPosition + bottomOffset, DrawInfo.Matrix), 90 | Vector2Extensions.Transform(barPosition + bottomOffset + amplitudeOffset, DrawInfo.Matrix) 91 | ); 92 | 93 | renderer.DrawQuad( 94 | Texture, 95 | rectangle, 96 | DrawColourInfo.Colour, 97 | null, 98 | VertexBatch.AddAction, 99 | Vector2.Divide(inflation, barSize.Yx)); 100 | 101 | // Fall bar 102 | 103 | var fallBarData = Reversed ? fallAudioData[fallAudioData.Count - 1 - index] : fallAudioData[index]; 104 | 105 | var scale = (fallBarData * 2 + Size.X) / Size.X; 106 | var multiplier = 1f / (scale * 2); 107 | 108 | var fallBarPosition = new Vector2(rotationCos / 2 + multiplier, rotationSin / 2 + multiplier) * Size.X * scale; 109 | var fallBarSize = new Vector2((float)BarWidth, 2); 110 | 111 | var fallBarAmplitudeOffset = new Vector2(rotationCos * fallBarSize.Y, rotationSin * fallBarSize.Y); 112 | 113 | var fallBarRectangle = new Quad( 114 | Vector2Extensions.Transform(fallBarPosition - bottomOffset, DrawInfo.Matrix), 115 | Vector2Extensions.Transform(fallBarPosition - bottomOffset + fallBarAmplitudeOffset, DrawInfo.Matrix), 116 | Vector2Extensions.Transform(fallBarPosition + bottomOffset, DrawInfo.Matrix), 117 | Vector2Extensions.Transform(fallBarPosition + bottomOffset + fallBarAmplitudeOffset, DrawInfo.Matrix) 118 | ); 119 | 120 | renderer.DrawQuad( 121 | Texture, 122 | fallBarRectangle, 123 | DrawColourInfo.Colour, 124 | null, 125 | VertexBatch.AddAction, 126 | Vector2.Divide(inflation, fallBarSize.Yx)); 127 | } 128 | } 129 | } 130 | } 131 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Sandbox/Screens/Visualizer/Components/Visualizers/Circular/RoundedMusicVisualizerDrawable.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using osu.Framework.Allocation; 3 | using osu.Framework.Graphics; 4 | using osu.Framework.Graphics.Primitives; 5 | using osu.Framework.Graphics.Rendering; 6 | using osu.Framework.Graphics.Shaders; 7 | using osuTK; 8 | 9 | namespace osu.Game.Rulesets.Sandbox.Screens.Visualizer.Components.Visualizers.Circular 10 | { 11 | public partial class RoundedMusicVisualizerDrawable : CircularMusicVisualizerDrawable 12 | { 13 | [BackgroundDependencyLoader] 14 | private void load(ShaderManager shaders) 15 | { 16 | Shader = shaders.Load(VertexShaderDescriptor.TEXTURE_2, "RoundedBar"); 17 | } 18 | 19 | protected override CircularVisualizerDrawNode CreateCircularVisualizerDrawNode() => new RoundedVisualizerDrawNode(this); 20 | 21 | private class RoundedVisualizerDrawNode : CircularVisualizerDrawNode 22 | { 23 | public RoundedVisualizerDrawNode(CircularMusicVisualizerDrawable source) 24 | : base(source) 25 | { 26 | } 27 | 28 | protected override void DrawBar(int index, float data, float spacing, Vector2 inflation, IRenderer renderer) 29 | { 30 | float rotation = MathHelper.DegreesToRadians(index * spacing - 90); 31 | float rotationCos = MathF.Cos(rotation); 32 | float rotationSin = MathF.Sin(rotation); 33 | 34 | var barPosition = new Vector2(rotationCos / 2 + 0.5f, rotationSin / 2 + 0.5f) * Size.X; 35 | var barSize = new Vector2((float)BarWidth, (float)BarWidth + data); 36 | 37 | var bottomOffset = new Vector2(-rotationSin * barSize.X / 2, rotationCos * barSize.X / 2); 38 | var amplitudeOffset = new Vector2(rotationCos * barSize.Y, rotationSin * barSize.Y); 39 | 40 | var drawQuad = new Quad( 41 | Vector2Extensions.Transform(barPosition - bottomOffset, DrawInfo.Matrix), 42 | Vector2Extensions.Transform(barPosition - bottomOffset + amplitudeOffset, DrawInfo.Matrix), 43 | Vector2Extensions.Transform(barPosition + bottomOffset, DrawInfo.Matrix), 44 | Vector2Extensions.Transform(barPosition + bottomOffset + amplitudeOffset, DrawInfo.Matrix) 45 | ); 46 | 47 | renderer.DrawQuad( 48 | Texture, 49 | drawQuad, 50 | DrawColourInfo.Colour, 51 | new RectangleF(Vector2.Zero, drawQuad.Size), 52 | VertexBatch.AddAction 53 | ); 54 | } 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Sandbox/Screens/Visualizer/Components/Visualizers/CircularMusicVisualizerDrawable.cs: -------------------------------------------------------------------------------- 1 | using osu.Framework.Bindables; 2 | using osuTK; 3 | 4 | namespace osu.Game.Rulesets.Sandbox.Screens.Visualizer.Components.Visualizers 5 | { 6 | public abstract partial class CircularMusicVisualizerDrawable : MusicVisualizerDrawable 7 | { 8 | public readonly Bindable DegreeValue = new Bindable(); 9 | 10 | protected override VisualizerDrawNode CreateVisualizerDrawNode() => CreateCircularVisualizerDrawNode(); 11 | 12 | protected abstract CircularVisualizerDrawNode CreateCircularVisualizerDrawNode(); 13 | 14 | protected abstract class CircularVisualizerDrawNode : VisualizerDrawNode 15 | { 16 | protected new CircularMusicVisualizerDrawable Source => (CircularMusicVisualizerDrawable)base.Source; 17 | 18 | protected float DegreeValue; 19 | 20 | public CircularVisualizerDrawNode(CircularMusicVisualizerDrawable source) 21 | : base(source) 22 | { 23 | } 24 | 25 | public override void ApplyState() 26 | { 27 | base.ApplyState(); 28 | DegreeValue = Source.DegreeValue.Value; 29 | } 30 | 31 | protected override float Spacing => DegreeValue / AudioData.Count; 32 | 33 | protected override Vector2 Inflation => DrawInfo.MatrixInverse.ExtractScale().Xy; 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Sandbox/Screens/Visualizer/Components/Visualizers/Linear/BasicLinearMusicVisualizerDrawable.cs: -------------------------------------------------------------------------------- 1 | using osu.Framework.Graphics.Rendering; 2 | using osuTK; 3 | 4 | namespace osu.Game.Rulesets.Sandbox.Screens.Visualizer.Components.Visualizers.Linear 5 | { 6 | public partial class BasicLinearMusicVisualizerDrawable : LinearMusicVisualizerDrawable 7 | { 8 | protected override LinearVisualizerDrawNode CreateLinearVisualizerDrawNode() => new BasicDrawNode(this); 9 | 10 | private class BasicDrawNode : LinearVisualizerDrawNode 11 | { 12 | public BasicDrawNode(LinearMusicVisualizerDrawable source) 13 | : base(source) 14 | { 15 | } 16 | 17 | protected override void DrawBar(Vector2 barPosition, Vector2 barSize, IRenderer renderer) 18 | { 19 | var adjustedSize = barSize + new Vector2(0, 2); 20 | 21 | renderer.DrawQuad( 22 | Texture, 23 | GetDrawQuad(barPosition, adjustedSize), 24 | DrawColourInfo.Colour, 25 | null, 26 | VertexBatch.AddAction, 27 | new Vector2(1f / barSize.Y, 1f / barSize.X)); 28 | } 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Sandbox/Screens/Visualizer/Components/Visualizers/Linear/RoundedLinearMusicVisualizerDrawable.cs: -------------------------------------------------------------------------------- 1 | using osu.Framework.Allocation; 2 | using osu.Framework.Graphics.Primitives; 3 | using osu.Framework.Graphics.Rendering; 4 | using osu.Framework.Graphics.Shaders; 5 | using osuTK; 6 | 7 | namespace osu.Game.Rulesets.Sandbox.Screens.Visualizer.Components.Visualizers.Linear 8 | { 9 | public partial class RoundedLinearMusicVisualizerDrawable : LinearMusicVisualizerDrawable 10 | { 11 | [BackgroundDependencyLoader] 12 | private void load(ShaderManager shaders) 13 | { 14 | Shader = shaders.Load(VertexShaderDescriptor.TEXTURE_2, "RoundedBar"); 15 | } 16 | 17 | protected override LinearVisualizerDrawNode CreateLinearVisualizerDrawNode() => new RoundedDrawNode(this); 18 | 19 | private class RoundedDrawNode : LinearVisualizerDrawNode 20 | { 21 | public RoundedDrawNode(LinearMusicVisualizerDrawable source) 22 | : base(source) 23 | { 24 | } 25 | 26 | protected override void DrawBar(Vector2 barPosition, Vector2 barSize, IRenderer renderer) 27 | { 28 | var adjustedSize = barSize + new Vector2(0, barSize.X); 29 | 30 | Quad drawQuad = GetDrawQuad(barPosition, adjustedSize); 31 | 32 | renderer.DrawQuad( 33 | Texture, 34 | drawQuad, 35 | DrawColourInfo.Colour, 36 | new RectangleF(Vector2.Zero, drawQuad.Size), 37 | VertexBatch.AddAction 38 | ); 39 | } 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Sandbox/Screens/Visualizer/Components/Visualizers/LinearMusicVisualizerDrawable.cs: -------------------------------------------------------------------------------- 1 | using osu.Framework.Bindables; 2 | using osu.Framework.Graphics; 3 | using osu.Framework.Graphics.Primitives; 4 | using osu.Framework.Graphics.Rendering; 5 | using osuTK; 6 | 7 | namespace osu.Game.Rulesets.Sandbox.Screens.Visualizer.Components.Visualizers 8 | { 9 | public abstract partial class LinearMusicVisualizerDrawable : MusicVisualizerDrawable 10 | { 11 | public readonly Bindable BarAnchorBindable = new Bindable(BarAnchor.Centre); 12 | 13 | protected LinearMusicVisualizerDrawable() 14 | { 15 | RelativeSizeAxes = Axes.Both; 16 | } 17 | 18 | protected override VisualizerDrawNode CreateVisualizerDrawNode() => CreateLinearVisualizerDrawNode(); 19 | 20 | protected abstract LinearVisualizerDrawNode CreateLinearVisualizerDrawNode(); 21 | 22 | protected abstract class LinearVisualizerDrawNode : VisualizerDrawNode 23 | { 24 | public new LinearMusicVisualizerDrawable Source => (LinearMusicVisualizerDrawable)base.Source; 25 | 26 | protected BarAnchor Origin; 27 | 28 | protected LinearVisualizerDrawNode(LinearMusicVisualizerDrawable source) 29 | : base(source) 30 | { 31 | } 32 | 33 | public override void ApplyState() 34 | { 35 | base.ApplyState(); 36 | Origin = Source.BarAnchorBindable.Value; 37 | } 38 | 39 | protected override float Spacing => (float)((Size.X - BarWidth) / (AudioData.Count - 1)); 40 | 41 | private float barY; 42 | 43 | protected override void PreCompute() 44 | { 45 | base.PreCompute(); 46 | barY = getBarPositionY(); 47 | } 48 | 49 | protected override void DrawBar(int index, float data, float spacing, Vector2 inflation, IRenderer renderer) 50 | { 51 | var barPosition = new Vector2(index * spacing, barY); 52 | var barSize = new Vector2((float)BarWidth, data); 53 | 54 | DrawBar(barPosition, barSize, renderer); 55 | } 56 | 57 | protected abstract void DrawBar(Vector2 barPosition, Vector2 barSize, IRenderer renderer); 58 | 59 | private float getBarPositionY() 60 | { 61 | switch (Origin) 62 | { 63 | default: 64 | case BarAnchor.Bottom: 65 | return Size.Y; 66 | 67 | case BarAnchor.Centre: 68 | return Size.Y / 2; 69 | 70 | case BarAnchor.Top: 71 | return 0; 72 | } 73 | } 74 | 75 | protected Quad GetDrawQuad(Vector2 barPosition, Vector2 barSize) 76 | { 77 | switch (Origin) 78 | { 79 | default: 80 | case BarAnchor.Bottom: 81 | return new Quad( 82 | Vector2Extensions.Transform(barPosition, DrawInfo.Matrix), 83 | Vector2Extensions.Transform(barPosition + new Vector2(0, -barSize.Y), DrawInfo.Matrix), 84 | Vector2Extensions.Transform(barPosition + new Vector2(barSize.X, 0), DrawInfo.Matrix), 85 | Vector2Extensions.Transform(barPosition + new Vector2(barSize.X, -barSize.Y), DrawInfo.Matrix) 86 | ); 87 | 88 | case BarAnchor.Centre: 89 | return new Quad( 90 | Vector2Extensions.Transform(barPosition + new Vector2(0, -barSize.Y / 2), DrawInfo.Matrix), 91 | Vector2Extensions.Transform(barPosition + new Vector2(0, barSize.Y / 2), DrawInfo.Matrix), 92 | Vector2Extensions.Transform(barPosition + new Vector2(barSize.X, -barSize.Y / 2), DrawInfo.Matrix), 93 | Vector2Extensions.Transform(barPosition + new Vector2(barSize.X, barSize.Y / 2), DrawInfo.Matrix) 94 | ); 95 | 96 | case BarAnchor.Top: 97 | return new Quad( 98 | Vector2Extensions.Transform(barPosition, DrawInfo.Matrix), 99 | Vector2Extensions.Transform(barPosition + new Vector2(0, barSize.Y), DrawInfo.Matrix), 100 | Vector2Extensions.Transform(barPosition + new Vector2(barSize.X, 0), DrawInfo.Matrix), 101 | Vector2Extensions.Transform(barPosition + new Vector2(barSize.X, barSize.Y), DrawInfo.Matrix) 102 | ); 103 | } 104 | } 105 | } 106 | } 107 | 108 | public enum BarAnchor 109 | { 110 | Top, 111 | Centre, 112 | Bottom 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Sandbox/Screens/Visualizer/VisualizerScreen.cs: -------------------------------------------------------------------------------- 1 | using osu.Framework.Allocation; 2 | using osu.Framework.Bindables; 3 | using osu.Framework.Graphics; 4 | using osu.Framework.Graphics.Containers; 5 | using osu.Framework.Graphics.Cursor; 6 | using osu.Framework.Input.Bindings; 7 | using osu.Framework.Input.Events; 8 | using osu.Framework.Screens; 9 | using osu.Game.Graphics.Cursor; 10 | using osu.Game.Input; 11 | using osu.Game.Input.Bindings; 12 | using osu.Game.Rulesets.Sandbox.Configuration; 13 | using osu.Game.Rulesets.Sandbox.Screens.Visualizer.Components; 14 | using osu.Game.Rulesets.Sandbox.Screens.Visualizer.Components.Settings; 15 | using osu.Game.Rulesets.Sandbox.UI; 16 | using osu.Game.Rulesets.Sandbox.UI.Settings; 17 | using osuTK; 18 | 19 | namespace osu.Game.Rulesets.Sandbox.Screens.Visualizer 20 | { 21 | public class VisualizerScreen : SandboxScreenWithSettings, IKeyBindingHandler 22 | { 23 | public override bool AllowBackButton => false; 24 | 25 | public override bool HideOverlaysOnEnter => true; 26 | 27 | private readonly IBindable isIdle = new BindableBool(); 28 | private readonly BindableBool showTip = new BindableBool(); 29 | private CursorHider cursorHider; 30 | 31 | [BackgroundDependencyLoader] 32 | private void load(SandboxRulesetConfigManager config, IdleTracker idleTracker) 33 | { 34 | config.BindWith(SandboxRulesetSetting.ShowSettingsTip, showTip); 35 | isIdle.BindTo(idleTracker.IsIdle); 36 | } 37 | 38 | protected override void LoadComplete() 39 | { 40 | base.LoadComplete(); 41 | 42 | if (showTip.Value) 43 | { 44 | var tip = new VisualizerSettingsTip(); 45 | AddInternal(tip); 46 | tip.Show(); 47 | } 48 | 49 | AddInternal(cursorHider = new CursorHider()); 50 | 51 | isIdle.BindValueChanged(idle => 52 | { 53 | if (idle.NewValue) 54 | { 55 | SettingsVisible.Value = false; 56 | cursorHider.Size = Vector2.One; 57 | } 58 | else 59 | { 60 | cursorHider.Size = Vector2.Zero; 61 | } 62 | }); 63 | } 64 | 65 | protected override Drawable CreateBackground() => new Container 66 | { 67 | RelativeSizeAxes = Axes.Both, 68 | Children = new Drawable[] 69 | { 70 | new StoryboardContainer(), 71 | new Particles() 72 | } 73 | }; 74 | 75 | protected override Drawable CreateContent() => new LayoutController(); 76 | 77 | protected override SandboxSettingsSection[] CreateSettingsSections() => new SandboxSettingsSection[] 78 | { 79 | new TrackSection(), 80 | new BackgroundSection(), 81 | new VisualizerSection() 82 | }; 83 | 84 | public bool OnPressed(KeyBindingPressEvent e) 85 | { 86 | switch (e.Action) 87 | { 88 | case GlobalAction.Back: 89 | this.Exit(); 90 | return true; 91 | } 92 | 93 | return false; 94 | } 95 | 96 | public void OnReleased(KeyBindingReleaseEvent e) 97 | { 98 | } 99 | 100 | private class CursorHider : CompositeDrawable, IProvideCursor 101 | { 102 | public CursorHider() 103 | { 104 | RelativeSizeAxes = Axes.Both; 105 | Size = Vector2.Zero; 106 | } 107 | 108 | public bool ProvidingUserCursor => true; 109 | 110 | public CursorContainer Cursor => new EmptyCursor(); 111 | 112 | protected override bool OnHover(HoverEvent e) 113 | { 114 | base.OnHover(e); 115 | return true; 116 | } 117 | 118 | private class EmptyCursor : CursorContainer 119 | { 120 | protected override Drawable CreateCursor() => Empty(); 121 | } 122 | } 123 | } 124 | } 125 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Sandbox/UI/DrawableSandboxRuleset.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using osu.Framework.Input; 3 | using osu.Game.Beatmaps; 4 | using osu.Game.Rulesets.Mods; 5 | using osu.Game.Rulesets.Sandbox.Objects; 6 | using osu.Game.Rulesets.Sandbox.Objects.Drawables; 7 | using osu.Game.Rulesets.Objects.Drawables; 8 | using osu.Game.Rulesets.UI; 9 | 10 | namespace osu.Game.Rulesets.Sandbox.UI 11 | { 12 | public partial class DrawableSandboxRuleset : DrawableRuleset 13 | { 14 | public DrawableSandboxRuleset(Ruleset ruleset, IBeatmap beatmap, IReadOnlyList mods = null) 15 | : base(ruleset, beatmap, mods) 16 | { 17 | } 18 | 19 | protected override PassThroughInputManager CreateInputManager() => new SandboxInputManager(Ruleset.RulesetInfo); 20 | 21 | protected override Playfield CreatePlayfield() => new SandboxPlayfield(); 22 | 23 | public override DrawableHitObject CreateDrawableRepresentation(SandboxHitObject h) 24 | { 25 | switch (h) 26 | { 27 | case SandboxHitObject hitObject: 28 | return new DrawableSandboxHitObject(hitObject); 29 | } 30 | 31 | return null; 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Sandbox/UI/InteractiveContainer.cs: -------------------------------------------------------------------------------- 1 | using osu.Framework.Graphics; 2 | using osu.Framework.Graphics.Containers; 3 | using osu.Framework.Graphics.Shapes; 4 | using osu.Framework.Input.Events; 5 | using osuTK; 6 | using osuTK.Graphics; 7 | 8 | namespace osu.Game.Rulesets.Sandbox.UI 9 | { 10 | public class InteractiveContainer : Container 11 | { 12 | private const float border_thickness = 4f; 13 | 14 | protected override Container Content => content; 15 | 16 | private readonly Container content; 17 | protected readonly Container ScalableContent; 18 | private readonly Container boundsContainer; 19 | 20 | public InteractiveContainer() 21 | { 22 | RelativeSizeAxes = Axes.Both; 23 | InternalChild = ScalableContent = new Container 24 | { 25 | Anchor = Anchor.Centre, 26 | Origin = Anchor.Centre, 27 | RelativeSizeAxes = Axes.Both, 28 | Children = new Drawable[] 29 | { 30 | boundsContainer = new Container 31 | { 32 | RelativeSizeAxes = Axes.Both, 33 | Masking = true, 34 | BorderColour = Color4.White, 35 | BorderThickness = border_thickness, 36 | Child = new Box 37 | { 38 | RelativeSizeAxes = Axes.Both, 39 | Alpha = 0, 40 | AlwaysPresent = true 41 | } 42 | }, 43 | content = new Container 44 | { 45 | RelativeSizeAxes = Axes.Both 46 | } 47 | } 48 | }; 49 | } 50 | 51 | private float zoom = 1f; 52 | 53 | public void Reset() 54 | { 55 | Clear(); 56 | 57 | boundsContainer.BorderThickness = border_thickness; 58 | ScalableContent.ClearTransforms(); 59 | ScalableContent.Anchor = Anchor.Centre; 60 | ScalableContent.Origin = Anchor.Centre; 61 | ScalableContent.Position = Vector2.Zero; 62 | ScalableContent.Size = Vector2.Zero; 63 | ScalableContent.Scale = Vector2.One; 64 | zoom = 1f; 65 | } 66 | 67 | protected override bool OnDragStart(DragStartEvent e) => true; 68 | 69 | protected override void OnDrag(DragEvent e) 70 | { 71 | base.OnDrag(e); 72 | ScalableContent.Position += e.Delta; 73 | } 74 | 75 | protected override bool OnScroll(ScrollEvent e) 76 | { 77 | base.OnScroll(e); 78 | 79 | ScalableContent.OriginPosition = ToSpaceOfOtherDrawable(e.MousePosition, ScalableContent); 80 | ScalableContent.Anchor = Anchor.TopLeft; 81 | ScalableContent.Position = e.MousePosition; 82 | 83 | zoom += (e.ScrollDelta.Y > 0 ? 1 : -1) * zoom * 0.1f; 84 | ScalableContent.ScaleTo(zoom, 200, Easing.OutQuint); 85 | boundsContainer.BorderThickness = border_thickness / zoom; 86 | 87 | return true; 88 | } 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Sandbox/UI/Overlays/SandboxCheckbox.cs: -------------------------------------------------------------------------------- 1 | using osu.Framework.Allocation; 2 | using osu.Framework.Audio; 3 | using osu.Framework.Audio.Sample; 4 | using osu.Framework.Bindables; 5 | using osu.Framework.Graphics; 6 | using osu.Framework.Graphics.Containers; 7 | using osu.Framework.Graphics.Shapes; 8 | using osu.Framework.Graphics.Sprites; 9 | using osu.Framework.Input.Events; 10 | using osu.Game.Graphics; 11 | using osuTK; 12 | using osuTK.Graphics; 13 | 14 | namespace osu.Game.Rulesets.Sandbox.UI.Overlays 15 | { 16 | public class SandboxCheckbox : CompositeDrawable 17 | { 18 | public readonly BindableBool Current = new BindableBool(); 19 | 20 | private Sample sampleChecked; 21 | private Sample sampleUnchecked; 22 | 23 | public SandboxCheckbox(string label) 24 | { 25 | AutoSizeAxes = Axes.Both; 26 | AddInternal(new FillFlowContainer 27 | { 28 | AutoSizeAxes = Axes.Both, 29 | Direction = FillDirection.Horizontal, 30 | Spacing = new Vector2(10, 0), 31 | Children = new Drawable[] 32 | { 33 | new LocalBox 34 | { 35 | Anchor = Anchor.CentreLeft, 36 | Origin = Anchor.CentreLeft, 37 | Current = { BindTarget = Current } 38 | }, 39 | new SpriteText 40 | { 41 | Anchor = Anchor.CentreLeft, 42 | Origin = Anchor.CentreLeft, 43 | Colour = Color4.Black, 44 | Font = OsuFont.GetFont(size: 20), 45 | Text = label 46 | } 47 | } 48 | }); 49 | } 50 | 51 | [BackgroundDependencyLoader] 52 | private void load(AudioManager audio) 53 | { 54 | sampleChecked = audio.Samples.Get(@"UI/check-on"); 55 | sampleUnchecked = audio.Samples.Get(@"UI/check-off"); 56 | } 57 | 58 | protected override bool OnClick(ClickEvent e) 59 | { 60 | Current.Toggle(); 61 | 62 | if (Current.Value) 63 | sampleChecked?.Play(); 64 | else 65 | sampleUnchecked?.Play(); 66 | 67 | return true; 68 | } 69 | 70 | private class LocalBox : CompositeDrawable 71 | { 72 | public readonly BindableBool Current = new BindableBool(); 73 | 74 | private readonly Container fill; 75 | 76 | public LocalBox() 77 | { 78 | Size = new Vector2(20); 79 | Masking = true; 80 | BorderColour = Color4.Black; 81 | BorderThickness = 3; 82 | CornerRadius = 3; 83 | InternalChildren = new Drawable[] 84 | { 85 | new Container 86 | { 87 | RelativeSizeAxes = Axes.Both, 88 | Masking = true, 89 | BorderColour = Color4.Black, 90 | BorderThickness = 3, 91 | CornerRadius = 3, 92 | Child = new Box 93 | { 94 | RelativeSizeAxes = Axes.Both, 95 | Alpha = 0, 96 | AlwaysPresent = true 97 | } 98 | }, 99 | fill = new Container 100 | { 101 | Anchor = Anchor.Centre, 102 | Origin = Anchor.Centre, 103 | RelativeSizeAxes = Axes.Both, 104 | Masking = true, 105 | CornerRadius = 3, 106 | Child = new Box 107 | { 108 | RelativeSizeAxes = Axes.Both, 109 | Colour = Color4.Black 110 | } 111 | } 112 | }; 113 | } 114 | 115 | protected override void LoadComplete() 116 | { 117 | base.LoadComplete(); 118 | 119 | Current.BindValueChanged(enabled => 120 | { 121 | fill.ScaleTo(enabled.NewValue ? 0.5f : 0, 250, Easing.OutQuint); 122 | }, true); 123 | 124 | fill.FinishTransforms(); 125 | } 126 | } 127 | } 128 | } 129 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Sandbox/UI/SandboxPlayfield.cs: -------------------------------------------------------------------------------- 1 | using osu.Framework.Allocation; 2 | using osu.Framework.Graphics; 3 | using osu.Framework.Graphics.Containers; 4 | using osu.Game.Graphics; 5 | using osu.Game.Graphics.Sprites; 6 | using osu.Game.Rulesets.UI; 7 | using osuTK; 8 | 9 | namespace osu.Game.Rulesets.Sandbox.UI 10 | { 11 | public class SandboxPlayfield : Playfield 12 | { 13 | [BackgroundDependencyLoader] 14 | private void load(OsuColour colours) 15 | { 16 | TextFlowContainer flow; 17 | 18 | InternalChildren = new Drawable[] 19 | { 20 | HitObjectContainer, 21 | flow = new TextFlowContainer 22 | { 23 | Anchor = Anchor.Centre, 24 | Origin = Anchor.Centre, 25 | AutoSizeAxes = Axes.Both, 26 | Direction = FillDirection.Vertical, 27 | Spacing = new Vector2(0, 10) 28 | } 29 | }; 30 | 31 | flow.AddText(new OsuSpriteText 32 | { 33 | Anchor = Anchor.Centre, 34 | Origin = Anchor.Centre, 35 | Text = "How to use:", 36 | Colour = colours.Yellow, 37 | Font = OsuFont.GetFont(size: 30, weight: FontWeight.Bold) 38 | }); 39 | 40 | flow.AddText(new OsuSpriteText 41 | { 42 | Anchor = Anchor.Centre, 43 | Origin = Anchor.Centre, 44 | Text = "* go to Main Menu", 45 | Font = OsuFont.GetFont(size: 20) 46 | }); 47 | 48 | flow.AddText(new OsuSpriteText 49 | { 50 | Anchor = Anchor.Centre, 51 | Origin = Anchor.Centre, 52 | Text = "* open settings", 53 | Font = OsuFont.GetFont(size: 20) 54 | }); 55 | 56 | flow.AddText(new OsuSpriteText 57 | { 58 | Anchor = Anchor.Centre, 59 | Origin = Anchor.Centre, 60 | Text = "* type \"Sandbox\"", 61 | Font = OsuFont.GetFont(size: 20) 62 | }); 63 | 64 | flow.AddText(new OsuSpriteText 65 | { 66 | Anchor = Anchor.Centre, 67 | Origin = Anchor.Centre, 68 | Text = "* click \"Open Main Screen\"", 69 | Font = OsuFont.GetFont(size: 20) 70 | }); 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Sandbox/UI/SandboxSettingsSubsection.cs: -------------------------------------------------------------------------------- 1 | using osu.Framework.Allocation; 2 | using osu.Framework.Graphics; 3 | using osu.Framework.Graphics.Containers; 4 | using osu.Framework.Localisation; 5 | using osu.Game.Graphics.Sprites; 6 | using osu.Game.Overlays.Settings; 7 | using osu.Game.Rulesets.Sandbox.Extensions; 8 | using osu.Game.Rulesets.Sandbox.Screens.Main; 9 | using osu.Game.Screens.Menu; 10 | 11 | namespace osu.Game.Rulesets.Sandbox.UI 12 | { 13 | public class SandboxSettingsSubsection : RulesetSettingsSubsection 14 | { 15 | protected override LocalisableString Header => "Sandbox"; 16 | 17 | [Resolved] 18 | private OsuGame game { get; set; } 19 | 20 | public SandboxSettingsSubsection(Ruleset ruleset) 21 | : base(ruleset) 22 | { 23 | } 24 | 25 | [BackgroundDependencyLoader] 26 | private void load() 27 | { 28 | Children = new Drawable[] 29 | { 30 | new SettingsButton 31 | { 32 | Text = "Open Main Screen", 33 | Action = () => 34 | { 35 | try 36 | { 37 | var screenStack = game.GetScreenStack(); 38 | if (!(screenStack.CurrentScreen is MainMenu)) 39 | return; 40 | 41 | var settingOverlay = game.GetSettingsOverlay(); 42 | screenStack?.Push(new MainRulesetScreen()); 43 | settingOverlay?.Hide(); 44 | } 45 | catch 46 | { 47 | } 48 | } 49 | }, 50 | new Container 51 | { 52 | RelativeSizeAxes = Axes.X, 53 | AutoSizeAxes = Axes.Y, 54 | Child = new OsuSpriteText 55 | { 56 | Anchor = Anchor.Centre, 57 | Origin = Anchor.Centre, 58 | Text = "(Available only in the Main Menu)" 59 | } 60 | } 61 | }; 62 | } 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Sandbox/UI/Settings/ColourPickerDropdown.cs: -------------------------------------------------------------------------------- 1 | using osu.Framework.Allocation; 2 | using osu.Framework.Bindables; 3 | using osu.Framework.Graphics; 4 | using osu.Framework.Graphics.Containers; 5 | using osu.Game.Graphics.Sprites; 6 | using osu.Game.Graphics.UserInterfaceV2; 7 | using osu.Game.Rulesets.Sandbox.Configuration; 8 | using osuTK; 9 | 10 | namespace osu.Game.Rulesets.Sandbox.UI.Settings 11 | { 12 | public partial class ColourPickerDropdown : FillFlowContainer 13 | { 14 | private readonly Bindable hexColour = new Bindable(); 15 | 16 | private OsuColourPicker picker; 17 | private readonly SandboxRulesetSetting lookup; 18 | 19 | public ColourPickerDropdown(string name, SandboxRulesetSetting lookup) 20 | { 21 | this.lookup = lookup; 22 | 23 | RelativeSizeAxes = Axes.X; 24 | AutoSizeAxes = Axes.Y; 25 | Direction = FillDirection.Vertical; 26 | Spacing = new Vector2(5); 27 | Children = new Drawable[] 28 | { 29 | new OsuSpriteText 30 | { 31 | Anchor = Anchor.TopCentre, 32 | Origin = Anchor.TopCentre, 33 | Text = name 34 | }, 35 | picker = new OsuColourPicker 36 | { 37 | Anchor = Anchor.TopCentre, 38 | Origin = Anchor.TopCentre 39 | } 40 | }; 41 | } 42 | 43 | [BackgroundDependencyLoader] 44 | private void load(SandboxRulesetConfigManager rulesetConfig) 45 | { 46 | rulesetConfig.BindWith(lookup, hexColour); 47 | } 48 | 49 | protected override void LoadComplete() 50 | { 51 | base.LoadComplete(); 52 | 53 | picker.Current.Value = Colour4.FromHex(hexColour.Value); 54 | picker.Current.BindValueChanged(c => 55 | { 56 | hexColour.Value = c.NewValue.ToHex(); 57 | }); 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Sandbox/UI/Settings/SandboxSettings.cs: -------------------------------------------------------------------------------- 1 | using osu.Framework.Bindables; 2 | using osu.Framework.Graphics.Containers; 3 | using osu.Framework.Graphics; 4 | using osu.Framework.Input.Bindings; 5 | using osu.Game.Input.Bindings; 6 | using osu.Framework.Input.Events; 7 | using osu.Game.Overlays; 8 | using osu.Framework.Graphics.Effects; 9 | using osuTK.Graphics; 10 | using osu.Framework.Graphics.Shapes; 11 | using osu.Game.Graphics.Containers; 12 | using osuTK; 13 | using osu.Framework.Allocation; 14 | 15 | namespace osu.Game.Rulesets.Sandbox.UI.Settings 16 | { 17 | public partial class SandboxSettings : CompositeDrawable, IKeyBindingHandler 18 | { 19 | private const int width = 400; 20 | private const float duration = 250f; 21 | 22 | public SandboxSettingsSection[] Sections 23 | { 24 | set => content.Sections = value; 25 | } 26 | 27 | public readonly BindableBool IsVisible = new BindableBool(); 28 | 29 | private readonly SettingsContent content; 30 | 31 | public SandboxSettings() 32 | { 33 | Anchor = Anchor.CentreRight; 34 | Origin = Anchor.CentreRight; 35 | RelativeSizeAxes = Axes.Y; 36 | InternalChild = content = new SettingsContent 37 | { 38 | Anchor = Anchor.CentreLeft, 39 | Origin = Anchor.CentreLeft, 40 | IsVisible = { BindTarget = IsVisible } 41 | }; 42 | } 43 | 44 | protected override void LoadComplete() 45 | { 46 | base.LoadComplete(); 47 | 48 | IsVisible.BindValueChanged(v => 49 | { 50 | this.ResizeWidthTo(v.NewValue ? width : 0, duration, Easing.OutQuint); 51 | }, true); 52 | 53 | FinishTransforms(true); 54 | } 55 | 56 | public bool OnPressed(KeyBindingPressEvent e) 57 | { 58 | if (!IsVisible.Value) 59 | return false; 60 | 61 | switch (e.Action) 62 | { 63 | case GlobalAction.Back: 64 | IsVisible.Value = false; 65 | return true; 66 | } 67 | 68 | return false; 69 | } 70 | 71 | public void OnReleased(KeyBindingReleaseEvent e) 72 | { 73 | } 74 | 75 | protected override bool OnClick(ClickEvent e) => true; 76 | 77 | private partial class SettingsContent : CompositeDrawable 78 | { 79 | public readonly BindableBool IsVisible = new BindableBool(); 80 | 81 | public SandboxSettingsSection[] Sections 82 | { 83 | set => sectionsFlow.Children = value; 84 | } 85 | 86 | [Cached] 87 | private readonly OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Purple); 88 | private readonly FillFlowContainer sectionsFlow; 89 | 90 | public SettingsContent() 91 | { 92 | RelativeSizeAxes = Axes.Y; 93 | Width = width; 94 | Masking = true; 95 | EdgeEffect = new EdgeEffectParameters 96 | { 97 | Colour = Color4.Black, 98 | Radius = 15, 99 | Type = EdgeEffectType.Shadow 100 | }; 101 | InternalChildren = new Drawable[] 102 | { 103 | new Box 104 | { 105 | RelativeSizeAxes = Axes.Both, 106 | Colour = colourProvider.Background3 107 | }, 108 | new OsuScrollContainer 109 | { 110 | RelativeSizeAxes = Axes.Both, 111 | Child = new Container 112 | { 113 | RelativeSizeAxes = Axes.X, 114 | Padding = new MarginPadding { Horizontal = 15 }, 115 | AutoSizeAxes = Axes.Y, 116 | Margin = new MarginPadding { Vertical = 10 }, 117 | Child = sectionsFlow = new FillFlowContainer 118 | { 119 | RelativeSizeAxes = Axes.X, 120 | AutoSizeAxes = Axes.Y, 121 | Direction = FillDirection.Vertical, 122 | Spacing = new Vector2(0, 10) 123 | } 124 | } 125 | } 126 | }; 127 | } 128 | 129 | protected override void LoadComplete() 130 | { 131 | base.LoadComplete(); 132 | 133 | IsVisible.BindValueChanged(visible => 134 | { 135 | FadeEdgeEffectTo(visible.NewValue ? 0.6f : 0, duration, Easing.OutQuint); 136 | }, true); 137 | } 138 | } 139 | } 140 | } 141 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Sandbox/UI/Settings/SandboxSettingsSection.cs: -------------------------------------------------------------------------------- 1 | using osu.Framework.Allocation; 2 | using osu.Framework.Graphics; 3 | using osu.Framework.Graphics.Containers; 4 | using osu.Game.Graphics; 5 | using osu.Game.Graphics.Sprites; 6 | using osu.Game.Rulesets.Sandbox.Graphics; 7 | using osuTK; 8 | 9 | namespace osu.Game.Rulesets.Sandbox.UI.Settings 10 | { 11 | public abstract partial class SandboxSettingsSection : Container 12 | { 13 | protected abstract string HeaderName { get; } 14 | 15 | protected override Container Content => content; 16 | 17 | private readonly OsuSpriteText header; 18 | private readonly LocalShadowContainer content; 19 | 20 | protected SandboxSettingsSection() 21 | { 22 | RelativeSizeAxes = Axes.X; 23 | AutoSizeAxes = Axes.Y; 24 | InternalChild = new FillFlowContainer 25 | { 26 | RelativeSizeAxes = Axes.X, 27 | AutoSizeAxes = Axes.Y, 28 | Direction = FillDirection.Vertical, 29 | Spacing = new Vector2(0, 10), 30 | Children = new Drawable[] 31 | { 32 | header = new OsuSpriteText 33 | { 34 | Anchor = Anchor.TopCentre, 35 | Origin = Anchor.TopCentre, 36 | Text = HeaderName, 37 | Font = OsuFont.GetFont(size: 30) 38 | }, 39 | content = new LocalShadowContainer() 40 | } 41 | }; 42 | } 43 | 44 | [BackgroundDependencyLoader] 45 | private void load(OsuColour colours) 46 | { 47 | header.Colour = colours.Yellow; 48 | } 49 | 50 | private partial class LocalShadowContainer : InnerShadowContainer 51 | { 52 | protected override Container Content => content; 53 | 54 | private FillFlowContainer content; 55 | 56 | public LocalShadowContainer() 57 | { 58 | RelativeSizeAxes = Axes.X; 59 | AutoSizeAxes = Axes.Y; 60 | CornerRadius = 10; 61 | } 62 | 63 | protected override Container CreateContent() => new Container 64 | { 65 | RelativeSizeAxes = Axes.X, 66 | AutoSizeAxes = Axes.Y, 67 | Padding = new MarginPadding 68 | { 69 | Vertical = 15, 70 | Horizontal = 10 71 | }, 72 | Child = content = new FillFlowContainer 73 | { 74 | Anchor = Anchor.TopCentre, 75 | Origin = Anchor.TopCentre, 76 | RelativeSizeAxes = Axes.X, 77 | AutoSizeAxes = Axes.Y, 78 | Direction = FillDirection.Vertical, 79 | Spacing = new Vector2(0, 5) 80 | } 81 | }; 82 | } 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Sandbox/UI/Settings/SettingsDropdownContainer.cs: -------------------------------------------------------------------------------- 1 | using osu.Framework.Graphics.Containers; 2 | using osu.Framework.Graphics; 3 | using static osu.Game.Graphics.UserInterface.OsuDropdown; 4 | using osu.Framework.Bindables; 5 | 6 | namespace osu.Game.Rulesets.Sandbox.UI.Settings 7 | { 8 | public abstract partial class SettingsDropdownContainer : CompositeDrawable 9 | { 10 | private readonly BindableBool expanded = new BindableBool(); 11 | 12 | protected SettingsDropdownContainer(string label) 13 | { 14 | RelativeSizeAxes = Axes.X; 15 | AutoSizeAxes = Axes.Y; 16 | Padding = new MarginPadding { Horizontal = 20 }; 17 | InternalChild = new FillFlowContainer 18 | { 19 | RelativeSizeAxes = Axes.X, 20 | AutoSizeAxes = Axes.Y, 21 | Direction = FillDirection.Vertical, 22 | Children = new Drawable[] 23 | { 24 | new Header(label), 25 | new DropdownContent 26 | { 27 | Expanded = { BindTarget = expanded }, 28 | Child = CreateContent().With(c => 29 | { 30 | c.Anchor = Anchor.TopCentre; 31 | c.Origin = Anchor.TopCentre; 32 | }) 33 | } 34 | } 35 | }; 36 | } 37 | 38 | protected abstract Drawable CreateContent(); 39 | 40 | private partial class Header : OsuDropdownHeader 41 | { 42 | public Header(string label) 43 | { 44 | Label = label; 45 | } 46 | } 47 | 48 | private partial class DropdownContent : Container 49 | { 50 | private const int animation_duration = 250; 51 | 52 | public readonly BindableBool Expanded = new BindableBool(); 53 | 54 | protected override Container Content { get; } 55 | 56 | public DropdownContent() 57 | { 58 | RelativeSizeAxes = Axes.X; 59 | AutoSizeAxes = Axes.Y; 60 | AutoSizeDuration = animation_duration; 61 | AutoSizeEasing = Easing.Out; 62 | InternalChild = Content = new Container 63 | { 64 | Margin = new MarginPadding { Top = 5 }, 65 | RelativeSizeAxes = Axes.X, 66 | AutoSizeAxes = Axes.Y, 67 | Alpha = 0 68 | }; 69 | } 70 | 71 | protected override void LoadComplete() 72 | { 73 | base.LoadComplete(); 74 | Expanded.BindValueChanged(updateState, true); 75 | } 76 | 77 | private void updateState(ValueChangedEvent expanded) 78 | { 79 | ClearTransforms(true); 80 | 81 | if (expanded.NewValue) 82 | { 83 | AutoSizeAxes = Axes.Y; 84 | Content.FadeIn(animation_duration, Easing.OutQuint); 85 | } 86 | else 87 | { 88 | AutoSizeAxes = Axes.None; 89 | this.ResizeHeightTo(0, animation_duration, Easing.OutQuint); 90 | 91 | Content.FadeOut(animation_duration, Easing.OutQuint); 92 | } 93 | } 94 | } 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Sandbox/UI/StoryboardContainer.cs: -------------------------------------------------------------------------------- 1 | using osu.Framework.Allocation; 2 | using osu.Framework.Bindables; 3 | using osu.Framework.Graphics.Containers; 4 | using osu.Framework.Graphics; 5 | using osu.Game.Beatmaps; 6 | using osu.Game.Configuration; 7 | using osu.Game.Rulesets.Sandbox.Configuration; 8 | using osu.Game.Rulesets.Sandbox.Screens.Visualizer.Components.MusicHelpers; 9 | using osuTK.Graphics; 10 | using System.Threading; 11 | using osu.Framework.Graphics.Shapes; 12 | using osu.Game.Graphics.Backgrounds; 13 | using osu.Game.Storyboards.Drawables; 14 | using osu.Framework.Timing; 15 | using osu.Game.Storyboards; 16 | using osuTK; 17 | using osu.Game.Graphics.UserInterface; 18 | 19 | namespace osu.Game.Rulesets.Sandbox.UI 20 | { 21 | public partial class StoryboardContainer : CurrentBeatmapProvider 22 | { 23 | private readonly BindableDouble dim = new BindableDouble(); 24 | private readonly BindableBool showStoryboard = new BindableBool(); 25 | 26 | private Container storyboardContainer; 27 | private LoadingSpinner loading; 28 | 29 | [BackgroundDependencyLoader] 30 | private void load(OsuConfigManager osuConfig, SandboxRulesetConfigManager rulesetConfig) 31 | { 32 | RelativeSizeAxes = Axes.Both; 33 | Children = new Drawable[] 34 | { 35 | new Container 36 | { 37 | AutoSizeAxes = Axes.Both, 38 | Margin = new MarginPadding(20), 39 | Child = loading = new LoadingSpinner(true) 40 | { 41 | Scale = new Vector2(1.5f) 42 | }, 43 | }, 44 | storyboardContainer = new Container 45 | { 46 | RelativeSizeAxes = Axes.Both 47 | } 48 | }; 49 | 50 | osuConfig?.BindWith(OsuSetting.DimLevel, dim); 51 | rulesetConfig?.BindWith(SandboxRulesetSetting.ShowStoryboard, showStoryboard); 52 | } 53 | 54 | protected override void LoadComplete() 55 | { 56 | base.LoadComplete(); 57 | 58 | dim.BindValueChanged(d => updateStoryboardDim((float)d.NewValue), true); 59 | showStoryboard.BindValueChanged(_ => updateStoryboard(Beatmap.Value)); 60 | } 61 | 62 | protected override void OnBeatmapChanged(ValueChangedEvent beatmap) 63 | { 64 | updateStoryboard(beatmap.NewValue); 65 | } 66 | 67 | private CancellationTokenSource cancellationToken; 68 | private StoryboardLayer storyboard; 69 | 70 | private void updateStoryboard(WorkingBeatmap beatmap) 71 | { 72 | cancellationToken?.Cancel(); 73 | storyboard?.FadeOut(250, Easing.OutQuint).Expire(); 74 | storyboard = null; 75 | 76 | if (!(showStoryboard.Value && beatmap.Storyboard.HasDrawable)) 77 | { 78 | loading.Hide(); 79 | return; 80 | } 81 | 82 | loading.Show(); 83 | 84 | LoadComponentAsync(new StoryboardLayer(beatmap), loaded => 85 | { 86 | storyboardContainer.Add(storyboard = loaded); 87 | loaded.FadeIn(250, Easing.OutQuint); 88 | loading.Hide(); 89 | }, (cancellationToken = new CancellationTokenSource()).Token); 90 | } 91 | 92 | private void updateStoryboardDim(float newDim) => Colour = new Color4(1 - newDim, 1 - newDim, 1 - newDim, 1); 93 | 94 | private partial class StoryboardLayer : AudioContainer 95 | { 96 | private readonly WorkingBeatmap beatmap; 97 | private readonly InterpolatingFramedClock storyboardClock; 98 | 99 | public StoryboardLayer(WorkingBeatmap beatmap) 100 | { 101 | this.beatmap = beatmap; 102 | 103 | storyboardClock = new InterpolatingFramedClock(); 104 | storyboardClock.ChangeSource(beatmap.Track); 105 | storyboardClock.ProcessFrame(); 106 | } 107 | 108 | [BackgroundDependencyLoader] 109 | private void load() 110 | { 111 | RelativeSizeAxes = Axes.Both; 112 | Volume.Value = 0; 113 | Alpha = 0; 114 | 115 | Drawable layer; 116 | 117 | if (beatmap.Storyboard.ReplacesBackground) 118 | { 119 | layer = new Box 120 | { 121 | RelativeSizeAxes = Axes.Both, 122 | Colour = Color4.Black 123 | }; 124 | } 125 | else 126 | { 127 | layer = new BeatmapBackground(beatmap); 128 | } 129 | 130 | Children = new Drawable[] 131 | { 132 | layer, 133 | new FillStoryboard(beatmap.Storyboard) { Clock = new InterpolatingFramedClock(storyboardClock) } 134 | }; 135 | } 136 | 137 | private partial class FillStoryboard : DrawableStoryboard 138 | { 139 | protected override Vector2 DrawScale => Scale; 140 | 141 | public FillStoryboard(Storyboard storyboard) 142 | : base(storyboard) 143 | { 144 | } 145 | 146 | protected override void Update() 147 | { 148 | base.Update(); 149 | Scale = DrawWidth / DrawHeight > Parent.DrawWidth / Parent.DrawHeight ? new Vector2(Parent.DrawHeight / Height) : new Vector2(Parent.DrawWidth / Width); 150 | } 151 | } 152 | } 153 | } 154 | } 155 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Sandbox/osu.Game.Rulesets.Sandbox.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | net8.0 4 | osu.Game.Rulesets.Sandbox 5 | Library 6 | AnyCPU 7 | osu.Game.Rulesets.Sandbox 8 | 8 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | --------------------------------------------------------------------------------