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); } }
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); } }
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); } }
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; } } }
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); }
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; } } }
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); } } }
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); } } }
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; } } }