diff --git a/SourceGen/Visualization.cs b/SourceGen/Visualization.cs
index 32e76be..1935c15 100644
--- a/SourceGen/Visualization.cs
+++ b/SourceGen/Visualization.cs
@@ -21,7 +21,7 @@ using System.Text;
using System.Windows;
using System.Windows.Media;
using System.Windows.Media.Imaging;
-
+using System.Windows.Shapes;
using CommonUtil;
using PluginCommon;
@@ -100,7 +100,7 @@ namespace SourceGen {
VisualizationAnimation.GenerateAnimOverlayImage();
internal static readonly BitmapSource BLANK_IMAGE = GenerateBlankImage();
- internal static readonly BitmapSource BLACK_IMAGE = GenerateBlackImage();
+ //internal static readonly BitmapSource BLACK_IMAGE = GenerateBlackImage();
///
/// Serial number, for reference from other Visualization objects. Not serialized.
@@ -172,6 +172,15 @@ namespace SourceGen {
}
}
+ public void SetThumbnail(IVisualizationWireframe visWire,
+ ReadOnlyDictionary parms) {
+ if (visWire == null) {
+ CachedImage = BROKEN_IMAGE;
+ } else {
+ CachedImage = GenerateWireframeImage(visWire, parms, 64);
+ }
+ }
+
///
/// Trims a tag, removing leading/trailing whitespace, and checks it for validity.
///
@@ -228,33 +237,118 @@ namespace SourceGen {
///
/// Visualization data.
/// Parameter set, for rotations and render options.
- /// Output bitmap width.
- /// Output bitmap height.
- ///
+ /// Output bitmap dimension (width and height).
+ /// Rendered bitmap.
public static BitmapSource GenerateWireframeImage(IVisualizationWireframe visWire,
- ReadOnlyDictionary parms, double width, double height) {
- // TODO(xyzzy): need to get path into a bitmap for thumbnails / GIFs...; call
- // GenerateWireframePath and then render the path
- // https://stackoverflow.com/a/23582564/294248
- Debug.WriteLine("Render " + visWire + " at " + width + "x" + height);
- return null;
+ ReadOnlyDictionary parms, double dim) {
+ GeometryGroup geo = GenerateWireframePath(visWire, parms, dim);
+
+ // Render Path to bitmap -- https://stackoverflow.com/a/23582564/294248
+ Rect bounds = geo.GetRenderBounds(null);
+
+ Debug.WriteLine("RenderWF dim=" + dim + " bounds=" + bounds + ": " + visWire);
+
+ // Create bitmap.
+ RenderTargetBitmap bitmap = new RenderTargetBitmap(
+ (int)bounds.Width,
+ (int)bounds.Height,
+ 96,
+ 96,
+ PixelFormats.Pbgra32);
+ //RenderOptions.SetEdgeMode(bitmap, EdgeMode.Aliased); <-- doesn't work?
+
+ // Clear the bitmap to black. (Is there an easier way?)
+ GeometryGroup bkgnd = new GeometryGroup();
+ bkgnd.Children.Add(new RectangleGeometry(new Rect(0, 0, bounds.Width, bounds.Height)));
+ Path path = new Path();
+ path.Data = bkgnd;
+ path.Stroke = path.Fill = Brushes.Black;
+ path.Measure(bounds.Size);
+ path.Arrange(bounds);
+ bitmap.Render(path);
+
+ path = new Path();
+ path.Data = geo;
+ path.Stroke = Brushes.White;
+ path.Measure(bounds.Size);
+ path.Arrange(bounds);
+ bitmap.Render(path);
+
+ return bitmap;
}
///
- /// Generates a WPF path from IVisualizationWireframe data.
+ /// Generates a WPF path from IVisualizationWireframe data. Line widths get scaled
+ /// if the output area is larger or smaller than the path, so this scales coordinates
+ /// so they fit within the box.
///
+ /// Visualization data.
+ /// Visualization parameters.
+ /// Width/height to use for path area.
public static GeometryGroup GenerateWireframePath(IVisualizationWireframe visWire,
- ReadOnlyDictionary parms, double scale) {
+ ReadOnlyDictionary parms, double dim) {
+ // WPF path drawing is based on a system where a pixel is drawn at the center
+ // of the coordinate, and integer coordinates start at the top left edge. If
+ // you draw a pixel at (0,0), most of the pixel will be outside the window
+ // (visible or not based on ClipToBounds).
+ //
+ // If you draw a line from (1,1 to 4,1), the line's length will appear to
+ // be (4 - 1) = 3. It touches four pixels -- the end point is not exclusive --
+ // but because the thickness doesn't extend past the endpoints, the filled
+ // area is only three. If you have a window of size 10x10, and you draw from
+ // 0,0 to 9,9, the line will extend for half a line-thickness off the top,
+ // but will not go past the right/left edges.
+ //
+ // Similarly, drawing a horizontal line two units long results in a square, and
+ // drawing a line that starts and ends at the same point doesn't appear to
+ // produce anything.
+ //
+ // It's possible to clean up the edges by adding 0.5 to all coordinate values.
+ // This turns out to be important for another reason: a line from (1,1) to (9,1)
+ // shows up as a double-wide half-bright line, while a line from (1.5,1.5) to
+ // (9.5,1.5) is drawn as a single-wide full-brightness line. This is because of
+ // the anti-aliasing.
+ //
+ // The path has a bounding box that starts at (0,0) in the top left, and extends
+ // out as far as needed. If we want a path-drawn shape to animate smoothly we
+ // want to ensure that the bounds are constant across all renderings of a shape
+ // (which could get thinner or wider as it rotates), so we draw an invisible
+ // pixel in our desired bottom-right corner.
+ //
+ // If we want an 8x8 bitmap, we draw a line from (8,8) to (8,8) to establish the
+ // bounds, then draw lines with coordinates from 0.5 to 7.5.
+
GeometryGroup geo = new GeometryGroup();
// This establishes the geometry bounds. It's a zero-length line segment, so
// nothing is actually drawn.
- Debug.WriteLine("using scale=" + scale);
- Point corner = new Point(scale + 1, scale + 1);
+ Debug.WriteLine("using max=" + dim);
+ // TODO: currently ignoring dim
+ Point corner = new Point(8, 8);
+ geo.Children.Add(new LineGeometry(corner, corner));
+ corner = new Point(0, 0);
geo.Children.Add(new LineGeometry(corner, corner));
// TODO(xyzzy): render
- geo.Children.Add(new LineGeometry(new Point(6, 6), new Point(197, 197)));
- geo.Children.Add(new LineGeometry(new Point(6, 197), new Point(197, 6)));
+ //geo.Children.Add(new LineGeometry(new Point(0.0, 0.0), new Point(1.0, 0.0)));
+ //geo.Children.Add(new LineGeometry(new Point(0.5, 0.5), new Point(1.5, 0.5)));
+ //geo.Children.Add(new LineGeometry(new Point(0.75, 0.75), new Point(1.75, 0.75)));
+ geo.Children.Add(new LineGeometry(new Point(0.0, 0.0), new Point(5.0, 7.0)));
+
+ geo.Children.Add(new LineGeometry(new Point(0.5, 2), new Point(0.5, 3)));
+ geo.Children.Add(new LineGeometry(new Point(1.5, 3), new Point(1.5, 4)));
+ geo.Children.Add(new LineGeometry(new Point(2.5, 2), new Point(2.5, 3)));
+ geo.Children.Add(new LineGeometry(new Point(3.5, 3), new Point(3.5, 4)));
+ geo.Children.Add(new LineGeometry(new Point(4.5, 2), new Point(4.5, 3)));
+ geo.Children.Add(new LineGeometry(new Point(5.5, 3), new Point(5.5, 4)));
+ geo.Children.Add(new LineGeometry(new Point(6.5, 2), new Point(6.5, 3)));
+ geo.Children.Add(new LineGeometry(new Point(7.5, 3), new Point(7.5, 4)));
+
+ //geo.Children.Add(new LineGeometry(new Point(4, 5), new Point(3, 5)));
+ //geo.Children.Add(new LineGeometry(new Point(2, 5), new Point(1, 5)));
+
+ //geo.Children.Add(new LineGeometry(new Point(4, 7), new Point(1, 7)));
+ //geo.Children.Add(new LineGeometry(new Point(5, 7), new Point(9, 7)));
+ //geo.Children.Add(new LineGeometry(new Point(0, 8.5), new Point(9, 8.5)));
return geo;
}
@@ -270,20 +364,20 @@ namespace SourceGen {
///
/// Returns a bitmap with a single black pixel.
///
- private static BitmapSource GenerateBlackImage() {
- BitmapPalette palette = new BitmapPalette(new List { Colors.Black });
- BitmapSource image = BitmapSource.Create(
- 1,
- 1,
- 96.0,
- 96.0,
- PixelFormats.Indexed8,
- palette,
- new byte[] { 0 },
- 1);
+ //private static BitmapSource GenerateBlackImage() {
+ // BitmapPalette palette = new BitmapPalette(new List { Colors.Black });
+ // BitmapSource image = BitmapSource.Create(
+ // 1,
+ // 1,
+ // 96.0,
+ // 96.0,
+ // PixelFormats.Indexed8,
+ // palette,
+ // new byte[] { 0 },
+ // 1);
- return image;
- }
+ // return image;
+ //}
public override string ToString() {
diff --git a/SourceGen/VisualizationSet.cs b/SourceGen/VisualizationSet.cs
index 5887236..911a888 100644
--- a/SourceGen/VisualizationSet.cs
+++ b/SourceGen/VisualizationSet.cs
@@ -206,20 +206,33 @@ namespace SourceGen {
continue;
}
- IVisualization2d vis2d;
+ IVisualization2d vis2d = null;
+ IVisualizationWireframe visWire = null;
+ ReadOnlyDictionary parms =
+ new ReadOnlyDictionary(vis.VisGenParams);
try {
- vis2d = vplug.Generate2d(visDescr,
- new ReadOnlyDictionary(vis.VisGenParams));
- if (vis2d == null) {
- Debug.WriteLine("Vis generator returned null");
+ if (visDescr.VisualizationType == VisDescr.VisType.Bitmap) {
+ vis2d = vplug.Generate2d(visDescr, parms);
+ if (vis2d == null) {
+ Debug.WriteLine("Vis2d generator returned null");
+ }
+ } else if (visDescr.VisualizationType == VisDescr.VisType.Wireframe) {
+ IPlugin_Visualizer_v2 plugin2 = (IPlugin_Visualizer_v2)vplug;
+ visWire = plugin2.GenerateWireframe(visDescr, parms);
+ if (visWire == null) {
+ Debug.WriteLine("VisWire generator returned null");
+ }
+ } else {
+ Debug.Assert(false);
}
} catch (Exception ex) {
Debug.WriteLine("Vis generation failed: " + ex);
- vis2d = null;
}
if (vis2d != null) {
//Debug.WriteLine(" Rendered thumbnail: " + vis.Tag);
vis.SetThumbnail(vis2d);
+ } else if (visWire != null) {
+ vis.SetThumbnail(visWire, parms);
}
}
}
diff --git a/SourceGen/WpfGui/EditVisualization.xaml b/SourceGen/WpfGui/EditVisualization.xaml
index 3de5ab2..808ffb6 100644
--- a/SourceGen/WpfGui/EditVisualization.xaml
+++ b/SourceGen/WpfGui/EditVisualization.xaml
@@ -134,9 +134,14 @@ limitations under the License.
+
+
+
+
diff --git a/SourceGen/WpfGui/EditVisualization.xaml.cs b/SourceGen/WpfGui/EditVisualization.xaml.cs
index 370ae27..c15f906 100644
--- a/SourceGen/WpfGui/EditVisualization.xaml.cs
+++ b/SourceGen/WpfGui/EditVisualization.xaml.cs
@@ -472,7 +472,6 @@ namespace SourceGen.WpfGui {
}
} catch (Exception ex) {
Debug.WriteLine("Vis generation failed: " + ex);
- vis2d = null;
if (string.IsNullOrEmpty(LastPluginMessage)) {
LastPluginMessage = ex.Message;
}
@@ -487,12 +486,14 @@ namespace SourceGen.WpfGui {
}
IsValid = false;
} else if (vis2d != null) {
+ previewGrid.Background = null;
previewImage.Source = Visualization.ConvertToBitmapSource(vis2d);
wireframePath.Data = new GeometryGroup();
BitmapDimensions = string.Format("{0}x{1}",
previewImage.Source.Width, previewImage.Source.Height);
} else {
- previewImage.Source = Visualization.BLACK_IMAGE;
+ previewGrid.Background = Brushes.Black;
+ previewImage.Source = Visualization.BLANK_IMAGE;
wireframePath.Data = Visualization.GenerateWireframePath(visWire, parms,
previewImage.ActualWidth / 2);
BitmapDimensions = "n/a";