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 = redTooltip ? warningBrush : theme.LightGreyFillBrush2; var messageFont = ThemeBase.FontMedium; var messageFontCenter = ThemeBase.FontMediumCenter; g.PushClip(lastButtonX, 0, Width, Height); 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; } } g.PopClip(); }