Пример #1
0
        // For ScoreEditor
        public void Render(Graphics context, Score score, ScoreEditorConfig config, ScoreEditorLook look, float scrollOffsetY, Rectangle selectionRectangle)
        {
            var hasAnyBar = score?.HasAnyBar ?? false;

            if (hasAnyBar)
            {
                RenderBars(context, score, config, look, scrollOffsetY);
            }
            var hasAnyNote = score?.HasAnyNote ?? false;

            if (hasAnyNote)
            {
                RenderNotes(context, score, config, look, scrollOffsetY);
            }
            RenderSelectionRectangle(context, selectionRectangle);
        }
Пример #2
0
        // For ScorePreviewer
        public void Render(Graphics context, Score score, ScoreEditorConfig config, ScoreEditorLook look, float scrollOffsetY, TimeSpan now)
        {
            var hasAnyBar = score?.HasAnyBar ?? false;

            if (hasAnyBar)
            {
                RenderBars(context, score, config, look, scrollOffsetY);
            }
            var hasAnyNote = score?.HasAnyNote ?? false;

            if (hasAnyNote)
            {
                RenderNotes(context, score, config, look, scrollOffsetY);
            }
            if (look.TimeInfoVisible)
            {
                var controlArea = new Rectangle(Point.Zero, context.Bounds.Size);
                DrawBarTimePreviewInfo(context, controlArea, now);
            }
        }
Пример #3
0
        public static float GetScrollOffsetY(Score score, IReadOnlyList <IReadOnlyList <TimeSpan> > scoreTimingInfo, TimeSpan now, ScoreEditorLook look, Size clientSize, float fullHeight)
        {
            if (!score.HasAnyBar)
            {
                return(0);
            }

            var middleY = clientSize.Height / 2;
            var unit    = look.BarLineSpaceUnit;

            // If we haven't reached the first note...
            var firstBarTimingInfo = scoreTimingInfo[0];

            if (now < firstBarTimingInfo[0])
            {
                var firstDeltaTime = firstBarTimingInfo[1] - firstBarTimingInfo[0];
                var expectedUnits  = unit * (float)(firstBarTimingInfo[0].TotalSeconds / firstDeltaTime.TotalSeconds);
                var firstRatio     = (float)((now - firstBarTimingInfo[0]).TotalSeconds / scoreTimingInfo[0][0].TotalSeconds);
                return(middleY + expectedUnits * firstRatio);
            }

            // Or the song has ended...
            var lastBarInfo = scoreTimingInfo[scoreTimingInfo.Count - 1];

            if (now > lastBarInfo[lastBarInfo.Count - 1])
            {
                var lastDeltaTime = lastBarInfo[lastBarInfo.Count - 1] - lastBarInfo[lastBarInfo.Count - 2];
                var expectedUnits = unit * (float)((now - lastBarInfo[lastBarInfo.Count - 1]).TotalSeconds / lastDeltaTime.TotalSeconds);
                return(middleY + fullHeight + expectedUnits);
            }

            // Otherwise, scan through the bars and find the first match.
            var currentBar = score.Bars[0];

            for (var i = 1; i < score.Bars.Count; ++i)
            {
                if (scoreTimingInfo[i][0] >= now)
                {
                    break;
                }
                currentBar = score.Bars[i];
            }

            // Find the grid.
            var currentBarIndex      = currentBar.Basic.Index;
            var currentBarTimingInfo = scoreTimingInfo[currentBarIndex];
            var prevTimingIndex      = 0;

            for (var i = 1; i < currentBarTimingInfo.Count; ++i)
            {
                if (currentBarTimingInfo[i] > now)
                {
                    break;
                }
                prevTimingIndex = i;
            }

            TimeSpan nextTiming;
            var      prevTiming = currentBarTimingInfo[prevTimingIndex];

            if (prevTimingIndex == currentBarTimingInfo.Count - 1)
            {
                // The "last line of last bar" occasion is already filtered out,
                // so here we handle a simpler case.
                nextTiming = scoreTimingInfo[currentBarIndex + 1][0];
            }
            else
            {
                nextTiming = currentBarTimingInfo[prevTimingIndex + 1];
            }

            var ratio = (float)((now - prevTiming).TotalSeconds / (nextTiming - prevTiming).TotalSeconds);

            float offset = middleY;

            for (var i = 0; i < currentBarIndex; ++i)
            {
                offset += unit * score.Bars[i].GetNumberOfGrids();
            }
            offset += unit * prevTimingIndex + unit * ratio;

            return(offset);
        }
Пример #4
0
        private void RenderBars(Graphics context, Score score, ScoreEditorConfig config, ScoreEditorLook look, float barStartY)
        {
            var bars            = score.Bars;
            var primaryBeatMode = look.PrimaryBeatMode;
            var gridArea        = ScoreEditorLayout.GetGridArea(config, context.Bounds);
            var barArea         = ScoreEditorLayout.GetBarArea(config, context.Bounds);
            var infoArea        = ScoreEditorLayout.GetInfoArea(config, context.Bounds);

            var unit       = look.BarLineSpaceUnit;
            var noteRadius = config.NoteRadius;

            foreach (var bar in bars)
            {
                var numberOfGrids = bar.GetNumberOfGrids();
                var visible       = ScoreEditorLayout.IsBarVisible(barArea, barStartY, numberOfGrids, unit);
                if (visible)
                {
                    if (look.BarInfoTextVisible)
                    {
                        DrawBarInfoText(context, bar, infoArea, barStartY);
                    }
                    DrawBarGrid(context, gridArea, config, barStartY, numberOfGrids, unit, noteRadius, primaryBeatMode);
                    DrawBarOutline(context, bar, barArea, barStartY, numberOfGrids, unit);
                }
                barStartY -= numberOfGrids * unit;
            }
        }
Пример #5
0
        private void DrawNotes(Graphics context, Score score, Rectangle gridArea, ScoreEditorConfig config, ScoreEditorLook look, Rectangle specialNoteArea, float noteStartY, float radius)
        {
            if (!score.HasAnyNote)
            {
                return;
            }

            var unit = look.BarLineSpaceUnit;
            var startPositionFont    = _noteStartPositionFont;
            var shouldDrawIndicators = look.IndicatorsVisible;
            var numColumns           = config.NumberOfColumns;

            foreach (var bar in score.Bars)
            {
                var numberOfGrids = bar.GetNumberOfGrids();
                if (bar.Helper.HasAnyNote)
                {
                    foreach (var note in bar.Notes)
                    {
                        if (!ScoreEditorLayout.IsNoteVisible(note, gridArea, noteStartY, unit, radius))
                        {
                            continue;
                        }

                        if (note.Helper.IsGaming)
                        {
                            var x = ScoreEditorLayout.GetNotePositionX(note, gridArea, numColumns);
                            var y = ScoreEditorLayout.GetNotePositionY(note, unit, noteStartY);
                            var h = note.Helper;
                            if (h.IsSlide)
                            {
                                if (h.HasNextFlick)
                                {
                                    DrawFlickNote(context, note, x, y, radius, note.Basic.FlickType);
                                }
                                else
                                {
                                    DrawSlideNote(context, note, x, y, radius, h.IsSlideMidway);
                                }
                            }
                            else if (h.IsHoldStart)
                            {
                                DrawHoldNote(context, note, x, y, radius);
                            }
                            else
                            {
                                if (note.Basic.FlickType != NoteFlickType.None)
                                {
                                    DrawFlickNote(context, note, x, y, radius, note.Basic.FlickType);
                                }
                                else if (h.IsHoldEnd)
                                {
                                    DrawHoldNote(context, note, x, y, radius);
                                }
                                else
                                {
                                    DrawTapNote(context, note, x, y, radius);
                                }
                            }

                            // Indicators
                            if (shouldDrawIndicators)
                            {
                                if (note.Helper.IsSync)
                                {
                                    context.FillCircle(_syncIndicatorBrush, x + radius, y - radius, Definitions.IndicatorRadius);
                                }
                                if (note.Helper.IsHold)
                                {
                                    context.FillCircle(_holdIndicatorBrush, x - radius, y + radius, Definitions.IndicatorRadius);
                                }
                                if (note.Helper.IsSlide)
                                {
                                    context.FillCircle(_slideIndicatorBrush, x + radius, y + radius, Definitions.IndicatorRadius);
                                }
                                else if (note.Helper.IsFlick)
                                {
                                    context.FillCircle(_flickIndicatorBrush, x + radius, y + radius, Definitions.IndicatorRadius);
                                }
                            }

                            // Start position
                            if (note.Basic.StartPosition != note.Basic.FinishPosition)
                            {
                                var startPositionX = x - radius - Definitions.StartPositionFontSize / 2;
                                var startPositionY = y - radius - Definitions.StartPositionFontSize / 2;
                                var text           = ((int)note.Basic.StartPosition).ToString();
                                var textSize       = context.MeasureString(startPositionFont, text);
                                context.FillString(_noteCommonFill, startPositionFont, text, startPositionX, startPositionY + textSize.Y);
                            }
                        }
                        else if (note.Helper.IsSpecial)
                        {
                            // Draw a special note (a rectangle)
                            var left   = specialNoteArea.Left + radius * 4;
                            var gridY  = ScoreEditorLayout.GetNotePositionY(note, unit, noteStartY);
                            var top    = gridY - radius * Definitions.SpecialNoteHeightFactor;
                            var width  = specialNoteArea.Right - left;
                            var height = radius * 2 * Definitions.SpecialNoteHeightFactor;
                            context.DrawRectangle(_specialNoteStroke, left, top, width, height);
                            context.FillRectangle(_specialNoteFill, left, top, width, height);

                            string specialNoteText;
                            switch (note.Basic.Type)
                            {
                            case NoteType.VariantBpm:
                                specialNoteText = $"BPM: {note.Params.NewBpm:0.00}";
                                break;

                            default:
                                throw new ArgumentOutOfRangeException(nameof(note.Basic.Type), note.Basic.Type, null);
                            }
                            var rect     = context.MeasureString(_specialNoteDescriptionFont, specialNoteText);
                            var textLeft = left + 2;
                            var textTop  = gridY + rect.Y / 2;
                            context.FillString(_specialNoteTextBrush, _specialNoteDescriptionFont, specialNoteText, textLeft, textTop);
                        }
                    }
                }
                noteStartY -= numberOfGrids * unit;
            }
        }
Пример #6
0
        private void DrawNoteConnections(Graphics context, Score score, Rectangle gridArea, ScoreEditorConfig config, ScoreEditorLook look, float scrollOffsetY, float noteStartY, float radius)
        {
            if (!score.HasAnyNote)
            {
                return;
            }

            var unit       = look.BarLineSpaceUnit;
            var numColumns = config.NumberOfColumns;

            foreach (var bar in score.Bars)
            {
                var numberOfGrids = bar.GetNumberOfGrids();
                if (bar.Helper.HasAnyNote)
                {
                    foreach (var note in bar.Notes)
                    {
                        var thisStatus = ScoreEditorLayout.GetNoteOnStageStatus(note, gridArea, noteStartY, unit, radius);
                        var x1         = ScoreEditorLayout.GetNotePositionX(note, gridArea, numColumns);
                        var y1         = ScoreEditorLayout.GetNotePositionY(note, unit, noteStartY);
                        if (note.Helper.HasNextSync && thisStatus == OnStageStatus.OnStage)
                        {
                            var n2 = note.Editor.NextSync;
                            var x2 = ScoreEditorLayout.GetNotePositionX(n2, gridArea, numColumns);
                            // Draw sync line
                            context.DrawLine(_syncLineStroke, x1, y1, x2, y1);
                        }
                        if (note.Helper.IsHoldStart)
                        {
                            var n2 = note.Editor.HoldPair;
                            var s2 = noteStartY;
                            // We promise only calculate the latter note, so this method works.
                            if (note.Basic.Bar != n2.Basic.Bar)
                            {
                                for (var i = note.Basic.Bar.Basic.Index; i < n2.Basic.Bar.Basic.Index; ++i)
                                {
                                    s2 -= score.Bars[i].GetNumberOfGrids() * unit;
                                }
                            }
                            var thatStatus = ScoreEditorLayout.GetNoteOnStageStatus(n2, gridArea, s2, unit, radius);
                            if ((int)thisStatus * (int)thatStatus <= 0)
                            {
                                var x2 = ScoreEditorLayout.GetNotePositionX(n2, gridArea, numColumns);
                                var y2 = ScoreEditorLayout.GetNotePositionY(score.Bars, n2.Basic.Bar.Basic.Index, n2.Basic.IndexInGrid, unit, scrollOffsetY);
                                // Draw hold line
                                context.DrawLine(_holdLineStroke, x1, y1, x2, y2);
                            }
                        }
                        if (note.Helper.HasNextFlick)
                        {
                            var n2 = note.Editor.NextFlick;
                            var s2 = noteStartY;
                            if (note.Basic.Bar != n2.Basic.Bar)
                            {
                                for (var i = note.Basic.Bar.Basic.Index; i < n2.Basic.Bar.Basic.Index; ++i)
                                {
                                    s2 -= score.Bars[i].GetNumberOfGrids() * unit;
                                }
                            }
                            var thatStatus = ScoreEditorLayout.GetNoteOnStageStatus(n2, gridArea, s2, unit, radius);
                            if ((int)thisStatus * (int)thatStatus <= 0)
                            {
                                var x2 = ScoreEditorLayout.GetNotePositionX(n2, gridArea, numColumns);
                                var y2 = ScoreEditorLayout.GetNotePositionY(score.Bars, n2.Basic.Bar.Basic.Index, n2.Basic.IndexInGrid, unit, scrollOffsetY);
                                // Draw flick line
                                context.DrawLine(_flickLineStroke, x1, y1, x2, y2);
                            }
                        }
                        if (note.Helper.HasNextSlide)
                        {
                            var n2 = note.Editor.NextSlide;
                            var s2 = noteStartY;
                            if (note.Basic.Bar != n2.Basic.Bar)
                            {
                                for (var i = note.Basic.Bar.Basic.Index; i < n2.Basic.Bar.Basic.Index; ++i)
                                {
                                    s2 -= score.Bars[i].GetNumberOfGrids() * unit;
                                }
                            }
                            var thatStatus = ScoreEditorLayout.GetNoteOnStageStatus(n2, gridArea, s2, unit, radius);
                            if ((int)thisStatus * (int)thatStatus <= 0)
                            {
                                var x2 = ScoreEditorLayout.GetNotePositionX(n2, gridArea, numColumns);
                                var y2 = ScoreEditorLayout.GetNotePositionY(score.Bars, n2.Basic.Bar.Basic.Index, n2.Basic.IndexInGrid, unit, scrollOffsetY);
                                // Draw slide line
                                context.DrawLine(_slideLineStroke, x1, y1, x2, y2);
                            }
                        }
                    }
                }
                noteStartY -= numberOfGrids * unit;
            }
        }
Пример #7
0
        private void RenderNotes(Graphics context, Score score, ScoreEditorConfig config, ScoreEditorLook look, float scrollOffsetY)
        {
            var gridArea        = ScoreEditorLayout.GetGridArea(config, context.Bounds);
            var radius          = config.NoteRadius;
            var specialNoteArea = ScoreEditorLayout.GetSpecialNoteArea(config, context.Bounds);

            DrawNoteConnections(context, score, gridArea, config, look, scrollOffsetY, scrollOffsetY, radius);
            DrawNotes(context, score, gridArea, config, look, specialNoteArea, scrollOffsetY, radius);
        }