private int _yBottomOfPedigree; // used for descendents public PedigreeControl() { InitializeComponent(); SetStyle(ControlStyles.UserPaint | ControlStyles.AllPaintingInWmPaint | ControlStyles.OptimizedDoubleBuffer, true); _lines = new[] { new List <int[]>(), new List <int[]>(), new List <int[]>() }; NoCreatureSelected(); listViewCreatures.ListViewItemSorter = new ListViewColumnSorter(); splitContainer1.Panel2.Paint += Panel2_Paint; _tt = new ToolTip { AutoPopDelay = 10000 }; _compactGenerations = Properties.Settings.Default.PedigreeCompactViewGenerations; switch ((PedigreeViewMode)Properties.Settings.Default.PedigreeViewMode) { case PedigreeViewMode.Compact: RbViewCompact.Checked = true; break; case PedigreeViewMode.HView: RbViewH.Checked = true; break; default: RbViewClassic.Checked = true; break; } TbZoom.Value = (int)(10 * Properties.Settings.Default.PedigreeZoomFactor); PedigreeCreatureCompact.SetSizeFactor(Properties.Settings.Default.PedigreeZoomFactor); nudGenerations.ValueSave = _compactGenerations; statSelector1.StatIndexSelected += StatSelector1_StatIndexSelected; }
CreateParentsChildCompact(Creature creature, int x, int y, int xOffsetParents, List <int[]>[] lines, List <Control> pcs, ToolTip tt, bool onlyDrawParents, bool highlightCreature, int highlightStatIndex, bool hView, int hViewRotation, out Point locationMother, out Point locationFather, int highlightMotherLine = 0, int highlightFatherLine = 0) { locationMother = Point.Empty; locationFather = Point.Empty; if (creature == null) { return((0, 0), (0, 0)); } if (!onlyDrawParents) { // creature var c = new PedigreeCreatureCompact(creature, highlightCreature, highlightStatIndex, tt) { Location = new Point(x, y) }; pcs.Add(c); if (highlightStatIndex != -1) { (highlightMotherLine, highlightFatherLine) = c.PossibleStatInheritance(highlightStatIndex); } } if (creature.Mother == null && creature.Father == null) { return((0, 0), (0, 0)); } var statInheritanceMother = (0, 0); var statInheritanceFather = (0, 0); var yParents = y - PedigreeCreatureCompact.ControlHeight * 13 / 12; // mother if (creature.Mother != null) { locationMother = hView ? RotateOffset(x, y, -xOffsetParents, 0, hViewRotation) : new Point(x - xOffsetParents, yParents); var c = new PedigreeCreatureCompact(creature.Mother, highlightStatIndex: highlightMotherLine != 0 ? highlightStatIndex : -1, tt: tt) { Location = locationMother }; pcs.Add(c); if (highlightMotherLine != 0 && highlightStatIndex != -1) { statInheritanceMother = c.PossibleStatInheritance(highlightStatIndex); } } // father if (creature.Father != null) { locationFather = hView ? RotateOffset(x, y, xOffsetParents, 0, hViewRotation) : new Point(x + xOffsetParents, yParents); var c = new PedigreeCreatureCompact(creature.Father, highlightStatIndex: highlightFatherLine != 0 ? highlightStatIndex : -1, tt: tt) { Location = locationFather }; pcs.Add(c); if (highlightFatherLine != 0 && highlightStatIndex != -1) { statInheritanceFather = c.PossibleStatInheritance(highlightStatIndex); } } // lines if (hView) { // M──O──F // keep normal lines black to make them more visible in this mode if (highlightMotherLine == 0) { highlightMotherLine = 1; } if (highlightFatherLine == 0) { highlightFatherLine = 1; } var halfControlWidth = PedigreeCreatureCompact.ControlWidth / 2 - 1; var xCenter = x + halfControlWidth; var yCenter = y + PedigreeCreatureCompact.ControlHeight / 2; var start = RotateOffset(xCenter, yCenter, -xOffsetParents + halfControlWidth, 0, hViewRotation); var end = RotateOffset(xCenter, yCenter, -halfControlWidth, 0, hViewRotation); lines[1].Add(new[] { start.X, start.Y, end.X, end.Y, highlightMotherLine }); start = RotateOffset(xCenter, yCenter, xOffsetParents - halfControlWidth, 0, hViewRotation); end = RotateOffset(xCenter, yCenter, halfControlWidth, 0, hViewRotation); lines[1].Add(new[] { start.X, start.Y, end.X, end.Y, highlightFatherLine }); } else { // M──┬──F // O var yLineHorizontal = y - PedigreeCreatureCompact.ControlHeight / 2; var xCenterOffspring = x + PedigreeCreatureCompact.ControlWidth / 2; lines[2].Add(new[] { x - xOffsetParents + PedigreeCreatureCompact.ControlWidth, yLineHorizontal, xCenterOffspring, yLineHorizontal, highlightMotherLine }); lines[2].Add(new[] { x + xOffsetParents, yLineHorizontal, xCenterOffspring, yLineHorizontal, highlightFatherLine }); lines[1].Add(new[] { xCenterOffspring, yLineHorizontal, xCenterOffspring, y, Math.Max(highlightMotherLine, highlightFatherLine) }); } return(statInheritanceMother, statInheritanceFather); }
private static void DrawKey(PictureBox pb, Species species) { if (species == null) { return; } var w = pb.Width; var h = pb.Height; Bitmap bmp = new Bitmap(w, h); using (Graphics g = Graphics.FromImage(bmp)) using (var font = new Font("Microsoft Sans Serif", 8.25f)) using (var format = new StringFormat { Alignment = StringAlignment.Center, LineAlignment = StringAlignment.Center }) using (var pen = new Pen(Color.Black)) using (var brush = new SolidBrush(Color.Black)) { g.SmoothingMode = SmoothingMode.AntiAlias; g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAlias; // border g.DrawRectangle(pen, 0, 0, w - 1, h - 1); // stats const int padding = 4; const int statCircleSize = PedigreeCreatureCompact.DefaultStatSize * 3 / 2; const int statRadius = statCircleSize / 2; const int radiusInnerCircle = statRadius / 7; var statLeftTopCoords = new Point(padding, padding); var center = new Point(statLeftTopCoords.X + statRadius, statLeftTopCoords.Y + statRadius); brush.Color = Color.White; g.FillEllipse(brush, statLeftTopCoords.X, statLeftTopCoords.Y, statRadius * 2, statRadius * 2); brush.Color = Color.Black; var usedStats = Enumerable.Range(0, Values.STATS_COUNT).Where(si => si != (int)StatNames.Torpidity && species.UsesStat(si)).ToArray(); var anglePerStat = 360f / usedStats.Length; var i = 0; foreach (var si in usedStats) { var angle = PedigreeCreatureCompact.AngleOffset + anglePerStat * i++; g.DrawPie(pen, statLeftTopCoords.X, statLeftTopCoords.Y, statCircleSize, statCircleSize, angle, anglePerStat); // text const int radiusPosition = statRadius * 7 / 10; var anglePosition = Math.PI * 2 / 360 * (angle + anglePerStat / 2); const int statTexSizeHalf = 15; var x = (int)Math.Round(radiusPosition * Math.Cos(anglePosition) + center.X - statTexSizeHalf); var y = (int)Math.Round(radiusPosition * Math.Sin(anglePosition) + center.Y - statTexSizeHalf); g.DrawString(Utils.StatName(si, true, species.statNames), font, brush, new RectangleF(x, y, statTexSizeHalf * 2, statTexSizeHalf * 2), format); } brush.Color = Color.Gray; g.FillEllipse(brush, center.X - radiusInnerCircle, center.Y - radiusInnerCircle, 2 * radiusInnerCircle, 2 * radiusInnerCircle); // circles const int textX = 3 * padding + 6; const int lineHeight = 15; void CircleExplanation(Color circleColor, string text, int y, int circleSize, int circleOffset = 0) { PedigreeCreatureCompact.DrawFilledCircle(g, brush, pen, circleColor, padding + circleOffset, y + lineHeight / 4 + circleOffset, circleSize); brush.Color = Color.Black; g.DrawString(text, font, brush, textX, y); } void RectangleExplanation(Color rectangleColor, string text, int y, int size) { pen.Color = rectangleColor; pen.Width = 2; g.DrawRectangle(pen, padding, y, size, size); brush.Color = Color.Black; g.DrawString(text, font, brush, textX, y); } void ArrowExplanation(List <int[]> linesList, int lineStyle, string text, int y, int size) { var yLine = y + lineHeight / 2; linesList.Add(new[] { padding, yLine, padding + size, yLine, lineStyle }); brush.Color = Color.Black; g.DrawString(text, font, brush, textX, y); } int yText = statRadius * 2 + 4 * padding; CircleExplanation(Utils.MutationMarkerColor, "mutation in stat", yText, 6); yText += lineHeight; CircleExplanation(Utils.MutationMarkerPossibleColor, "possible mutation in stat", yText, 6); yText += lineHeight; CircleExplanation(Color.Yellow, "mutation in color", yText, 4, 1); yText += lineHeight; CircleExplanation(Color.GreenYellow, "creature without mutations", yText, 6); yText += lineHeight; CircleExplanation(Utils.MutationColor, "creature mutations < limit", yText, 6); yText += lineHeight; CircleExplanation(Color.DarkRed, "creature mutations ≥ limit", yText, 6); yText += lineHeight; // rectangles RectangleExplanation(Color.DodgerBlue, "selected creature", yText, 10); yText += lineHeight; RectangleExplanation(Utils.MutationMarkerColor, "creature with mutation", yText, 10); yText += lineHeight; // arrows var lines = new[] { null, new List <int[]>(), null }; ArrowExplanation(lines[1], 1, "offspring", yText, 10); yText += lineHeight; ArrowExplanation(lines[1], 2, "stat inheritance", yText, 10); yText += lineHeight; ArrowExplanation(lines[1], 3, "stat inheritance with", yText, 10); g.DrawString("possible mutation", font, brush, textX, yText + lineHeight); DrawLines(g, lines); } pb.SetImageAndDisposeOld(bmp); }