Exemplo n.º 1
0
        private void RenderButtons(RenderGraphics g)
        {
            g.FillRectangle(0, 0, Width, Height, toolbarBrush);

            var pt = this.PointToClient(Cursor.Position);

            // Buttons
            foreach (var btn in buttons)
            {
                if (!btn.Visible)
                {
                    continue;
                }

                bool hover = btn.IsPointIn(pt.X, pt.Y, Width);
                var  bmp   = btn.GetBitmap != null?btn.GetBitmap() : btn.Bmp;

                if (bmp == null)
                {
                    bmp = btn.Bmp;
                }

                var status  = btn.Enabled == null ? ButtonStatus.Enabled : btn.Enabled();
                var opacity = status == ButtonStatus.Enabled ? 1.0f : 0.25f;

                if (status != ButtonStatus.Disabled && hover)
                {
                    opacity *= 0.75f;
                }

                int x = btn.RightAligned ? Width - btn.X : btn.X;
                g.DrawBitmap(bmp, x, btn.Y, opacity);
            }
        }
Exemplo n.º 2
0
        protected override void OnRenderInitialized(RenderGraphics g)
        {
            theme = RenderTheme.CreateResourcesForGraphics(g);

            bmpSong = g.CreateBitmapFromResource("Music");
            bmpInstrument[Project.ExpansionNone] = g.CreateBitmapFromResource("Instrument");
            bmpInstrument[Project.ExpansionVrc6] = g.CreateBitmapFromResource("InstrumentVRC6");
#if DEV
            bmpInstrument[Project.ExpansionVrc7]    = g.CreateBitmapFromResource("InstrumentVRC6");
            bmpInstrument[Project.ExpansionFds]     = g.CreateBitmapFromResource("Instrument");
            bmpInstrument[Project.ExpansionMmc5]    = g.CreateBitmapFromResource("Instrument");
            bmpInstrument[Project.ExpansionNamco]   = g.CreateBitmapFromResource("Instrument");
            bmpInstrument[Project.ExpansionSunsoft] = g.CreateBitmapFromResource("Instrument");
#endif
            bmpAdd            = g.CreateBitmapFromResource("Add");
            bmpDPCM           = g.CreateBitmapFromResource("DPCM");
            bmpDuty[0]        = g.CreateBitmapFromResource("Duty0");
            bmpDuty[1]        = g.CreateBitmapFromResource("Duty1");
            bmpDuty[2]        = g.CreateBitmapFromResource("Duty2");
            bmpDuty[3]        = g.CreateBitmapFromResource("Duty3");
            bmpDuty[4]        = g.CreateBitmapFromResource("Duty4");
            bmpDuty[5]        = g.CreateBitmapFromResource("Duty5");
            bmpDuty[6]        = g.CreateBitmapFromResource("Duty6");
            bmpDuty[7]        = g.CreateBitmapFromResource("Duty7");
            bmpArpeggio       = g.CreateBitmapFromResource("Arpeggio");
            bmpPitch          = g.CreateBitmapFromResource("Pitch");
            bmpVolume         = g.CreateBitmapFromResource("Volume");
            bmpLoadInstrument = g.CreateBitmapFromResource("InstrumentOpen");
        }
Exemplo n.º 3
0
 protected override void OnRender(RenderGraphics g)
 {
     RenderButtons(g);
     RenderTimecode(g);
     RenderOscilloscope(g);
     RenderWarningAndTooltip(g);
 }
Exemplo n.º 4
0
        protected override void OnRenderInitialized(RenderGraphics g)
        {
            theme = RenderTheme.CreateResourcesForGraphics(g);

            bmpTracks[Channel.Square1]  = g.CreateBitmapFromResource("Square");
            bmpTracks[Channel.Square2]  = g.CreateBitmapFromResource("Square");
            bmpTracks[Channel.Triangle] = g.CreateBitmapFromResource("Triangle");
            bmpTracks[Channel.Noise]    = g.CreateBitmapFromResource("Noise");
            bmpTracks[Channel.DPCM]     = g.CreateBitmapFromResource("DPCM");

            bmpGhostNote = g.CreateBitmapFromResource("GhostSmall");

            seekBarBrush                  = g.CreateSolidBrush(ThemeBase.SeekBarColor);
            whiteKeyBrush                 = g.CreateHorizontalGradientBrush(0, trackNameSizeX, ThemeBase.LightGreyFillColor1, ThemeBase.LightGreyFillColor2);
            patternHeaderBrush            = g.CreateVerticalGradientBrush(0, patternHeaderSizeY, ThemeBase.LightGreyFillColor1, ThemeBase.LightGreyFillColor2);
            selectedPatternVisibleBrush   = g.CreateSolidBrush(Color.FromArgb(64, ThemeBase.LightGreyFillColor1));
            selectedPatternInvisibleBrush = g.CreateSolidBrush(Color.FromArgb(32, ThemeBase.LightGreyFillColor1));

            seekGeometry = g.CreateConvexPath(new[]
            {
                new Point(-headerSizeY / 2, 1),
                new Point(0, headerSizeY - 2),
                new Point(headerSizeY / 2, 1)
            });
        }
Exemplo n.º 5
0
 public virtual void InitializeForGraphics(RenderGraphics g)
 {
     BlackBrush          = g.CreateSolidBrush(BlackColor);
     LightGreyFillBrush1 = g.CreateSolidBrush(LightGreyFillColor1);
     LightGreyFillBrush2 = g.CreateSolidBrush(LightGreyFillColor2);
     DarkGreyLineBrush1  = g.CreateSolidBrush(DarkGreyLineColor1);
     DarkGreyLineBrush2  = g.CreateSolidBrush(DarkGreyLineColor2);
     DarkGreyFillBrush1  = g.CreateSolidBrush(DarkGreyFillColor1);
     DarkGreyFillBrush2  = g.CreateSolidBrush(DarkGreyFillColor2);
 }
Exemplo n.º 6
0
        protected override void OnRenderInitialized(RenderGraphics g)
        {
            theme = RenderTheme.CreateResourcesForGraphics(g);

            bmpTracks[Channel.Square1]  = g.CreateBitmapFromResource("Square");
            bmpTracks[Channel.Square2]  = g.CreateBitmapFromResource("Square");
            bmpTracks[Channel.Triangle] = g.CreateBitmapFromResource("Triangle");
            bmpTracks[Channel.Noise]    = g.CreateBitmapFromResource("Noise");
            bmpTracks[Channel.DPCM]     = g.CreateBitmapFromResource("DPCM");

            bmpGhostNote = g.CreateBitmapFromResource("GhostSmall");

            playPositionBrush    = g.CreateSolidBrush(Color.FromArgb(192, ThemeBase.LightGreyFillColor1));
            whiteKeyBrush        = g.CreateHorizontalGradientBrush(0, trackNameSizeX, ThemeBase.LightGreyFillColor1, ThemeBase.LightGreyFillColor2);
            patternHeaderBrush   = g.CreateVerticalGradientBrush(0, patternHeaderSizeY, ThemeBase.LightGreyFillColor1, ThemeBase.LightGreyFillColor2);
            selectedPatternBrush = g.CreateSolidBrush(Color.FromArgb(128, ThemeBase.LightGreyFillColor1));
        }
Exemplo n.º 7
0
        protected override void OnRenderInitialized(RenderGraphics g)
        {
            theme = RenderTheme.CreateResourcesForGraphics(g);

            bmpButtonIcons[(int)ButtonType.Song]       = g.CreateBitmapFromResource("Music");
            bmpButtonIcons[(int)ButtonType.Instrument] = g.CreateBitmapFromResource("Pattern");

            bmpSubButtonIcons[(int)SubButtonType.Add]        = g.CreateBitmapFromResource("Add");
            bmpSubButtonIcons[(int)SubButtonType.DPCM]       = g.CreateBitmapFromResource("DPCM");
            bmpSubButtonIcons[(int)SubButtonType.DutyCycle0] = g.CreateBitmapFromResource("Duty0");
            bmpSubButtonIcons[(int)SubButtonType.DutyCycle1] = g.CreateBitmapFromResource("Duty1");
            bmpSubButtonIcons[(int)SubButtonType.DutyCycle2] = g.CreateBitmapFromResource("Duty2");
            bmpSubButtonIcons[(int)SubButtonType.DutyCycle3] = g.CreateBitmapFromResource("Duty3");
            bmpSubButtonIcons[(int)SubButtonType.Arpeggio]   = g.CreateBitmapFromResource("Arpeggio");
            bmpSubButtonIcons[(int)SubButtonType.Pitch]      = g.CreateBitmapFromResource("Pitch");
            bmpSubButtonIcons[(int)SubButtonType.Volume]     = g.CreateBitmapFromResource("Volume");
        }
Exemplo n.º 8
0
        protected override void OnRender(RenderGraphics g)
        {
            g.Clear(ThemeBase.DarkGreyFillColor1);
            g.DrawLine(0, 0, 0, Height, theme.BlackBrush);

            int actualWidth = Width - scrollBarSizeX;

            int y = -scrollY;

            foreach (var button in buttons)
            {
                var icon = bmpButtonIcons[(int)button.type];

                g.PushTranslation(0, y);
                g.FillAndDrawRectangle(0, 0, actualWidth, buttonSizeY, g.GetVerticalGradientBrush(button.GetColor(), buttonSizeY, 0.8f), theme.BlackBrush);
                g.DrawText(button.GetText(App.Project), button.GetFont(selectedSong, selectedInstrument), icon == null ? buttonTextNoIconPosX : buttonTextPosX, buttonTextPosY, theme.BlackBrush, actualWidth - buttonTextNoIconPosX * 2);

                if (icon != null)
                {
                    g.DrawBitmap(icon, buttonIconPosX, buttonIconPosY);
                }

                var subButtons = button.GetSubButtons(out var active);
                if (subButtons != null)
                {
                    for (int i = 0, x = actualWidth - subButtonSpacingX; i < subButtons.Length; i++, x -= subButtonSpacingX)
                    {
                        g.DrawBitmap(bmpSubButtonIcons[(int)subButtons[i]], x, subButtonPosY, active[i] ? 1.0f : 0.2f);
                    }
                }

                g.PopTransform();
                y += buttonSizeY;
            }

            if (needsScrollBar)
            {
                int virtualSizeY   = this.virtualSizeY;
                int scrollBarSizeY = (int)Math.Round(Height * (Height / (float)virtualSizeY));
                int scrollBarPosY  = (int)Math.Round(Height * (scrollY / (float)virtualSizeY));

                g.FillAndDrawRectangle(actualWidth, 0, Width - 1, Height, theme.DarkGreyFillBrush1, theme.BlackBrush);
                g.FillAndDrawRectangle(actualWidth, scrollBarPosY, Width - 1, scrollBarPosY + scrollBarSizeY, theme.LightGreyFillBrush1, theme.BlackBrush);
            }
        }
Exemplo n.º 9
0
        public virtual void InitializeForGraphics(RenderGraphics g)
        {
            BlackBrush          = g.CreateSolidBrush(BlackColor);
            LightGreyFillBrush1 = g.CreateSolidBrush(LightGreyFillColor1);
            LightGreyFillBrush2 = g.CreateSolidBrush(LightGreyFillColor2);
            DarkGreyLineBrush1  = g.CreateSolidBrush(DarkGreyLineColor1);
            DarkGreyLineBrush2  = g.CreateSolidBrush(DarkGreyLineColor2);
            DarkGreyFillBrush1  = g.CreateSolidBrush(DarkGreyFillColor1);
            DarkGreyFillBrush2  = g.CreateSolidBrush(DarkGreyFillColor2);

            for (int j = 0; j < CustomColors.GetLength(1); j++)
            {
                for (int i = 0; i < CustomColors.GetLength(0); i++)
                {
                    CustomColorBrushes[CustomColors[i, j]] = g.CreateSolidBrush(CustomColors[i, j]);
                }
            }
        }
Exemplo n.º 10
0
        private void RenderButtons(RenderGraphics g)
        {
            g.FillRectangle(0, 0, Width, Height, toolbarBrush);

            var pt = this.PointToClient(Cursor.Position);

            // Buttons
            foreach (var btn in buttons)
            {
                bool hover = btn.IsPointIn(pt.X, pt.Y, Width);
                var  bmp   = btn.GetBitmap != null?btn.GetBitmap() : btn.Bmp;

                if (bmp == null)
                {
                    bmp = btn.Bmp;
                }
                bool enabled = btn.Enabled != null?btn.Enabled() : true;

                int x = btn.RightAligned ? Width - btn.X : btn.X;
                g.DrawBitmap(bmp, x, btn.Y, enabled ? (hover ? 0.75f : 1.0f) : 0.25f);
            }
        }
Exemplo n.º 11
0
        private void RenderOscilloscope(RenderGraphics g)
        {
            if (!oscilloscopeVisible)
            {
                return;
            }

            var oscilloscopeSizeX = timecodeSizeX;
            var oscilloscopeSizeY = Height - timecodePosY * 2;

            g.FillRectangle(oscilloscopePosX, timecodePosY, oscilloscopePosX + oscilloscopeSizeX, Height - timecodePosY, theme.BlackBrush);

            var oscilloscopeGeometry = App.GetOscilloscopeGeometry(out lastOscilloscopeHadNonZeroSample);

            if (oscilloscopeGeometry != null && lastOscilloscopeHadNonZeroSample)
            {
                float scaleX = oscilloscopeSizeX;
                float scaleY = oscilloscopeSizeY / 2;

                RenderGeometry geo = g.CreateGeometry(oscilloscopeGeometry, false);
                g.PushTransform(oscilloscopePosX, timecodePosY + oscilloscopeSizeY / 2, scaleX, scaleY);
                g.AntiAliasing = true;
                g.DrawGeometry(geo, theme.LightGreyFillBrush2);
                g.AntiAliasing = false;
                g.PopTransform();
                geo.Dispose();
            }
            else
            {
                g.PushTranslation(oscilloscopePosX, timecodePosY + oscilloscopeSizeY / 2);
                g.AntiAliasing = true;
                g.DrawLine(0, 0, oscilloscopeSizeX, 0, theme.LightGreyFillBrush2);
                g.AntiAliasing = false;
                g.PopTransform();
            }

            g.DrawRectangle(oscilloscopePosX, timecodePosY, oscilloscopePosX + oscilloscopeSizeX, Height - timecodePosY, theme.LightGreyFillBrush2);
        }
Exemplo n.º 12
0
        protected override void OnRender(RenderGraphics g)
        {
            g.FillRectangle(0, 0, Width, Height, toolbarBrush);

            var scaling = RenderTheme.MainWindowScaling;
            var pt      = this.PointToClient(Cursor.Position);

            // Buttons
            foreach (var btn in buttons)
            {
                bool hover = btn.IsPointIn(pt.X, pt.Y);
                var  bmp   = btn.GetBitmap != null?btn.GetBitmap() : btn.Bmp;

                if (bmp == null)
                {
                    bmp = btn.Bmp;
                }
                bool enabled = btn.Enabled != null?btn.Enabled() : true;

                g.DrawBitmap(bmp, btn.X, btn.Y, enabled ? (hover ? 0.75f : 1.0f) : 0.25f);
            }

            // Timecode
            int frame      = App.CurrentFrame;
            int patternIdx = frame / App.Song.PatternLength;
            int noteIdx    = frame % App.Song.PatternLength;

            g.FillAndDrawRectangle(timecodePosX, timecodePosY, timecodePosX + timecodeSizeX, Height - timecodePosY, theme.DarkGreyFillBrush1, theme.BlackBrush);
            g.DrawText($"{patternIdx:D3}:{noteIdx:D3}", ThemeBase.FontHuge, timecodePosX + timecodeTextPosX, 2, theme.LightGreyFillBrush1, timecodeSizeX);

            // Tooltip
            if (!string.IsNullOrEmpty(tooltip))
            {
                g.DrawText(tooltip, ThemeBase.FontMediumRight, Width - 314, tooltipPosY, theme.BlackBrush, 300);
            }
        }
Exemplo n.º 13
0
        protected override void OnRenderInitialized(RenderGraphics g)
        {
            theme        = RenderTheme.CreateResourcesForGraphics(g);
            toolbarBrush = g.CreateHorizontalGradientBrush(0, 81, ThemeBase.LightGreyFillColor1, ThemeBase.LightGreyFillColor2);

            bmpLoopNone    = g.CreateBitmapFromResource("LoopNone");
            bmpLoopSong    = g.CreateBitmapFromResource("Loop");
            bmpLoopPattern = g.CreateBitmapFromResource("LoopPattern");
            bmpPlay        = g.CreateBitmapFromResource("Play");
            bmpPause       = g.CreateBitmapFromResource("Pause");

            buttons[ButtonNew] = new Button {
                X = 4, Y = 4, Bmp = g.CreateBitmapFromResource("File"), Click = OnNew
            };
            buttons[ButtonOpen] = new Button {
                X = 44, Y = 4, Bmp = g.CreateBitmapFromResource("Open"), Click = OnOpen
            };
            buttons[ButtonSave] = new Button {
                X = 84, Y = 4, Bmp = g.CreateBitmapFromResource("Save"), Click = OnSave, RightClick = OnSaveAs
            };
            buttons[ButtonExport] = new Button {
                X = 124, Y = 4, Bmp = g.CreateBitmapFromResource("Export"), Click = OnExport
            };
            buttons[ButtonUndo] = new Button {
                X = 164, Y = 4, Bmp = g.CreateBitmapFromResource("Undo"), Click = OnUndo, Enabled = OnUndoEnabled
            };
            buttons[ButtonRedo] = new Button {
                X = 204, Y = 4, Bmp = g.CreateBitmapFromResource("Redo"), Click = OnRedo, Enabled = OnRedoEnabled
            };
            buttons[ButtonConfig] = new Button {
                X = 244, Y = 4, Bmp = g.CreateBitmapFromResource("Config"), Click = OnConfig
            };
            buttons[ButtonPlay] = new Button {
                X = 476, Y = 4, Click = OnPlay, GetBitmap = OnPlayGetBitmap
            };
            buttons[ButtonRewind] = new Button {
                X = 516, Y = 4, Bmp = g.CreateBitmapFromResource("Rewind"), Click = OnRewind
            };
            buttons[ButtonLoop] = new Button {
                X = 556, Y = 4, Click = OnLoop, GetBitmap = OnLoopGetBitmap
            };

            buttons[ButtonNew].ToolTip    = "New Project (Ctrl-N)";
            buttons[ButtonOpen].ToolTip   = "Open Project (Ctrl-O)";
            buttons[ButtonSave].ToolTip   = "Save Project (Ctrl-S) [Right-Click: Save As...]";
            buttons[ButtonExport].ToolTip = "Export to various formats (Ctrl+E)";
            buttons[ButtonUndo].ToolTip   = "Undo (Ctrl+Z)";
            buttons[ButtonRedo].ToolTip   = "Redo (Ctrl+Y)";
            buttons[ButtonConfig].ToolTip = "Edit Application Settings";
            buttons[ButtonPlay].ToolTip   = "Play/Pause (Space) [Ctrl+Space: Play pattern loop, Shift-Space: Play song loop]";
            buttons[ButtonRewind].ToolTip = "Rewind (Home) [Ctrl+Home: Rewind to beginning of current pattern]";
            buttons[ButtonLoop].ToolTip   = "Toggle Loop Mode";

            var scaling = RenderTheme.MainWindowScaling;

            for (int i = 0; i < ButtonCount; i++)
            {
                var btn = buttons[i];
                btn.X    = (int)(btn.X * scaling);
                btn.Y    = (int)(btn.Y * scaling);
                btn.Size = (int)(btn.Size * scaling);
            }

            timecodePosX     = (int)(DefaultTimecodePosX * scaling);
            timecodePosY     = (int)(DefaultTimecodePosY * scaling);
            timecodeSizeX    = (int)(DefaultTimecodeSizeX * scaling);
            timecodeTextPosX = (int)(DefaultTimecodeTextPosX * scaling);
            tooltipPosY      = (int)(DefaultTooltipPosY * scaling);
        }
Exemplo n.º 14
0
        protected override void OnRenderInitialized(RenderGraphics g)
        {
            theme        = RenderTheme.CreateResourcesForGraphics(g);
            toolbarBrush = g.CreateHorizontalGradientBrush(0, 81, ThemeBase.LightGreyFillColor1, ThemeBase.LightGreyFillColor2);

            bmpLoopNone    = g.CreateBitmapFromResource("LoopNone");
            bmpLoopSong    = g.CreateBitmapFromResource("Loop");
            bmpLoopPattern = g.CreateBitmapFromResource("LoopPattern");
            bmpPlay        = g.CreateBitmapFromResource("Play");
            bmpPause       = g.CreateBitmapFromResource("Pause");

            buttons[ButtonNew] = new Button {
                X = 4, Y = 4, Bmp = g.CreateBitmapFromResource("File"), Click = OnNew
            };
            buttons[ButtonOpen] = new Button {
                X = 44, Y = 4, Bmp = g.CreateBitmapFromResource("Open"), Click = OnOpen
            };
            buttons[ButtonSave] = new Button {
                X = 84, Y = 4, Bmp = g.CreateBitmapFromResource("Save"), Click = OnSave, RightClick = OnSaveAs
            };
            buttons[ButtonExport] = new Button {
                X = 124, Y = 4, Bmp = g.CreateBitmapFromResource("Export"), Click = OnExport
            };
            buttons[ButtonCopy] = new Button {
                X = 164, Y = 4, Bmp = g.CreateBitmapFromResource("Copy"), Click = OnCopy, Enabled = OnCopyEnabled
            };
            buttons[ButtonCut] = new Button {
                X = 204, Y = 4, Bmp = g.CreateBitmapFromResource("Cut"), Click = OnCut, Enabled = OnCutEnabled
            };
            buttons[ButtonPaste] = new Button {
                X = 244, Y = 4, Bmp = g.CreateBitmapFromResource("Paste"), Click = OnPaste, RightClick = OnPasteSpecial, Enabled = OnPasteEnabled
            };
            buttons[ButtonUndo] = new Button {
                X = 284, Y = 4, Bmp = g.CreateBitmapFromResource("Undo"), Click = OnUndo, Enabled = OnUndoEnabled
            };
            buttons[ButtonRedo] = new Button {
                X = 324, Y = 4, Bmp = g.CreateBitmapFromResource("Redo"), Click = OnRedo, Enabled = OnRedoEnabled
            };
            buttons[ButtonConfig] = new Button {
                X = 364, Y = 4, Bmp = g.CreateBitmapFromResource("Config"), Click = OnConfig
            };
            buttons[ButtonPlay] = new Button {
                X = 594, Y = 4, Click = OnPlay, GetBitmap = OnPlayGetBitmap
            };
            buttons[ButtonRewind] = new Button {
                X = 634, Y = 4, Bmp = g.CreateBitmapFromResource("Rewind"), Click = OnRewind
            };
            buttons[ButtonLoop] = new Button {
                X = 674, Y = 4, Click = OnLoop, GetBitmap = OnLoopGetBitmap
            };

            buttons[ButtonNew].ToolTip    = "{MouseLeft} New Project {Ctrl} {N}";
            buttons[ButtonOpen].ToolTip   = "{MouseLeft} Open Project {Ctrl} {O}";
            buttons[ButtonSave].ToolTip   = "{MouseLeft} Save Project {Ctrl} {S}  - {MouseRight} Save As...";
            buttons[ButtonExport].ToolTip = "{MouseLeft} Export to various formats {Ctrl} {E}";
            buttons[ButtonCopy].ToolTip   = "{MouseLeft} Copy selection {Ctrl} {C}";
            buttons[ButtonCut].ToolTip    = "{MouseLeft} Cut selection {Ctrl} {X}";
            buttons[ButtonPaste].ToolTip  = "{MouseLeft} Paste {Ctrl} {V}\n{MouseRight} Paste Special... {Ctrl} {Shift} {V}";
            buttons[ButtonUndo].ToolTip   = "{MouseLeft} Undo {Ctrl} {Z}";
            buttons[ButtonRedo].ToolTip   = "{MouseLeft} Redo {Ctrl} {Y}";
            buttons[ButtonConfig].ToolTip = "{MouseLeft} Edit Application Settings";
            buttons[ButtonPlay].ToolTip   = "{MouseLeft} Play/Pause {Space}\nPlay pattern loop {Ctrl} {Space}  - Play song loop {Shift} {Space}";
            buttons[ButtonRewind].ToolTip = "{MouseLeft} Rewind {Home}\nRewind to beginning of current pattern {Ctrl} {Home}";
            buttons[ButtonLoop].ToolTip   = "{MouseLeft} Toggle Loop Mode";

            var scaling = RenderTheme.MainWindowScaling;

            for (int i = 0; i < ButtonCount; i++)
            {
                var btn = buttons[i];
                btn.X    = (int)(btn.X * scaling);
                btn.Y    = (int)(btn.Y * scaling);
                btn.Size = (int)(btn.Size * scaling);
            }

            timecodePosX            = (int)(DefaultTimecodePosX * scaling);
            timecodePosY            = (int)(DefaultTimecodePosY * scaling);
            timecodeSizeX           = (int)(DefaultTimecodeSizeX * scaling);
            timecodeTextPosX        = (int)(DefaultTimecodeTextPosX * scaling);
            tooltipSingleLinePosY   = (int)(DefaultTooltipSingleLinePosY * scaling);
            tooltipMultiLinePosY    = (int)(DefaultTooltipMultiLinePosY * scaling);
            tooltipLineSizeY        = (int)(DefaultTooltipLineSizeY * scaling);
            tooltipSpecialCharSizeX = (int)(DefaultTooltipSpecialCharSizeX * scaling);
            tooltipSpecialCharSizeY = (int)(DefaultTooltipSpecialCharSizeY * scaling);

            specialCharacters["Shift"] = new TooltipSpecialCharacter {
                Width = (int)(32 * scaling)
            };
            specialCharacters["Space"] = new TooltipSpecialCharacter {
                Width = (int)(38 * scaling)
            };
            specialCharacters["Home"] = new TooltipSpecialCharacter {
                Width = (int)(38 * scaling)
            };
            specialCharacters["Ctrl"] = new TooltipSpecialCharacter {
                Width = (int)(28 * scaling)
            };
            specialCharacters["Alt"] = new TooltipSpecialCharacter {
                Width = (int)(24 * scaling)
            };
            specialCharacters["Drag"] = new TooltipSpecialCharacter {
                Bmp = g.CreateBitmapFromResource("Drag"), OffsetY = 2 * scaling
            };
            specialCharacters["MouseLeft"] = new TooltipSpecialCharacter {
                Bmp = g.CreateBitmapFromResource("MouseLeft"), OffsetY = 2 * scaling
            };
            specialCharacters["MouseRight"] = new TooltipSpecialCharacter {
                Bmp = g.CreateBitmapFromResource("MouseRight"), OffsetY = 2 * scaling
            };
            specialCharacters["MouseWheel"] = new TooltipSpecialCharacter {
                Bmp = g.CreateBitmapFromResource("MouseWheel"), OffsetY = 2 * scaling
            };

            for (char i = 'A'; i <= 'Z'; i++)
            {
                specialCharacters[i.ToString()] = new TooltipSpecialCharacter {
                    Width = tooltipSpecialCharSizeX
                }
            }
            ;

            foreach (var specialChar in specialCharacters.Values)
            {
                if (specialChar.Bmp != null)
                {
                    specialChar.Width = (int)g.GetBitmapWidth(specialChar.Bmp);
                }
                specialChar.Height = tooltipSpecialCharSizeY;
            }
        }
Exemplo n.º 15
0
        private void RenderTimecode(RenderGraphics g)
        {
            var frame            = App.CurrentFrame;
            var famitrackerTempo = App.Project != null && App.Project.UsesFamiTrackerTempo;

            var zeroSizeX  = g.MeasureString("0", ThemeBase.FontHuge);
            var colonSizeX = g.MeasureString(":", ThemeBase.FontHuge);

            var timeCodeSizeY = Height - timecodePosY * 2;
            var textColor     = App.IsRecording ? theme.DarkRedFillBrush : theme.LightGreyFillBrush2;

            g.FillAndDrawRectangle(timecodePosX, timecodePosY, timecodePosX + timecodeSizeX, Height - timecodePosY, theme.BlackBrush, theme.LightGreyFillBrush2);

            if (Settings.TimeFormat == 0 || famitrackerTempo) // MM:SS:mmm cant be used with FamiTracker tempo.
            {
                var location = NoteLocation.FromAbsoluteNoteIndex(App.Song, frame);

                var numPatternDigits = Utils.NumDecimalDigits(App.Song.Length - 1);
                var numNoteDigits    = Utils.NumDecimalDigits(App.Song.GetPatternLength(location.PatternIndex) - 1);

                var patternString = location.PatternIndex.ToString("D" + numPatternDigits);
                var noteString    = location.NoteIndex.ToString("D" + numNoteDigits);

                var charPosX = timecodePosX + timecodeSizeX / 2 - ((numPatternDigits + numNoteDigits) * zeroSizeX + colonSizeX) / 2;

                for (int i = 0; i < numPatternDigits; i++, charPosX += zeroSizeX)
                {
                    g.DrawText(patternString[i].ToString(), ThemeBase.FontHuge, charPosX, 2, textColor, zeroSizeX);
                }

                g.DrawText(":", ThemeBase.FontHuge, charPosX, 2, textColor, colonSizeX);
                charPosX += colonSizeX;

                for (int i = 0; i < numNoteDigits; i++, charPosX += zeroSizeX)
                {
                    g.DrawText(noteString[i].ToString(), ThemeBase.FontHuge, charPosX, 2, textColor, zeroSizeX);
                }
            }
            else
            {
                TimeSpan time = App.CurrentTime;

                var minutesString      = time.Minutes.ToString("D2");
                var secondsString      = time.Seconds.ToString("D2");
                var millisecondsString = time.Milliseconds.ToString("D3");

                // 00:00:000
                var charPosX = timecodePosX + timecodeSizeX / 2 - (7 * zeroSizeX + 2 * colonSizeX) / 2;

                for (int i = 0; i < 2; i++, charPosX += zeroSizeX)
                {
                    g.DrawText(minutesString[i].ToString(), ThemeBase.FontHuge, charPosX, 2, textColor, zeroSizeX);
                }
                g.DrawText(":", ThemeBase.FontHuge, charPosX, 2, textColor, colonSizeX);
                charPosX += colonSizeX;
                for (int i = 0; i < 2; i++, charPosX += zeroSizeX)
                {
                    g.DrawText(secondsString[i].ToString(), ThemeBase.FontHuge, charPosX, 2, textColor, zeroSizeX);
                }
                g.DrawText(":", ThemeBase.FontHuge, charPosX, 2, textColor, colonSizeX);
                charPosX += colonSizeX;
                for (int i = 0; i < 3; i++, charPosX += zeroSizeX)
                {
                    g.DrawText(millisecondsString[i].ToString(), ThemeBase.FontHuge, charPosX, 2, textColor, zeroSizeX);
                }
            }
        }
Exemplo n.º 16
0
        protected override void OnRenderInitialized(RenderGraphics g)
        {
            theme = RenderTheme.CreateResourcesForGraphics(g);

            toolbarBrush = g.CreateHorizontalGradientBrush(0, 81, ThemeBase.LightGreyFillColor1, ThemeBase.LightGreyFillColor2);
            warningBrush = g.CreateSolidBrush(ThemeBase.Darken(ThemeBase.CustomColors[0, 0]));

            bmpLoopNone    = g.CreateBitmapFromResource("LoopNone");
            bmpLoopSong    = g.CreateBitmapFromResource("Loop");
            bmpLoopPattern = g.CreateBitmapFromResource("LoopPattern");
            bmpPlay        = g.CreateBitmapFromResource("Play");
            bmpPause       = g.CreateBitmapFromResource("Pause");
            bmpNtsc        = g.CreateBitmapFromResource("NTSC");
            bmpPal         = g.CreateBitmapFromResource("PAL");

            buttons[ButtonNew] = new Button {
                X = 4, Y = 4, Bmp = g.CreateBitmapFromResource("File"), Click = OnNew
            };
            buttons[ButtonOpen] = new Button {
                X = 40, Y = 4, Bmp = g.CreateBitmapFromResource("Open"), Click = OnOpen
            };
            buttons[ButtonSave] = new Button {
                X = 76, Y = 4, Bmp = g.CreateBitmapFromResource("Save"), Click = OnSave, RightClick = OnSaveAs
            };
            buttons[ButtonExport] = new Button {
                X = 112, Y = 4, Bmp = g.CreateBitmapFromResource("Export"), Click = OnExport
            };
            buttons[ButtonCopy] = new Button {
                X = 148, Y = 4, Bmp = g.CreateBitmapFromResource("Copy"), Click = OnCopy, Enabled = OnCopyEnabled
            };
            buttons[ButtonCut] = new Button {
                X = 184, Y = 4, Bmp = g.CreateBitmapFromResource("Cut"), Click = OnCut, Enabled = OnCutEnabled
            };
            buttons[ButtonPaste] = new Button {
                X = 220, Y = 4, Bmp = g.CreateBitmapFromResource("Paste"), Click = OnPaste, RightClick = OnPasteSpecial, Enabled = OnPasteEnabled
            };
            buttons[ButtonUndo] = new Button {
                X = 256, Y = 4, Bmp = g.CreateBitmapFromResource("Undo"), Click = OnUndo, Enabled = OnUndoEnabled
            };
            buttons[ButtonRedo] = new Button {
                X = 292, Y = 4, Bmp = g.CreateBitmapFromResource("Redo"), Click = OnRedo, Enabled = OnRedoEnabled
            };
            buttons[ButtonTransform] = new Button {
                X = 328, Y = 4, Bmp = g.CreateBitmapFromResource("Transform"), Click = OnTransform
            };
            buttons[ButtonConfig] = new Button {
                X = 364, Y = 4, Bmp = g.CreateBitmapFromResource("Config"), Click = OnConfig
            };
            buttons[ButtonPlay] = new Button {
                X = 572, Y = 4, Click = OnPlay, GetBitmap = OnPlayGetBitmap
            };
            buttons[ButtonRewind] = new Button {
                X = 608, Y = 4, Bmp = g.CreateBitmapFromResource("Rewind"), Click = OnRewind
            };
            buttons[ButtonLoop] = new Button {
                X = 644, Y = 4, Click = OnLoop, GetBitmap = OnLoopGetBitmap
            };
            buttons[ButtonMachine] = new Button {
                X = 680, Y = 4, Click = OnMachine, GetBitmap = OnMachineGetBitmap, Enabled = OnMachineEnabled
            };
            buttons[ButtonHelp] = new Button {
                X = 36, Y = 4, Bmp = g.CreateBitmapFromResource("Help"), RightAligned = true, Click = OnHelp
            };

            buttons[ButtonNew].ToolTip       = "{MouseLeft} New Project {Ctrl} {N}";
            buttons[ButtonOpen].ToolTip      = "{MouseLeft} Open Project {Ctrl} {O}";
            buttons[ButtonSave].ToolTip      = "{MouseLeft} Save Project {Ctrl} {S} - {MouseRight} Save As...";
            buttons[ButtonExport].ToolTip    = "{MouseLeft} Export to various formats {Ctrl} {E}";
            buttons[ButtonCopy].ToolTip      = "{MouseLeft} Copy selection {Ctrl} {C}";
            buttons[ButtonCut].ToolTip       = "{MouseLeft} Cut selection {Ctrl} {X}";
            buttons[ButtonPaste].ToolTip     = "{MouseLeft} Paste {Ctrl} {V}\n{MouseRight} Paste Special... {Ctrl} {Shift} {V}";
            buttons[ButtonUndo].ToolTip      = "{MouseLeft} Undo {Ctrl} {Z}";
            buttons[ButtonRedo].ToolTip      = "{MouseLeft} Redo {Ctrl} {Y}";
            buttons[ButtonTransform].ToolTip = "{MouseLeft} Perform cleanup and various operations";
            buttons[ButtonConfig].ToolTip    = "{MouseLeft} Edit Application Settings";
            buttons[ButtonPlay].ToolTip      = "{MouseLeft} Play/Pause {Space} - Play from start of pattern {Ctrl} {Space}";
            buttons[ButtonRewind].ToolTip    = "{MouseLeft} Rewind {Home}\nRewind to beginning of current pattern {Ctrl} {Home}";
            buttons[ButtonLoop].ToolTip      = "{MouseLeft} Toggle Loop Mode";
            buttons[ButtonMachine].ToolTip   = "{MouseLeft} Toggle between NTSC/PAL playback mode";
            buttons[ButtonHelp].ToolTip      = "{MouseLeft} Online documentation";

            var scaling = RenderTheme.MainWindowScaling;

            for (int i = 0; i < ButtonCount; i++)
            {
                var btn = buttons[i];
                btn.X    = (int)(btn.X * scaling);
                btn.Y    = (int)(btn.Y * scaling);
                btn.Size = (int)(btn.Size * scaling);
            }

            timecodePosX            = (int)(DefaultTimecodePosX * scaling);
            timecodePosY            = (int)(DefaultTimecodePosY * scaling);
            timecodeSizeX           = (int)(DefaultTimecodeSizeX * scaling);
            tooltipSingleLinePosY   = (int)(DefaultTooltipSingleLinePosY * scaling);
            tooltipMultiLinePosY    = (int)(DefaultTooltipMultiLinePosY * scaling);
            tooltipLineSizeY        = (int)(DefaultTooltipLineSizeY * scaling);
            tooltipSpecialCharSizeX = (int)(DefaultTooltipSpecialCharSizeX * scaling);
            tooltipSpecialCharSizeY = (int)(DefaultTooltipSpecialCharSizeY * scaling);

            specialCharacters["Shift"] = new TooltipSpecialCharacter {
                Width = (int)(32 * scaling)
            };
            specialCharacters["Space"] = new TooltipSpecialCharacter {
                Width = (int)(38 * scaling)
            };
            specialCharacters["Home"] = new TooltipSpecialCharacter {
                Width = (int)(38 * scaling)
            };
            specialCharacters["Ctrl"] = new TooltipSpecialCharacter {
                Width = (int)(28 * scaling)
            };
            specialCharacters["Alt"] = new TooltipSpecialCharacter {
                Width = (int)(24 * scaling)
            };
            specialCharacters["Drag"] = new TooltipSpecialCharacter {
                Bmp = g.CreateBitmapFromResource("Drag"), OffsetY = 2 * scaling
            };
            specialCharacters["MouseLeft"] = new TooltipSpecialCharacter {
                Bmp = g.CreateBitmapFromResource("MouseLeft"), OffsetY = 2 * scaling
            };
            specialCharacters["MouseRight"] = new TooltipSpecialCharacter {
                Bmp = g.CreateBitmapFromResource("MouseRight"), OffsetY = 2 * scaling
            };
            specialCharacters["MouseWheel"] = new TooltipSpecialCharacter {
                Bmp = g.CreateBitmapFromResource("MouseWheel"), OffsetY = 2 * scaling
            };
            specialCharacters["Warning"] = new TooltipSpecialCharacter {
                Bmp = g.CreateBitmapFromResource("Warning")
            };

            for (char i = 'A'; i <= 'Z'; i++)
            {
                specialCharacters[i.ToString()] = new TooltipSpecialCharacter {
                    Width = tooltipSpecialCharSizeX
                }
            }
            ;
            for (char i = '0'; i <= '9'; i++)
            {
                specialCharacters[i.ToString()] = new TooltipSpecialCharacter {
                    Width = tooltipSpecialCharSizeX
                }
            }
            ;

            specialCharacters["~"] = new TooltipSpecialCharacter {
                Width = tooltipSpecialCharSizeX
            };

            foreach (var specialChar in specialCharacters.Values)
            {
                if (specialChar.Bmp != null)
                {
                    specialChar.Width = (int)g.GetBitmapWidth(specialChar.Bmp);
                }
                specialChar.Height = tooltipSpecialCharSizeY;
            }
        }
Exemplo n.º 17
0
        protected override void OnRender(RenderGraphics g)
        {
            g.FillRectangle(0, 0, Width, Height, toolbarBrush);

            var scaling = RenderTheme.MainWindowScaling;
            var pt      = this.PointToClient(Cursor.Position);

            // Buttons
            foreach (var btn in buttons)
            {
                bool hover = btn.IsPointIn(pt.X, pt.Y, Width);
                var  bmp   = btn.GetBitmap != null?btn.GetBitmap() : btn.Bmp;

                if (bmp == null)
                {
                    bmp = btn.Bmp;
                }
                bool enabled = btn.Enabled != null?btn.Enabled() : true;

                int x = btn.RightAligned ? Width - btn.X : btn.X;
                g.DrawBitmap(bmp, x, btn.Y, enabled ? (hover ? 0.75f : 1.0f) : 0.25f);
            }

            // Timecode
            int frame      = App.CurrentFrame;
            int patternIdx = App.Song.FindPatternInstanceIndex(frame, out int noteIdx);

            g.FillAndDrawRectangle(timecodePosX, timecodePosY, timecodePosX + timecodeSizeX, Height - timecodePosY, theme.DarkGreyFillBrush1, theme.BlackBrush);

            var numPatternDigits = Utils.NumDecimalDigits(App.Song.Length - 1);
            var numNoteDigits    = Utils.NumDecimalDigits(App.Song.GetPatternLength(patternIdx) - 1);

            var zeroSizeX  = g.MeasureString("0", ThemeBase.FontHuge);
            var colonSizeX = g.MeasureString(":", ThemeBase.FontHuge);

            var patternString = patternIdx.ToString("D" + numPatternDigits);
            var noteString    = noteIdx.ToString("D" + numNoteDigits);

            var charPosX = timecodePosX + timecodeSizeX / 2 - ((numPatternDigits + numNoteDigits) * zeroSizeX + colonSizeX) / 2;

            for (int i = 0; i < numPatternDigits; i++, charPosX += zeroSizeX)
            {
                g.DrawText(patternString[i].ToString(), ThemeBase.FontHuge, charPosX, 2, theme.LightGreyFillBrush1, zeroSizeX);
            }

            g.DrawText(":", ThemeBase.FontHuge, charPosX, 2, theme.LightGreyFillBrush1, colonSizeX);
            charPosX += colonSizeX;

            for (int i = 0; i < numNoteDigits; i++, charPosX += zeroSizeX)
            {
                g.DrawText(noteString[i].ToString(), ThemeBase.FontHuge, charPosX, 2, theme.LightGreyFillBrush1, zeroSizeX);
            }

            var message           = tooltip;
            var messageBrush      = theme.BlackBrush;
            var messageFont       = ThemeBase.FontMedium;
            var messageFontCenter = ThemeBase.FontMediumCenter;

            if (!string.IsNullOrEmpty(warning))
            {
                var span = DateTime.Now - warningTime;

                if (span.TotalMilliseconds >= 2000)
                {
                    warning = "";
                }
                else
                {
                    message           = (((((long)span.TotalMilliseconds) / 250) & 1) != 0) ? warning : "";
                    messageBrush      = warningBrush;
                    messageFont       = ThemeBase.FontMediumBold;
                    messageFontCenter = ThemeBase.FontMediumBoldCenter;
                }
            }

            // Tooltip
            if (!string.IsNullOrEmpty(message))
            {
                var lines = message.Split(new[] { '\n' }, StringSplitOptions.RemoveEmptyEntries);
                var posY  = lines.Length == 1 ? tooltipSingleLinePosY : tooltipMultiLinePosY;

                for (int j = 0; j < lines.Length; j++)
                {
                    var splits = lines[j].Split(new char[] { '{', '}' }, StringSplitOptions.RemoveEmptyEntries);
                    var posX   = Width - 40 * RenderTheme.MainWindowScaling;

                    for (int i = splits.Length - 1; i >= 0; i--)
                    {
                        var str = splits[i];

                        if (specialCharacters.TryGetValue(str, out var specialCharacter))
                        {
                            posX -= specialCharacter.Width;

                            if (specialCharacter.Bmp != null)
                            {
                                g.DrawBitmap(specialCharacter.Bmp, posX, posY + specialCharacter.OffsetY);
                            }
                            else
                            {
#if FAMISTUDIO_MACOS
                                if (str == "Ctrl")
                                {
                                    str = "Cmd";
                                }
#endif

#if !FAMISTUDIO_WINDOWS
                                // HACK: The way we handle fonts in OpenGL is so different, i cant be bothered to debug this.
                                posX -= (int)scaling;
#endif

                                g.DrawRectangle(posX, posY + specialCharacter.OffsetY, posX + specialCharacter.Width, posY + specialCharacter.Height + specialCharacter.OffsetY, messageBrush);
                                g.DrawText(str, messageFontCenter, posX, posY, messageBrush, specialCharacter.Width);

#if !FAMISTUDIO_WINDOWS
                                // HACK: The way we handle fonts in OpenGL is so different, i cant be bothered to debug this.
                                posX -= (int)scaling;
#endif
                            }
                        }
                        else
                        {
                            posX -= g.MeasureString(splits[i], messageFont);
                            g.DrawText(str, messageFont, posX, posY, messageBrush);
                        }
                    }

                    posY += tooltipLineSizeY;
                }
            }
        }
Exemplo n.º 18
0
        private void RenderTimecode(RenderGraphics g)
        {
            var frame            = App.CurrentFrame;
            var famitrackerTempo = App.Project != null && App.Project.UsesFamiTrackerTempo;

            var zeroSizeX  = g.MeasureString("0", ThemeBase.FontHuge);
            var colonSizeX = g.MeasureString(":", ThemeBase.FontHuge);

            g.FillAndDrawRectangle(timecodePosX, timecodePosY, timecodePosX + timecodeSizeX, Height - timecodePosY, theme.DarkGreyFillBrush1, theme.BlackBrush);

            if (Settings.TimeFormat == 0 || famitrackerTempo) // MM:SS:mmm cant be used with FamiTracker tempo.
            {
                int patternIdx = App.Song.FindPatternInstanceIndex(frame, out int noteIdx);

                var numPatternDigits = Utils.NumDecimalDigits(App.Song.Length - 1);
                var numNoteDigits    = Utils.NumDecimalDigits(App.Song.GetPatternLength(patternIdx) - 1);

                var patternString = patternIdx.ToString("D" + numPatternDigits);
                var noteString    = noteIdx.ToString("D" + numNoteDigits);

                var charPosX = timecodePosX + timecodeSizeX / 2 - ((numPatternDigits + numNoteDigits) * zeroSizeX + colonSizeX) / 2;

                for (int i = 0; i < numPatternDigits; i++, charPosX += zeroSizeX)
                {
                    g.DrawText(patternString[i].ToString(), ThemeBase.FontHuge, charPosX, 2, theme.LightGreyFillBrush1, zeroSizeX);
                }

                g.DrawText(":", ThemeBase.FontHuge, charPosX, 2, theme.LightGreyFillBrush1, colonSizeX);
                charPosX += colonSizeX;

                for (int i = 0; i < numNoteDigits; i++, charPosX += zeroSizeX)
                {
                    g.DrawText(noteString[i].ToString(), ThemeBase.FontHuge, charPosX, 2, theme.LightGreyFillBrush1, zeroSizeX);
                }
            }
            else
            {
                TimeSpan time = App.Project != null?
                                TimeSpan.FromMilliseconds(frame * 1000.0 / (App.Project.PalMode ? NesApu.FpsPAL : NesApu.FpsNTSC)) :
                                    TimeSpan.Zero;

                var minutesString      = time.Minutes.ToString("D2");
                var secondsString      = time.Seconds.ToString("D2");
                var millisecondsString = time.Milliseconds.ToString("D3");

                // 00:00:000
                var charPosX = timecodePosX + timecodeSizeX / 2 - (7 * zeroSizeX + 2 * colonSizeX) / 2;

                for (int i = 0; i < 2; i++, charPosX += zeroSizeX)
                {
                    g.DrawText(minutesString[i].ToString(), ThemeBase.FontHuge, charPosX, 2, theme.LightGreyFillBrush1, zeroSizeX);
                }
                g.DrawText(":", ThemeBase.FontHuge, charPosX, 2, theme.LightGreyFillBrush1, colonSizeX);
                charPosX += colonSizeX;
                for (int i = 0; i < 2; i++, charPosX += zeroSizeX)
                {
                    g.DrawText(secondsString[i].ToString(), ThemeBase.FontHuge, charPosX, 2, theme.LightGreyFillBrush1, zeroSizeX);
                }
                g.DrawText(":", ThemeBase.FontHuge, charPosX, 2, theme.LightGreyFillBrush1, colonSizeX);
                charPosX += colonSizeX;
                for (int i = 0; i < 3; i++, charPosX += zeroSizeX)
                {
                    g.DrawText(millisecondsString[i].ToString(), ThemeBase.FontHuge, charPosX, 2, theme.LightGreyFillBrush1, zeroSizeX);
                }
            }
        }
Exemplo n.º 19
0
        protected override void OnRender(RenderGraphics g)
        {
            g.Clear(ThemeBase.DarkGreyFillColor1);
            g.DrawLine(0, 0, 0, Height, theme.BlackBrush);

            int actualWidth = Width - scrollBarSizeX;

            int y = -scrollY;

            foreach (var button in buttons)
            {
                var icon = button.GetIcon();

                g.PushTranslation(0, y);
                g.FillAndDrawRectangle(0, 0, actualWidth, buttonSizeY, g.GetVerticalGradientBrush(button.GetColor(), buttonSizeY, 0.8f), theme.BlackBrush);

                var leftPadding = 0;
                if (App.Project.NeedsExpansionInstruments && (button.type == ButtonType.Instrument || button.type == ButtonType.Song))
                {
                    var tabColor = button.instrument != null && button.instrument.IsExpansionInstrument ? ThemeBase.MediumGreyFillColor1 : ThemeBase.LightGreyFillColor1;
                    g.FillRectangle(1, 1, 1 + expansionTypeSizeX, buttonSizeY, g.GetVerticalGradientBrush(tabColor, buttonSizeY, 0.8f));
                    g.PushTranslation(1 + expansionTypeSizeX, 0);
                    g.DrawLine(0, 0, 0, buttonSizeY, theme.BlackBrush);
                    leftPadding = expansionTypeSizeX;
                }

                g.DrawText(button.GetText(App.Project), button.GetFont(selectedSong, selectedInstrument), icon == null ? buttonTextNoIconPosX : buttonTextPosX, buttonTextPosY, theme.BlackBrush, actualWidth - buttonTextNoIconPosX * 2);

                if (icon != null)
                {
                    g.DrawBitmap(icon, buttonIconPosX, buttonIconPosY);
                }

                var subButtons = button.GetSubButtons(out var active);
                if (subButtons != null)
                {
                    for (int i = 0, x = actualWidth - subButtonSpacingX - leftPadding; i < subButtons.Length; i++, x -= subButtonSpacingX)
                    {
                        g.DrawBitmap(button.GetIcon(subButtons[i]), x, subButtonPosY, active[i] ? 1.0f : 0.2f);
                    }
                }

                if (leftPadding != 0)
                {
                    g.PopTransform();
                }

                g.PopTransform();
                y += buttonSizeY;
            }

            if (needsScrollBar)
            {
                int virtualSizeY   = this.virtualSizeY;
                int scrollBarSizeY = (int)Math.Round(Height * (Height / (float)virtualSizeY));
                int scrollBarPosY  = (int)Math.Round(Height * (scrollY / (float)virtualSizeY));

                g.FillAndDrawRectangle(actualWidth, 0, Width - 1, Height, theme.DarkGreyFillBrush1, theme.BlackBrush);
                g.FillAndDrawRectangle(actualWidth, scrollBarPosY, Width - 1, scrollBarPosY + scrollBarSizeY, theme.LightGreyFillBrush1, theme.BlackBrush);
            }
        }
Exemplo n.º 20
0
        protected override void OnRenderInitialized(RenderGraphics g)
        {
            theme = RenderTheme.CreateResourcesForGraphics(g);

            toolbarBrush = g.CreateVerticalGradientBrush(0, Height, ThemeBase.DarkGreyFillColor2, ThemeBase.DarkGreyFillColor1);
            warningBrush = g.CreateSolidBrush(System.Drawing.Color.FromArgb(205, 77, 64));

            bmpLoopNone    = g.CreateBitmapFromResource("LoopNone");
            bmpLoopSong    = g.CreateBitmapFromResource("Loop");
            bmpLoopPattern = g.CreateBitmapFromResource("LoopPattern");
            bmpPlay        = g.CreateBitmapFromResource("Play");
            bmpPause       = g.CreateBitmapFromResource("Pause");
            bmpNtsc        = g.CreateBitmapFromResource("NTSC");
            bmpPal         = g.CreateBitmapFromResource("PAL");
            bmpNtscToPal   = g.CreateBitmapFromResource("NTSCToPAL");
            bmpPalToNtsc   = g.CreateBitmapFromResource("PALToNTSC");
            bmpRec         = g.CreateBitmapFromResource("Rec");
            bmpRecRed      = g.CreateBitmapFromResource("RecRed");

            buttons[ButtonNew] = new Button {
                Bmp = g.CreateBitmapFromResource("File"), Click = OnNew
            };
            buttons[ButtonOpen] = new Button {
                Bmp = g.CreateBitmapFromResource("Open"), Click = OnOpen
            };
            buttons[ButtonSave] = new Button {
                Bmp = g.CreateBitmapFromResource("Save"), Click = OnSave, RightClick = OnSaveAs
            };
            buttons[ButtonExport] = new Button {
                Bmp = g.CreateBitmapFromResource("Export"), Click = OnExport, RightClick = OnRepeatLastExport
            };
            buttons[ButtonCopy] = new Button {
                Bmp = g.CreateBitmapFromResource("Copy"), Click = OnCopy, Enabled = OnCopyEnabled
            };
            buttons[ButtonCut] = new Button {
                Bmp = g.CreateBitmapFromResource("Cut"), Click = OnCut, Enabled = OnCutEnabled
            };
            buttons[ButtonPaste] = new Button {
                Bmp = g.CreateBitmapFromResource("Paste"), Click = OnPaste, RightClick = OnPasteSpecial, Enabled = OnPasteEnabled
            };
            buttons[ButtonUndo] = new Button {
                Bmp = g.CreateBitmapFromResource("Undo"), Click = OnUndo, Enabled = OnUndoEnabled
            };
            buttons[ButtonRedo] = new Button {
                Bmp = g.CreateBitmapFromResource("Redo"), Click = OnRedo, Enabled = OnRedoEnabled
            };
            buttons[ButtonTransform] = new Button {
                Bmp = g.CreateBitmapFromResource("Transform"), Click = OnTransform
            };
            buttons[ButtonConfig] = new Button {
                Bmp = g.CreateBitmapFromResource("Config"), Click = OnConfig
            };
            buttons[ButtonPlay] = new Button {
                Click = OnPlay, GetBitmap = OnPlayGetBitmap
            };
            buttons[ButtonRec] = new Button {
                GetBitmap = OnRecordGetBitmap, Click = OnRecord
            };
            buttons[ButtonRewind] = new Button {
                Bmp = g.CreateBitmapFromResource("Rewind"), Click = OnRewind
            };
            buttons[ButtonLoop] = new Button {
                Click = OnLoop, GetBitmap = OnLoopGetBitmap
            };
            buttons[ButtonQwerty] = new Button {
                Bmp = g.CreateBitmapFromResource("QwertyPiano"), Click = OnQwerty, Enabled = OnQwertyEnabled
            };
            buttons[ButtonMachine] = new Button {
                Click = OnMachine, GetBitmap = OnMachineGetBitmap, Enabled = OnMachineEnabled
            };
            buttons[ButtonFollow] = new Button {
                Bmp = g.CreateBitmapFromResource("Follow"), Click = OnFollow, Enabled = OnFollowEnabled
            };
            buttons[ButtonHelp] = new Button {
                Bmp = g.CreateBitmapFromResource("Help"), RightAligned = true, Click = OnHelp
            };

            buttons[ButtonNew].ToolTip       = "{MouseLeft} New Project {Ctrl} {N}";
            buttons[ButtonOpen].ToolTip      = "{MouseLeft} Open Project {Ctrl} {O}";
            buttons[ButtonSave].ToolTip      = "{MouseLeft} Save Project {Ctrl} {S} - {MouseRight} Save As...";
            buttons[ButtonExport].ToolTip    = "{MouseLeft} Export to various formats {Ctrl} {E}\n{MouseRight} Repeat last export {Ctrl} {Shift} {E}";
            buttons[ButtonCopy].ToolTip      = "{MouseLeft} Copy selection {Ctrl} {C}";
            buttons[ButtonCut].ToolTip       = "{MouseLeft} Cut selection {Ctrl} {X}";
            buttons[ButtonPaste].ToolTip     = "{MouseLeft} Paste {Ctrl} {V}\n{MouseRight} Paste Special... {Ctrl} {Shift} {V}";
            buttons[ButtonUndo].ToolTip      = "{MouseLeft} Undo {Ctrl} {Z}";
            buttons[ButtonRedo].ToolTip      = "{MouseLeft} Redo {Ctrl} {Y}";
            buttons[ButtonTransform].ToolTip = "{MouseLeft} Perform cleanup and various operations";
            buttons[ButtonConfig].ToolTip    = "{MouseLeft} Edit Application Settings";
            buttons[ButtonPlay].ToolTip      = "{MouseLeft} Play/Pause {Space} - Play from start of pattern {Ctrl} {Space}\nPlay from start of song {Shift} {Space} - Play from loop point {Ctrl} {Shift} {Space}";
            buttons[ButtonRewind].ToolTip    = "{MouseLeft} Rewind {Home}\nRewind to beginning of current pattern {Ctrl} {Home}";
            buttons[ButtonRec].ToolTip       = "{MouseLeft} Toggles recording mode {Enter}\nAbort recording {Esc}";
            buttons[ButtonLoop].ToolTip      = "{MouseLeft} Toggle Loop Mode";
            buttons[ButtonQwerty].ToolTip    = "{MouseLeft} Toggle QWERTY keyboard piano input";
            buttons[ButtonMachine].ToolTip   = "{MouseLeft} Toggle between NTSC/PAL playback mode";
            buttons[ButtonFollow].ToolTip    = "{MouseLeft} Toggle follow mode {Shift} {F}";
            buttons[ButtonHelp].ToolTip      = "{MouseLeft} Online documentation";

            UpdateButtonLayout();

            var scaling = RenderTheme.MainWindowScaling;

            timecodePosY            = (int)(DefaultTimecodePosY * scaling);
            timecodeSizeX           = (int)(DefaultTimecodeSizeX * scaling);
            tooltipSingleLinePosY   = (int)(DefaultTooltipSingleLinePosY * scaling);
            tooltipMultiLinePosY    = (int)(DefaultTooltipMultiLinePosY * scaling);
            tooltipLineSizeY        = (int)(DefaultTooltipLineSizeY * scaling);
            tooltipSpecialCharSizeX = (int)(DefaultTooltipSpecialCharSizeX * scaling);
            tooltipSpecialCharSizeY = (int)(DefaultTooltipSpecialCharSizeY * scaling);

            specialCharacters["Shift"] = new TooltipSpecialCharacter {
                Width = (int)(32 * scaling)
            };
            specialCharacters["Space"] = new TooltipSpecialCharacter {
                Width = (int)(38 * scaling)
            };
            specialCharacters["Home"] = new TooltipSpecialCharacter {
                Width = (int)(38 * scaling)
            };
            specialCharacters["Ctrl"] = new TooltipSpecialCharacter {
                Width = (int)(28 * scaling)
            };
            specialCharacters["Alt"] = new TooltipSpecialCharacter {
                Width = (int)(24 * scaling)
            };
            specialCharacters["Enter"] = new TooltipSpecialCharacter {
                Width = (int)(38 * scaling)
            };
            specialCharacters["Esc"] = new TooltipSpecialCharacter {
                Width = (int)(24 * scaling)
            };
            specialCharacters["Del"] = new TooltipSpecialCharacter {
                Width = (int)(24 * scaling)
            };
            specialCharacters["Drag"] = new TooltipSpecialCharacter {
                Bmp = g.CreateBitmapFromResource("Drag"), OffsetY = 2 * scaling
            };
            specialCharacters["MouseLeft"] = new TooltipSpecialCharacter {
                Bmp = g.CreateBitmapFromResource("MouseLeft"), OffsetY = 2 * scaling
            };
            specialCharacters["MouseRight"] = new TooltipSpecialCharacter {
                Bmp = g.CreateBitmapFromResource("MouseRight"), OffsetY = 2 * scaling
            };
            specialCharacters["MouseWheel"] = new TooltipSpecialCharacter {
                Bmp = g.CreateBitmapFromResource("MouseWheel"), OffsetY = 2 * scaling
            };
            specialCharacters["Warning"] = new TooltipSpecialCharacter {
                Bmp = g.CreateBitmapFromResource("Warning")
            };

            for (char i = 'A'; i <= 'Z'; i++)
            {
                specialCharacters[i.ToString()] = new TooltipSpecialCharacter {
                    Width = tooltipSpecialCharSizeX
                }
            }
            ;
            for (char i = '0'; i <= '9'; i++)
            {
                specialCharacters[i.ToString()] = new TooltipSpecialCharacter {
                    Width = tooltipSpecialCharSizeX
                }
            }
            ;

            specialCharacters["~"] = new TooltipSpecialCharacter {
                Width = tooltipSpecialCharSizeX
            };

            foreach (var specialChar in specialCharacters.Values)
            {
                if (specialChar.Bmp != null)
                {
                    specialChar.Width = (int)g.GetBitmapWidth(specialChar.Bmp);
                }
                specialChar.Height = tooltipSpecialCharSizeY;
            }
        }
Exemplo n.º 21
0
        private unsafe RenderBitmap GetPatternBitmapFromCache(RenderGraphics g, Pattern p)
        {
            int patternSizeX = Song.PatternLength - 1;
            int patternSizeY = trackSizeY - patternHeaderSizeY - 1;

            RenderBitmap bmp;

            if (patternBitmapCache.TryGetValue(p.Id, out bmp))
            {
                if (bmp.Size.Width == patternSizeX)
                {
                    return(bmp);
                }
                else
                {
                    patternBitmapCache.Remove(p.Id);
                    bmp.Dispose();
                    bmp = null;
                }
            }

            uint[] data = new uint[patternSizeX * patternSizeY];

            Note minNote;
            Note maxNote;

            if (p.GetMinMaxNote(out minNote, out maxNote))
            {
                if (maxNote.Value == minNote.Value)
                {
                    minNote.Value = (byte)(minNote.Value - 5);
                    maxNote.Value = (byte)(maxNote.Value + 5);
                }
                else
                {
                    minNote.Value = (byte)(minNote.Value - 2);
                    maxNote.Value = (byte)(maxNote.Value + 2);
                }

                Note lastValid = new Note {
                    Value = Note.NoteInvalid
                };

                for (int i = 0; i < Song.PatternLength - 1; i++) // TODO: We always skip the last note.
                {
                    var n = p.Notes[i];

                    if (n.IsValid && !n.IsStop)
                    {
                        lastValid = p.Notes[i];
                    }

                    if (lastValid.IsValid)
                    {
                        float scaleY = (patternSizeY - noteSizeY) / (float)patternSizeY;

                        int x = i;
                        int y = Math.Min((int)Math.Round((lastValid.Value - minNote.Value) / (float)(maxNote.Value - minNote.Value) * scaleY * patternSizeY), patternSizeY - noteSizeY);

                        var instrument = lastValid.Instrument;
                        var color      = instrument == null ? ThemeBase.LightGreyFillColor1 : instrument.Color;

                        for (int j = 0; j < noteSizeY; j++)
                        {
                            data[(patternSizeY - 1 - (y + j)) * patternSizeX + x] = (uint)color.ToArgb();
                        }
                    }

                    //if (n.HasEffect)
                    //{
                    //    for (int y = 0; y < patternSizeY; y++)
                    //    {
                    //        data[y * patternSizeX + i] = 0xff000000;
                    //    }
                    //}
                }
            }

            bmp = g.CreateBitmap(patternSizeX, patternSizeY, data);
            patternBitmapCache[p.Id] = bmp;

            return(bmp);
        }
Exemplo n.º 22
0
        protected override void OnRender(RenderGraphics g)
        {
            g.Clear(ThemeBase.DarkGreyFillColor1);

            int patternSizeX      = PatternSizeX;
            int minVisiblePattern = Math.Max((int)Math.Floor(scrollX / (float)patternSizeX), 0);
            int maxVisiblePattern = Math.Min((int)Math.Ceiling((scrollX + Width) / (float)patternSizeX), Song.Length);

            // Track name background
            g.FillRectangle(0, 0, trackNameSizeX, Height, whiteKeyBrush);

            // Header
            g.DrawLine(0, 0, Width, 0, theme.BlackBrush);
            g.DrawLine(trackNameSizeX - 1, 0, trackNameSizeX - 1, headerSizeY, theme.DarkGreyLineBrush1);
            g.PushTranslation(trackNameSizeX, 0);
            g.PushClip(0, 0, Width, Height);

            for (int i = minVisiblePattern, x = minVisiblePattern * patternSizeX - scrollX; i <= maxVisiblePattern; i++, x += patternSizeX)
            {
                if (i != 0)
                {
                    g.DrawLine(x, 0, x, Height, theme.DarkGreyLineBrush1);
                }
            }

            for (int i = minVisiblePattern, x = minVisiblePattern * patternSizeX - scrollX; i < maxVisiblePattern; i++, x += patternSizeX)
            {
                g.PushTranslation(x, 0);
                g.DrawText(i.ToString(), ThemeBase.FontMediumCenter, 0, barTextPosY, theme.LightGreyFillBrush1, patternSizeX);
                g.PopTransform();
            }

            g.PopClip();
            g.PopTransform();

            g.PushTranslation(0, headerSizeY);

            // Icons
            for (int i = 0, y = 0; i < Song.Channels.Length; i++, y += trackSizeY)
            {
                g.DrawBitmap(bmpTracks[(int)Song.Channels[i].Type], trackIconPosX, y + trackIconPosY, RenderTheme.MainWindowScaling, (App.ChannelMask & (1 << i)) != 0 ? 1.0f : 0.2f);
            }

            // Track names
            for (int i = 0, y = 0; i < Song.Channels.Length; i++, y += trackSizeY)
            {
                g.DrawText(Song.Channels[i].Name, i == selectedChannel ? ThemeBase.FontMediumBold : ThemeBase.FontMedium, trackNamePosX, y + trackNamePosY, theme.BlackBrush);
            }

            // Ghost note icons
            for (int i = 0, y = 0; i < Song.Channels.Length; i++, y += trackSizeY)
            {
                g.DrawBitmap(bmpGhostNote, trackNameSizeX - ghostNoteOffsetX, y + trackSizeY - ghostNoteOffsetY - 1, RenderTheme.MainWindowScaling, (App.GhostChannelMask & (1 << i)) != 0 ? 1.0f : 0.2f);
            }

            // Vertical line seperating the track labels.
            g.DrawLine(trackNameSizeX - 1, 0, trackNameSizeX - 1, Height, theme.DarkGreyLineBrush1);

            // Grey background rectangles ever other pattern + vertical lines
            g.PushClip(trackNameSizeX, 0, Width, Height);
            g.PushTranslation(trackNameSizeX, 0);
            for (int i = minVisiblePattern, x = minVisiblePattern * patternSizeX - scrollX; i < maxVisiblePattern; i++, x += patternSizeX)
            {
                if ((i & 1) == 0)
                {
                    g.FillRectangle(x, 0, x + patternSizeX, Height, theme.DarkGreyFillBrush2);
                }
            }
            for (int i = minVisiblePattern, x = minVisiblePattern * patternSizeX - scrollX; i <= maxVisiblePattern; i++, x += patternSizeX)
            {
                if (i != 0)
                {
                    g.DrawLine(x, 0, x, Height, theme.DarkGreyLineBrush1);
                }
            }
            g.PopTransform();
            g.PopClip();

            // Horizontal lines
            for (int i = 0, y = 0; i < Song.Channels.Length; i++, y += trackSizeY)
            {
                g.DrawLine(0, y, Width, y, theme.DarkGreyLineBrush1);
            }

            g.PushClip(trackNameSizeX, 0, Width, Height);

            // Seek
            int xxx = ScaleForZoom(App.CurrentFrame) + trackNameSizeX - scrollX;

            g.DrawLine(xxx, -headerSizeY, xxx, Height, playPositionBrush);

            // Patterns
            for (int t = 0, y = 0; t < Song.Channels.Length; t++, y += trackSizeY)
            {
                for (int i = minVisiblePattern, x = minVisiblePattern * patternSizeX + trackNameSizeX - scrollX; i < maxVisiblePattern; i++, x += patternSizeX)
                {
                    var pattern = Song.Channels[t].PatternInstances[i];

                    if (pattern != null)
                    {
                        var bmp = GetPatternBitmapFromCache(g, pattern);

                        g.PushTranslation(x, y);
                        g.FillRectangle(1, 1, patternSizeX, patternHeaderSizeY, g.GetVerticalGradientBrush(pattern.Color, patternHeaderSizeY - 1, 0.9f));
                        g.DrawLine(0, patternHeaderSizeY, patternSizeX, patternHeaderSizeY, theme.DarkGreyLineBrush1);
                        if (IsPatternSelected(t, i))
                        {
                            g.FillRectangle(1, 1 + patternHeaderSizeY, PatternSizeX, patternHeaderSizeY + bmp.Size.Height + 1, selectedPatternBrush);
                        }

                        g.DrawBitmap(bmp, 1, 1 + patternHeaderSizeY, PatternSizeX - 1, bmp.Size.Height, 1.0f);
                        g.PushClip(0, 0, PatternSizeX, trackSizeY);
                        g.DrawText(pattern.Name, ThemeBase.FontSmall, patternNamePosX, patternNamePosY, theme.BlackBrush);
                        g.PopClip();
                        g.PopTransform();
                    }
                }
            }

            // Dragging selection
            if (isDraggingSelection)
            {
                var pt = this.PointToClient(Cursor.Position);

                //pt.X -= TrackNameSizeX;
                pt.Y -= headerSizeY;

                var drawX = pt.X - selectionDragAnchorX;
                var drawY = minSelectedChannelIdx * trackSizeY;
                var sizeX = (maxSelectedPatternIdx - minSelectedPatternIdx + 1) * patternSizeX;
                var sizeY = (maxSelectedChannelIdx - minSelectedChannelIdx + 1) * trackSizeY;

                g.FillRectangle(drawX, drawY, drawX + sizeX, drawY + sizeY, selectedPatternBrush);
            }

            g.PopClip();
            g.PopTransform();

            g.DrawLine(0, Height - 1, Width, Height - 1, theme.DarkGreyLineBrush1);
        }
Exemplo n.º 23
0
        protected override void OnRender(RenderGraphics g)
        {
            g.FillRectangle(0, 0, Width, Height, toolbarBrush);

            var scaling = RenderTheme.MainWindowScaling;
            var pt      = this.PointToClient(Cursor.Position);

            // Buttons
            foreach (var btn in buttons)
            {
                bool hover = btn.IsPointIn(pt.X, pt.Y);
                var  bmp   = btn.GetBitmap != null?btn.GetBitmap() : btn.Bmp;

                if (bmp == null)
                {
                    bmp = btn.Bmp;
                }
                bool enabled = btn.Enabled != null?btn.Enabled() : true;

                g.DrawBitmap(bmp, btn.X, btn.Y, enabled ? (hover ? 0.75f : 1.0f) : 0.25f);
            }

            // Timecode
            int frame      = App.CurrentFrame;
            int patternIdx = frame / App.Song.PatternLength;
            int noteIdx    = frame % App.Song.PatternLength;

            g.FillAndDrawRectangle(timecodePosX, timecodePosY, timecodePosX + timecodeSizeX, Height - timecodePosY, theme.DarkGreyFillBrush1, theme.BlackBrush);
            g.DrawText($"{patternIdx:D3}:{noteIdx:D3}", ThemeBase.FontHuge, timecodePosX + timecodeTextPosX, 2, theme.LightGreyFillBrush1, timecodeSizeX);

            // Tooltip
            if (!string.IsNullOrEmpty(tooltip))
            {
                var lines = tooltip.Split(new[] { '\n' }, StringSplitOptions.RemoveEmptyEntries);
                var posY  = lines.Length == 1 ? tooltipSingleLinePosY : tooltipMultiLinePosY;

                for (int j = 0; j < lines.Length; j++)
                {
                    var splits = lines[j].Split(new char[] { '{', '}' }, StringSplitOptions.RemoveEmptyEntries);
                    var posX   = Width - 8 * RenderTheme.MainWindowScaling;

                    for (int i = splits.Length - 1; i >= 0; i--)
                    {
                        var str = splits[i];

                        if (specialCharacters.TryGetValue(str, out var specialCharacter))
                        {
                            posX -= specialCharacter.Width;

                            if (specialCharacter.Bmp != null)
                            {
                                g.DrawBitmap(specialCharacter.Bmp, posX, posY + specialCharacter.OffsetY);
                            }
                            else
                            {
#if FAMISTUDIO_MACOS
                                if (str == "Ctrl")
                                {
                                    str = "Cmd";
                                }
#endif

#if !FAMISTUDIO_WINDOWS
                                // HACK: The way we handle fonts in OpenGL is so different, i cant be bothered to debug this.
                                posX--;
#endif

                                g.DrawRectangle(posX, posY + specialCharacter.OffsetY, posX + specialCharacter.Width, posY + specialCharacter.Height + specialCharacter.OffsetY, theme.BlackBrush, RenderTheme.MainWindowScaling * 2 - 1);
                                g.DrawText(str, ThemeBase.FontMediumCenter, posX, posY, theme.BlackBrush, specialCharacter.Width);

#if !FAMISTUDIO_WINDOWS
                                // HACK: The way we handle fonts in OpenGL is so different, i cant be bothered to debug this.
                                posX--;
#endif
                            }
                        }
                        else
                        {
                            posX -= g.MeasureString(splits[i], ThemeBase.FontMedium);
                            g.DrawText(str, ThemeBase.FontMedium, posX, posY, theme.BlackBrush);
                        }
                    }

                    posY += tooltipLineSizeY;
                }
            }
        }
Exemplo n.º 24
0
        private void RenderWarningAndTooltip(RenderGraphics g)
        {
            var scaling           = RenderTheme.MainWindowScaling;
            var message           = tooltip;
            var messageBrush      = theme.BlackBrush;
            var messageFont       = ThemeBase.FontMedium;
            var messageFontCenter = ThemeBase.FontMediumCenter;

            if (!string.IsNullOrEmpty(warning))
            {
                var span = DateTime.Now - warningTime;

                if (span.TotalMilliseconds >= 2000)
                {
                    warning = "";
                }
                else
                {
                    message           = (((((long)span.TotalMilliseconds) / 250) & 1) != 0) ? warning : "";
                    messageBrush      = warningBrush;
                    messageFont       = ThemeBase.FontMediumBold;
                    messageFontCenter = ThemeBase.FontMediumBoldCenter;
                }
            }

            // Tooltip
            if (!string.IsNullOrEmpty(message))
            {
                var lines = message.Split(new[] { '\n' }, StringSplitOptions.RemoveEmptyEntries);
                var posY  = lines.Length == 1 ? tooltipSingleLinePosY : tooltipMultiLinePosY;

                for (int j = 0; j < lines.Length; j++)
                {
                    var splits = lines[j].Split(new char[] { '{', '}' }, StringSplitOptions.RemoveEmptyEntries);
                    var posX   = Width - 40 * scaling;

                    for (int i = splits.Length - 1; i >= 0; i--)
                    {
                        var str = splits[i];

                        if (specialCharacters.TryGetValue(str, out var specialCharacter))
                        {
                            posX -= specialCharacter.Width;

                            if (specialCharacter.Bmp != null)
                            {
                                g.DrawBitmap(specialCharacter.Bmp, posX, posY + specialCharacter.OffsetY);
                            }
                            else
                            {
#if FAMISTUDIO_MACOS
                                if (str == "Ctrl")
                                {
                                    str = "Cmd";
                                }
#endif

#if !FAMISTUDIO_WINDOWS
                                // HACK: The way we handle fonts in OpenGL is so different, i cant be bothered to debug this.
                                posX -= (int)scaling;
#endif

                                g.DrawRectangle(posX, posY + specialCharacter.OffsetY, posX + specialCharacter.Width, posY + specialCharacter.Height + specialCharacter.OffsetY, messageBrush);
                                g.DrawText(str, messageFontCenter, posX, posY, messageBrush, specialCharacter.Width);

#if !FAMISTUDIO_WINDOWS
                                // HACK: The way we handle fonts in OpenGL is so different, i cant be bothered to debug this.
                                posX -= (int)scaling;
#endif
                            }
                        }
                        else
                        {
                            posX -= g.MeasureString(splits[i], messageFont);
                            g.DrawText(str, messageFont, posX, posY, messageBrush);
                        }
                    }

                    posY += tooltipLineSizeY;
                }
            }
        }