/// <summary/> protected override void BeginTransition(TransitionEventArgs e) { AddBackSnapshot(e); AddFrontSnapshot(e); var prop = (Direction.IsHorizontal() ? TranslateTransform.XProperty : TranslateTransform.YProperty); var value = 0.0; switch (Direction) { case MoveDirection.Up: value = -e.Bounds.Height; break; case MoveDirection.Down: value = +e.Bounds.Height; break; case MoveDirection.Left: value = -e.Bounds.Width; break; case MoveDirection.Right: value = +e.Bounds.Width; break; } var txBack = new TranslateTransform(); txBack.SetValue(prop, 0.0); e.BackSnapshot.RenderTransform = txBack; AddAnimation(e, txBack, prop, 0.0, value); var txFront = new TranslateTransform(); txFront.SetValue(prop, -value); e.FrontSnapshot.RenderTransform = txFront; AddAnimation(e, txFront, prop, -value, 0.0); }
/// <summary/> protected override void BeginTransition(TransitionEventArgs e) { if (Direction == FadeDirection.FadeIn) { AddBackSnapshot(e); AddFrontSnapshot(e); AddAnimation(e, e.FrontSnapshot, FrameworkElement.OpacityProperty, 0.0, 1.0); } else { AddFrontSnapshot(e); AddBackSnapshot(e); AddAnimation(e, e.BackSnapshot, FrameworkElement.OpacityProperty, 1.0, 0.0); } }
/// <summary>Adds a 3D viewport to the transition panel.</summary> protected Viewport3D AddViewport3D(TransitionEventArgs e) { var panel = (TransitionPanel)e.Source; var viewport = new Viewport3D(); viewport.IsHitTestVisible = false; viewport.Camera = CreateCamera(panel, FieldOfView); viewport.ClipToBounds = false; ModelVisual3D light = new ModelVisual3D(); light.Content = Light; viewport.Children.Add(light); panel.Children.Add(viewport); return viewport; }
/// <summary/> protected override void BeginTransition(TransitionEventArgs e) { AddFrontSnapshot(e); var viewport = AddViewport3D(e); var panel = (TransitionPanel)e.Source; var size = panel.RenderSize; // Create a rectangle MeshGeometry3D mesh = CreateMesh(new Point3D(), new Vector3D(size.Width, 0, 0), new Vector3D(0, size.Height, 0), 1, 1, new Rect(0, 0, 1, 1)); GeometryModel3D geometry = new GeometryModel3D(); geometry.Geometry = mesh; var cloneBrush = ToBrush(e.BackSnapshot); geometry.Material = new DiffuseMaterial(cloneBrush); ModelVisual3D model = new ModelVisual3D(); model.Content = geometry; viewport.Children.Add(model); Vector3D axis; Point3D center = new Point3D(); switch (Direction) { case MoveDirection.Left: axis = new Vector3D(0, 1, 0); break; case MoveDirection.Right: axis = new Vector3D(0, -1, 0); center = new Point3D(size.Width, 0, 0); break; case MoveDirection.Up: axis = new Vector3D(-1, 0, 0); break; default: axis = new Vector3D(1, 0, 0); center = new Point3D(0, size.Height, 0); break; } AxisAngleRotation3D rotation = new AxisAngleRotation3D(axis, 0); model.Transform = new RotateTransform3D(rotation, center); AddAnimation(e, rotation, AxisAngleRotation3D.AngleProperty, 90); AddAnimation(e, cloneBrush, Brush.OpacityProperty, 0); }
/// <summary/> protected override void BeginTransition(TransitionEventArgs e) { AddFrontSnapshot(e); var viewport = AddViewport3D(e); var panel = (TransitionPanel)e.Source; var cloneBrush = ToBrush(e.BackSnapshot); Size size = panel.RenderSize; MeshGeometry3D leftDoor = CreateMesh(new Point3D(), new Vector3D(size.Width / 2, 0, 0), new Vector3D(0, size.Height, 0), 1, 1, new Rect(0, 0, 0.5, 1)); GeometryModel3D leftDoorGeometry = new GeometryModel3D(); leftDoorGeometry.Geometry = leftDoor; leftDoorGeometry.Material = new DiffuseMaterial(cloneBrush); AxisAngleRotation3D leftRotation = new AxisAngleRotation3D(new Vector3D(0, 1, 0), 0); leftDoorGeometry.Transform = new RotateTransform3D(leftRotation); GeometryModel3D rightDoorGeometry = new GeometryModel3D(); MeshGeometry3D rightDoor = CreateMesh(new Point3D(size.Width / 2, 0, 0), new Vector3D(size.Width / 2, 0, 0), new Vector3D(0, size.Height, 0), 1, 1, new Rect(0.5, 0, 0.5, 1)); rightDoorGeometry.Geometry = rightDoor; rightDoorGeometry.Material = new DiffuseMaterial(cloneBrush); AxisAngleRotation3D rightRotation = new AxisAngleRotation3D(new Vector3D(0, 1, 0), 0); rightDoorGeometry.Transform = new RotateTransform3D(rightRotation, size.Width, 0, 0); Model3DGroup doors = new Model3DGroup(); doors.Children.Add(leftDoorGeometry); doors.Children.Add(rightDoorGeometry); ModelVisual3D model = new ModelVisual3D(); model.Content = doors; viewport.Children.Add(model); AddAnimation(e, leftRotation, AxisAngleRotation3D.AngleProperty, 90 - 0.5 * FieldOfView); AddAnimation(e, rightRotation, AxisAngleRotation3D.AngleProperty, -(90 - 0.5 * FieldOfView)); AddAnimation(e, cloneBrush, Brush.OpacityProperty, 0); }
/// <summary/> protected override void BeginTransition(TransitionEventArgs e) { var viewport = AddViewport3D(e); var panel = (TransitionPanel)e.Source; var size = panel.RenderSize; Point3D origin = new Point3D(); // origin of 2nd face Vector3D u = new Vector3D(), v = new Vector3D(); // u & v vectors of 2nd face double angleRads = Angle.ToRadians(); double halfAngleRads = (Angle / 2).ToRadians(); Point3D rotationCenter; Vector3D rotationAxis; TranslateTransform3D translation = null; if (Direction.IsHorizontal()) { var RTL = (Direction == MoveDirection.Left); if (IsContained) { rotationCenter = new Point3D(RTL ? size.Width : 0, 0, 0); translation = new TranslateTransform3D(); DoubleAnimation x = new DoubleAnimation(RTL ? -size.Width : size.Width, Duration); translation.BeginAnimation(TranslateTransform3D.OffsetXProperty, x); } else { rotationCenter = new Point3D(size.Width / 2, 0, size.Width / 2 * Math.Tan(halfAngleRads)); } rotationAxis = new Vector3D(0, 1, 0); if (RTL) { u.X = -size.Width * Math.Cos(angleRads); u.Z = size.Width * Math.Sin(angleRads); origin.X = size.Width; } else { u.X = -size.Width * Math.Cos(angleRads); u.Z = -size.Width * Math.Sin(angleRads); origin.X = -u.X; origin.Z = -u.Z; } v.Y = size.Height; } else { var BTT = (Direction == MoveDirection.Up); if (IsContained) { rotationCenter = new Point3D(0, BTT ? size.Height : 0, 0); translation = new TranslateTransform3D(); DoubleAnimation y = new DoubleAnimation(BTT ? -size.Height : size.Height, Duration); translation.BeginAnimation(TranslateTransform3D.OffsetYProperty, y); } else { rotationCenter = new Point3D(0, size.Height / 2, size.Height / 2 * Math.Tan(halfAngleRads)); } rotationAxis = new Vector3D(1, 0, 0); if (BTT) { v.Y = -size.Height * Math.Cos(angleRads); v.Z = size.Height * Math.Sin(angleRads); origin.Y = size.Height; } else { v.Y = -size.Height * Math.Cos(angleRads); v.Z = -size.Height * Math.Sin(angleRads); origin.Y = -v.Y; origin.Z = -v.Z; } u.X = size.Width; } double endAngle = 180 - Angle; if (Direction == MoveDirection.Right || Direction == MoveDirection.Up) { endAngle = -endAngle; } var m1 = _createSide(e, e.BackSnapshot, new Point3D(), new Vector3D(size.Width, 0, 0), new Vector3D(0, size.Height, 0), endAngle, rotationCenter, rotationAxis); var m2 = _createSide(e, e.FrontSnapshot, origin, u, v, endAngle, rotationCenter, rotationAxis); viewport.Children.Add(m1); viewport.Children.Add(m2); m1.Transform = m2.Transform = translation; }
private ModelVisual3D _createSide(TransitionEventArgs e, Image snapshot, Point3D origin, Vector3D u, Vector3D v, double endAngle, Point3D rotationCenter, Vector3D rotationAxis) { var sideMesh = CreateMesh(origin, u, v, 1, 1, new Rect(0, 0, 1, 1)); var sideModel = new GeometryModel3D(); sideModel.Geometry = sideMesh; var cloneBrush = ToBrush(snapshot); sideModel.Material = new DiffuseMaterial(cloneBrush); var rotation = new AxisAngleRotation3D(rotationAxis, 0); sideModel.Transform = new RotateTransform3D(rotation, rotationCenter); AddAnimation(e, rotation, AxisAngleRotation3D.AngleProperty, endAngle); var side = new ModelVisual3D(); side.Content = sideModel; return side; }
/// <summary/> protected override void BeginTransition(TransitionEventArgs e) { AddFrontSnapshot(e); var viewport = AddViewport3D(e); var panel = (TransitionPanel)e.Source; var width = panel.ActualWidth; var height = panel.ActualHeight; if (!width.IsPositive() || !height.IsPositive()) { CompleteTransition(e); return; } var xparticles = (width > height ? MeshGranularity : (int)(MeshGranularity * width / height)); var yparticles = (width > height ? (int)(MeshGranularity * height / width) : MeshGranularity); var mesh = CreateMesh(new Point3D(), new Vector3D(width, 0, 0), new Vector3D(0, height, 0), xparticles - 1, yparticles - 1, new Rect(0, 0, 1, 1)); var cloneBrush = ToBrush(e.BackSnapshot); var cloneMaterial = new DiffuseMaterial(cloneBrush); var ustep = width / (xparticles - 1); var vstep = height / (yparticles - 1); var points = mesh.Positions; var rand = new Random(); // add some random movement to the z order for (int i = 0; i < points.Count; i++) { points[i] += 0.1 * ustep * (rand.NextDouble() * 2 - 1) * new Vector3D(0, 0, 1); } var oldPoints = points.Clone(); // TODO: Respect the duration property var timeStep = 1 / 60.0; var timer = new DispatcherTimer(); timer.Interval = TimeSpan.FromSeconds(timeStep/2); bool fading = false; double time = 0; double slideVelocity = width / 2.0; double windScale = 30 * width * height; Vector3D acceleration = new Vector3D(0, 700, 0); //gravity timer.Tick += delegate { time = time + timeStep; Point mousePos = Mouse.GetPosition(viewport); Point3D mousePos3D = new Point3D(mousePos.X, mousePos.Y, -10); // Cloth physics based on work of Thomas Jakobsen http://www.teknikus.dk/tj/gdc2001.htm for (int i = 0; i < oldPoints.Count; i++) { Point3D currentPoint = points[i]; Vector3D wind = new Vector3D(0, 0, windScale / (mousePos3D - currentPoint).LengthSquared); Point3D newPoint = currentPoint + (currentPoint - oldPoints[i]) + timeStep * timeStep * (acceleration + wind); if (newPoint.Y > height) newPoint.Y = height; oldPoints[i] = newPoint; } for (int i = oldPoints.Count - 1; i > 0; i--) { // constrain with point to the left if (i > yparticles) _constrain(oldPoints, i, i - yparticles, ustep); // constrain with point to the top if (i % yparticles != 0) _constrain(oldPoints, i, i - 1, vstep); } // slide the top row of points to the left for (int i = 0; i < xparticles; i += 1) { oldPoints[i * yparticles] = new Point3D((i * ustep - slideVelocity * time * i / (xparticles - 1)).Max(0), 0, 0); } if (!fading && points[points.Count - yparticles].X < width / 2) { fading = true; DoubleAnimation da = new DoubleAnimation(0, new Duration(TimeSpan.FromSeconds(1.0))); da.Completed += delegate { timer.Stop(); CompleteTransition(e); }; cloneBrush.BeginAnimation(Brush.OpacityProperty, da); } // Swap position arrays mesh.Positions = oldPoints; oldPoints = points; points = mesh.Positions; }; GeometryModel3D geo = new GeometryModel3D(mesh, cloneMaterial); geo.BackMaterial = cloneMaterial; ModelVisual3D model = new ModelVisual3D(); model.Content = geo; viewport.Children.Add(model); AddAnimation(e, timer); }
// completes an animated transition private void _onCompleteAnimatedTransition(TransitionEventArgs transitionData) { if (transitionData == null || transitionData != _transitionData) return; // remove any visual children added for the transition for (var i = Children.Count - 1; i > 1; i--) { Children.RemoveAt(i); } // restore the front/back layers and cleanup _transitionData = null; InTransition = false; BackLayer.Content = null; FrontLayer.Show(); BackLayer.Show(); CoerceValue(ClipToBoundsProperty); // raise the transition completed event var completedArgs = new TransitionEventArgs(TransitionPanel.TransitionCompletedEvent, this) { OldContent = transitionData.OldContent, NewContent = transitionData.NewContent }; RaiseEvent(completedArgs); }
// begins an animated self transition private void _beginAnimatedSelfTransition(Transition transition, Action onComplete) { InTransition = true; CoerceValue(ClipToBoundsProperty); _transitionData = new TransitionEventArgs(TransitionPanel.TransitionStartedEvent, this) { Bounds = RenderSize, OldContent = FrontLayer.Content, NewContent = FrontLayer.Content, Transition = transition }; _transitionData.BackSnapshot = _selfTransitionSnapshot; _transitionData.FrontSnapshot = _captureSnapshot(FrontLayer, true); _transitionData.OnCompleteCallback = () => { _onCompleteAnimatedTransition(_transitionData); if (onComplete != null) onComplete(); }; RaiseEvent(_transitionData); transition.InvokeBeginTransition(_transitionData); }
// begins an animated transition private void _beginAnimatedTransition(Transition transition, Action onComplete) { // swap the front and back layers (without adding and removing them from the visual tree to avoid superfluous loaded/unloaded events) _flipLayers = !_flipLayers; // set the front layer's content FrontLayer.Content = Content; FrontLayer.ContentTemplate = ContentTemplate; FrontLayer.ContentTemplateSelector = ContentTemplateSelector; // start the transition from back layer to front layer InTransition = true; CoerceValue(ClipToBoundsProperty); _transitionData = new TransitionEventArgs(TransitionPanel.TransitionStartedEvent, this) { Bounds = RenderSize, OldContent = BackLayer.Content, NewContent = FrontLayer.Content, Transition = transition }; _transitionData.OnCompleteCallback = () => { _onCompleteAnimatedTransition(_transitionData); if (onComplete != null) onComplete(); }; Action invokeTransition = () => { _transitionData.BackSnapshot = _captureSnapshot(BackLayer, true); _transitionData.FrontSnapshot = _captureSnapshot(FrontLayer, true); transition.InvokeBeginTransition(_transitionData); }; RaiseEvent(_transitionData); if ((Content is DependencyObject) && GetHasNestedTransitionPanel((DependencyObject)Content)) { // if content has a nested transition panel, use a timer to allow the nested transition panel to draw its initial state before the // enclosing transition is started to avoid seeing a blank panel during the transition var timer = new GuiTimer(DispatcherPriority.Background); timer.Start(t => invokeTransition()); } else { invokeTransition(); } }
/// <summary/> protected override void BeginTransition(TransitionEventArgs e) { CompleteTransition(e); }
/// <summary/> protected override void BeginTransition(TransitionEventArgs e) { AddFrontSnapshot(e); var viewport = AddViewport3D(e); var panel = (TransitionPanel)e.Source; var width = panel.ActualWidth; var height = panel.ActualHeight; if (!width.IsPositive() || !height.IsPositive()) { CompleteTransition(e); return; } var xparticles = (width > height ? MeshGranularity : (int)(MeshGranularity * width / height)); var yparticles = (width > height ? (int)(MeshGranularity * height / width) : MeshGranularity); var mesh = CreateMesh(new Point3D(), new Vector3D(width, 0, 0), new Vector3D(0, height, 0), xparticles - 1, yparticles - 1, new Rect(0, 0, 1, 1)); var cloneBrush = ToBrush(e.BackSnapshot); var cloneMaterial = new DiffuseMaterial(cloneBrush); double ustep = width / (xparticles - 1), vstep = height / (yparticles - 1); var points = mesh.Positions; var oldPoints = points.Clone(); double time = 0; double duration = Duration.TotalSeconds; double timeStep = 1.0 / 30.0; DispatcherTimer timer = new DispatcherTimer(); timer.Interval = TimeSpan.FromSeconds(timeStep * (duration / 2.0)); timer.Tick += delegate { time = time + timeStep; Point mousePos = Mouse.GetPosition(viewport); Point3D mousePos3D = new Point3D(mousePos.X, mousePos.Y, -10); // Cloth physics based on work of Thomas Jakobsen http://www.ioi.dk/~thomas for (int i = 0; i < oldPoints.Count; i++) { Point3D currentPoint = points[i]; Point3D newPoint = currentPoint + 0.9 * (currentPoint - oldPoints[i]); if (newPoint.Y > height) newPoint.Y = height; oldPoints[i] = newPoint; } for (int a = yparticles - 1; a >= 0; a--) for (int b = xparticles - 1; b >= 0; b--) { int i = b * yparticles + a; // constrain with point to the left if (i > yparticles) { _constrain(oldPoints, i, i - yparticles, ustep); } // constrain with point to the top if (i % yparticles != 0) { _constrain(oldPoints, i, i - 1, vstep); } // constrain the sides if (a == 0) { oldPoints[i] = new Point3D(oldPoints[i].X, 0, oldPoints[i].Z); } if (a == yparticles - 1) { oldPoints[i] = new Point3D(oldPoints[i].X, height, oldPoints[i].Z); } if (b == 0) { oldPoints[i] = new Point3D(0, a * height / (yparticles - 1), 0); } if (b == xparticles - 1) { double angle = time / duration * Math.PI / (0.8 + 0.5 * (yparticles - (double)a) / yparticles); oldPoints[i] = new Point3D(width * Math.Cos(angle), a * height / (yparticles - 1), -width * Math.Sin(angle)); } } if (time > duration) { timer.Stop(); CompleteTransition(e); } // Swap position arrays mesh.Positions = oldPoints; oldPoints = points; points = mesh.Positions; }; GeometryModel3D geo = new GeometryModel3D(mesh, cloneMaterial); geo.BackMaterial = cloneMaterial; ModelVisual3D model = new ModelVisual3D(); model.Content = geo; viewport.Children.Add(model); AddAnimation(e, timer); }
/// <summary/> protected override void CompleteTransition(TransitionEventArgs e) { Storyboard oldStoryboard = (Storyboard)e.BackSnapshot.GetValue(OldContentStoryboardProperty); if (oldStoryboard != null) oldStoryboard.Stop(e.BackSnapshot); e.BackSnapshot.ClearValue(FrameworkElement.StyleProperty); Storyboard newStoryboard = (Storyboard)e.FrontSnapshot.GetValue(NewContentStoryboardProperty); if (newStoryboard != null) newStoryboard.Stop(e.FrontSnapshot); e.FrontSnapshot.ClearValue(FrameworkElement.StyleProperty); base.CompleteTransition(e); }
/// <summary/> protected override void BeginTransition(TransitionEventArgs e) { var oldStoryboard = OldContentStoryboard; var newStoryboard = NewContentStoryboard; if (NewContentOnTop) { AddFrontSnapshot(e); AddBackSnapshot(e); } else { AddBackSnapshot(e); AddFrontSnapshot(e); } if (oldStoryboard != null || newStoryboard != null) { e.BackSnapshot.Style = OldContentStyle; e.FrontSnapshot.Style = NewContentStyle; // Flag to determine when both storyboards are done bool done = oldStoryboard == null || newStoryboard == null; if (oldStoryboard != null) { oldStoryboard = oldStoryboard.Clone(); e.BackSnapshot.SetValue(OldContentStoryboardProperty, oldStoryboard); oldStoryboard.Completed += delegate { if (done) CompleteTransition(e); done = true; }; oldStoryboard.Begin(e.BackSnapshot, true); } if (newStoryboard != null) { newStoryboard = newStoryboard.Clone(); e.FrontSnapshot.SetValue(NewContentStoryboardProperty, newStoryboard); newStoryboard.Completed += delegate { if (done) CompleteTransition(e); done = true; }; newStoryboard.Begin(e.FrontSnapshot, true); } } else { CompleteTransition(e); } }