mirror of
https://github.com/fadden/6502bench.git
synced 2024-11-29 10:50:28 +00:00
Progress toward wireframe animations
Moved X/Y/Z rotation out of the plugin, since it has nothing to do with the plugin at all. (Backface removal and perspective projection are somewhat based on the data contents, as is the choice for whether or not they should be options.) Added sliders for X/Y/Z rotation. Much more fun that way. Renamed VisualizationAnimation to VisBitmapAnimation, as we're not going to use it for wireframe animation. Created a new class to hold wireframe animation data, which is really just a reference to the IVisualizationWireframe so we can generate an animated GIF without having to pry open the plugin again. Renamed the "frame-delay-msec" parameter, which should start with an underscore to ensure it doesn't clash with plugin parameters. If we don't find it with an underscore we check again without for backward compatibility.
This commit is contained in:
parent
b686d2d208
commit
7e92a86ffa
@ -181,7 +181,7 @@ namespace PluginCommon {
|
|||||||
public class VisDescr {
|
public class VisDescr {
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Unique identifier. This is stored in the project file. Names beginning with
|
/// Unique identifier. This is stored in the project file. Names beginning with
|
||||||
/// underscores ('_') are reserved.
|
/// underscores ('_') are reserved and must not be defined by plugins.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string Ident { get; private set; }
|
public string Ident { get; private set; }
|
||||||
|
|
||||||
|
@ -27,9 +27,6 @@ namespace PluginCommon {
|
|||||||
public class VisWireframe : IVisualizationWireframe {
|
public class VisWireframe : IVisualizationWireframe {
|
||||||
public const string P_IS_PERSPECTIVE = "_isPerspective";
|
public const string P_IS_PERSPECTIVE = "_isPerspective";
|
||||||
public const string P_IS_BFC_ENABLED = "_isBfcEnabled";
|
public const string P_IS_BFC_ENABLED = "_isBfcEnabled";
|
||||||
public const string P_EULER_ROT_X = "_eulerRotX";
|
|
||||||
public const string P_EULER_ROT_Y = "_eulerRotY";
|
|
||||||
public const string P_EULER_ROT_Z = "_eulerRotZ";
|
|
||||||
|
|
||||||
public static VisParamDescr Param_IsPerspective(string uiLabel, bool defaultVal) {
|
public static VisParamDescr Param_IsPerspective(string uiLabel, bool defaultVal) {
|
||||||
return new VisParamDescr(uiLabel, P_IS_PERSPECTIVE, typeof(bool), 0, 0, 0, defaultVal);
|
return new VisParamDescr(uiLabel, P_IS_PERSPECTIVE, typeof(bool), 0, 0, 0, defaultVal);
|
||||||
@ -37,15 +34,6 @@ namespace PluginCommon {
|
|||||||
public static VisParamDescr Param_IsBfcEnabled(string uiLabel, bool defaultVal) {
|
public static VisParamDescr Param_IsBfcEnabled(string uiLabel, bool defaultVal) {
|
||||||
return new VisParamDescr(uiLabel, P_IS_BFC_ENABLED, typeof(bool), 0, 0, 0, defaultVal);
|
return new VisParamDescr(uiLabel, P_IS_BFC_ENABLED, typeof(bool), 0, 0, 0, defaultVal);
|
||||||
}
|
}
|
||||||
public static VisParamDescr Param_EulerX(string uiLabel, int defaultVal) {
|
|
||||||
return new VisParamDescr(uiLabel, P_EULER_ROT_X, typeof(int), 0, 359, 0, defaultVal);
|
|
||||||
}
|
|
||||||
public static VisParamDescr Param_EulerY(string uiLabel, int defaultVal) {
|
|
||||||
return new VisParamDescr(uiLabel, P_EULER_ROT_Y, typeof(int), 0, 359, 0, defaultVal);
|
|
||||||
}
|
|
||||||
public static VisParamDescr Param_EulerZ(string uiLabel, int defaultVal) {
|
|
||||||
return new VisParamDescr(uiLabel, P_EULER_ROT_Z, typeof(int), 0, 359, 0, defaultVal);
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<float> mVerticesX = new List<float>();
|
private List<float> mVerticesX = new List<float>();
|
||||||
private List<float> mVerticesY = new List<float>();
|
private List<float> mVerticesY = new List<float>();
|
||||||
|
@ -791,11 +791,11 @@ namespace SourceGen {
|
|||||||
int dispWidth, dispHeight;
|
int dispWidth, dispHeight;
|
||||||
|
|
||||||
Visualization vis = visSet[index];
|
Visualization vis = visSet[index];
|
||||||
if (vis is VisualizationAnimation) {
|
if (vis is VisBitmapAnimation) {
|
||||||
// Animated visualization.
|
// Animated visualization.
|
||||||
VisualizationAnimation visAnim = (VisualizationAnimation)vis;
|
VisBitmapAnimation visAnim = (VisBitmapAnimation)vis;
|
||||||
int frameDelay = PluginCommon.Util.GetFromObjDict(visAnim.VisGenParams,
|
int frameDelay = PluginCommon.Util.GetFromObjDict(visAnim.VisGenParams,
|
||||||
VisualizationAnimation.FRAME_DELAY_MSEC_PARAM, 330);
|
VisBitmapAnimation.P_FRAME_DELAY_MSEC_PARAM, 330);
|
||||||
AnimatedGifEncoder encoder = new AnimatedGifEncoder();
|
AnimatedGifEncoder encoder = new AnimatedGifEncoder();
|
||||||
|
|
||||||
// Gather list of frames.
|
// Gather list of frames.
|
||||||
|
@ -373,11 +373,11 @@ namespace SourceGen {
|
|||||||
VisGenParams = new Dictionary<string, object>(vis.VisGenParams);
|
VisGenParams = new Dictionary<string, object>(vis.VisGenParams);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public class SerVisualizationAnimation : SerVisualization {
|
public class SerVisBitmapAnimation : SerVisualization {
|
||||||
public List<string> Tags { get; set; }
|
public List<string> Tags { get; set; }
|
||||||
|
|
||||||
public SerVisualizationAnimation() { }
|
public SerVisBitmapAnimation() { }
|
||||||
public SerVisualizationAnimation(VisualizationAnimation visAnim,
|
public SerVisBitmapAnimation(VisBitmapAnimation visAnim,
|
||||||
SortedList<int, VisualizationSet> visSets)
|
SortedList<int, VisualizationSet> visSets)
|
||||||
: base(visAnim) {
|
: base(visAnim) {
|
||||||
Tags = new List<string>(visAnim.Count);
|
Tags = new List<string>(visAnim.Count);
|
||||||
@ -400,7 +400,7 @@ namespace SourceGen {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fields are serialized to/from JSON. Do not change the field names.
|
// Fields are serialized to/from JSON. DO NOT change the field names.
|
||||||
public int _ContentVersion { get; set; }
|
public int _ContentVersion { get; set; }
|
||||||
public int FileDataLength { get; set; }
|
public int FileDataLength { get; set; }
|
||||||
public int FileDataCrc32 { get; set; }
|
public int FileDataCrc32 { get; set; }
|
||||||
@ -415,7 +415,7 @@ namespace SourceGen {
|
|||||||
public Dictionary<string, SerFormatDescriptor> OperandFormats { get; set; }
|
public Dictionary<string, SerFormatDescriptor> OperandFormats { get; set; }
|
||||||
public Dictionary<string, SerLocalVariableTable> LvTables { get; set; }
|
public Dictionary<string, SerLocalVariableTable> LvTables { get; set; }
|
||||||
public List<SerVisualization> Visualizations { get; set; }
|
public List<SerVisualization> Visualizations { get; set; }
|
||||||
public List<SerVisualizationAnimation> VisualizationAnimations { get; set; }
|
public List<SerVisBitmapAnimation> VisualizationAnimations { get; set; }
|
||||||
public Dictionary<string, SerVisualizationSet> VisualizationSets { get; set; }
|
public Dictionary<string, SerVisualizationSet> VisualizationSets { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -506,15 +506,15 @@ namespace SourceGen {
|
|||||||
spf.LvTables.Add(kvp.Key.ToString(), new SerLocalVariableTable(kvp.Value));
|
spf.LvTables.Add(kvp.Key.ToString(), new SerLocalVariableTable(kvp.Value));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Output Visualizations, VisualizationAnimations, and VisualizationSets
|
// Output Visualizations, VisBitmapAnimations, and VisualizationSets
|
||||||
spf.Visualizations = new List<SerVisualization>();
|
spf.Visualizations = new List<SerVisualization>();
|
||||||
spf.VisualizationAnimations = new List<SerVisualizationAnimation>();
|
spf.VisualizationAnimations = new List<SerVisBitmapAnimation>();
|
||||||
spf.VisualizationSets = new Dictionary<string, SerVisualizationSet>();
|
spf.VisualizationSets = new Dictionary<string, SerVisualizationSet>();
|
||||||
foreach (KeyValuePair<int, VisualizationSet> kvp in proj.VisualizationSets) {
|
foreach (KeyValuePair<int, VisualizationSet> kvp in proj.VisualizationSets) {
|
||||||
foreach (Visualization vis in kvp.Value) {
|
foreach (Visualization vis in kvp.Value) {
|
||||||
if (vis is VisualizationAnimation) {
|
if (vis is VisBitmapAnimation) {
|
||||||
VisualizationAnimation visAnim = (VisualizationAnimation)vis;
|
VisBitmapAnimation visAnim = (VisBitmapAnimation)vis;
|
||||||
spf.VisualizationAnimations.Add(new SerVisualizationAnimation(visAnim,
|
spf.VisualizationAnimations.Add(new SerVisBitmapAnimation(visAnim,
|
||||||
proj.VisualizationSets));
|
proj.VisualizationSets));
|
||||||
} else {
|
} else {
|
||||||
spf.Visualizations.Add(new SerVisualization(vis));
|
spf.Visualizations.Add(new SerVisualization(vis));
|
||||||
@ -793,10 +793,10 @@ namespace SourceGen {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Extract the VisualizationAnimations, which link to Visualizations by tag.
|
// Extract the VisBitmapAnimations, which link to Visualizations by tag.
|
||||||
foreach (SerVisualizationAnimation serVisAnim in spf.VisualizationAnimations) {
|
foreach (SerVisBitmapAnimation serVisAnim in spf.VisualizationAnimations) {
|
||||||
if (CreateVisualizationAnimation(serVisAnim, visDict, report,
|
if (CreateVisBitmapAnimation(serVisAnim, visDict, report,
|
||||||
out VisualizationAnimation visAnim)) {
|
out VisBitmapAnimation visAnim)) {
|
||||||
try {
|
try {
|
||||||
visDict.Add(visAnim.Tag, visAnim);
|
visDict.Add(visAnim.Tag, visAnim);
|
||||||
} catch (ArgumentException) {
|
} catch (ArgumentException) {
|
||||||
@ -1057,11 +1057,11 @@ namespace SourceGen {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates a VisualizationAnimation from its serialized form.
|
/// Creates a VisBitmapAnimation from its serialized form.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private static bool CreateVisualizationAnimation(SerVisualizationAnimation serVisAnim,
|
private static bool CreateVisBitmapAnimation(SerVisBitmapAnimation serVisAnim,
|
||||||
Dictionary<string, Visualization> visList, FileLoadReport report,
|
Dictionary<string, Visualization> visList, FileLoadReport report,
|
||||||
out VisualizationAnimation visAnim) {
|
out VisBitmapAnimation visAnim) {
|
||||||
if (!CheckVis(serVisAnim, report, out Dictionary<string, object> parms)) {
|
if (!CheckVis(serVisAnim, report, out Dictionary<string, object> parms)) {
|
||||||
visAnim = null;
|
visAnim = null;
|
||||||
return false;
|
return false;
|
||||||
@ -1074,7 +1074,7 @@ namespace SourceGen {
|
|||||||
report.Add(FileLoadItem.Type.Warning, str);
|
report.Add(FileLoadItem.Type.Warning, str);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (vis is VisualizationAnimation) {
|
if (vis is VisBitmapAnimation) {
|
||||||
string str = string.Format(Res.Strings.ERR_BAD_VISUALIZATION_FMT,
|
string str = string.Format(Res.Strings.ERR_BAD_VISUALIZATION_FMT,
|
||||||
"animation in animation: " + tag);
|
"animation in animation: " + tag);
|
||||||
report.Add(FileLoadItem.Type.Warning, str);
|
report.Add(FileLoadItem.Type.Warning, str);
|
||||||
@ -1082,8 +1082,8 @@ namespace SourceGen {
|
|||||||
}
|
}
|
||||||
serialNumbers.Add(vis.SerialNumber);
|
serialNumbers.Add(vis.SerialNumber);
|
||||||
}
|
}
|
||||||
visAnim = new VisualizationAnimation(serVisAnim.Tag, serVisAnim.VisGenIdent,
|
visAnim = new VisBitmapAnimation(serVisAnim.Tag, serVisAnim.VisGenIdent,
|
||||||
new ReadOnlyDictionary<string, object>(parms), serialNumbers, null);
|
new ReadOnlyDictionary<string, object>(parms), null, serialNumbers);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -43,9 +43,6 @@ namespace WireframeTest {
|
|||||||
P_OFFSET, typeof(int), 0, 0x00ffffff, VisParamDescr.SpecialMode.Offset, 0),
|
P_OFFSET, typeof(int), 0, 0x00ffffff, VisParamDescr.SpecialMode.Offset, 0),
|
||||||
|
|
||||||
// These are interpreted by the main app.
|
// These are interpreted by the main app.
|
||||||
VisWireframe.Param_EulerX("Rotation about X", 0),
|
|
||||||
VisWireframe.Param_EulerY("Rotation about Y", 0),
|
|
||||||
VisWireframe.Param_EulerZ("Rotation about Z", 0),
|
|
||||||
VisWireframe.Param_IsPerspective("Perspective projection", true),
|
VisWireframe.Param_IsPerspective("Perspective projection", true),
|
||||||
VisWireframe.Param_IsBfcEnabled("Backface culling", true),
|
VisWireframe.Param_IsBfcEnabled("Backface culling", true),
|
||||||
}),
|
}),
|
||||||
|
@ -245,11 +245,11 @@
|
|||||||
"VisGenIdent":"wireframe-test",
|
"VisGenIdent":"wireframe-test",
|
||||||
"VisGenParams":{
|
"VisGenParams":{
|
||||||
"offset":10,
|
"offset":10,
|
||||||
"_eulerRotX":15,
|
|
||||||
"_eulerRotY":30,
|
|
||||||
"_eulerRotZ":0,
|
|
||||||
"_isPerspective":true,
|
"_isPerspective":true,
|
||||||
"_isBfcEnabled":true}},
|
"_isBfcEnabled":true,
|
||||||
|
"_eulerRotX":0,
|
||||||
|
"_eulerRotY":34,
|
||||||
|
"_eulerRotZ":65}},
|
||||||
|
|
||||||
{
|
{
|
||||||
"Tag":"bmp_data",
|
"Tag":"bmp_data",
|
||||||
@ -263,8 +263,17 @@
|
|||||||
"isColor":true,
|
"isColor":true,
|
||||||
"isFirstOdd":false,
|
"isFirstOdd":false,
|
||||||
"isHighBitFlipped":false}}],
|
"isHighBitFlipped":false}}],
|
||||||
"VisualizationAnimations":[],
|
"VisualizationAnimations":[{
|
||||||
|
"Tags":["wf_data",
|
||||||
|
"bmp_data"],
|
||||||
|
"Tag":"anim00002c",
|
||||||
|
"VisGenIdent":"(animation)",
|
||||||
|
"VisGenParams":{
|
||||||
|
"_frame-delay-msec":500}}],
|
||||||
"VisualizationSets":{
|
"VisualizationSets":{
|
||||||
"10":{
|
"10":{
|
||||||
"Tags":["wf_data",
|
"Tags":["wf_data",
|
||||||
"bmp_data"]}}}
|
"bmp_data"]},
|
||||||
|
|
||||||
|
"44":{
|
||||||
|
"Tags":["anim00002c"]}}}
|
||||||
|
@ -103,8 +103,9 @@
|
|||||||
</Compile>
|
</Compile>
|
||||||
<Compile Include="LocalVariableTable.cs" />
|
<Compile Include="LocalVariableTable.cs" />
|
||||||
<Compile Include="Visualization.cs" />
|
<Compile Include="Visualization.cs" />
|
||||||
<Compile Include="VisualizationAnimation.cs" />
|
<Compile Include="VisBitmapAnimation.cs" />
|
||||||
<Compile Include="VisualizationSet.cs" />
|
<Compile Include="VisualizationSet.cs" />
|
||||||
|
<Compile Include="VisWireframeAnimation.cs" />
|
||||||
<Compile Include="WireframeObject.cs" />
|
<Compile Include="WireframeObject.cs" />
|
||||||
<Compile Include="WpfGui\AboutBox.xaml.cs">
|
<Compile Include="WpfGui\AboutBox.xaml.cs">
|
||||||
<DependentUpon>AboutBox.xaml</DependentUpon>
|
<DependentUpon>AboutBox.xaml</DependentUpon>
|
||||||
|
@ -27,17 +27,17 @@ namespace SourceGen {
|
|||||||
/// A visualization with animated contents.
|
/// A visualization with animated contents.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <remarks>
|
/// <remarks>
|
||||||
/// References to Visualization objects (such as a 3D mesh or list of bitmaps) are held
|
/// This has a list of references to Visualization objects. The cached images are
|
||||||
/// here. The VisGenParams property holds animation properties, such as frame rate and
|
/// displayed in sequence, at a rate determined by animation parameters also held here.
|
||||||
/// view angles.
|
|
||||||
///
|
///
|
||||||
/// As with the base class, instances are generally immutable for the benefit of undo/redo.
|
/// As with the base class, instances are generally immutable for the benefit of undo/redo.
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
public class VisualizationAnimation : Visualization {
|
public class VisBitmapAnimation : Visualization {
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Frame delay parameter.
|
/// Frame delay parameter.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public const string FRAME_DELAY_MSEC_PARAM = "frame-delay-msec";
|
public const string P_FRAME_DELAY_MSEC_PARAM = "_frame-delay-msec";
|
||||||
|
public const string P_FRAME_DELAY_MSEC_PARAM_OLD = "frame-delay-msec";
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Fake visualization generation identifier.
|
/// Fake visualization generation identifier.
|
||||||
@ -68,9 +68,9 @@ namespace SourceGen {
|
|||||||
/// <param name="visGenIdent">Visualization generator identifier.</param>
|
/// <param name="visGenIdent">Visualization generator identifier.</param>
|
||||||
/// <param name="visGenParams">Parameters for visualization generator.</param>
|
/// <param name="visGenParams">Parameters for visualization generator.</param>
|
||||||
/// <param name="visSerialNumbers">Serial numbers of referenced Visualizations.</param>
|
/// <param name="visSerialNumbers">Serial numbers of referenced Visualizations.</param>
|
||||||
public VisualizationAnimation(string tag, string visGenIdent,
|
public VisBitmapAnimation(string tag, string visGenIdent,
|
||||||
ReadOnlyDictionary<string, object> visGenParams, List<int> visSerialNumbers,
|
ReadOnlyDictionary<string, object> visGenParams, VisBitmapAnimation oldObj,
|
||||||
VisualizationAnimation oldObj)
|
List<int> visSerialNumbers)
|
||||||
: base(tag, visGenIdent, visGenParams, oldObj) {
|
: base(tag, visGenIdent, visGenParams, oldObj) {
|
||||||
Debug.Assert(visSerialNumbers != null);
|
Debug.Assert(visSerialNumbers != null);
|
||||||
|
|
||||||
@ -143,8 +143,8 @@ namespace SourceGen {
|
|||||||
/// <param name="removedSerials">List of serial numbers to remove.</param>
|
/// <param name="removedSerials">List of serial numbers to remove.</param>
|
||||||
/// <param name="newAnim">Object with changes, or null if nothing changed.</param>
|
/// <param name="newAnim">Object with changes, or null if nothing changed.</param>
|
||||||
/// <returns>True if something was actually removed.</returns>
|
/// <returns>True if something was actually removed.</returns>
|
||||||
public static bool StripEntries(VisualizationAnimation visAnim, List<int> removedSerials,
|
public static bool StripEntries(VisBitmapAnimation visAnim, List<int> removedSerials,
|
||||||
out VisualizationAnimation newAnim) {
|
out VisBitmapAnimation newAnim) {
|
||||||
bool somethingRemoved = false;
|
bool somethingRemoved = false;
|
||||||
|
|
||||||
// Both sets should be small, so not worried about O(m*n).
|
// Both sets should be small, so not worried about O(m*n).
|
||||||
@ -159,45 +159,16 @@ namespace SourceGen {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (somethingRemoved) {
|
if (somethingRemoved) {
|
||||||
newAnim = new VisualizationAnimation(visAnim.Tag, visAnim.VisGenIdent,
|
newAnim = new VisBitmapAnimation(visAnim.Tag, visAnim.VisGenIdent,
|
||||||
visAnim.VisGenParams, newSerials, visAnim);
|
visAnim.VisGenParams, visAnim, newSerials);
|
||||||
} else {
|
} else {
|
||||||
newAnim = null;
|
newAnim = null;
|
||||||
}
|
}
|
||||||
return somethingRemoved;
|
return somethingRemoved;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static BitmapSource GenerateAnimOverlayImage() {
|
|
||||||
const int IMAGE_SIZE = 128;
|
|
||||||
|
|
||||||
// Glowy "high tech" blue.
|
public static bool operator ==(VisBitmapAnimation a, VisBitmapAnimation b) {
|
||||||
SolidColorBrush outlineBrush = new SolidColorBrush(Color.FromArgb(255, 0, 216, 255));
|
|
||||||
SolidColorBrush fillBrush = new SolidColorBrush(Color.FromArgb(128, 0, 182, 215));
|
|
||||||
|
|
||||||
DrawingVisual visual = new DrawingVisual();
|
|
||||||
using (DrawingContext dc = visual.RenderOpen()) {
|
|
||||||
// Thanks: https://stackoverflow.com/a/29249100/294248
|
|
||||||
Point p1 = new Point(IMAGE_SIZE * 5 / 8, IMAGE_SIZE / 2);
|
|
||||||
Point p2 = new Point(IMAGE_SIZE * 3 / 8, IMAGE_SIZE / 4);
|
|
||||||
Point p3 = new Point(IMAGE_SIZE * 3 / 8, IMAGE_SIZE * 3 / 4);
|
|
||||||
StreamGeometry sg = new StreamGeometry();
|
|
||||||
using (StreamGeometryContext sgc = sg.Open()) {
|
|
||||||
sgc.BeginFigure(p1, true, true);
|
|
||||||
PointCollection points = new PointCollection() { p2, p3 };
|
|
||||||
sgc.PolyLineTo(points, true, true);
|
|
||||||
}
|
|
||||||
sg.Freeze();
|
|
||||||
dc.DrawGeometry(fillBrush, new Pen(outlineBrush, 3), sg);
|
|
||||||
}
|
|
||||||
|
|
||||||
RenderTargetBitmap bmp = new RenderTargetBitmap(IMAGE_SIZE, IMAGE_SIZE, 96.0, 96.0,
|
|
||||||
PixelFormats.Pbgra32);
|
|
||||||
bmp.Render(visual);
|
|
||||||
return bmp;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public static bool operator ==(VisualizationAnimation a, VisualizationAnimation b) {
|
|
||||||
if (ReferenceEquals(a, b)) {
|
if (ReferenceEquals(a, b)) {
|
||||||
return true; // same object, or both null
|
return true; // same object, or both null
|
||||||
}
|
}
|
||||||
@ -206,18 +177,18 @@ namespace SourceGen {
|
|||||||
}
|
}
|
||||||
return a.Equals(b);
|
return a.Equals(b);
|
||||||
}
|
}
|
||||||
public static bool operator !=(VisualizationAnimation a, VisualizationAnimation b) {
|
public static bool operator !=(VisBitmapAnimation a, VisBitmapAnimation b) {
|
||||||
return !(a == b);
|
return !(a == b);
|
||||||
}
|
}
|
||||||
public override bool Equals(object obj) {
|
public override bool Equals(object obj) {
|
||||||
if (!(obj is VisualizationAnimation)) {
|
if (!(obj is VisBitmapAnimation)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// Do base-class equality comparison and the ReferenceEquals check.
|
// Do base-class equality comparison and the ReferenceEquals check.
|
||||||
if (!base.Equals(obj)) {
|
if (!base.Equals(obj)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
VisualizationAnimation other = (VisualizationAnimation)obj;
|
VisBitmapAnimation other = (VisBitmapAnimation)obj;
|
||||||
if (other.mSerialNumbers.Count != mSerialNumbers.Count) {
|
if (other.mSerialNumbers.Count != mSerialNumbers.Count) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
57
SourceGen/VisWireframeAnimation.cs
Normal file
57
SourceGen/VisWireframeAnimation.cs
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2020 faddenSoft
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Collections.ObjectModel;
|
||||||
|
using System.Diagnostics;
|
||||||
|
|
||||||
|
using PluginCommon;
|
||||||
|
|
||||||
|
namespace SourceGen {
|
||||||
|
/// <summary>
|
||||||
|
/// A wireframe visualization with animation.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// All of the animation parameters get added to the Visualization parameter set, so this
|
||||||
|
/// is just a place to hold the IVisualizationWireframe reference and some constants.
|
||||||
|
/// </remarks>
|
||||||
|
public class VisWireframeAnimation : Visualization {
|
||||||
|
/// <summary>
|
||||||
|
/// Frame delay parameter.
|
||||||
|
/// </summary>
|
||||||
|
public const string P_FRAME_DELAY_MSEC = "_frame-delay-msec";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Frame count parameter.
|
||||||
|
/// </summary>
|
||||||
|
public const string P_FRAME_COUNT = "_frame-count";
|
||||||
|
|
||||||
|
public const string P_EULER_ROT_X = "_eulerRotX";
|
||||||
|
public const string P_EULER_ROT_Y = "_eulerRotY";
|
||||||
|
public const string P_EULER_ROT_Z = "_eulerRotZ";
|
||||||
|
|
||||||
|
private IVisualizationWireframe mVisWire;
|
||||||
|
|
||||||
|
public VisWireframeAnimation(string tag, string visGenIdent,
|
||||||
|
ReadOnlyDictionary<string, object> visGenParams, Visualization oldObj,
|
||||||
|
IVisualizationWireframe visWire)
|
||||||
|
: base(tag, visGenIdent, visGenParams, oldObj) {
|
||||||
|
Debug.Assert(visWire != null);
|
||||||
|
|
||||||
|
mVisWire = visWire;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -35,6 +35,20 @@ namespace SourceGen {
|
|||||||
/// Immutability is useful here because the undo/redo mechanism operates at VisualizationSet
|
/// Immutability is useful here because the undo/redo mechanism operates at VisualizationSet
|
||||||
/// granularity. We want to know that the undo/redo operations are operating on objects
|
/// granularity. We want to know that the undo/redo operations are operating on objects
|
||||||
/// that weren't changed while sitting in the undo buffer.
|
/// that weren't changed while sitting in the undo buffer.
|
||||||
|
///
|
||||||
|
/// At a basic level, bitmap and wireframe visualizations are the same: you take a
|
||||||
|
/// visualization generation identifier and a bunch of parameters, and generate Stuff.
|
||||||
|
/// The nature of the Stuff and what you do with it after are very different, however.
|
||||||
|
///
|
||||||
|
/// For a bitmap, we can generate the data once, and then scale or transform it as
|
||||||
|
/// necessary. Bitmap animations are a collection of bitmap visualizations.
|
||||||
|
///
|
||||||
|
/// For wireframes, we generate a WireframeObject using some of the parameters, and then
|
||||||
|
/// transform it with other parameters. The parameters are stored in a single dictionary,
|
||||||
|
/// but viewer-only parameters are prefixed with '_', which is not allowed in plugins.
|
||||||
|
///
|
||||||
|
/// This class represents the common ground between bitmaps and wireframes. It holds the
|
||||||
|
/// identifier and parameters, as well as the thumbnail data that we display in the list.
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
public class Visualization {
|
public class Visualization {
|
||||||
public const double THUMBNAIL_DIM = 64;
|
public const double THUMBNAIL_DIM = 64;
|
||||||
@ -98,8 +112,7 @@ namespace SourceGen {
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Image to overlay on animation visualizations.
|
/// Image to overlay on animation visualizations.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal static readonly BitmapSource ANIM_OVERLAY_IMAGE =
|
internal static readonly BitmapSource ANIM_OVERLAY_IMAGE = GenerateAnimOverlayImage();
|
||||||
VisualizationAnimation.GenerateAnimOverlayImage();
|
|
||||||
|
|
||||||
internal static readonly BitmapSource BLANK_IMAGE = GenerateBlankImage();
|
internal static readonly BitmapSource BLANK_IMAGE = GenerateBlankImage();
|
||||||
//internal static readonly BitmapSource BLACK_IMAGE = GenerateBlackImage();
|
//internal static readonly BitmapSource BLACK_IMAGE = GenerateBlackImage();
|
||||||
@ -246,6 +259,7 @@ namespace SourceGen {
|
|||||||
/// <returns>Rendered bitmap.</returns>
|
/// <returns>Rendered bitmap.</returns>
|
||||||
public static BitmapSource GenerateWireframeImage(IVisualizationWireframe visWire,
|
public static BitmapSource GenerateWireframeImage(IVisualizationWireframe visWire,
|
||||||
ReadOnlyDictionary<string, object> parms, double dim) {
|
ReadOnlyDictionary<string, object> parms, double dim) {
|
||||||
|
// Generate the path geometry.
|
||||||
GeometryGroup geo = GenerateWireframePath(visWire, parms, dim);
|
GeometryGroup geo = GenerateWireframePath(visWire, parms, dim);
|
||||||
|
|
||||||
// Render Path to bitmap -- https://stackoverflow.com/a/23582564/294248
|
// Render Path to bitmap -- https://stackoverflow.com/a/23582564/294248
|
||||||
@ -283,15 +297,19 @@ namespace SourceGen {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Generates a WPF path from IVisualizationWireframe data. Line widths get scaled
|
/// Generates WPF Path geometry from IVisualizationWireframe data. Line widths get
|
||||||
/// if the output area is larger or smaller than the path, so this scales coordinates
|
/// scaled if the output area is larger or smaller than the path bounds, so this scales
|
||||||
/// so they fit within the box.
|
/// coordinates so they fit within the box.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="visWire">Visualization data.</param>
|
/// <param name="visWire">Visualization data.</param>
|
||||||
/// <param name="parms">Visualization parameters.</param>
|
/// <param name="parms">Visualization parameters.</param>
|
||||||
/// <param name="dim">Width/height to use for path area.</param>
|
/// <param name="dim">Width/height to use for path area.</param>
|
||||||
public static GeometryGroup GenerateWireframePath(IVisualizationWireframe visWire,
|
public static GeometryGroup GenerateWireframePath(IVisualizationWireframe visWire,
|
||||||
ReadOnlyDictionary<string, object> parms, double dim) {
|
ReadOnlyDictionary<string, object> parms, double dim) {
|
||||||
|
int eulerX = Util.GetFromObjDict(parms, VisWireframeAnimation.P_EULER_ROT_X, 0);
|
||||||
|
int eulerY = Util.GetFromObjDict(parms, VisWireframeAnimation.P_EULER_ROT_Y, 0);
|
||||||
|
int eulerZ = Util.GetFromObjDict(parms, VisWireframeAnimation.P_EULER_ROT_Z, 0);
|
||||||
|
|
||||||
// WPF path drawing is based on a system where a pixel is drawn at the center
|
// 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
|
// 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
|
// you draw a pixel at (0,0), most of the pixel will be outside the window
|
||||||
@ -334,7 +352,7 @@ namespace SourceGen {
|
|||||||
// Generate a list of clip-space line segments. Coordinate values are in the
|
// Generate a list of clip-space line segments. Coordinate values are in the
|
||||||
// range [-1,1], with +X to the right and +Y upward.
|
// range [-1,1], with +X to the right and +Y upward.
|
||||||
WireframeObject wireObj = WireframeObject.Create(visWire);
|
WireframeObject wireObj = WireframeObject.Create(visWire);
|
||||||
List<WireframeObject.LineSeg> segs = wireObj.Generate(parms);
|
List<WireframeObject.LineSeg> segs = wireObj.Generate(parms, eulerX, eulerY, eulerZ);
|
||||||
|
|
||||||
// Convert clip-space coords to screen. We need to translate to [0,2] with +Y
|
// Convert clip-space coords to screen. We need to translate to [0,2] with +Y
|
||||||
// toward the bottom of the screen, scale up, round to the nearest whole pixel,
|
// toward the bottom of the screen, scale up, round to the nearest whole pixel,
|
||||||
@ -361,6 +379,39 @@ namespace SourceGen {
|
|||||||
return bmp;
|
return bmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Generate an image to overlay on thumbnails of animations.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
private static BitmapSource GenerateAnimOverlayImage() {
|
||||||
|
const int IMAGE_SIZE = 128;
|
||||||
|
|
||||||
|
// Glowy "high tech" blue.
|
||||||
|
SolidColorBrush outlineBrush = new SolidColorBrush(Color.FromArgb(255, 0, 216, 255));
|
||||||
|
SolidColorBrush fillBrush = new SolidColorBrush(Color.FromArgb(128, 0, 182, 215));
|
||||||
|
|
||||||
|
DrawingVisual visual = new DrawingVisual();
|
||||||
|
using (DrawingContext dc = visual.RenderOpen()) {
|
||||||
|
// Thanks: https://stackoverflow.com/a/29249100/294248
|
||||||
|
Point p1 = new Point(IMAGE_SIZE * 5 / 8, IMAGE_SIZE / 2);
|
||||||
|
Point p2 = new Point(IMAGE_SIZE * 3 / 8, IMAGE_SIZE / 4);
|
||||||
|
Point p3 = new Point(IMAGE_SIZE * 3 / 8, IMAGE_SIZE * 3 / 4);
|
||||||
|
StreamGeometry sg = new StreamGeometry();
|
||||||
|
using (StreamGeometryContext sgc = sg.Open()) {
|
||||||
|
sgc.BeginFigure(p1, true, true);
|
||||||
|
PointCollection points = new PointCollection() { p2, p3 };
|
||||||
|
sgc.PolyLineTo(points, true, true);
|
||||||
|
}
|
||||||
|
sg.Freeze();
|
||||||
|
dc.DrawGeometry(fillBrush, new Pen(outlineBrush, 3), sg);
|
||||||
|
}
|
||||||
|
|
||||||
|
RenderTargetBitmap bmp = new RenderTargetBitmap(IMAGE_SIZE, IMAGE_SIZE, 96.0, 96.0,
|
||||||
|
PixelFormats.Pbgra32);
|
||||||
|
bmp.Render(visual);
|
||||||
|
return bmp;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns a bitmap with a single black pixel.
|
/// Returns a bitmap with a single black pixel.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -118,13 +118,13 @@ namespace SourceGen {
|
|||||||
bool somethingRemoved = false;
|
bool somethingRemoved = false;
|
||||||
newSet = new VisualizationSet(visSet.Count);
|
newSet = new VisualizationSet(visSet.Count);
|
||||||
foreach (Visualization vis in visSet) {
|
foreach (Visualization vis in visSet) {
|
||||||
if (!(vis is VisualizationAnimation)) {
|
if (!(vis is VisBitmapAnimation)) {
|
||||||
newSet.Add(vis);
|
newSet.Add(vis);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (VisualizationAnimation.StripEntries((VisualizationAnimation) vis,
|
if (VisBitmapAnimation.StripEntries((VisBitmapAnimation) vis,
|
||||||
removedSerials, out VisualizationAnimation newAnim)) {
|
removedSerials, out VisBitmapAnimation newAnim)) {
|
||||||
somethingRemoved = true;
|
somethingRemoved = true;
|
||||||
if (newAnim.Count != 0) {
|
if (newAnim.Count != 0) {
|
||||||
newSet.Add(newAnim);
|
newSet.Add(newAnim);
|
||||||
@ -186,7 +186,7 @@ namespace SourceGen {
|
|||||||
}
|
}
|
||||||
//Debug.WriteLine("Vis needs refresh: " + vis.Tag);
|
//Debug.WriteLine("Vis needs refresh: " + vis.Tag);
|
||||||
|
|
||||||
if (vis is VisualizationAnimation) {
|
if (vis is VisBitmapAnimation) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -242,14 +242,14 @@ namespace SourceGen {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Now that we've generated images for the Visualizations, update any
|
// Now that we've generated images for the Visualizations, update any
|
||||||
// VisualizationAnimation thumbnails that may have been affected.
|
// VisBitmapAnimation thumbnails that may have been affected.
|
||||||
foreach (KeyValuePair<int, VisualizationSet> kvp in visSets) {
|
foreach (KeyValuePair<int, VisualizationSet> kvp in visSets) {
|
||||||
VisualizationSet visSet = kvp.Value;
|
VisualizationSet visSet = kvp.Value;
|
||||||
foreach (Visualization vis in visSet) {
|
foreach (Visualization vis in visSet) {
|
||||||
if (!(vis is VisualizationAnimation)) {
|
if (!(vis is VisBitmapAnimation)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
VisualizationAnimation visAnim = (VisualizationAnimation)vis;
|
VisBitmapAnimation visAnim = (VisBitmapAnimation)vis;
|
||||||
visAnim.GenerateImage(visSets);
|
visAnim.GenerateImage(visSets);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -209,7 +209,8 @@ namespace SourceGen {
|
|||||||
/// <param name="parms">Visualization parameters.</param>
|
/// <param name="parms">Visualization parameters.</param>
|
||||||
/// <returns>List of line segments, which could be empty if backface removal
|
/// <returns>List of line segments, which could be empty if backface removal
|
||||||
/// was especially successful.</returns>
|
/// was especially successful.</returns>
|
||||||
public List<LineSeg> Generate(ReadOnlyDictionary<string, object> parms) {
|
public List<LineSeg> Generate(ReadOnlyDictionary<string, object> parms,
|
||||||
|
int eulerX, int eulerY, int eulerZ) {
|
||||||
List<LineSeg> segs = new List<LineSeg>(mEdges.Count);
|
List<LineSeg> segs = new List<LineSeg>(mEdges.Count);
|
||||||
bool doPersp = Util.GetFromObjDict(parms, VisWireframe.P_IS_PERSPECTIVE, false);
|
bool doPersp = Util.GetFromObjDict(parms, VisWireframe.P_IS_PERSPECTIVE, false);
|
||||||
bool doBfc = Util.GetFromObjDict(parms, VisWireframe.P_IS_BFC_ENABLED, false);
|
bool doBfc = Util.GetFromObjDict(parms, VisWireframe.P_IS_BFC_ENABLED, false);
|
||||||
@ -226,9 +227,6 @@ namespace SourceGen {
|
|||||||
scale = (scale * zadj) / (zadj + 0.5);
|
scale = (scale * zadj) / (zadj + 0.5);
|
||||||
}
|
}
|
||||||
|
|
||||||
int eulerX = Util.GetFromObjDict(parms, VisWireframe.P_EULER_ROT_X, 0);
|
|
||||||
int eulerY = Util.GetFromObjDict(parms, VisWireframe.P_EULER_ROT_Y, 0);
|
|
||||||
int eulerZ = Util.GetFromObjDict(parms, VisWireframe.P_EULER_ROT_Z, 0);
|
|
||||||
Matrix44 rotMat = new Matrix44();
|
Matrix44 rotMat = new Matrix44();
|
||||||
rotMat.SetRotationEuler(eulerX, eulerY, eulerZ);
|
rotMat.SetRotationEuler(eulerX, eulerY, eulerZ);
|
||||||
|
|
||||||
|
@ -36,11 +36,11 @@ namespace SourceGen.WpfGui {
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// New/edited animation, only valid when dialog result is true.
|
/// New/edited animation, only valid when dialog result is true.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public VisualizationAnimation NewAnim { get; private set; }
|
public VisBitmapAnimation NewAnim { get; private set; }
|
||||||
|
|
||||||
private int mSetOffset;
|
private int mSetOffset;
|
||||||
private SortedList<int, VisualizationSet> mEditedList;
|
private SortedList<int, VisualizationSet> mEditedList;
|
||||||
private VisualizationAnimation mOrigAnim;
|
private VisBitmapAnimation mOrigAnim;
|
||||||
|
|
||||||
private Brush mDefaultLabelColor = SystemColors.WindowTextBrush;
|
private Brush mDefaultLabelColor = SystemColors.WindowTextBrush;
|
||||||
private Brush mErrorLabelColor = Brushes.Red;
|
private Brush mErrorLabelColor = Brushes.Red;
|
||||||
@ -135,7 +135,7 @@ namespace SourceGen.WpfGui {
|
|||||||
/// Constructor.
|
/// Constructor.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public EditBitmapAnimation(Window owner, int setOffset,
|
public EditBitmapAnimation(Window owner, int setOffset,
|
||||||
SortedList<int, VisualizationSet> editedList, VisualizationAnimation origAnim) {
|
SortedList<int, VisualizationSet> editedList, VisBitmapAnimation origAnim) {
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
Owner = owner;
|
Owner = owner;
|
||||||
DataContext = this;
|
DataContext = this;
|
||||||
@ -149,7 +149,12 @@ namespace SourceGen.WpfGui {
|
|||||||
if (origAnim != null) {
|
if (origAnim != null) {
|
||||||
TagString = origAnim.Tag;
|
TagString = origAnim.Tag;
|
||||||
mFrameDelayIntMsec = PluginCommon.Util.GetFromObjDict(origAnim.VisGenParams,
|
mFrameDelayIntMsec = PluginCommon.Util.GetFromObjDict(origAnim.VisGenParams,
|
||||||
VisualizationAnimation.FRAME_DELAY_MSEC_PARAM, DEFAULT_FRAME_DELAY);
|
VisBitmapAnimation.P_FRAME_DELAY_MSEC_PARAM, DEFAULT_FRAME_DELAY);
|
||||||
|
if (mFrameDelayIntMsec == DEFAULT_FRAME_DELAY) {
|
||||||
|
// check for old-style
|
||||||
|
mFrameDelayIntMsec = PluginCommon.Util.GetFromObjDict(origAnim.VisGenParams,
|
||||||
|
VisBitmapAnimation.P_FRAME_DELAY_MSEC_PARAM_OLD, DEFAULT_FRAME_DELAY);
|
||||||
|
}
|
||||||
FrameDelayTimeMsec = mFrameDelayIntMsec.ToString();
|
FrameDelayTimeMsec = mFrameDelayIntMsec.ToString();
|
||||||
} else {
|
} else {
|
||||||
TagString = "anim" + mSetOffset.ToString("x6");
|
TagString = "anim" + mSetOffset.ToString("x6");
|
||||||
@ -179,7 +184,7 @@ namespace SourceGen.WpfGui {
|
|||||||
// Add all remaining non-animation Visualizations to the "source" set.
|
// Add all remaining non-animation Visualizations to the "source" set.
|
||||||
foreach (KeyValuePair<int, VisualizationSet> kvp in mEditedList) {
|
foreach (KeyValuePair<int, VisualizationSet> kvp in mEditedList) {
|
||||||
foreach (Visualization vis in kvp.Value) {
|
foreach (Visualization vis in kvp.Value) {
|
||||||
if (vis is VisualizationAnimation) {
|
if (vis is VisBitmapAnimation) {
|
||||||
// disallow using animations as animation frames
|
// disallow using animations as animation frames
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -210,15 +215,15 @@ namespace SourceGen.WpfGui {
|
|||||||
|
|
||||||
private void OkButton_Click(object sender, RoutedEventArgs e) {
|
private void OkButton_Click(object sender, RoutedEventArgs e) {
|
||||||
Dictionary<string, object> visGenParams = new Dictionary<string, object>(1);
|
Dictionary<string, object> visGenParams = new Dictionary<string, object>(1);
|
||||||
visGenParams.Add(VisualizationAnimation.FRAME_DELAY_MSEC_PARAM, mFrameDelayIntMsec);
|
visGenParams.Add(VisBitmapAnimation.P_FRAME_DELAY_MSEC_PARAM, mFrameDelayIntMsec);
|
||||||
|
|
||||||
List<int> serials = new List<int>(VisAnimItems.Count);
|
List<int> serials = new List<int>(VisAnimItems.Count);
|
||||||
foreach (Visualization vis in VisAnimItems) {
|
foreach (Visualization vis in VisAnimItems) {
|
||||||
serials.Add(vis.SerialNumber);
|
serials.Add(vis.SerialNumber);
|
||||||
}
|
}
|
||||||
|
|
||||||
NewAnim = new VisualizationAnimation(TagString, VisualizationAnimation.ANIM_VIS_GEN,
|
NewAnim = new VisBitmapAnimation(TagString, VisBitmapAnimation.ANIM_VIS_GEN,
|
||||||
new ReadOnlyDictionary<string, object>(visGenParams), serials, mOrigAnim);
|
new ReadOnlyDictionary<string, object>(visGenParams), mOrigAnim, serials);
|
||||||
NewAnim.GenerateImage(mEditedList);
|
NewAnim.GenerateImage(mEditedList);
|
||||||
|
|
||||||
DialogResult = true;
|
DialogResult = true;
|
||||||
|
@ -98,6 +98,7 @@ limitations under the License.
|
|||||||
<RowDefinition Height="Auto"/>
|
<RowDefinition Height="Auto"/>
|
||||||
<RowDefinition Height="Auto"/>
|
<RowDefinition Height="Auto"/>
|
||||||
<RowDefinition Height="Auto"/>
|
<RowDefinition Height="Auto"/>
|
||||||
|
<RowDefinition Height="Auto"/>
|
||||||
</Grid.RowDefinitions>
|
</Grid.RowDefinitions>
|
||||||
|
|
||||||
<Grid Grid.Row="0">
|
<Grid Grid.Row="0">
|
||||||
@ -135,7 +136,7 @@ limitations under the License.
|
|||||||
BorderBrush="{DynamicResource {x:Static SystemColors.WindowFrameBrushKey}}"
|
BorderBrush="{DynamicResource {x:Static SystemColors.WindowFrameBrushKey}}"
|
||||||
Background="{StaticResource CheckerBackground}">
|
Background="{StaticResource CheckerBackground}">
|
||||||
<!-- explicit width gets cleared after initial window layout -->
|
<!-- explicit width gets cleared after initial window layout -->
|
||||||
<Grid Name="previewGrid" Width="400" Height="400">
|
<Grid Name="previewGrid" Width="548" Height="400">
|
||||||
<!-- either the image or the path is shown, not both; background is set to
|
<!-- either the image or the path is shown, not both; background is set to
|
||||||
transparent for image, black for path -->
|
transparent for image, black for path -->
|
||||||
<Image Name="previewImage" Source="/Res/RedX.png"
|
<Image Name="previewImage" Source="/Res/RedX.png"
|
||||||
@ -174,7 +175,77 @@ limitations under the License.
|
|||||||
</ItemsControl>
|
</ItemsControl>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|
||||||
<DockPanel Grid.Column="0" Grid.Row="4" Margin="0,8,0,0" LastChildFill="False">
|
<Grid Grid.Row="4" HorizontalAlignment="Left" Visibility="{Binding WireframeCtrlVisibility}">
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="Auto"/>
|
||||||
|
<ColumnDefinition Width="Auto"/>
|
||||||
|
<ColumnDefinition Width="Auto"/>
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
<Grid.RowDefinitions>
|
||||||
|
<RowDefinition Height="Auto"/>
|
||||||
|
<RowDefinition Height="Auto"/>
|
||||||
|
<RowDefinition Height="Auto"/>
|
||||||
|
<RowDefinition Height="Auto"/>
|
||||||
|
<RowDefinition Height="Auto"/>
|
||||||
|
<RowDefinition Height="Auto"/>
|
||||||
|
<RowDefinition Height="Auto"/>
|
||||||
|
<RowDefinition Height="Auto"/>
|
||||||
|
</Grid.RowDefinitions>
|
||||||
|
|
||||||
|
<Rectangle Grid.Row="0" Grid.ColumnSpan="3" Margin="4" HorizontalAlignment="Stretch"
|
||||||
|
Fill="LightGray" Height="2"/>
|
||||||
|
|
||||||
|
<TextBlock Grid.Column="0" Grid.Row="1" Text="Initial X rotation (deg):" Margin="0,5,0,0"/>
|
||||||
|
<TextBox Grid.Column="1" Grid.Row="1" Margin="4,4,0,0" Width="30" MaxLength="3"
|
||||||
|
Text="{Binding ElementName=initialXSlider, Path=Value, UpdateSourceTrigger=PropertyChanged}"/>
|
||||||
|
<Slider Name="initialXSlider" Grid.Column="2" Grid.Row="1" Margin="4,4,0,0" Width="360"
|
||||||
|
Minimum="0" Maximum="359" TickFrequency="1" IsSnapToTickEnabled="True"
|
||||||
|
ValueChanged="InitialRotSlider_ValueChanged"/>
|
||||||
|
|
||||||
|
<TextBlock Grid.Column="0" Grid.Row="2" Text="Initial Y rotation (deg):" Margin="0,5,0,0"/>
|
||||||
|
<TextBox Grid.Column="1" Grid.Row="2" Margin="4,4,0,0" Width="30" MaxLength="3"
|
||||||
|
Text="{Binding ElementName=initialYSlider, Path=Value, UpdateSourceTrigger=PropertyChanged}"/>
|
||||||
|
<Slider Name="initialYSlider" Grid.Column="2" Grid.Row="2" Margin="4,4,0,0" Width="360"
|
||||||
|
Minimum="0" Maximum="359" TickFrequency="1" IsSnapToTickEnabled="True"
|
||||||
|
ValueChanged="InitialRotSlider_ValueChanged"/>
|
||||||
|
|
||||||
|
<TextBlock Grid.Column="0" Grid.Row="3" Text="Initial Z rotation (deg):" Margin="0,5,0,0"/>
|
||||||
|
<TextBox Grid.Column="1" Grid.Row="3" Margin="4,4,0,0" Width="30" MaxLength="3"
|
||||||
|
Text="{Binding ElementName=initialZSlider, Path=Value, UpdateSourceTrigger=PropertyChanged}"/>
|
||||||
|
<Slider Name="initialZSlider" Grid.Column="2" Grid.Row="3" Margin="4,4,0,0" Width="360"
|
||||||
|
Minimum="0" Maximum="359" TickFrequency="1" IsSnapToTickEnabled="True"
|
||||||
|
ValueChanged="InitialRotSlider_ValueChanged"/>
|
||||||
|
|
||||||
|
<CheckBox Name="isAnimated" Grid.Column="0" Grid.Row="4" Content="Animated" Margin="0,4,0,0"
|
||||||
|
IsChecked="{Binding IsWireframeAnimated}"/>
|
||||||
|
|
||||||
|
<!-- remaining items are enabled when "isAnimated" checkbox is checked -->
|
||||||
|
|
||||||
|
<TextBlock Grid.Column="0" Grid.Row="5" Grid.ColumnSpan="2" Margin="0,5,0,0"
|
||||||
|
Text="Rotation per frame:"/>
|
||||||
|
<StackPanel Grid.Column="1" Grid.Row="5" Grid.ColumnSpan="2" Orientation="Horizontal" Margin="4,4,0,0"
|
||||||
|
IsEnabled="{Binding ElementName=isAnimated, Path=IsChecked}">
|
||||||
|
<TextBlock Text="X:" Margin="0,1,0,0"/>
|
||||||
|
<TextBox Width="40" MaxLength="4" Margin="4,0,0,0"/>
|
||||||
|
<TextBlock Text="Y:" Margin="8,1,0,0"/>
|
||||||
|
<TextBox Width="40" MaxLength="4" Margin="4,0,0,0"/>
|
||||||
|
<TextBlock Text="Z:" Margin="8,1,0,0"/>
|
||||||
|
<TextBox Width="40" MaxLength="4" Margin="4,0,0,0"/>
|
||||||
|
</StackPanel>
|
||||||
|
|
||||||
|
<TextBlock Grid.Column="0" Grid.Row="6" Text="Frame count:" Margin="0,5,0,0"/>
|
||||||
|
<TextBox Grid.Column="1" Grid.Row="6" Width="50" Height="18" Margin="4,4,0,0"/>
|
||||||
|
<Button Grid.Column="2" Grid.Row="6" Width="70" Margin="4,4,0,0" HorizontalAlignment="Left"
|
||||||
|
Content="Auto" />
|
||||||
|
|
||||||
|
<TextBlock Grid.Column="0" Grid.Row="7" Text="Frame delay (msec):" Margin="0,5,0,0"/>
|
||||||
|
<TextBox Grid.Column="1" Grid.Row="7" Width="50" Margin="4,4,0,0"/>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
<DockPanel Grid.Column="0" Grid.Row="5" Margin="0,8,0,0" LastChildFill="False">
|
||||||
|
<Button DockPanel.Dock="Left" Content="Test Animation" Padding="4,0" Click="TestAnim_Click"
|
||||||
|
Visibility="{Binding WireframeCtrlVisibility}"
|
||||||
|
IsEnabled="{Binding ElementName=isAnimated, Path=IsChecked}"/>
|
||||||
<Button DockPanel.Dock="Right" Content="Cancel" Width="70" Margin="8,0,0,0" IsCancel="True"/>
|
<Button DockPanel.Dock="Right" Content="Cancel" Width="70" Margin="8,0,0,0" IsCancel="True"/>
|
||||||
<Button DockPanel.Dock="Right" Grid.Column="1" Content="OK" Width="70"
|
<Button DockPanel.Dock="Right" Grid.Column="1" Content="OK" Width="70"
|
||||||
IsDefault="True" IsEnabled="{Binding IsValid}" Click="OkButton_Click"/>
|
IsDefault="True" IsEnabled="{Binding IsValid}" Click="OkButton_Click"/>
|
||||||
|
@ -31,6 +31,15 @@ namespace SourceGen.WpfGui {
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Visualization editor.
|
/// Visualization editor.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// This provides editing of bitmap and wireframe visualizations, which have some
|
||||||
|
/// significant differences. We deal with them both here to provide an illusion of
|
||||||
|
/// consistency, and because it's nice to have the plugin management and generated
|
||||||
|
/// parameter edit controls in one place.
|
||||||
|
///
|
||||||
|
/// The most significant difference is that, while bitmap animations are a collection
|
||||||
|
/// of visualizations, wireframe animations are just additional parameters.
|
||||||
|
/// </remarks>
|
||||||
public partial class EditVisualization : Window, INotifyPropertyChanged {
|
public partial class EditVisualization : Window, INotifyPropertyChanged {
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// New/edited visualization, only valid when dialog result is true.
|
/// New/edited visualization, only valid when dialog result is true.
|
||||||
@ -43,7 +52,7 @@ namespace SourceGen.WpfGui {
|
|||||||
private SortedList<int, VisualizationSet> mEditedList;
|
private SortedList<int, VisualizationSet> mEditedList;
|
||||||
private Visualization mOrigVis;
|
private Visualization mOrigVis;
|
||||||
|
|
||||||
public BitmapSource mThumbnail;
|
public object mVisObj;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Visualization generation identifier for the last visualizer we used, for the benefit
|
/// Visualization generation identifier for the last visualizer we used, for the benefit
|
||||||
@ -72,6 +81,18 @@ namespace SourceGen.WpfGui {
|
|||||||
}
|
}
|
||||||
private bool mIsValid;
|
private bool mIsValid;
|
||||||
|
|
||||||
|
public Visibility WireframeCtrlVisibility {
|
||||||
|
get { return mWireframeCtrlVisibility; }
|
||||||
|
set { mWireframeCtrlVisibility = value; OnPropertyChanged(); }
|
||||||
|
}
|
||||||
|
private Visibility mWireframeCtrlVisibility;
|
||||||
|
|
||||||
|
public bool IsWireframeAnimated {
|
||||||
|
get { return mIsWireframeAnimated; }
|
||||||
|
set { mIsWireframeAnimated = value; OnPropertyChanged(); }
|
||||||
|
}
|
||||||
|
private bool mIsWireframeAnimated;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Visualization tag.
|
/// Visualization tag.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -318,18 +339,34 @@ namespace SourceGen.WpfGui {
|
|||||||
private void OkButton_Click(object sender, RoutedEventArgs e) {
|
private void OkButton_Click(object sender, RoutedEventArgs e) {
|
||||||
VisualizationItem item = (VisualizationItem)visComboBox.SelectedItem;
|
VisualizationItem item = (VisualizationItem)visComboBox.SelectedItem;
|
||||||
Debug.Assert(item != null);
|
Debug.Assert(item != null);
|
||||||
ReadOnlyDictionary<string, object> valueDict = sLastParams = CreateVisGenParams();
|
bool isWireframe = (item.VisDescriptor.VisualizationType == VisDescr.VisType.Wireframe);
|
||||||
|
ReadOnlyDictionary<string, object> valueDict = CreateVisGenParams(isWireframe);
|
||||||
|
sLastParams = valueDict;
|
||||||
|
|
||||||
string trimTag = Visualization.TrimAndValidateTag(TagString, out bool isTagValid);
|
string trimTag = Visualization.TrimAndValidateTag(TagString, out bool isTagValid);
|
||||||
Debug.Assert(isTagValid);
|
Debug.Assert(isTagValid);
|
||||||
|
if (isWireframe && IsWireframeAnimated) {
|
||||||
|
NewVis = new VisWireframeAnimation(trimTag, item.VisDescriptor.Ident, valueDict,
|
||||||
|
mOrigVis, (IVisualizationWireframe) mVisObj);
|
||||||
|
} else {
|
||||||
NewVis = new Visualization(trimTag, item.VisDescriptor.Ident, valueDict, mOrigVis);
|
NewVis = new Visualization(trimTag, item.VisDescriptor.Ident, valueDict, mOrigVis);
|
||||||
NewVis.CachedImage = mThumbnail;
|
}
|
||||||
|
if (isWireframe) {
|
||||||
|
Debug.Assert(mVisObj is IVisualizationWireframe);
|
||||||
|
NewVis.CachedImage =
|
||||||
|
Visualization.GenerateWireframeImage((IVisualizationWireframe)mVisObj,
|
||||||
|
valueDict, Visualization.THUMBNAIL_DIM);
|
||||||
|
} else {
|
||||||
|
Debug.Assert(mVisObj is IVisualization2d);
|
||||||
|
NewVis.CachedImage =
|
||||||
|
Visualization.ConvertToBitmapSource((IVisualization2d)mVisObj);
|
||||||
|
}
|
||||||
|
|
||||||
sLastVisIdent = NewVis.VisGenIdent;
|
sLastVisIdent = NewVis.VisGenIdent;
|
||||||
|
|
||||||
DialogResult = true;
|
DialogResult = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private ReadOnlyDictionary<string, object> CreateVisGenParams() {
|
private ReadOnlyDictionary<string, object> CreateVisGenParams(bool includeWire) {
|
||||||
// Generate value dictionary.
|
// Generate value dictionary.
|
||||||
Dictionary<string, object> valueDict =
|
Dictionary<string, object> valueDict =
|
||||||
new Dictionary<string, object>(ParameterList.Count);
|
new Dictionary<string, object>(ParameterList.Count);
|
||||||
@ -351,6 +388,17 @@ namespace SourceGen.WpfGui {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
WireframeCtrlVisibility = includeWire ? Visibility.Visible : Visibility.Collapsed;
|
||||||
|
if (includeWire) {
|
||||||
|
int rotX = (int)initialXSlider.Value;
|
||||||
|
int rotY = (int)initialYSlider.Value;
|
||||||
|
int rotZ = (int)initialZSlider.Value;
|
||||||
|
|
||||||
|
valueDict.Add(VisWireframeAnimation.P_EULER_ROT_X, rotX);
|
||||||
|
valueDict.Add(VisWireframeAnimation.P_EULER_ROT_Y, rotY);
|
||||||
|
valueDict.Add(VisWireframeAnimation.P_EULER_ROT_Z, rotZ);
|
||||||
|
}
|
||||||
|
|
||||||
return new ReadOnlyDictionary<string, object>(valueDict);
|
return new ReadOnlyDictionary<string, object>(valueDict);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -446,26 +494,28 @@ namespace SourceGen.WpfGui {
|
|||||||
VisualizationItem item = (VisualizationItem)visComboBox.SelectedItem;
|
VisualizationItem item = (VisualizationItem)visComboBox.SelectedItem;
|
||||||
|
|
||||||
BitmapDimensions = "?";
|
BitmapDimensions = "?";
|
||||||
if (!IsValid || item == null) {
|
|
||||||
previewImage.Source = sBadParamsImage;
|
|
||||||
previewGrid.Background = null;
|
previewGrid.Background = null;
|
||||||
wireframePath.Data = new GeometryGroup();
|
wireframePath.Data = new GeometryGroup();
|
||||||
|
if (!IsValid || item == null) {
|
||||||
|
previewImage.Source = sBadParamsImage;
|
||||||
} else {
|
} else {
|
||||||
// Invoke the plugin.
|
// Invoke the plugin.
|
||||||
PluginErrMessage = string.Empty;
|
PluginErrMessage = string.Empty;
|
||||||
|
|
||||||
IVisualization2d vis2d = null;
|
IVisualization2d vis2d = null;
|
||||||
IVisualizationWireframe visWire = null;
|
IVisualizationWireframe visWire = null;
|
||||||
ReadOnlyDictionary<string, object> parms = CreateVisGenParams();
|
ReadOnlyDictionary<string, object> parms = null;
|
||||||
try {
|
try {
|
||||||
IPlugin_Visualizer plugin =
|
IPlugin_Visualizer plugin =
|
||||||
(IPlugin_Visualizer)mProject.GetPlugin(item.ScriptIdent);
|
(IPlugin_Visualizer)mProject.GetPlugin(item.ScriptIdent);
|
||||||
if (item.VisDescriptor.VisualizationType == VisDescr.VisType.Bitmap) {
|
if (item.VisDescriptor.VisualizationType == VisDescr.VisType.Bitmap) {
|
||||||
|
parms = CreateVisGenParams(false);
|
||||||
vis2d = plugin.Generate2d(item.VisDescriptor, parms);
|
vis2d = plugin.Generate2d(item.VisDescriptor, parms);
|
||||||
if (vis2d == null) {
|
if (vis2d == null) {
|
||||||
Debug.WriteLine("Vis2d generator returned null");
|
Debug.WriteLine("Vis2d generator returned null");
|
||||||
}
|
}
|
||||||
} else if (item.VisDescriptor.VisualizationType == VisDescr.VisType.Wireframe) {
|
} else if (item.VisDescriptor.VisualizationType == VisDescr.VisType.Wireframe) {
|
||||||
|
parms = CreateVisGenParams(true);
|
||||||
IPlugin_Visualizer_v2 plugin2 = (IPlugin_Visualizer_v2)plugin;
|
IPlugin_Visualizer_v2 plugin2 = (IPlugin_Visualizer_v2)plugin;
|
||||||
visWire = plugin2.GenerateWireframe(item.VisDescriptor, parms);
|
visWire = plugin2.GenerateWireframe(item.VisDescriptor, parms);
|
||||||
if (visWire == null) {
|
if (visWire == null) {
|
||||||
@ -496,16 +546,15 @@ namespace SourceGen.WpfGui {
|
|||||||
BitmapDimensions = string.Format("{0}x{1}",
|
BitmapDimensions = string.Format("{0}x{1}",
|
||||||
previewImage.Source.Width, previewImage.Source.Height);
|
previewImage.Source.Width, previewImage.Source.Height);
|
||||||
|
|
||||||
mThumbnail = (BitmapSource)previewImage.Source;
|
mVisObj = vis2d;
|
||||||
} else {
|
} else {
|
||||||
previewGrid.Background = Brushes.Black;
|
previewGrid.Background = Brushes.Black;
|
||||||
previewImage.Source = Visualization.BLANK_IMAGE;
|
previewImage.Source = Visualization.BLANK_IMAGE;
|
||||||
wireframePath.Data = Visualization.GenerateWireframePath(visWire, parms,
|
wireframePath.Data = Visualization.GenerateWireframePath(visWire, parms,
|
||||||
previewImage.ActualWidth / 2);
|
Math.Min(previewImage.ActualWidth, previewImage.ActualHeight) / 2);
|
||||||
BitmapDimensions = "n/a";
|
BitmapDimensions = "n/a";
|
||||||
|
|
||||||
mThumbnail = Visualization.GenerateWireframeImage(visWire, parms,
|
mVisObj = visWire;
|
||||||
Visualization.THUMBNAIL_DIM);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -533,6 +582,16 @@ namespace SourceGen.WpfGui {
|
|||||||
}
|
}
|
||||||
Debug.WriteLine("VisComboBox sel change: " + item.VisDescriptor.Ident);
|
Debug.WriteLine("VisComboBox sel change: " + item.VisDescriptor.Ident);
|
||||||
GenerateParamControls(item.VisDescriptor);
|
GenerateParamControls(item.VisDescriptor);
|
||||||
|
|
||||||
|
if (mOrigVis != null) {
|
||||||
|
initialXSlider.Value = Util.GetFromObjDict(mOrigVis.VisGenParams,
|
||||||
|
VisWireframeAnimation.P_EULER_ROT_X, 0);
|
||||||
|
initialYSlider.Value = Util.GetFromObjDict(mOrigVis.VisGenParams,
|
||||||
|
VisWireframeAnimation.P_EULER_ROT_Y, 0);
|
||||||
|
initialZSlider.Value = Util.GetFromObjDict(mOrigVis.VisGenParams,
|
||||||
|
VisWireframeAnimation.P_EULER_ROT_Z, 0);
|
||||||
|
}
|
||||||
|
|
||||||
UpdateControls();
|
UpdateControls();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -549,6 +608,15 @@ namespace SourceGen.WpfGui {
|
|||||||
//Debug.WriteLine("CHECK CHANGE" + pv);
|
//Debug.WriteLine("CHECK CHANGE" + pv);
|
||||||
UpdateControls();
|
UpdateControls();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void InitialRotSlider_ValueChanged(object sender,
|
||||||
|
RoutedPropertyChangedEventArgs<double> e) {
|
||||||
|
UpdateControls();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void TestAnim_Click(object sender, RoutedEventArgs e) {
|
||||||
|
Debug.WriteLine("TEST!");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -221,9 +221,9 @@ namespace SourceGen.WpfGui {
|
|||||||
Visualization item = (Visualization)visualizationGrid.SelectedItem;
|
Visualization item = (Visualization)visualizationGrid.SelectedItem;
|
||||||
Visualization newVis;
|
Visualization newVis;
|
||||||
|
|
||||||
if (item is VisualizationAnimation) {
|
if (item is VisBitmapAnimation) {
|
||||||
EditBitmapAnimation dlg = new EditBitmapAnimation(this, mOffset,
|
EditBitmapAnimation dlg = new EditBitmapAnimation(this, mOffset,
|
||||||
CreateEditedSetList(), (VisualizationAnimation)item);
|
CreateEditedSetList(), (VisBitmapAnimation)item);
|
||||||
if (dlg.ShowDialog() != true) {
|
if (dlg.ShowDialog() != true) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -264,18 +264,18 @@ namespace SourceGen.WpfGui {
|
|||||||
// (This is a bit awkward because we can't modify VisualizationList while iterating
|
// (This is a bit awkward because we can't modify VisualizationList while iterating
|
||||||
// through it, and there's no simple "replace entry" operation on an observable
|
// through it, and there's no simple "replace entry" operation on an observable
|
||||||
// collection. Fortunately we don't do this often and the data sets are small.)
|
// collection. Fortunately we don't do this often and the data sets are small.)
|
||||||
List<VisualizationAnimation> needsUpdate = new List<VisualizationAnimation>();
|
List<VisBitmapAnimation> needsUpdate = new List<VisBitmapAnimation>();
|
||||||
foreach (Visualization vis in VisualizationList) {
|
foreach (Visualization vis in VisualizationList) {
|
||||||
if (vis is VisualizationAnimation) {
|
if (vis is VisBitmapAnimation) {
|
||||||
VisualizationAnimation visAnim = (VisualizationAnimation)vis;
|
VisBitmapAnimation visAnim = (VisBitmapAnimation)vis;
|
||||||
if (visAnim.ContainsSerial(item.SerialNumber)) {
|
if (visAnim.ContainsSerial(item.SerialNumber)) {
|
||||||
needsUpdate.Add(visAnim);
|
needsUpdate.Add(visAnim);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
foreach (VisualizationAnimation visAnim in needsUpdate) {
|
foreach (VisBitmapAnimation visAnim in needsUpdate) {
|
||||||
VisualizationAnimation newAnim;
|
VisBitmapAnimation newAnim;
|
||||||
if (VisualizationAnimation.StripEntries(visAnim,
|
if (VisBitmapAnimation.StripEntries(visAnim,
|
||||||
new List<int>(1) { item.SerialNumber }, out newAnim)) {
|
new List<int>(1) { item.SerialNumber }, out newAnim)) {
|
||||||
if (newAnim.Count == 0) {
|
if (newAnim.Count == 0) {
|
||||||
VisualizationList.Remove(visAnim);
|
VisualizationList.Remove(visAnim);
|
||||||
|
Loading…
Reference in New Issue
Block a user