public void AddChunkDrawdataToMeshQueue() { int3 chunkSize = CONST.chunkSize; ChunkDrawData chunkDrawData = new ChunkDrawData(new List <Vector3>(), new List <int>(), new List <Vector2>(), this); int offset = 0; BlockDrawInfo drawData; for (int x = 0; x < chunkSize.x; x++) { for (int y = 0; y < chunkSize.y; y++) { for (int z = 0; z < chunkSize.z; z++) { if (getBlock(x, y, z) != BlockType.Air) { drawData = getBlockDrawData(x, y, z, offset); chunkDrawData.vertexList.AddRange(drawData.blockVertexList); chunkDrawData.UVList.AddRange(drawData.blockUVList); /* * int j = 0; * foreach (int val in drawData.blockTriangleList) * { * drawData.blockTriangleList[j] = val + offset; * j++; * } */ offset += drawData.triangleCount; chunkDrawData.triangleList.AddRange(drawData.blockTriangleList); } } } } ChunkDrawDataArray cdda = new ChunkDrawDataArray(chunkDrawData.vertexList.ToArray(), chunkDrawData.triangleList.ToArray(), chunkDrawData.UVList.ToArray(), this); MeshGenerationQueue.AddToQueue(cdda); }
public void AddChunkDrawdataToMeshQueue(System.Object stateInfo) { int3 chunkSize = CONST.chunkSize; ChunkDrawData chunkDrawData = new ChunkDrawData(new List<Vector3>(), new List<int>(), new List<Vector2>(),this); int offset = 0; BlockDrawInfo drawData; for (int x = 0; x < chunkSize.x; x++) { for (int y = 0; y < chunkSize.y; y++) { for (int z = 0; z < chunkSize.z; z++) { if (blocks[x, y, z].blockType != BlockType.Air) { drawData = getBlockDrawData(x, y, z); chunkDrawData.vertexList.AddRange(drawData.blockVertexList); chunkDrawData.UVList.AddRange(drawData.blockUVList); int j = 0; foreach (int val in drawData.blockTriangleList) { drawData.blockTriangleList[j] = val + offset; j++; } offset += drawData.triangleCount; chunkDrawData.triangleList.AddRange(drawData.blockTriangleList); } } } } ChunkDrawDataArray cdda = new ChunkDrawDataArray(chunkDrawData.vertexList.ToArray(), chunkDrawData.triangleList.ToArray(), chunkDrawData.UVList.ToArray(), this); MeshGenerationQueue.AddToQueue(cdda); }
void DrawLastDelayedAndForcedDrawChunks(DrawingContext drawingContext, ChunkDrawData drawData, List <IEventDataNode> forceDrawChunks) { if (drawData != null) { drawingContext.DrawRectangle(drawData.Fill, drawData.Pen, drawData.Rect); } foreach (var forcedChunk in forceDrawChunks) { Brush brush = this.SelectedFill; Pen pen = this.selectedPen; if (forcedChunk == this.hotChunk) { brush = this.HighlightedFill; pen = this.highlightedPen; } DrawChunk(drawingContext, forcedChunk, brush, pen, null, forceDraw: true); } }
ChunkDrawData DrawChunk(DrawingContext drawingContext, IEventDataNode chunk, Brush brush, Pen pen, ChunkDrawData previousChunkData, bool forceDraw) { var x1 = TimeAxis.TimeToScreen(chunk.StartTime); var x2 = Math.Max(x1, TimeAxis.TimeToScreen(chunk.StartTime + chunk.Duration)); // Max in case the duration is bogus if (x2 < 0 || x1 > this.ActualWidth) { if (previousChunkData != null) { drawingContext.DrawRectangle(previousChunkData.Fill, previousChunkData.Pen, previousChunkData.Rect); } return(null); } var r = new Rect(new Point(x1, verticalMargin), new Size(x2 - x1, this.ActualHeight - (verticalMargin * 2))); var halfHeightRect = new Rect(new Point(x1, (this.ActualHeight - halfHeight) / 2), new Size(x2 - x1, halfHeight)); var style = chunk.Style; if (pen == null) { // Since there is no stroke (pen == null), this is a "normal" chunk with no border // (the bar has already been filled w/ border color) so deflate 1/2 pixel to simulate // a border stroke. r.Inflate(-0.5, -0.5); } else { r.Inflate(0, -0.5); } const int minWidth = 3; // Points-in-time (markers) are always 3px wide if (style == EventRenderStyle.ParentedMarker) { r = new Rect(x1 - Math.Floor((double)minWidth / 2), verticalMargin, minWidth, this.ActualHeight - (verticalMargin * 2)); } // Adjust rect height based on chunk nesting depth if (chunk.ZIndex > 0 && !r.IsEmpty && style != EventRenderStyle.HalfHeight) { double delta = chunk.ZIndex * 2; r.Inflate(0, -delta); } if (forceDraw) { // This is a special (hot or selected) chunk, so enforce a minimum width and always draw it. if (style == EventRenderStyle.HalfHeight) { r = halfHeightRect; } var width = r.Width; if (width < minWidth) { var halfGap = (minWidth - width) / 2; r = new Rect(new Point(r.Left - halfGap, r.Top), new Point(r.Right + halfGap, r.Bottom)); } drawingContext.DrawRectangle(brush, pen, r); return(null); } const double minDistance = 16; if (style == EventRenderStyle.HalfHeight) { r = halfHeightRect; } // Draw the chunk. We may need to merge it with the previous rect if there is one. if (previousChunkData != null) { // We have a previous rect. If it's far enough away from this one, then draw it. // OR, if this one is big enough BY ITSELF to be drawn, draw the previous one. // Otherwise, merge it with this one, and draw the result if it's wide enough. if (previousChunkData.Rect.Right < (r.Left - (minDistance / 4)) || (r.Width >= minDistance)) { drawingContext.DrawRectangle(previousChunkData.Fill, previousChunkData.Pen, previousChunkData.Rect); } else { previousChunkData.Rect = Rect.Union(previousChunkData.Rect, r); previousChunkData.Fill = Brushes.Gray; if (previousChunkData.Rect.Width >= minDistance) { drawingContext.DrawRectangle(previousChunkData.Fill, previousChunkData.Pen, previousChunkData.Rect); previousChunkData = null; } return(previousChunkData); } } if (r.Width >= minDistance) { drawingContext.DrawRectangle(brush, pen, r); previousChunkData = null; } else { previousChunkData = new ChunkDrawData { Fill = brush, Rect = r, Pen = pen }; } return(previousChunkData); }
public override void Draw(DrawingContext drawingContext, ulong tickMinVis, ulong tickMaxVis) { Rect r = new Rect(new Point(0, 0), new Size(this.ActualWidth, this.ActualHeight)); // Use a slightly oversize clip region. Otherwise the user wouldn't see the left edge // of the outline on an event starting right at zero. Rect r2 = new Rect(new Point(-2, 0), new Size(this.ActualWidth + 4, this.ActualHeight)); RectangleGeometry rg = new RectangleGeometry(r2); drawingContext.PushClip(rg); drawingContext.DrawRectangle(Brushes.Transparent, null, r); drawingContext.DrawLine(axisPen, new Point(0, this.ActualHeight / 2), new Point(this.ActualWidth, this.ActualHeight / 2)); bool doOptimizedBorders = false; // Chunks are ordered by z-index, then by start time. For each z-index, chunks should be in left-to-right order // and not overlap. Track the maximum drawn X pixel for each z-index pass, so we can draw very small events // without drawing a crazy number of rectangles. See DrawChunk() for the comparisons against maximumDrawnX. int currentZIndex = -1; ChunkDrawData previousChunkData = null; List <IEventDataNode> forceDrawChunks = new List <IEventDataNode>(); foreach (var chunk in this.sortedNodes) { if (chunk.ZIndex > currentZIndex) { currentZIndex = chunk.ZIndex; // Draw the previous chunk data (if any) and the forced-drawn (selected/hot) chunks at the previous level DrawLastDelayedAndForcedDrawChunks(drawingContext, previousChunkData, forceDrawChunks); previousChunkData = null; forceDrawChunks.Clear(); // If dataSource.ContiguousEvents is true, then we are guaranteed that the events are // always right next to each other -- but only at level 0. At higher levels, they may // not be contiguous due to the tree expansion state. The "doOptimizedBorders" mode is to // fill the entire region with the outline color, then draw the chunks with no borders // (if they are big enough to be visible). doOptimizedBorders = (dataSource.ContiguousEvents && currentZIndex == 0); if (doOptimizedBorders) { // Draw the full bar in the standard pen brush color, as if it were full of 1-px wide chunks. r = new Rect(new Point(0, verticalMargin), new Size(this.ActualWidth, this.ActualHeight - (verticalMargin * 2))); if (currentZIndex > 0) { double delta = chunk.ZIndex * 2; r.Inflate(0, -delta); } drawingContext.DrawRectangle(this.Stroke, null, r); } } if (chunk.Visible) { Brush brush; Pen pen; if (chunk == hotChunk || this.selectedChunks.Contains(chunk)) { // We need to draw these a second time. If we skip them, it causes different // merging behavior and you get visual artifacts as you select/hover over events. forceDrawChunks.Add(chunk); } pen = doOptimizedBorders ? null : standardPen; if (UseEventColor) { uint nodeColor = chunk.Color; if (!customBrushes.TryGetValue(nodeColor, out brush)) { brush = new SolidColorBrush(new EventColor(nodeColor)); customBrushes.Add(nodeColor, brush); } } else { brush = this.Fill; } previousChunkData = DrawChunk(drawingContext, chunk, brush, pen, previousChunkData, forceDraw: false); } } DrawLastDelayedAndForcedDrawChunks(drawingContext, previousChunkData, forceDrawChunks); double?lastDrawnSlicingMarkerX = null; foreach (var marker in this.slicingMarkers) { lastDrawnSlicingMarkerX = DrawSlicingMarker(drawingContext, marker, lastDrawnSlicingMarkerX); } List <Rect> labelRects = new List <Rect>(); FormattedText ftLabel = null; // Draw selected chunk arrows, and calculate label rect requirements foreach (var selectedChunk in this.selectedChunks) { if (selectedChunk != hotChunk) { var brush = IsFocused ? this.SelectedFill : this.InactiveSelectedFill; var middle = TimeAxis.TimeToScreen(selectedChunk.StartTime + (selectedChunk.Duration / 2)); double heightAdjust = 0.5; if (selectedChunk.Style == EventRenderStyle.SlicingMarker) { heightAdjust = verticalMargin - 6; } var geom = selectionArrowGeometry.Clone(); geom.Transform = new TranslateTransform(middle, verticalMargin - heightAdjust); drawingContext.DrawGeometry(brush, selectedPen, geom); var x1 = TimeAxis.TimeToScreen(selectedChunk.StartTime); var x2 = TimeAxis.TimeToScreen(selectedChunk.StartTime + selectedChunk.Duration); if (x1 < this.ActualWidth && x2 > 0) { // Draw label, if selected chunk is visible if (ftLabel == null) { // NOTE: It is assumed that all selected chunks have the same name... ftLabel = new FormattedText(selectedChunk.Name, CultureInfo.CurrentCulture, FlowDirection.LeftToRight, labelTypeface, labelFontSize, Brushes.Black); } // Try to center the label under the event. But adjust its position if it // is clipped by the left or right edge of the timeline. var left = middle - ftLabel.Width / 2; if (left < 0) { left = 0; } else if (left + ftLabel.Width > this.ActualWidth) { left = this.ActualWidth - ftLabel.Width; } // Create a rect (top/height insignificant) for this label and remember it labelRects.Add(new Rect(left, 0, ftLabel.Width, 10)); } } } if (ftLabel != null) { List <Rect> mergedRects = new List <Rect>(labelRects.Count); // Merge the overlapping label rects together while (labelRects.Count > 0) { Rect rect = labelRects[0]; labelRects.RemoveAt(0); for (int i = 0; i < labelRects.Count;) { if (rect.IntersectsWith(labelRects[i])) { rect.Union(labelRects[i]); labelRects.RemoveAt(i); } else { i++; } } mergedRects.Add(rect); } // Draw the text centered in each of the remaining label rects foreach (var rect in mergedRects) { double centerX = rect.Left + (rect.Width / 2) - (ftLabel.Width / 2); drawingContext.DrawText(ftLabel, new Point(centerX, this.ActualHeight - verticalMargin)); } } // Draw hot chunk arrow if (hotChunk != null) { var middle = TimeAxis.TimeToScreen(hotChunk.StartTime + (hotChunk.Duration / 2)); double heightAdjust = 0.5; if (hotChunk.Style == EventRenderStyle.SlicingMarker) { heightAdjust = verticalMargin - 6; } hotArrowGeometry.Transform = new TranslateTransform(middle, verticalMargin - heightAdjust); drawingContext.DrawGeometry(this.HighlightedFill, this.highlightedPen, hotArrowGeometry); } drawingContext.Pop(); // pop clip UpdateToolTip(); }
ChunkDrawData DrawChunk(DrawingContext drawingContext, IEventDataNode chunk, Brush brush, Pen pen, ChunkDrawData previousChunkData, bool forceDraw) { var x1 = TimeAxis.TimeToScreen(chunk.StartTime); var x2 = Math.Max(x1, TimeAxis.TimeToScreen(chunk.StartTime + chunk.Duration)); // Max in case the duration is bogus if (x2 < 0 || x1 > this.ActualWidth) { if (previousChunkData != null) { drawingContext.DrawRectangle(previousChunkData.Fill, previousChunkData.Pen, previousChunkData.Rect); } return null; } var r = new Rect(new Point(x1, verticalMargin), new Size(x2 - x1, this.ActualHeight - (verticalMargin * 2))); var halfHeightRect = new Rect(new Point(x1, (this.ActualHeight - halfHeight) / 2), new Size(x2 - x1, halfHeight)); var style = chunk.Style; if (pen == null) { // Since there is no stroke (pen == null), this is a "normal" chunk with no border // (the bar has already been filled w/ border color) so deflate 1/2 pixel to simulate // a border stroke. r.Inflate(-0.5, -0.5); } else { r.Inflate(0, -0.5); } const int minWidth = 3; // Points-in-time (markers) are always 3px wide if (style == EventRenderStyle.ParentedMarker) { r = new Rect(x1 - Math.Floor((double)minWidth / 2), verticalMargin, minWidth, this.ActualHeight - (verticalMargin * 2)); } // Adjust rect height based on chunk nesting depth if (chunk.ZIndex > 0 && !r.IsEmpty && style != EventRenderStyle.HalfHeight) { double delta = chunk.ZIndex * 2; r.Inflate(0, -delta); } if (forceDraw) { // This is a special (hot or selected) chunk, so enforce a minimum width and always draw it. if (style == EventRenderStyle.HalfHeight) { r = halfHeightRect; } var width = r.Width; if (width < minWidth) { var halfGap = (minWidth - width) / 2; r = new Rect(new Point(r.Left - halfGap, r.Top), new Point(r.Right + halfGap, r.Bottom)); } drawingContext.DrawRectangle(brush, pen, r); return null; } const double minDistance = 16; if (style == EventRenderStyle.HalfHeight) { r = halfHeightRect; } // Draw the chunk. We may need to merge it with the previous rect if there is one. if (previousChunkData != null) { // We have a previous rect. If it's far enough away from this one, then draw it. // OR, if this one is big enough BY ITSELF to be drawn, draw the previous one. // Otherwise, merge it with this one, and draw the result if it's wide enough. if (previousChunkData.Rect.Right < (r.Left - (minDistance / 4)) || (r.Width >= minDistance)) { drawingContext.DrawRectangle(previousChunkData.Fill, previousChunkData.Pen, previousChunkData.Rect); } else { previousChunkData.Rect = Rect.Union(previousChunkData.Rect, r); previousChunkData.Fill = Brushes.Gray; if (previousChunkData.Rect.Width >= minDistance) { drawingContext.DrawRectangle(previousChunkData.Fill, previousChunkData.Pen, previousChunkData.Rect); previousChunkData = null; } return previousChunkData; } } if (r.Width >= minDistance) { drawingContext.DrawRectangle(brush, pen, r); previousChunkData = null; } else { previousChunkData = new ChunkDrawData { Fill = brush, Rect = r, Pen = pen }; } return previousChunkData; }
void DrawLastDelayedAndForcedDrawChunks(DrawingContext drawingContext, ChunkDrawData drawData, List<IEventDataNode> forceDrawChunks) { if (drawData != null) { drawingContext.DrawRectangle(drawData.Fill, drawData.Pen, drawData.Rect); } foreach (var forcedChunk in forceDrawChunks) { Brush brush = this.SelectedFill; Pen pen = this.selectedPen; if (forcedChunk == this.hotChunk) { brush = this.HighlightedFill; pen = this.highlightedPen; } DrawChunk(drawingContext, forcedChunk, brush, pen, null, forceDraw: true); } }