Skip to content

Commit a85f6b7

Browse files
committed
Merge branch 'flipablz' of https://github.com/ButchersBoy/MaterialDesignInXamlToolkit into flipablz
2 parents f44a495 + 175c3ba commit a85f6b7

File tree

6 files changed

+331
-10
lines changed

6 files changed

+331
-10
lines changed

MainDemo.Wpf/App.xaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<Application x:Class="MaterialDesignColors.WpfExample.App"
22
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
33
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
4-
StartupUri="MainWindow.xaml">
4+
StartupUri="ProvingGround.xaml">
55
<Application.Resources>
66
<ResourceDictionary>
77
<ResourceDictionary.MergedDictionaries>

MainDemo.Wpf/MaterialDesignDemo.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,7 @@
157157
<DependentUpon>ProvingGround.xaml</DependentUpon>
158158
</Compile>
159159
<Compile Include="ProvingGroundStuff\MeasuringTextBox.cs" />
160+
<Compile Include="ProvingGroundStuff\Planez.cs" />
160161
<Compile Include="Shadows.xaml.cs">
161162
<DependentUpon>Shadows.xaml</DependentUpon>
162163
</Compile>

MainDemo.Wpf/ProvingGround.xaml

Lines changed: 29 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -15,37 +15,57 @@
1515
Background="{DynamicResource MaterialDesignPaper}"
1616
FontFamily="{StaticResource MaterialDesignFont}"
1717
mc:Ignorable="d"
18-
d:DesignWidth="477" d:DesignHeight="272"
18+
d:DesignWidth="477" d:DesignHeight="272"
1919
d:DataContext="{d:DesignInstance wpfExample:ProvingGroundViewModel, d:IsDesignTimeCreatable=False}">
2020
<UserControl.Resources>
2121
<ResourceDictionary>
2222
<ResourceDictionary.MergedDictionaries>
23+
24+
<ResourceDictionary Source="pack://application:,,,/MaterialDesignThemes.Wpf;component/Themes/MaterialDesignTheme.Button.xaml" />
25+
26+
<!--
2327
<ResourceDictionary Source="pack://application:,,,/MaterialDesignThemes.Wpf;component/Themes/MaterialDesignTheme.TextBox.xaml" />
2428
<ResourceDictionary Source="pack://application:,,,/MaterialDesignThemes.Wpf;component/Themes/MaterialDesignTheme.TextBlock.xaml" />
25-
<!--
29+
2630
<ResourceDictionary Source="pack://application:,,,/MaterialDesignThemes.Wpf;component/Themes/MaterialDesignTheme.Light.xaml" />
2731
<ResourceDictionary Source="pack://application:,,,/MaterialDesignThemes.Wpf;component/Themes/MaterialDesignTheme.ProgressBar.xaml" />
2832
<ResourceDictionary Source="pack://application:,,,/MaterialDesignThemes.Wpf;component/Themes/MaterialDesignTheme.Slider.xaml" />
2933
<ResourceDictionary Source="pack://application:,,,/MaterialDesignColors;component/Themes/Recommended/Primary/MaterialDesignColor.DeepPurple.xaml" />
3034
<ResourceDictionary Source="pack://application:,,,/MaterialDesignColors;component/Themes/Recommended/Accent/MaterialDesignColor.Lime.xaml" />
3135
-->
36+
3237
</ResourceDictionary.MergedDictionaries>
3338

3439

3540

36-
<Style TargetType="{x:Type provingGroundStuff:MeasuringTextBox}" BasedOn="{StaticResource MaterialDesignTextBox}" />
41+
3742

3843

3944

4045
</ResourceDictionary>
4146
</UserControl.Resources>
4247

4348
<Grid>
44-
<ComboBox materialDesign:HintAssist.Hint="OS">
45-
<ComboBoxItem>Android</ComboBoxItem>
46-
<ComboBoxItem>iOS</ComboBoxItem>
47-
<ComboBoxItem>Linux</ComboBoxItem>
48-
<ComboBoxItem>Windows</ComboBoxItem>
49-
</ComboBox>
49+
<ContentControl RenderTransformOrigin=".5,.5">
50+
<materialDesign:Card Margin="4 4 0 0" Width="220">
51+
<Grid>
52+
<Grid.RowDefinitions>
53+
<RowDefinition Height="140" />
54+
<RowDefinition Height="140" />
55+
</Grid.RowDefinitions>
56+
<Image Source="Resources/Contact.png" Height="140" Stretch="UniformToFill"/>
57+
<Button Grid.Row="1" Style="{StaticResource MaterialDesignFlatButton}"
58+
HorizontalAlignment="Center" VerticalAlignment="Center">
59+
<StackPanel Orientation="Horizontal">
60+
<materialDesign:PackIcon Kind="Rotate3d" />
61+
<TextBlock Margin="8 0 0 0">FLIP ME!</TextBlock>
62+
</StackPanel>
63+
</Button>
64+
</Grid>
65+
</materialDesign:Card>
66+
<ContentControl.RenderTransform>
67+
<SkewTransform AngleX="0" AngleY="45" CenterX=".5" CenterY=".5" ></SkewTransform>
68+
</ContentControl.RenderTransform>
69+
</ContentControl>
5070
</Grid>
5171
</UserControl>
Lines changed: 282 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,282 @@
1+
using System;
2+
using System.Windows;
3+
using System.Windows.Controls;
4+
using System.Windows.Markup;
5+
using System.Windows.Media;
6+
using System.Windows.Media.Media3D;
7+
8+
namespace Planerator
9+
{
10+
/// <summary>
11+
/// Planerator - dead simple interactive 3D in WPF. Read more at
12+
/// http://blogs.msdn.com/greg_schechter/archive/2007/10/26/enter-the-planerator-dead-simple-3d-in-wpf-with-a-stupid-name.aspx
13+
///
14+
/// Greg Schechter - Fall 2007
15+
/// </summary>
16+
[ContentProperty("Child")]
17+
public class Planerator : FrameworkElement
18+
{
19+
#region Public API
20+
21+
#region Dependency Properties
22+
23+
public static readonly DependencyProperty RotationXProperty =
24+
DependencyProperty.Register("RotationX", typeof(double), typeof(Planerator), new UIPropertyMetadata(0.0, (d, args) => ((Planerator)d).UpdateRotation()));
25+
public static readonly DependencyProperty RotationYProperty =
26+
DependencyProperty.Register("RotationY", typeof(double), typeof(Planerator), new UIPropertyMetadata(0.0, (d, args) => ((Planerator)d).UpdateRotation()));
27+
public static readonly DependencyProperty RotationZProperty =
28+
DependencyProperty.Register("RotationZ", typeof(double), typeof(Planerator), new UIPropertyMetadata(0.0, (d, args) => ((Planerator)d).UpdateRotation()));
29+
public static readonly DependencyProperty FieldOfViewProperty =
30+
DependencyProperty.Register("FieldOfView", typeof(double), typeof(Planerator), new UIPropertyMetadata(45.0, (d, args) => ((Planerator)d).Update3D(),
31+
(d, val) => Math.Min(Math.Max((double)val, 0.5), 179.9))); // clamp to a meaningful range
32+
33+
34+
public double RotationX
35+
{
36+
get { return (double)GetValue(RotationXProperty); }
37+
set { SetValue(RotationXProperty, value); }
38+
}
39+
public double RotationY
40+
{
41+
get { return (double)GetValue(RotationYProperty); }
42+
set { SetValue(RotationYProperty, value); }
43+
}
44+
public double RotationZ
45+
{
46+
get { return (double)GetValue(RotationZProperty); }
47+
set { SetValue(RotationZProperty, value); }
48+
}
49+
public double FieldOfView
50+
{
51+
get { return (double)GetValue(FieldOfViewProperty); }
52+
set { SetValue(FieldOfViewProperty, value); }
53+
}
54+
55+
#endregion
56+
57+
public FrameworkElement Child
58+
{
59+
get
60+
{
61+
return _originalChild;
62+
}
63+
set
64+
{
65+
if (_originalChild != value)
66+
{
67+
this.RemoveVisualChild(_visualChild);
68+
this.RemoveLogicalChild(_logicalChild);
69+
70+
// Wrap child with special decorator that catches layout invalidations.
71+
_originalChild = value;
72+
_logicalChild = new LayoutInvalidationCatcher() { Child = _originalChild };
73+
_visualChild = CreateVisualChild();
74+
75+
this.AddVisualChild(_visualChild);
76+
77+
// Need to use a logical child here to make sure databinding operations get down to it,
78+
// since otherwise the child appears only as the Visual to a Viewport2DVisual3D, which
79+
// doesn't have databinding operations pass into it from above.
80+
this.AddLogicalChild(_logicalChild);
81+
this.InvalidateMeasure();
82+
}
83+
}
84+
}
85+
86+
#endregion
87+
88+
#region Layout Stuff
89+
90+
protected override Size MeasureOverride(Size availableSize)
91+
{
92+
Size result;
93+
if (_logicalChild != null)
94+
{
95+
// Measure based on the size of the logical child, since we want to align with it.
96+
_logicalChild.Measure(availableSize);
97+
result = _logicalChild.DesiredSize;
98+
_visualChild.Measure(result);
99+
}
100+
else
101+
{
102+
result = new Size(0, 0);
103+
}
104+
return result;
105+
}
106+
107+
protected override Size ArrangeOverride(Size finalSize)
108+
{
109+
if (_logicalChild != null)
110+
{
111+
_logicalChild.Arrange(new Rect(finalSize));
112+
_visualChild.Arrange(new Rect(finalSize));
113+
Update3D();
114+
}
115+
return base.ArrangeOverride(finalSize);
116+
}
117+
118+
protected override Visual GetVisualChild(int index)
119+
{
120+
return _visualChild;
121+
122+
}
123+
124+
protected override int VisualChildrenCount
125+
{
126+
get
127+
{
128+
return _visualChild == null ? 0 : 1;
129+
}
130+
}
131+
132+
#endregion
133+
134+
#region 3D Stuff
135+
136+
private FrameworkElement CreateVisualChild()
137+
{
138+
MeshGeometry3D simpleQuad = new MeshGeometry3D()
139+
{
140+
Positions = new Point3DCollection(_mesh),
141+
TextureCoordinates = new PointCollection(_texCoords),
142+
TriangleIndices = new Int32Collection(_indices)
143+
};
144+
145+
// Front material is interactive, back material is not.
146+
Material frontMaterial = new DiffuseMaterial(Brushes.White);
147+
frontMaterial.SetValue(Viewport2DVisual3D.IsVisualHostMaterialProperty, true);
148+
149+
VisualBrush vb = new VisualBrush(_logicalChild);
150+
SetCachingForObject(vb); // big perf wins by caching!!
151+
Material backMaterial = new DiffuseMaterial(vb);
152+
153+
_rotationTransform.Rotation = _quaternionRotation;
154+
var xfGroup = new Transform3DGroup() { Children = { _scaleTransform, _rotationTransform } };
155+
156+
GeometryModel3D backModel = new GeometryModel3D() { Geometry = simpleQuad, Transform = xfGroup, BackMaterial = backMaterial };
157+
Model3DGroup m3dGroup = new Model3DGroup()
158+
{
159+
Children = { new DirectionalLight(Colors.White, new Vector3D(0, 0, -1)),
160+
new DirectionalLight(Colors.White, new Vector3D(0.1, -0.1, 1)),
161+
backModel }
162+
};
163+
164+
// Non-interactive Visual3D consisting of the backside, and two lights.
165+
ModelVisual3D mv3d = new ModelVisual3D() { Content = m3dGroup };
166+
167+
// Interactive frontside Visual3D
168+
Viewport2DVisual3D frontModel = new Viewport2DVisual3D() { Geometry = simpleQuad, Visual = _logicalChild, Material = frontMaterial, Transform = xfGroup };
169+
170+
// Cache the brush in the VP2V3 by setting caching on it. Big perf wins.
171+
SetCachingForObject(frontModel);
172+
173+
// Scene consists of both the above Visual3D's.
174+
_viewport3d = new Viewport3D() { ClipToBounds = false, Children = { mv3d, frontModel } };
175+
176+
UpdateRotation();
177+
178+
return _viewport3d;
179+
}
180+
181+
private void SetCachingForObject(DependencyObject d)
182+
{
183+
RenderOptions.SetCachingHint(d, CachingHint.Cache);
184+
RenderOptions.SetCacheInvalidationThresholdMinimum(d, 0.5);
185+
RenderOptions.SetCacheInvalidationThresholdMaximum(d, 2.0);
186+
}
187+
188+
private void UpdateRotation()
189+
{
190+
Quaternion qx = new Quaternion(_xAxis, RotationX);
191+
Quaternion qy = new Quaternion(_yAxis, RotationY);
192+
Quaternion qz = new Quaternion(_zAxis, RotationZ);
193+
194+
_quaternionRotation.Quaternion = qx * qy * qz;
195+
}
196+
197+
private void Update3D()
198+
{
199+
// Use GetDescendantBounds for sizing and centering since DesiredSize includes layout whitespace, whereas GetDescendantBounds
200+
// is tighter
201+
Rect logicalBounds = VisualTreeHelper.GetDescendantBounds(_logicalChild);
202+
double w = logicalBounds.Width;
203+
double h = logicalBounds.Height;
204+
205+
// Create a camera that looks down -Z, with up as Y, and positioned right halfway in X and Y on the element,
206+
// and back along Z the right distance based on the field-of-view is the same projected size as the 2D content
207+
// that it's looking at. See http://blogs.msdn.com/greg_schechter/archive/2007/04/03/camera-construction-in-parallaxui.aspx
208+
// for derivation of this camera.
209+
double fovInRadians = FieldOfView * (Math.PI / 180);
210+
double zValue = w / Math.Tan(fovInRadians / 2) / 1.5;
211+
_viewport3d.Camera = new PerspectiveCamera(new Point3D(w / 2, h / 2, zValue),
212+
-_zAxis,
213+
_yAxis,
214+
FieldOfView);
215+
216+
217+
_scaleTransform.ScaleX = w;
218+
_scaleTransform.ScaleY = h;
219+
_rotationTransform.CenterX = w / 2;
220+
_rotationTransform.CenterY = h / 2;
221+
}
222+
223+
#endregion
224+
225+
#region Private Classes
226+
227+
/// <summary>
228+
/// Wrap this around a class that we want to catch the measure and arrange
229+
/// processes occuring on, and propagate to the parent Planerator, if any.
230+
/// Do this because layout invalidations don't flow up out of a
231+
/// Viewport2DVisual3D object.
232+
/// </summary>
233+
private class LayoutInvalidationCatcher : Decorator
234+
{
235+
protected override Size MeasureOverride(Size constraint)
236+
{
237+
Planerator pl = this.Parent as Planerator;
238+
if (pl != null)
239+
{
240+
pl.InvalidateMeasure();
241+
}
242+
return base.MeasureOverride(constraint);
243+
}
244+
245+
protected override Size ArrangeOverride(Size arrangeSize)
246+
{
247+
Planerator pl = this.Parent as Planerator;
248+
if (pl != null)
249+
{
250+
pl.InvalidateArrange();
251+
}
252+
return base.ArrangeOverride(arrangeSize);
253+
}
254+
}
255+
256+
#endregion
257+
258+
#region Private data
259+
260+
// Instance data
261+
private FrameworkElement _logicalChild;
262+
private FrameworkElement _visualChild;
263+
private FrameworkElement _originalChild;
264+
265+
private QuaternionRotation3D _quaternionRotation = new QuaternionRotation3D();
266+
private RotateTransform3D _rotationTransform = new RotateTransform3D();
267+
private Viewport3D _viewport3d;
268+
private ScaleTransform3D _scaleTransform = new ScaleTransform3D();
269+
270+
// Static data
271+
static private readonly Point3D[] _mesh = new Point3D[] { new Point3D(0, 0, 0), new Point3D(0, 1, 0), new Point3D(1, 1, 0), new Point3D(1, 0, 0) };
272+
static private readonly Point[] _texCoords = new Point[] { new Point(0, 1), new Point(0, 0), new Point(1, 0), new Point(1, 1) };
273+
static private readonly int[] _indices = new int[] { 0, 2, 1, 0, 3, 2 };
274+
static private readonly Vector3D _xAxis = new Vector3D(1, 0, 0);
275+
static private readonly Vector3D _yAxis = new Vector3D(0, 1, 0);
276+
static private readonly Vector3D _zAxis = new Vector3D(0, 0, 1);
277+
278+
#endregion
279+
}
280+
281+
282+
}

MaterialDesignThemes.Wpf/MaterialDesignThemes.Wpf.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -305,6 +305,7 @@
305305
<Compile Include="SnackbarMessageQueueItem.cs" />
306306
<Compile Include="Transitions\CircleWipe.cs" />
307307
<Compile Include="IHintProxy.cs" />
308+
<Compile Include="Transitions\FlipWipe.cs" />
308309
<Compile Include="Transitions\IndexedItemOffsetMultiplierExtension.cs" />
309310
<Compile Include="Transitions\ITransitionEffect.cs" />
310311
<Compile Include="Transitions\ITransitionEffectSubject.cs" />
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Text;
5+
using System.Threading.Tasks;
6+
using System.Windows;
7+
8+
namespace MaterialDesignThemes.Wpf.Transitions
9+
{
10+
public class FlipWipe : ITransitionWipe
11+
{
12+
public void Wipe(TransitionerSlide fromSlide, TransitionerSlide toSlide, Point origin, IZIndexController zIndexController)
13+
{
14+
15+
}
16+
}
17+
}

0 commit comments

Comments
 (0)