diff --git a/PluginCommon/VisWireframe.cs b/PluginCommon/VisWireframe.cs
index cebc7b9..d0fde4c 100644
--- a/PluginCommon/VisWireframe.cs
+++ b/PluginCommon/VisWireframe.cs
@@ -20,9 +20,27 @@ using System.Diagnostics;
namespace PluginCommon {
///
/// Wireframe mesh with optional backface normals, for use with visualization generators.
+ /// Call the various functions to add data, then call Validate() to check for broken
+ /// references.
///
[Serializable]
public class VisWireframe : IVisualizationWireframe {
+ public static VisParamDescr Param_IsPerspective(string uiLabel, bool defaultVal) {
+ return new VisParamDescr(uiLabel, "_isPerspective", typeof(bool), 0, 0, 0, defaultVal);
+ }
+ public static VisParamDescr Param_IsBackfaceRemoved(string uiLabel, bool defaultVal) {
+ return new VisParamDescr(uiLabel, "_isBackfaceRemoved", typeof(bool), 0, 0, 0, defaultVal);
+ }
+ public static VisParamDescr Param_EulerX(string uiLabel, int defaultVal) {
+ return new VisParamDescr(uiLabel, "_eulerRotX", typeof(int), 0, 359, 0, defaultVal);
+ }
+ public static VisParamDescr Param_EulerY(string uiLabel, int defaultVal) {
+ return new VisParamDescr(uiLabel, "_eulerRotY", typeof(int), 0, 359, 0, defaultVal);
+ }
+ public static VisParamDescr Param_EulerZ(string uiLabel, int defaultVal) {
+ return new VisParamDescr(uiLabel, "_eulerRotZ", typeof(int), 0, 359, 0, defaultVal);
+ }
+
private List mVerticesX = new List();
private List mVerticesY = new List();
private List mVerticesZ = new List();
@@ -56,14 +74,15 @@ namespace PluginCommon {
}
///
- /// Adds the edge to the list.
+ /// Adds an edge to the list. The referenced vertices do not need to be defined
+ /// before calling.
///
/// Index of first vertex.
/// Index of second vertex.
/// Edge index. Indices start at zero and count up.
public int AddEdge(int index0, int index1) {
- Debug.Assert(index0 >= 0 && index0 < mVerticesX.Count);
- Debug.Assert(index1 >= 0 && index1 < mVerticesX.Count);
+ Debug.Assert(index0 >= 0);
+ Debug.Assert(index1 >= 0);
mEdges.Add(new IntPair(index0, index1));
return mEdges.Count - 1;
}
@@ -84,24 +103,26 @@ namespace PluginCommon {
}
///
- /// Marks a vertex's visibility as being tied to the specified face. The face does
- /// not need to be in the list yet.
+ /// Marks a vertex's visibility as being tied to the specified face. The vertices and
+ /// faces being referenced do not need to exist yet.
///
/// Index of vertex.
/// Index of face.
public void AddVertexFace(int vertexIndex, int faceIndex) {
- Debug.Assert(vertexIndex >= 0 && vertexIndex < mVerticesX.Count);
+ Debug.Assert(vertexIndex >= 0);
+ Debug.Assert(faceIndex >= 0);
mVertexFaces.Add(new IntPair(vertexIndex, faceIndex));
}
///
- /// Marks an edge's visibility as being tied to the specified face. The face does
- /// not need to be in the list yet.
+ /// Marks an edge's visibility as being tied to the specified face. The edges and
+ /// faces being referenced do not need to exist yet.
///
/// Index of edge.
/// Index of face.
public void AddEdgeFace(int edgeIndex, int faceIndex) {
- Debug.Assert(edgeIndex >= 0 && edgeIndex < mEdges.Count);
+ Debug.Assert(edgeIndex >= 0);
+ Debug.Assert(faceIndex >= 0);
mEdgeFaces.Add(new IntPair(edgeIndex, faceIndex));
}
diff --git a/SourceGen/MainController.cs b/SourceGen/MainController.cs
index 04c853a..3897a76 100644
--- a/SourceGen/MainController.cs
+++ b/SourceGen/MainController.cs
@@ -697,7 +697,7 @@ namespace SourceGen {
float dataPerc = (mProject.ByteCounts.DataByteCount * 100.0f) / total;
float junkPerc = (mProject.ByteCounts.JunkByteCount * 100.0f) / total;
mMainWin.ByteCountText = string.Format(Res.Strings.STATUS_BYTE_COUNT_FMT,
- codePerc, dataPerc, junkPerc);
+ total / 1024.0f, codePerc, dataPerc, junkPerc);
}
#endregion Init and settings
diff --git a/SourceGen/Res/Strings.xaml b/SourceGen/Res/Strings.xaml
index a4c2d5d..c0d3718 100644
--- a/SourceGen/Res/Strings.xaml
+++ b/SourceGen/Res/Strings.xaml
@@ -161,7 +161,7 @@ limitations under the License.
C64 Screen Code
{1} CPU @ {2} MHz
Show
- {0:F1}% code, {1:F1}% data, {2:F1}% junk
+ {0:F1}KB: {1:F1}% code, {2:F1}% data, {3:F1}% junk
Ready
DCI string has mixed data
DCI string not terminated
diff --git a/SourceGen/SGTestData/Visualization/VisWireframeTest.cs b/SourceGen/SGTestData/Visualization/VisWireframeTest.cs
index 12cb916..6baba6d 100644
--- a/SourceGen/SGTestData/Visualization/VisWireframeTest.cs
+++ b/SourceGen/SGTestData/Visualization/VisWireframeTest.cs
@@ -41,6 +41,12 @@ namespace WireframeTest {
new VisParamDescr[] {
new VisParamDescr("File offset (hex)",
P_OFFSET, typeof(int), 0, 0x00ffffff, VisParamDescr.SpecialMode.Offset, 0),
+
+ // These are interpreted by the main app.
+ VisWireframe.Param_EulerX("Euler rotation X", 0),
+ VisWireframe.Param_EulerY("Euler rotation Y", 0),
+ VisWireframe.Param_EulerZ("Euler rotation Z", 0),
+ VisWireframe.Param_IsPerspective("Perspective projection", true),
}),
};
diff --git a/SourceGen/SGTestData/Visualization/wireframe-test.dis65 b/SourceGen/SGTestData/Visualization/wireframe-test.dis65
index 56c868a..bf0eebf 100644
--- a/SourceGen/SGTestData/Visualization/wireframe-test.dis65
+++ b/SourceGen/SGTestData/Visualization/wireframe-test.dis65
@@ -17,7 +17,8 @@
"SmartPlpHandling":true},
"PlatformSymbolFileIdentifiers":[],
-"ExtensionScriptFileIdentifiers":["PROJ:VisWireframeTest.cs"],
+"ExtensionScriptFileIdentifiers":["PROJ:VisWireframeTest.cs",
+"RT:Apple/VisHiRes.cs"],
"ProjectSyms":{
}},
@@ -239,7 +240,30 @@
"LvTables":{
},
-"Visualizations":[],
+"Visualizations":[{
+"Tag":"wf_data",
+"VisGenIdent":"wireframe-test",
+"VisGenParams":{
+"offset":10,
+"_eulerRotX":0,
+"_eulerRotY":0,
+"_eulerRotZ":0,
+"_isPerspective":true}},
+
+{
+"Tag":"bmp_data",
+"VisGenIdent":"apple2-hi-res-bitmap",
+"VisGenParams":{
+"offset":10,
+"byteWidth":3,
+"height":11,
+"colStride":0,
+"rowStride":0,
+"isColor":true,
+"isFirstOdd":false,
+"isHighBitFlipped":false}}],
"VisualizationAnimations":[],
"VisualizationSets":{
-}}
+"10":{
+"Tags":["wf_data",
+"bmp_data"]}}}
diff --git a/SourceGen/Visualization.cs b/SourceGen/Visualization.cs
index c9515d9..32e76be 100644
--- a/SourceGen/Visualization.cs
+++ b/SourceGen/Visualization.cs
@@ -18,6 +18,7 @@ using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Text;
+using System.Windows;
using System.Windows.Media;
using System.Windows.Media.Imaging;
@@ -99,6 +100,7 @@ namespace SourceGen {
VisualizationAnimation.GenerateAnimOverlayImage();
internal static readonly BitmapSource BLANK_IMAGE = GenerateBlankImage();
+ internal static readonly BitmapSource BLACK_IMAGE = GenerateBlackImage();
///
/// Serial number, for reference from other Visualization objects. Not serialized.
@@ -106,9 +108,10 @@ namespace SourceGen {
///
/// This value is only valid in the current session. It exists because animations
/// need to refer to other Visualization objects, and doing so by Tag gets sticky
- /// if a tag gets renamed. We need a way to uniquely identify a reference to a
+ /// if a Tag gets renamed. We need a way to uniquely identify a reference to a
/// Visualization that persists across Tag renames and other edits. When the objects
- /// are serialized to the project file we just output the tags.
+ /// are serialized to the project file we don't include the serial, and just reference
+ /// by Tag.
///
public int SerialNumber { get; private set; }
@@ -191,7 +194,8 @@ namespace SourceGen {
}
///
- /// Converts an IVisualization2d to a BitmapSource for display.
+ /// Converts an IVisualization2d to a BitmapSource for display. The bitmap will be
+ /// the same size as the original content.
///
public static BitmapSource ConvertToBitmapSource(IVisualization2d vis2d) {
// Create indexed color palette.
@@ -218,12 +222,69 @@ namespace SourceGen {
return image;
}
+ ///
+ /// Generates a BitmapSource from IVisualizationWireframe data. Useful for thumbnails
+ /// and GIF exports.
+ ///
+ /// Visualization data.
+ /// Parameter set, for rotations and render options.
+ /// Output bitmap width.
+ /// Output bitmap height.
+ ///
+ 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;
+ }
+
+ ///
+ /// Generates a WPF path from IVisualizationWireframe data.
+ ///
+ public static GeometryGroup GenerateWireframePath(IVisualizationWireframe visWire,
+ ReadOnlyDictionary parms, double scale) {
+ 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);
+ 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)));
+ return geo;
+ }
+
+ ///
+ /// Returns a bitmap with a single transparent pixel.
+ ///
private static BitmapSource GenerateBlankImage() {
RenderTargetBitmap bmp = new RenderTargetBitmap(1, 1, 96.0, 96.0,
PixelFormats.Pbgra32);
return bmp;
}
+ ///
+ /// 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);
+
+ return image;
+ }
+
public override string ToString() {
return "[Vis: " + Tag + " (" + VisGenIdent + ") count=" + VisGenParams.Count + "]";
diff --git a/SourceGen/WpfGui/EditVisualization.xaml b/SourceGen/WpfGui/EditVisualization.xaml
index d7ecef6..3de5ab2 100644
--- a/SourceGen/WpfGui/EditVisualization.xaml
+++ b/SourceGen/WpfGui/EditVisualization.xaml
@@ -134,8 +134,13 @@ limitations under the License.
-
+
+
+
+
+
+
diff --git a/SourceGen/WpfGui/EditVisualization.xaml.cs b/SourceGen/WpfGui/EditVisualization.xaml.cs
index 4b4ee60..370ae27 100644
--- a/SourceGen/WpfGui/EditVisualization.xaml.cs
+++ b/SourceGen/WpfGui/EditVisualization.xaml.cs
@@ -302,8 +302,8 @@ namespace SourceGen.WpfGui {
ClearValue(SizeToContentProperty);
SetValue(MinWidthProperty, this.Width);
SetValue(MinHeightProperty, this.Height);
- previewImage.ClearValue(WidthProperty);
- previewImage.ClearValue(HeightProperty);
+ previewGrid.ClearValue(WidthProperty);
+ previewGrid.ClearValue(HeightProperty);
tagTextBox.SelectAll();
tagTextBox.Focus();
@@ -450,13 +450,25 @@ namespace SourceGen.WpfGui {
// Invoke the plugin.
PluginErrMessage = string.Empty;
- IVisualization2d vis2d;
+ IVisualization2d vis2d = null;
+ IVisualizationWireframe visWire = null;
+ ReadOnlyDictionary parms = CreateVisGenParams();
try {
IPlugin_Visualizer plugin =
(IPlugin_Visualizer)mProject.GetPlugin(item.ScriptIdent);
- vis2d = plugin.Generate2d(item.VisDescriptor, CreateVisGenParams());
- if (vis2d == null) {
- Debug.WriteLine("Vis generator returned null");
+ if (item.VisDescriptor.VisualizationType == VisDescr.VisType.Bitmap) {
+ vis2d = plugin.Generate2d(item.VisDescriptor, parms);
+ if (vis2d == null) {
+ Debug.WriteLine("Vis2d generator returned null");
+ }
+ } else if (item.VisDescriptor.VisualizationType == VisDescr.VisType.Wireframe) {
+ IPlugin_Visualizer_v2 plugin2 = (IPlugin_Visualizer_v2)plugin;
+ visWire = plugin2.GenerateWireframe(item.VisDescriptor, parms);
+ if (visWire == null) {
+ Debug.WriteLine("VisWire generator returned null");
+ }
+ } else {
+ Debug.Assert(false);
}
} catch (Exception ex) {
Debug.WriteLine("Vis generation failed: " + ex);
@@ -465,7 +477,7 @@ namespace SourceGen.WpfGui {
LastPluginMessage = ex.Message;
}
}
- if (vis2d == null) {
+ if (vis2d == null && visWire == null) {
previewImage.Source = sBadParamsImage;
if (!string.IsNullOrEmpty(LastPluginMessage)) {
// Report the last message we got as an error.
@@ -474,10 +486,16 @@ namespace SourceGen.WpfGui {
PluginErrMessage = (string)FindResource("str_VisGenFailed");
}
IsValid = false;
- } else {
+ } else if (vis2d != 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;
+ wireframePath.Data = Visualization.GenerateWireframePath(visWire, parms,
+ previewImage.ActualWidth / 2);
+ BitmapDimensions = "n/a";
}
}
diff --git a/SourceGen/WpfGui/EditVisualizationSet.xaml b/SourceGen/WpfGui/EditVisualizationSet.xaml
index 64f1bc8..bc2322e 100644
--- a/SourceGen/WpfGui/EditVisualizationSet.xaml
+++ b/SourceGen/WpfGui/EditVisualizationSet.xaml
@@ -85,15 +85,22 @@ limitations under the License.
-
+
-
-
+
+
+
diff --git a/SourceGen/WpfGui/EditVisualizationSet.xaml.cs b/SourceGen/WpfGui/EditVisualizationSet.xaml.cs
index 8a2340b..d954443 100644
--- a/SourceGen/WpfGui/EditVisualizationSet.xaml.cs
+++ b/SourceGen/WpfGui/EditVisualizationSet.xaml.cs
@@ -181,7 +181,7 @@ namespace SourceGen.WpfGui {
EditSelectedItem();
}
- private void NewBitmapButton_Click(object sender, RoutedEventArgs e) {
+ private void NewVisualizationButton_Click(object sender, RoutedEventArgs e) {
EditVisualization dlg = new EditVisualization(this, mProject, mFormatter, mOffset,
CreateEditedSetList(), null);
if (dlg.ShowDialog() != true) {
@@ -193,6 +193,10 @@ namespace SourceGen.WpfGui {
okButton.Focus();
}
+ private void NewWireframeAnimationButton_Click(object sender, RoutedEventArgs e) {
+ // TODO(xyzzy)
+ }
+
private void NewBitmapAnimationButton_Click(object sender, RoutedEventArgs e) {
EditBitmapAnimation dlg = new EditBitmapAnimation(this, mOffset,
CreateEditedSetList(), null);
diff --git a/SourceGen/WpfGui/MainWindow.xaml b/SourceGen/WpfGui/MainWindow.xaml
index 4e2d442..c7e32ef 100644
--- a/SourceGen/WpfGui/MainWindow.xaml
+++ b/SourceGen/WpfGui/MainWindow.xaml
@@ -107,7 +107,11 @@ limitations under the License.
-
+
+
+ Alt+V
+
+
@@ -480,7 +484,7 @@ limitations under the License.
+ Text="{Binding ByteCountText, FallbackValue=100KB: 30.0% code; 60.0% data; 10.0% junk}"/>