Пример #1
0
 /// <summary>
 /// Called on state update.
 /// </summary>
 /// <param name="DeltaTime">Game clock.</param>
 protected abstract void OnUpdate(IFrameBasedClock clock);
Пример #2
0
 protected abstract GameplayClock CreateGameplayClock(IFrameBasedClock source);
Пример #3
0
            /// <summary>
            /// Create an instance which provides the <see cref="IBeatmap"/> when requested.
            /// </summary>
            /// <param name="beatmap">The beatmap</param>
            /// <param name="storyboard">The storyboard.</param>
            /// <param name="referenceClock">An optional clock which should be used instead of a stopwatch for virtual time progression.</param>
            /// <param name="audio">Audio manager. Required if a reference clock isn't provided.</param>
            public ClockBackedTestWorkingBeatmap(IBeatmap beatmap, Storyboard storyboard, IFrameBasedClock referenceClock, AudioManager audio)
                : base(beatmap, storyboard, audio)
            {
                double trackLength = 60000;

                if (beatmap.HitObjects.Count > 0)
                {
                    // add buffer after last hitobject to allow for final replay frames etc.
                    trackLength = Math.Max(trackLength, beatmap.HitObjects.Max(h => h.GetEndTime()) + 2000);
                }

                if (referenceClock != null)
                {
                    store = new TrackVirtualStore(referenceClock);
                    audio.AddItem(store);
                    track = store.GetVirtual(trackLength);
                }
                else
                {
                    track = audio?.Tracks.GetVirtual(trackLength);
                }
            }
Пример #4
0
 public GameplayClock(IFrameBasedClock underlyingClock)
 {
     this.underlyingClock = underlyingClock;
 }
Пример #5
0
 public TrackVirtualManual(IFrameBasedClock referenceClock)
 {
     this.referenceClock = referenceClock;
     Length = double.PositiveInfinity;
 }
Пример #6
0
        private void load(IFrameBasedClock framedClock)
        {
            try
            {
                drawableRulesetWrapper = new DrawableEditRulesetWrapper <TObject>(CreateDrawableRuleset(Ruleset, workingBeatmap, Array.Empty <Mod>()))
                {
                    Clock = framedClock,
                    ProcessCustomClock = false
                };
            }
            catch (Exception e)
            {
                Logger.Error(e, "Could not load beatmap sucessfully!");
                return;
            }

            var layerBelowRuleset = drawableRulesetWrapper.CreatePlayfieldAdjustmentContainer().WithChildren(new Drawable[]
            {
                distanceSnapGridContainer = new Container {
                    RelativeSizeAxes = Axes.Both
                },
                new EditorPlayfieldBorder {
                    RelativeSizeAxes = Axes.Both
                }
            });

            var layerAboveRuleset = drawableRulesetWrapper.CreatePlayfieldAdjustmentContainer().WithChild(blueprintContainer = new BlueprintContainer());

            layerContainers.Add(layerBelowRuleset);
            layerContainers.Add(layerAboveRuleset);

            RadioButtonCollection toolboxCollection;

            InternalChild = new GridContainer
            {
                RelativeSizeAxes = Axes.Both,
                Content          = new[]
                {
                    new Drawable[]
                    {
                        new FillFlowContainer
                        {
                            Name             = "Sidebar",
                            RelativeSizeAxes = Axes.Both,
                            Padding          = new MarginPadding {
                                Right = 10
                            },
                            Children = new Drawable[]
                            {
                                new ToolboxGroup {
                                    Child = toolboxCollection = new RadioButtonCollection {
                                        RelativeSizeAxes = Axes.X
                                    }
                                }
                            }
                        },
                        new Container
                        {
                            Name             = "Content",
                            RelativeSizeAxes = Axes.Both,
                            Children         = new Drawable[]
                            {
                                layerBelowRuleset,
                                drawableRulesetWrapper,
                                layerAboveRuleset
                            }
                        }
                    },
                },
                ColumnDimensions = new[]
                {
                    new Dimension(GridSizeMode.Absolute, 200),
                }
            };

            toolboxCollection.Items =
                CompositionTools.Select(t => new RadioButton(t.Name, () => selectTool(t)))
                .Prepend(new RadioButton("Select", () => selectTool(null)))
                .ToList();

            toolboxCollection.Items[0].Select();

            blueprintContainer.SelectionChanged += selectionChanged;
        }
Пример #7
0
 public override void UpdateClock(IFrameBasedClock clock)
 {
     base.UpdateClock(clock);
     textUpdateScheduler.UpdateClock(Clock);
 }
Пример #8
0
        public TestCaseKeyCounter()
        {
            KeyCounterKeyboard   rewindTestKeyCounterKeyboard;
            KeyCounterCollection kc = new KeyCounterCollection
            {
                Origin   = Anchor.Centre,
                Anchor   = Anchor.Centre,
                Children = new KeyCounter[]
                {
                    rewindTestKeyCounterKeyboard = new KeyCounterKeyboard(Key.X),
                    new KeyCounterKeyboard(Key.X),
                    new KeyCounterMouse(MouseButton.Left),
                    new KeyCounterMouse(MouseButton.Right),
                },
            };

            AddStep("Add random", () =>
            {
                Key key = (Key)((int)Key.A + RNG.Next(26));
                kc.Add(new KeyCounterKeyboard(key));
            });
            AddSliderStep("Fade time", 0, 200, 50, v => kc.FadeTime = v);

            Key    testKey = ((KeyCounterKeyboard)kc.Children.First()).Key;
            double time1   = 0;

            AddStep($"Press {testKey} key", () =>
            {
                InputManager.PressKey(testKey);
                InputManager.ReleaseKey(testKey);
            });

            AddAssert($"Check {testKey} counter after keypress", () => rewindTestKeyCounterKeyboard.CountPresses == 1);

            AddStep($"Press {testKey} key", () =>
            {
                InputManager.PressKey(testKey);
                InputManager.ReleaseKey(testKey);
                time1 = Clock.CurrentTime;
            });

            AddAssert($"Check {testKey} counter after keypress", () => rewindTestKeyCounterKeyboard.CountPresses == 2);

            IFrameBasedClock oldClock = null;

            AddStep($"Rewind {testKey} counter once", () =>
            {
                oldClock = rewindTestKeyCounterKeyboard.Clock;
                rewindTestKeyCounterKeyboard.Clock = new FramedOffsetClock(new FixedClock(time1 - 10));
            });

            AddAssert($"Check {testKey} counter after rewind", () => rewindTestKeyCounterKeyboard.CountPresses == 1);

            AddStep($"Rewind {testKey} counter to zero", () => rewindTestKeyCounterKeyboard.Clock = new FramedOffsetClock(new FixedClock(0)));

            AddAssert($"Check {testKey} counter after rewind", () => rewindTestKeyCounterKeyboard.CountPresses == 0);

            AddStep("Restore clock", () => rewindTestKeyCounterKeyboard.Clock = oldClock);

            Add(kc);
        }
 public TestWorkingBeatmap(BeatmapInfo skinBeatmapInfo, IResourceStore <byte[]> resourceStore, IBeatmap beatmap, Storyboard storyboard, IFrameBasedClock referenceClock, AudioManager audio,
                           double length = 60000)
     : base(beatmap, storyboard, referenceClock, audio, length)
 {
     this.skinBeatmapInfo = skinBeatmapInfo;
     this.resourceStore   = resourceStore;
 }
Пример #10
0
 internal override void UpdateClock(IFrameBasedClock clock)
 {
     Content.Clock = clock;
     base.UpdateClock(clock);
 }
Пример #11
0
 protected virtual WorkingBeatmap CreateWorkingBeatmap(IBeatmap beatmap, IFrameBasedClock clock) =>
 new TestWorkingBeatmap(beatmap, Clock);
Пример #12
0
        /// <summary>
        /// Update the state of this element.
        /// </summary>
        /// <param name="clock">Game clock.</param>
        public override void Update(IFrameBasedClock clock)
        {
            base.Update(clock);

            HardwareInput.Update(clock);

            InputStates[HardwareKeyboard].Time = clock.CurrentTime;
            InputStates[HardwareMouse].Time    = clock.CurrentTime;

            // - Remove unused joypads
            var removed = InputStates.Keys.Where(x => x is IJoypad).Except(HardwareJoypads);

            foreach (IJoypad pad in removed)
            {
                InputStates.Remove(pad);
            }

            // - Update joypad states
            foreach (IJoypad pad in HardwareJoypads)
            {
                if (!InputStates.ContainsKey(pad))
                {
                    InputStates.Add(pad, new InputState());
                }

                for (uint i = 0; i < pad.Buttons.Count(); ++i)
                {
                    if (pad.Buttons[i] != InputStates[pad].GetKeyState(i))
                    {
                        InputStates[pad].Events.Enqueue(new InputEvent <JoypadKeyEventArgs>
                        {
                            Name = "OnButtonPress",
                            Info = new JoypadKeyEventArgs
                            {
                                Key    = (int)i,
                                Action = pad.Buttons[i]
                            }
                        });
                    }

                    InputStates[pad].SetKeyState(i, pad.Buttons[i]);
                }

                for (uint i = 0; i < pad.Axes.Count(); ++i)
                {
                    if (pad.Axes[i] != InputStates[pad].GetPositionState(i))
                    {
                        InputStates[pad].Events.Enqueue(new InputEvent <JoypadAxeEventArgs>
                        {
                            Name = "OnAxeMovement",
                            Info = new JoypadAxeEventArgs
                            {
                                Axe   = (int)i,
                                Value = pad.Axes[i]
                            }
                        });
                    }

                    InputStates[pad].SetPositionState(i, (float)pad.Axes[i]);
                }

                InputStates[pad].Time = clock.CurrentTime;
            }

            Mouse.UpdateCurrentState(InputStates?[HardwareMouse]);
            Keyboard.UpdateCurrentState(InputStates?[HardwareKeyboard]);

            Mouse.Update(clock);
            Keyboard.Update(clock);

            foreach (var j in Joypads)
            {
                j.UpdateCurrentState(InputStates?[HardwareJoypads.Where(x => x.Index == j.Index).FirstOrDefault()]);
                j.Update(clock);
            }

            // - Update binding
            CurrentBinding?.Update(clock);
        }
Пример #13
0
 internal virtual void UpdateClock(IFrameBasedClock clock)
 {
     this.clock = customClock ?? clock;
 }
Пример #14
0
 protected override GameplayClock CreateGameplayClock(IFrameBasedClock source) => new GameplayClock(source);
Пример #15
0
        private void load(OsuGameBase osuGame, IFrameBasedClock framedClock)
        {
            beatmap.BindTo(osuGame.Beatmap);

            try
            {
                rulesetContainer       = CreateRulesetContainer(ruleset, beatmap.Value);
                rulesetContainer.Clock = framedClock;
            }
            catch (Exception e)
            {
                Logger.Error(e, "Could not load beatmap sucessfully!");
                return;
            }

            var layerBelowRuleset = new BorderLayer
            {
                RelativeSizeAxes = Axes.Both,
                Child            = CreateLayerContainer()
            };

            var layerAboveRuleset = CreateLayerContainer();

            layerAboveRuleset.Child = new HitObjectMaskLayer(rulesetContainer.Playfield, this);

            layerContainers.Add(layerBelowRuleset);
            layerContainers.Add(layerAboveRuleset);

            RadioButtonCollection toolboxCollection;

            InternalChild = new GridContainer
            {
                RelativeSizeAxes = Axes.Both,
                Content          = new[]
                {
                    new Drawable[]
                    {
                        new FillFlowContainer
                        {
                            Name             = "Sidebar",
                            RelativeSizeAxes = Axes.Both,
                            Padding          = new MarginPadding {
                                Right = 10
                            },
                            Children = new Drawable[]
                            {
                                new ToolboxGroup {
                                    Child = toolboxCollection = new RadioButtonCollection {
                                        RelativeSizeAxes = Axes.X
                                    }
                                }
                            }
                        },
                        new Container
                        {
                            Name             = "Content",
                            RelativeSizeAxes = Axes.Both,
                            Children         = new Drawable[]
                            {
                                layerBelowRuleset,
                                rulesetContainer,
                                layerAboveRuleset
                            }
                        }
                    },
                },
                ColumnDimensions = new[]
                {
                    new Dimension(GridSizeMode.Absolute, 200),
                }
            };

            toolboxCollection.Items =
                CompositionTools.Select(t => new RadioButton(t.Name, () => setCompositionTool(t)))
                .Prepend(new RadioButton("Select", () => setCompositionTool(null)))
                .ToList();

            toolboxCollection.Items[0].Select();
        }
Пример #16
0
        private void load(IFrameBasedClock framedClock)
        {
            beatmapProcessor = Ruleset.CreateBeatmapProcessor(EditorBeatmap.PlayableBeatmap);

            EditorBeatmap.HitObjectAdded   += addHitObject;
            EditorBeatmap.HitObjectRemoved += removeHitObject;
            EditorBeatmap.StartTimeChanged += UpdateHitObject;

            Config = Dependencies.Get <RulesetConfigCache>().GetConfigFor(Ruleset);

            try
            {
                drawableRulesetWrapper = new DrawableEditRulesetWrapper <TObject>(CreateDrawableRuleset(Ruleset, EditorBeatmap.PlayableBeatmap))
                {
                    Clock = framedClock,
                    ProcessCustomClock = false
                };
            }
            catch (Exception e)
            {
                Logger.Error(e, "Could not load beatmap sucessfully!");
                return;
            }

            var layerBelowRuleset = drawableRulesetWrapper.CreatePlayfieldAdjustmentContainer().WithChildren(new Drawable[]
            {
                distanceSnapGridContainer = new Container {
                    RelativeSizeAxes = Axes.Both
                },
                new EditorPlayfieldBorder {
                    RelativeSizeAxes = Axes.Both
                }
            });

            var layerAboveRuleset = drawableRulesetWrapper.CreatePlayfieldAdjustmentContainer().WithChild(blueprintContainer = CreateBlueprintContainer());

            layerContainers.Add(layerBelowRuleset);
            layerContainers.Add(layerAboveRuleset);

            InternalChild = new GridContainer
            {
                RelativeSizeAxes = Axes.Both,
                Content          = new[]
                {
                    new Drawable[]
                    {
                        new FillFlowContainer
                        {
                            Name             = "Sidebar",
                            RelativeSizeAxes = Axes.Both,
                            Padding          = new MarginPadding {
                                Right = 10
                            },
                            Children = new Drawable[]
                            {
                                new ToolboxGroup {
                                    Child = toolboxCollection = new RadioButtonCollection {
                                        RelativeSizeAxes = Axes.X
                                    }
                                }
                            }
                        },
                        new Container
                        {
                            Name             = "Content",
                            RelativeSizeAxes = Axes.Both,
                            Children         = new Drawable[]
                            {
                                layerBelowRuleset,
                                drawableRulesetWrapper,
                                layerAboveRuleset
                            }
                        }
                    },
                },
                ColumnDimensions = new[]
                {
                    new Dimension(GridSizeMode.Absolute, 200),
                }
            };

            toolboxCollection.Items = CompositionTools
                                      .Prepend(new SelectTool())
                                      .Select(t => new RadioButton(t.Name, () => toolSelected(t)))
                                      .ToList();

            setSelectTool();

            blueprintContainer.SelectionChanged += selectionChanged;
        }
Пример #17
0
        private void load(IBindable <WorkingBeatmap> beatmap, IFrameBasedClock framedClock)
        {
            Beatmap.BindTo(beatmap);

            try
            {
                RulesetContainer       = CreateRulesetContainer();
                RulesetContainer.Clock = framedClock;
            }
            catch (Exception e)
            {
                Logger.Error(e, "Could not load beatmap sucessfully!");
                return;
            }

            var layerBelowRuleset = CreateLayerContainer();

            layerBelowRuleset.Child = new EditorPlayfieldBorder {
                RelativeSizeAxes = Axes.Both
            };

            var layerAboveRuleset = CreateLayerContainer();

            layerAboveRuleset.Child = blueprintContainer = new BlueprintContainer();

            layerContainers.Add(layerBelowRuleset);
            layerContainers.Add(layerAboveRuleset);

            RadioButtonCollection toolboxCollection;

            InternalChild = new GridContainer
            {
                RelativeSizeAxes = Axes.Both,
                Content          = new[]
                {
                    new Drawable[]
                    {
                        new FillFlowContainer
                        {
                            Name             = "Sidebar",
                            RelativeSizeAxes = Axes.Both,
                            Padding          = new MarginPadding {
                                Right = 10
                            },
                            Children = new Drawable[]
                            {
                                new ToolboxGroup {
                                    Child = toolboxCollection = new RadioButtonCollection {
                                        RelativeSizeAxes = Axes.X
                                    }
                                }
                            }
                        },
                        new Container
                        {
                            Name             = "Content",
                            RelativeSizeAxes = Axes.Both,
                            Children         = new Drawable[]
                            {
                                layerBelowRuleset,
                                RulesetContainer,
                                layerAboveRuleset
                            }
                        }
                    },
                },
                ColumnDimensions = new[]
                {
                    new Dimension(GridSizeMode.Absolute, 200),
                }
            };

            toolboxCollection.Items =
                CompositionTools.Select(t => new RadioButton(t.Name, () => blueprintContainer.CurrentTool = t))
                .Prepend(new RadioButton("Select", () => blueprintContainer.CurrentTool = null))
                .ToList();

            toolboxCollection.Items[0].Select();
        }
Пример #18
0
 public TestWorkingBeatmap(BeatmapInfo skinBeatmapInfo, IResourceStore <byte[]> resourceStore, IBeatmap beatmap, Storyboard storyboard, IFrameBasedClock referenceClock, IStorageResourceProvider resources)
     : base(beatmap, storyboard, referenceClock, resources.AudioManager)
 {
     this.skinBeatmapInfo = skinBeatmapInfo;
     this.resourceStore   = resourceStore;
     this.resources       = resources;
 }
Пример #19
0
        private void load(AudioManager audio, BeatmapDatabase beatmaps, OsuConfigManager config)
        {
            var beatmap = Beatmap.Beatmap;

            if (beatmap.BeatmapInfo?.Mode > PlayMode.Osu)
            {
                //we only support osu! mode for now because the hitobject parsing is crappy and needs a refactor.
                Exit();
                return;
            }

            Beatmap.Mods.Value.ForEach(m => m.PlayerLoading(this));

            dimLevel           = config.GetBindable <int>(OsuConfig.DimLevel);
            mouseWheelDisabled = config.GetBindable <bool>(OsuConfig.MouseDisableWheel);

            try
            {
                if (Beatmap == null)
                {
                    Beatmap = beatmaps.GetWorkingBeatmap(BeatmapInfo, withStoryboard: true);
                }

                if ((Beatmap?.Beatmap?.HitObjects.Count ?? 0) == 0)
                {
                    throw new Exception("No valid objects were found!");
                }

                if (Beatmap == null)
                {
                    throw new Exception("Beatmap was not loaded");
                }
            }
            catch (Exception e)
            {
                Logger.Log($"Could not load this beatmap sucessfully ({e})!", LoggingTarget.Runtime, LogLevel.Error);

                //couldn't load, hard abort!
                Exit();
                return;
            }

            Track track = Beatmap.Track;

            if (track != null)
            {
                audio.Track.SetExclusive(track);
                sourceClock = track;
            }

            sourceClock             = (IAdjustableClock)track ?? new StopwatchClock();
            interpolatedSourceClock = new InterpolatingFramedClock(sourceClock);

            Schedule(() =>
            {
                sourceClock.Reset();
            });

            ruleset = Ruleset.GetRuleset(Beatmap.PlayMode);

            hudOverlay = new StandardHudOverlay();
            hudOverlay.KeyCounter.Add(ruleset.CreateGameplayKeys());
            hudOverlay.BindProcessor(scoreProcessor = ruleset.CreateScoreProcessor(beatmap.HitObjects.Count));

            pauseOverlay = new PauseOverlay
            {
                Depth    = -1,
                OnResume = delegate
                {
                    Delay(400);
                    Schedule(Resume);
                },
                OnRetry = Restart,
                OnQuit  = Exit
            };

            hitRenderer = ruleset.CreateHitRendererWith(beatmap);

            if (ReplayInputHandler != null)
            {
                ReplayInputHandler.ToScreenSpace            = hitRenderer.MapPlayfieldToScreenSpace;
                hitRenderer.InputManager.ReplayInputHandler = ReplayInputHandler;
            }

            hudOverlay.BindHitRenderer(hitRenderer);

            //bind HitRenderer to ScoreProcessor and ourselves (for a pass situation)
            hitRenderer.OnJudgement += scoreProcessor.AddJudgement;
            hitRenderer.OnAllJudged += onPass;

            //bind ScoreProcessor to ourselves (for a fail situation)
            scoreProcessor.Failed += onFail;

            Children = new Drawable[]
            {
                new Container
                {
                    RelativeSizeAxes = Axes.Both,
                    Clock            = interpolatedSourceClock,
                    Children         = new Drawable[]
                    {
                        hitRenderer,
                        skipButton = new SkipButton
                        {
                            Alpha = 0
                        },
                    }
                },
                hudOverlay,
                pauseOverlay
            };
        }
Пример #20
0
 /// <summary>
 /// Handle a physics calculation frame.
 /// </summary>
 /// <param name="clock">Timed clock.</param>
 protected virtual void HandlePhysics(IFrameBasedClock clock)
 {
     // - Update game
     GameTree.Update(clock);
 }
 public CustomSkinWorkingBeatmap(IBeatmap beatmap, Storyboard storyboard, IFrameBasedClock referenceClock, AudioManager audio, ISkin beatmapSkin)
     : base(beatmap, storyboard, referenceClock, audio)
 {
     this.beatmapSkin = beatmapSkin;
 }
Пример #22
0
        /// <summary>
        /// Update the state of this element.
        /// </summary>
        /// <param name="clock">Game clock.</param>
        public override void Update(IFrameBasedClock clock)
        {
            base.Update(clock);

            RunningGame?.Update(clock);
        }
Пример #23
0
 /// <summary>
 /// Create an instance which provides the <see cref="IBeatmap"/> when requested.
 /// </summary>
 /// <param name="beatmap">The beatmap</param>
 /// <param name="storyboard">The storyboard.</param>
 /// <param name="referenceClock">An optional clock which should be used instead of a stopwatch for virtual time progression.</param>
 /// <param name="audio">Audio manager. Required if a reference clock isn't provided.</param>
 /// <param name="length">The length of the returned virtual track.</param>
 public ClockBackedTestWorkingBeatmap(IBeatmap beatmap, Storyboard storyboard, IFrameBasedClock referenceClock, AudioManager audio, double length = 60000)
     : base(beatmap, storyboard)
 {
     if (referenceClock != null)
     {
         store = new TrackVirtualStore(referenceClock);
         audio.AddItem(store);
         track = store.GetVirtual(length);
     }
     else
     {
         track = audio?.Tracks.GetVirtual(length);
     }
 }
Пример #24
0
 /// <summary>
 /// Update the state of this element
 /// </summary>
 /// <param name="DeltaTime">Game clock.</param>
 public void Update(IFrameBasedClock Clock)
 {
 }
Пример #25
0
 /// <summary>
 /// Update the state of this element
 /// </summary>
 /// <param name="DeltaTime">Game clock.</param>
 public virtual void Update(IFrameBasedClock clock)
 {
 }
Пример #26
0
 public FpsDisplay(IFrameBasedClock clock)
 {
     this.clock = clock;
 }
Пример #27
0
 /// <summary>
 /// Create an instance which creates a <see cref="TestBeatmap"/> for the provided ruleset when requested.
 /// </summary>
 /// <param name="ruleset">The target ruleset.</param>
 /// <param name="referenceClock">A clock which should be used instead of a stopwatch for virtual time progression.</param>
 /// <param name="audio">Audio manager. Required if a reference clock isn't provided.</param>
 public ClockBackedTestWorkingBeatmap(RulesetInfo ruleset, IFrameBasedClock referenceClock, AudioManager audio)
     : this(new TestBeatmap(ruleset), null, referenceClock, audio)
 {
 }
Пример #28
0
 public CustomSkinWorkingBeatmap(IBeatmap beatmap, IFrameBasedClock frameBasedClock, AudioManager audio, ISkinSource skin)
     : base(beatmap, frameBasedClock, audio)
 {
     this.skin = skin;
 }
Пример #29
0
 public TrackVirtualStore(IFrameBasedClock referenceClock)
 {
     this.referenceClock = referenceClock;
 }
Пример #30
0
        private void load([NotNull] OsuGameBase osuGame, [NotNull] IAdjustableClock adjustableClock, [NotNull] IFrameBasedClock framedClock, [CanBeNull] BindableBeatDivisor beatDivisor)
        {
            this.adjustableClock = adjustableClock;

            if (beatDivisor != null)
            {
                this.beatDivisor.BindTo(beatDivisor);
            }

            beatmap.BindTo(osuGame.Beatmap);

            try
            {
                rulesetContainer       = CreateRulesetContainer(ruleset, beatmap.Value);
                rulesetContainer.Clock = framedClock;
            }
            catch (Exception e)
            {
                Logger.Error(e, "Could not load beatmap sucessfully!");
                return;
            }

            HitObjectMaskLayer hitObjectMaskLayer = new HitObjectMaskLayer(this);
            SelectionLayer     selectionLayer     = new SelectionLayer(rulesetContainer.Playfield);

            var layerBelowRuleset = new BorderLayer
            {
                RelativeSizeAxes = Axes.Both,
                Child            = CreateLayerContainer()
            };

            var layerAboveRuleset = CreateLayerContainer();

            layerAboveRuleset.Children = new Drawable[]
            {
                selectionLayer,              // Below object overlays for input
                hitObjectMaskLayer,
                selectionLayer.CreateProxy() // Proxy above object overlays for selections
            };

            layerContainers.Add(layerBelowRuleset);
            layerContainers.Add(layerAboveRuleset);

            RadioButtonCollection toolboxCollection;

            InternalChild = new GridContainer
            {
                RelativeSizeAxes = Axes.Both,
                Content          = new[]
                {
                    new Drawable[]
                    {
                        new FillFlowContainer
                        {
                            Name             = "Sidebar",
                            RelativeSizeAxes = Axes.Both,
                            Padding          = new MarginPadding {
                                Right = 10
                            },
                            Children = new Drawable[]
                            {
                                new ToolboxGroup {
                                    Child = toolboxCollection = new RadioButtonCollection {
                                        RelativeSizeAxes = Axes.X
                                    }
                                }
                            }
                        },
                        new Container
                        {
                            Name             = "Content",
                            RelativeSizeAxes = Axes.Both,
                            Children         = new Drawable[]
                            {
                                layerBelowRuleset,
                                rulesetContainer,
                                layerAboveRuleset
                            }
                        }
                    },
                },
                ColumnDimensions = new[]
                {
                    new Dimension(GridSizeMode.Absolute, 200),
                }
            };

            selectionLayer.ObjectSelected    += hitObjectMaskLayer.AddOverlay;
            selectionLayer.ObjectDeselected  += hitObjectMaskLayer.RemoveOverlay;
            selectionLayer.SelectionCleared  += hitObjectMaskLayer.RemoveSelectionOverlay;
            selectionLayer.SelectionFinished += hitObjectMaskLayer.AddSelectionOverlay;

            toolboxCollection.Items =
                new[] { new RadioButton("Select", () => setCompositionTool(null)) }
            .Concat(
                CompositionTools.Select(t => new RadioButton(t.Name, () => setCompositionTool(t)))
                )
            .ToList();

            toolboxCollection.Items[0].Select();
        }