//intercept invalidation and render next frame protected override void OnInvalidated(InvalidateEventArgs e) { base.OnInvalidated(e); //if there's no rendering region or the invalid rect is not touching it, return here. if (Region == null || !DisplayRectangle.IntersectsWith(e.InvalidRect)) { return; } Graphics bufferGraphics = RenderingBufferedGraphics.GetNewGraphicsContext(); bufferGraphics.Clear(Color.Transparent); PreRendering(bufferGraphics); bufferGraphics.Dispose(); }
/// <summary> /// Gets coordinates in client space of indicator triangle to last marked tile. /// </summary> /// <param name="pointerHeight">Height of indicator, in pixels.</param> /// <param name="pointerWidth">Width of indicator, in pixels.</param> /// <returns>Returns table of 3 points making indicator triangle or null if last /// marked tile is in viewport and indicator is not needed.</returns> public Point[] GetIndicatorPointsToLastMarkedTile(int pointerHeight, int pointerWidth) { if (lastMarked == new Point(-1, -1)) { return(null); } Rectangle lastMarkedTile = new Rectangle(GetTilePositionInClientSpace(lastMarked), TileSizeInViewport); if (DisplayRectangle.IntersectsWith(lastMarkedTile)) { return(null); } Point[] result = new Point[3]; result[1] = new Point(-pointerHeight, pointerWidth / 2); result[2] = new Point(-pointerHeight, -pointerWidth / 2); Point viewToTileVector = new Point(lastMarkedTile.X + lastMarkedTile.Width / 2 - Width / 2, lastMarkedTile.Y + lastMarkedTile.Height / 2 - Height / 2); double viewToTileLength = Math.Sqrt(viewToTileVector.X * viewToTileVector.X + viewToTileVector.Y * viewToTileVector.Y); double xAxisAngleCos = viewToTileVector.X / viewToTileLength; double xAxisAngleSin = viewToTileVector.Y / viewToTileLength; // rotate points for (int i = 1; i < result.Length; ++i) { result[i] = new Point((int)(result[i].X * xAxisAngleCos - result[i].Y * xAxisAngleSin), (int)(result[i].X * xAxisAngleSin + result[i].Y * xAxisAngleCos)); } const int boundDistance = 20; int[] vecProductsSigns = { CrossProductSign(viewToTileVector, new Point(Width / 2, Height / 2)), CrossProductSign(viewToTileVector, new Point(-Width / 2, Height / 2)), CrossProductSign(viewToTileVector, new Point(-Width / 2, -Height / 2)), CrossProductSign(viewToTileVector, new Point(Width / 2, -Height / 2)) }; Point indicatorLineBeg, indicatorLineDir; if (vecProductsSigns[0] < 0 && vecProductsSigns[1] >= 0 && vecProductsSigns[2] > 0 && vecProductsSigns[3] < 0) { indicatorLineBeg = new Point(boundDistance, Height - boundDistance); indicatorLineDir = new Point(1, 0); } else if (vecProductsSigns[0] < 0 && vecProductsSigns[1] < 0 && vecProductsSigns[2] >= 0 && vecProductsSigns[3] > 0) { indicatorLineBeg = new Point(boundDistance, boundDistance); indicatorLineDir = new Point(0, 1); } else if (vecProductsSigns[0] > 0 && vecProductsSigns[1] < 0 && vecProductsSigns[2] < 0 && vecProductsSigns[3] >= 0) { indicatorLineBeg = new Point(boundDistance, boundDistance); indicatorLineDir = new Point(1, 0); } else { indicatorLineBeg = new Point(Width - boundDistance, boundDistance); indicatorLineDir = new Point(0, 1); } int mainDeterminant = viewToTileVector.X * indicatorLineDir.Y - viewToTileVector.Y * indicatorLineDir.X; int tDeterminant = (indicatorLineBeg.X - Width / 2) * indicatorLineDir.Y - (indicatorLineBeg.Y - Height / 2) * indicatorLineDir.X; double t0 = (double)tDeterminant / mainDeterminant; result[0] = new Point((int)(Width / 2 + viewToTileVector.X * t0), (int)(Height / 2 + viewToTileVector.Y * t0)); for (int i = 1; i < result.Length; ++i) { result[i].X += result[0].X; result[i].Y += result[0].Y; } return(result); }