Code:
/ Dotnetfx_Win7_3.5.1 / Dotnetfx_Win7_3.5.1 / 3.5.1 / DEVDIV / depot / DevDiv / releases / Orcas / NetFXw7 / wpf / src / Core / CSharp / System / Windows / Media3D / Viewport3DVisual.cs / 1 / Viewport3DVisual.cs
//---------------------------------------------------------------------------- // //// Copyright (C) Microsoft Corporation. All rights reserved. // // //--------------------------------------------------------------------------- using MS.Internal; using MS.Internal.Media; using MS.Internal.Media3D; using System; using System.ComponentModel; using System.ComponentModel.Design.Serialization; using System.Diagnostics; using System.Windows; using System.Windows.Media; using System.Windows.Media.Composition; using System.Windows.Markup; using System.Windows.Media.Effects; using MS.Internal.PresentationCore; using SR=MS.Internal.PresentationCore.SR; using SRID=MS.Internal.PresentationCore.SRID; namespace System.Windows.Media.Media3D { ////// The Viewport3DVisual provides the Camera and viewport Rect /// required to project the Visual3Ds into 2D. The Viewport3DVisual /// is the bridge between 2D visuals and 3D. /// [ContentProperty("Children")] public sealed class Viewport3DVisual : Visual, DUCE.IResource, IVisual3DContainer { //----------------------------------------------------- // // Constructors // //----------------------------------------------------- ////// Default constructor /// public Viewport3DVisual() : base(DUCE.ResourceType.TYPE_VIEWPORT3DVISUAL) { _children = new Visual3DCollection(this); } //------------------------------------------------------ // // Public Methods // //----------------------------------------------------- #region Public Methods // ------------------------------------------------------------------------------------------ // Publicly re-exposed VisualTreeHelper interfaces. // // Note that we do not want to expose the Children property on Viewport3DVisual // since the Viewport3DVisual provides its own set of Visual3D children. // ------------------------------------------------------------------------------------------ ////// Re-exposes the Visual base class's corresponding VisualTreeHelper implementation as public method. /// public DependencyObject Parent { get { return base.VisualParent; } } ////// Re-exposes the Visual base class's corresponding VisualTreeHelper implementation as public method. /// public Geometry Clip { get { return base.VisualClip; } set { base.VisualClip = value; } } ////// Re-exposes the Visual base class's corresponding VisualTreeHelper implementation as public method. /// public double Opacity { get { return base.VisualOpacity; } set { base.VisualOpacity = value; } } ////// Re-exposes the Visual base class's corresponding VisualTreeHelper implementation as public method. /// public Brush OpacityMask { get { return base.VisualOpacityMask; } set { base.VisualOpacityMask = value; } } ////// Re-exposes the Visual base class's corresponding VisualTreeHelper implementation as public method. /// [Obsolete(MS.Internal.Media.VisualTreeUtils.BitmapEffectObsoleteMessage)] public BitmapEffect BitmapEffect { get { return base.VisualBitmapEffect; } set { base.VisualBitmapEffect = value; } } ////// Re-exposes the Visual base class's corresponding VisualTreeHelper implementation as public method. /// [Obsolete(MS.Internal.Media.VisualTreeUtils.BitmapEffectObsoleteMessage)] public BitmapEffectInput BitmapEffectInput { get { return base.VisualBitmapEffectInput; } set { base.VisualBitmapEffectInput = value; } } ////// Re-exposes the Visual base class's corresponding VisualTreeHelper implementation as public method. /// new public HitTestResult HitTest(Point point) { return base.HitTest(point); } ////// Re-exposes the Visual base class's corresponding VisualTreeHelper implementation as public method. /// new public void HitTest(HitTestFilterCallback filterCallback, HitTestResultCallback resultCallback, HitTestParameters hitTestParameters) { base.HitTest(filterCallback, resultCallback, hitTestParameters); } ////// VisualContentBounds returns the bounding box for the contents of this Visual. /// public Rect ContentBounds { get { return base.VisualContentBounds; } } ////// Gets or sets the Transform property. /// public Transform Transform { get { return base.VisualTransform; } set { base.VisualTransform = value; } } ////// Gets or sets the Offset property. /// public Vector Offset { get { return base.VisualOffset; } set { base.VisualOffset = value; } } ////// DescendantBounds returns the union of all of the content bounding /// boxes for all of the descendants of the current visual, but not including /// the contents of the current visual. /// public Rect DescendantBounds { get { return base.VisualDescendantBounds; } } #endregion Public Methods //----------------------------------------------------- // // Public Properties // //------------------------------------------------------ #region Public Properties ////// DependencyProperty which backs the ModelVisual3D.Camera property. /// public static readonly DependencyProperty CameraProperty = DependencyProperty.Register( "Camera", /* propertyType = */ typeof(Camera), /* ownerType = */ typeof(Viewport3DVisual), new PropertyMetadata( FreezableOperations.GetAsFrozen(new PerspectiveCamera()), CameraPropertyChanged), (ValidateValueCallback) delegate { return MediaContext.CurrentMediaContext.WriteAccessEnabled; }); private static void CameraPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { Viewport3DVisual owner = ((Viewport3DVisual) d); if (!e.IsASubPropertyChange) { if (e.OldValue != null) { owner.DisconnectAttachedResource( VisualProxyFlags.Viewport3DVisual_IsCameraDirty, ((DUCE.IResource) e.OldValue)); } owner.SetFlagsOnAllChannels(true, VisualProxyFlags.Viewport3DVisual_IsCameraDirty | VisualProxyFlags.IsContentDirty); } owner.ContentsChanged(/* sender = */ owner, EventArgs.Empty); } ////// Camera for this Visual3D. /// public Camera Camera { get { return (Camera) GetValue(CameraProperty); } set { SetValue(CameraProperty, value); } } ////// DependencyProperty which backs the ModelVisual3D.Viewport property. /// public static readonly DependencyProperty ViewportProperty = DependencyProperty.Register( "Viewport", /* propertyType = */ typeof(Rect), /* ownerType = */ typeof(Viewport3DVisual), new PropertyMetadata(Rect.Empty, ViewportPropertyChanged), (ValidateValueCallback) delegate { return MediaContext.CurrentMediaContext.WriteAccessEnabled; }); private static void ViewportPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { Viewport3DVisual owner = ((Viewport3DVisual) d); Debug.Assert(!e.IsASubPropertyChange, "How are we receiving sub property changes from a struct?"); owner.SetFlagsOnAllChannels(true, VisualProxyFlags.Viewport3DVisual_IsViewportDirty | VisualProxyFlags.IsContentDirty); owner.ContentsChanged(/* sender = */ owner, EventArgs.Empty); } ////// Viewport for this Visual3D. /// public Rect Viewport { get { return (Rect) GetValue(ViewportProperty); } set { SetValue(ViewportProperty, value); } } ////// The 3D children to be projected by this Viewport3DVisual. /// [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)] public Visual3DCollection Children { get { return _children; } } #endregion Public Properties //----------------------------------------------------- // // Public Events // //----------------------------------------------------- //----------------------------------------------------- // // Protected Methods // //------------------------------------------------------ //----------------------------------------------------- // // Internal Methods // //------------------------------------------------------ #region Internal Methods // CS0536: Intreface implementation must be public or explicit so we re-expose // the internal methods as an explicit implementation of an internal interface. void IVisual3DContainer.VerifyAPIReadOnly() { this.VerifyAPIReadOnly(); } void IVisual3DContainer.VerifyAPIReadOnly(DependencyObject other) { this.VerifyAPIReadOnly(other); } void IVisual3DContainer.VerifyAPIReadWrite() { this.VerifyAPIReadWrite(); } void IVisual3DContainer.VerifyAPIReadWrite(DependencyObject other) { this.VerifyAPIReadWrite(other); } // NOTE: The code here is highly similar to AddChildCore in ModelVisual3D, // but slightly different because the parent is 2D here. void IVisual3DContainer.AddChild(Visual3D child) { // It is invalid to modify the children collection that we // might be iterating during a property invalidation tree walk. if (IsVisualChildrenIterationInProgress) { throw new InvalidOperationException(SR.Get(SRID.CannotModifyVisualChildrenDuringTreeWalk)); } Debug.Assert(child != null); Debug.Assert(child.InternalVisualParent == null); child.SetParent(this); // set the inheritance context so databinding, etc... work if (_inheritanceContextForChildren != null) { _inheritanceContextForChildren.ProvideSelfAsInheritanceContext(child, null); } SetFlagsOnAllChannels(true, VisualProxyFlags.IsContentDirty); // The child already might be dirty. Hence we need to propagate dirty information // from the parent and from the child. Visual.PropagateFlags( this, VisualFlags.IsSubtreeDirtyForPrecompute | VisualFlags.NodeNeedsBitmapEffectUpdate, VisualProxyFlags.IsSubtreeDirtyForRender); Visual3D.PropagateFlags( child, VisualFlags.IsSubtreeDirtyForPrecompute, VisualProxyFlags.IsSubtreeDirtyForRender); // // Fire notifications OnVisualChildrenChanged(child, /* visualRemoved = */ null); child.FireOnVisualParentChanged(null); } // NOTE: The code here is highly similar to RemoveChildCore in ModelVisual3D, // but slightly different because the parent is 2D here. void IVisual3DContainer.RemoveChild(Visual3D child) { int index = child.ParentIndex; // It is invalid to modify the children collection that we // might be iterating during a property invalidation tree walk. if (IsVisualChildrenIterationInProgress) { throw new InvalidOperationException(SR.Get(SRID.CannotModifyVisualChildrenDuringTreeWalk)); } Debug.Assert(child != null); Debug.Assert(child.InternalVisualParent == this); child.SetParent(/* newParent = */ (Visual) null); // CS0121: Call is ambigious without casting null to Visual. // remove the inheritance context if (_inheritanceContextForChildren != null) { _inheritanceContextForChildren.RemoveSelfAsInheritanceContext(child, null); } // // Remove the child on all channels this visual is marshalled to. // for (int i = 0, limit = _proxy3D.Count; i < limit; i++) { DUCE.Channel channel = _proxy3D.GetChannel(i); if (child.CheckFlagsAnd(channel, VisualProxyFlags.IsConnectedToParent)) { channel.AddToRemoveAndReleaseQueue( this, child); child.SetFlags(channel, false, VisualProxyFlags.IsConnectedToParent); } } SetFlagsOnAllChannels(true, VisualProxyFlags.IsContentDirty); // // Force a full precompute and render pass for this visual. // Visual.PropagateFlags( this, VisualFlags.IsSubtreeDirtyForPrecompute | VisualFlags.NodeNeedsBitmapEffectUpdate, VisualProxyFlags.IsSubtreeDirtyForRender); // child.FireOnVisualParentChanged(this); OnVisualChildrenChanged(/* visualAdded = */ null , child); } ////// Gets the number of Visual3D children that the IVisual3DContainer /// contains. /// int IVisual3DContainer.GetChildrenCount() { return InternalVisual2DOr3DChildrenCount; } ////// Gets the index children of the IVisual3DContainer /// Visual3D IVisual3DContainer.GetChild(int index) { return (Visual3D)InternalGet2DOr3DVisualChild(index); } ////// Returns the number of children of this object (in most cases this will be /// the number of Visuals, but it some cases, Viewport3DVisual for instance, /// this is the number of Visual3Ds). /// /// Used only by VisualTreeHelper. /// internal override int InternalVisual2DOr3DChildrenCount { get { return Children.Count; } } ////// Used only by VisualTreeHelper. /// /// Returns the child at index "index" (in most cases this will be /// a Visual, but it some cases, Viewport3DVisual, for instance, /// this is a Visual3D). /// internal override DependencyObject InternalGet2DOr3DVisualChild(int index) { return Children[index]; } internal override HitTestResultBehavior HitTestPointInternal( HitTestFilterCallback filterCallback, HitTestResultCallback resultCallback, PointHitTestParameters hitTestParameters) { if (_children.Count != 0) { double distanceAdjustment; RayHitTestParameters rayParams = Camera.RayFromViewportPoint( hitTestParameters.HitPoint, Viewport.Size, BBoxSubgraph, out distanceAdjustment); HitTestResultBehavior result = Visual3D.HitTestChildren(filterCallback, rayParams, this); return rayParams.RaiseCallback(resultCallback, filterCallback, result, distanceAdjustment); } return HitTestResultBehavior.Continue; } ////// Viewport3DVisual does not yet support Geometry hit testing. /// protected override GeometryHitTestResult HitTestCore(GeometryHitTestParameters hitTestParameters) { throw new NotSupportedException(SR.Get(SRID.HitTest_Invalid, typeof(GeometryHitTestParameters).Name, this.GetType().Name)); } internal Point WorldToViewport(Point4D point) { double aspectRatio = M3DUtil.GetAspectRatio(Viewport.Size); Camera camera = Camera; if (camera != null) { Matrix3D viewProjMatrix = camera.GetViewMatrix() * camera.GetProjectionMatrix(aspectRatio); point *= viewProjMatrix; Point point2D = new Point(point.X/point.W, point.Y/point.W); point2D *= M3DUtil.GetHomogeneousToViewportTransform(Viewport); return point2D; } else { return new Point(0,0); } } ////// Derived classes return the hit-test bounding box from the /// GetHitTestBounds virtual. Visual uses the bounds to optimize /// hit-testing. /// internal override Rect GetHitTestBounds() { return CalculateSubgraphBoundsInnerSpace(); } internal override Rect CalculateSubgraphBoundsInnerSpace(bool renderBounds) { Camera camera = Camera; if (camera == null) { return Rect.Empty; } // // Cache the 3D bounding box for future use. Here we are relying on // the fact that this method is called by PrecomputeContent(), // which is called prior to all usages of _bboxChildrenSubgraph3D. // _bboxChildrenSubgraph3D = ComputeSubgraphBounds3D(); if (_bboxChildrenSubgraph3D.IsEmpty) { // Attempting to project empty bounds will result in NaNs which // which will ruin descendant bounds for the 2D tree. We handle // this explicitly and early exit with the correct answer. return Rect.Empty; } Rect viewport = Viewport; // Common Case: Viewport3DVisual in a collasped UIElement. if (viewport.IsEmpty) { // Creating a 3D homogenous space to 2D viewport space transform // with an empty rectangle will result in NaNs which ruin the // descendant bounds for the 2D tree. We handle this explicitly // and early exit with the correct answer. // // (See also Windows OS Bugs #1637618) return Rect.Empty; } double aspectRatio = M3DUtil.GetAspectRatio(viewport.Size); Matrix3D viewProjMatrix = camera.GetViewMatrix() * camera.GetProjectionMatrix(aspectRatio); Rect projectedBounds2D = MILUtilities.ProjectBounds(ref viewProjMatrix, ref _bboxChildrenSubgraph3D); Matrix ----ToLocal = M3DUtil.GetHomogeneousToViewportTransform(viewport); MatrixUtil.TransformRect(ref projectedBounds2D, ref ----ToLocal); return projectedBounds2D; } // // NOTE: Must only be called after PrecomputeContent(). // private Rect3D BBoxSubgraph { get { Debug_VerifyCachedSubgraphBounds(); return _bboxChildrenSubgraph3D; } } internal Rect3D ComputeSubgraphBounds3D() { Rect3D bboxChildrenSubgraph3D = Rect3D.Empty; for (int i = 0, count = _children.InternalCount; i < count; i++) { Visual3D child = _children.InternalGetItem(i); bboxChildrenSubgraph3D.Union(child.CalculateSubgraphBoundsOuterSpace()); } return bboxChildrenSubgraph3D; } [Conditional("DEBUG")] private void Debug_VerifyCachedSubgraphBounds() { Rect3D currentBounds = Rect3D.Empty; currentBounds = ComputeSubgraphBounds3D(); Rect3D cachedBounds = _bboxChildrenSubgraph3D; // The funny boolean logic below avoids asserts when the cached // bounds contain NaNs. (NaN != NaN) bool boundsAreEqual = !(cachedBounds.X < currentBounds.X || cachedBounds.X > currentBounds.X) && !(cachedBounds.Y < currentBounds.Y || cachedBounds.Y > currentBounds.Y) && !(cachedBounds.Z < currentBounds.Z || cachedBounds.Z > currentBounds.Z) && !(cachedBounds.SizeX < currentBounds.SizeX || cachedBounds.SizeX > currentBounds.SizeX) && !(cachedBounds.SizeY < currentBounds.SizeY || cachedBounds.SizeY > currentBounds.SizeY) && !(cachedBounds.SizeZ < currentBounds.SizeZ || cachedBounds.SizeZ > currentBounds.SizeZ); if (!boundsAreEqual) { Debug.Fail("Cached bbox subgraph is incorrect!"); } } internal override DUCE.ResourceHandle AddRefOnChannelCore(DUCE.Channel channel) { DUCE.ResourceHandle handle = base.AddRefOnChannelCore(channel); bool created = _proxy3D.CreateOrAddRefOnChannel(channel, DUCE.ResourceType.TYPE_VISUAL3D); Debug.Assert( _proxy.Count == _proxy3D.Count, "Viewport has been marshalled to a different number of channels than the 3D content."); // If we are creating the Viewport3DVisual/Visual3D for the first // time on this channel we need to connect the 3D root. if (created) { DUCE.Viewport3DVisualNode.Set3DChild( handle, _proxy3D.GetHandle(channel), channel); } return handle; } internal override void ReleaseOnChannelCore(DUCE.Channel channel) { Debug.Assert( _proxy.Count == _proxy3D.Count, "Viewport has been marshalled to a different number of channels than the 3D content."); base.ReleaseOnChannelCore(channel); _proxy3D.ReleaseOnChannel(channel); } int DUCE.IResource.GetChannelCount() { return _proxy.Count; } DUCE.Channel DUCE.IResource.GetChannel(int index) { return _proxy.GetChannel(index); } ////// Precompute pass. /// internal override void PrecomputeContent() { base.PrecomputeContent(); // If any of our children root a 3D subtree which uses realization // caches we need to set NodeUsesRealizationCaches on ourselves. // // NOTE: There is no 2D content on Visual so base.PrecomputeContent() // does not initialize this flag. We start with false. bool subTreeUsesRealizationCaches = false; if (_children != null) { for (int i = 0, count = _children.InternalCount; i < count; i++) { Visual3D child = _children.InternalGetItem(i); if (child != null) { // This merely tells the Visual3Ds to update their bounds // caches if necessary. Later on we'll get the cached bounds // from calling Visual3D.CalculateSubgraphBounds Rect3D bboxSubgraphChildIgnored; child.PrecomputeRecursive(out bboxSubgraphChildIgnored); subTreeUsesRealizationCaches |= child.CheckFlagsAnd(VisualFlags.NodeInSubtreeUsesRealizationCaches); } } } // NOTE: We set NodeUseRealizationCaches rather than // NodeInSubtreeUsesRealizationCaches. This is because we // use UpdateRealizations() on the Viewport3DVisual to bridge // the realization walk into the Visual3D tree. SetFlags(subTreeUsesRealizationCaches, VisualFlags.NodeUsesRealizationCaches); // // If realizations are used in the subtree, they could be glyphs // which may induce multiple pathness. // SetFlags(subTreeUsesRealizationCaches, VisualFlags.NodeOrDescendantIntroducesGraphness); } internal override void RenderContent(RenderContext ctx, bool isOnChannel) { DUCE.Channel channel = ctx.Channel; // // At this point, the visual has to be marshalled. Force // marshalling of the camera and viewport in case we have // just created a new visual resource. // Debug.Assert(IsOnChannel(channel)); VisualProxyFlags flags = _proxy.GetFlags(channel); // // Make sure the camera resource is being marshalled properly. // if ((flags & VisualProxyFlags.Viewport3DVisual_IsCameraDirty) != 0) { Camera camera = Camera; if (camera != null) { DUCE.Viewport3DVisualNode.SetCamera( ((DUCE.IResource)this).GetHandle(channel), ((DUCE.IResource)camera).AddRefOnChannel(channel), channel); } else if (isOnChannel) /* camera == null */ { DUCE.Viewport3DVisualNode.SetCamera( ((DUCE.IResource)this).GetHandle(channel), DUCE.ResourceHandle.Null, channel); } SetFlags(channel, false, VisualProxyFlags.Viewport3DVisual_IsCameraDirty); } // // Set the viewport if it's dirty. // if ((flags & VisualProxyFlags.Viewport3DVisual_IsViewportDirty) != 0) { DUCE.Viewport3DVisualNode.SetViewport( ((DUCE.IResource)this).GetHandle(channel), Viewport, channel); SetFlags(channel, false, VisualProxyFlags.Viewport3DVisual_IsViewportDirty); } //we only want to recurse in the children if the visual does not have a bitmap effect //or we are in the BitmapVisualManager render pass // Visit children of this node ------------------------------------------------------------------------ Debug.Assert(!CheckFlagsAnd(channel, VisualProxyFlags.IsContentNodeConnected), "Only HostVisuals are expected to have a content node."); if (_children != null) { for (uint i = 0; i < _children.InternalCount; i++) { Visual3D child = _children.InternalGetItem((int) i); if (child != null) { if (child.CheckFlagsAnd(channel, VisualProxyFlags.IsSubtreeDirtyForRender) || // or the visual is dirty !(child.IsOnChannel(channel))) // or the child has not been marshalled yet. { child.RenderRecursive(ctx); } if (child.IsOnChannel(channel)) { if (!child.CheckFlagsAnd(channel, VisualProxyFlags.IsConnectedToParent)) { DUCE.Visual3DNode.InsertChildAt( _proxy3D.GetHandle(channel), ((DUCE.IResource)child).GetHandle(channel), /* iPosition = */ i, channel); child.SetFlags(channel, true, VisualProxyFlags.IsConnectedToParent); } } } } } } ////// Override this function in derived classes to release unmanaged resources during Dispose /// and during removal of a subtree. /// internal override void FreeContent(DUCE.Channel channel) { Debug.Assert(IsOnChannel(channel)); Camera camera = Camera; if (camera != null) { if (!CheckFlagsAnd(channel, VisualProxyFlags.Viewport3DVisual_IsCameraDirty)) { ((DUCE.IResource)camera).ReleaseOnChannel(channel); SetFlagsOnAllChannels(true, VisualProxyFlags.Viewport3DVisual_IsCameraDirty); } } if (_children != null) { for (int i = 0; i < _children.InternalCount; i++) { Visual3D visual = _children.InternalGetItem(i); ((DUCE.IResource)visual).ReleaseOnChannel(channel); } } SetFlagsOnAllChannels(true, VisualProxyFlags.IsContentDirty); base.FreeContent(channel); } ////// Called by the base class to update realization caches. /// Updates the realization cache on the scene3d. /// internal override void UpdateRealizations(RealizationContext ctx) { Debug.Assert(CheckFlagsAnd(VisualFlags.NodeUsesRealizationCaches)); Camera camera = Camera; if (camera != null) { // Do not call the base class here because that would kick of an // unnecessary realization pass over the render data content of this // Visual. Matrix3DStack stack3D = ctx.Transform3DStack; // PushWithoutAccumulating to enable nested usage of the Transform3DStack. stack3D.PushWithoutAccumulating(M3DUtil.GetWorldToViewportTransform3D(camera, Viewport)); bool wasIn3DMode = ctx.Set3DMode(true); for (int i = 0; i < _children.InternalCount; i++) { Visual3D child = _children.InternalGetItem(i); if (child.CheckFlagsAnd(VisualFlags.NodeInSubtreeUsesRealizationCaches)) { child.UpdateRealizations(ctx); } } ctx.Set3DMode(wasIn3DMode); stack3D.Pop(); // worldToViewport. } } // Notify the Viewport3DVisual that the Visual3D subtree it hosts // has been modified. internal void Visual3DTreeChanged() { // The Visual3D tree is plugged into the 2D Visual tree via the // same extensibility point we use for "content". SetFlagsOnAllChannels(true, VisualProxyFlags.IsContentDirty); ContentsChanged(/* sender = */ this, EventArgs.Empty); } ////// Returns the handle this visual has on the given channel. /// Note: The 3D handle is obtained from _proxy3D. /// DUCE.ResourceHandle DUCE.IResource.Get3DHandle(DUCE.Channel channel) { return _proxy3D.GetHandle(channel); } // Because 2D Visuals and FEs do not participate in inheritance context // we allow this backdoor for a Viewport3D to set itself as the inheritance // context of the Visual3DCollection it exposes as Children. [FriendAccessAllowed] internal void SetInheritanceContextForChildren(DependencyObject inheritanceContextForChildren) { _inheritanceContextForChildren = inheritanceContextForChildren; } #endregion Internal Methods //----------------------------------------------------- // // Private Fields // //------------------------------------------------------ #region Private Fields ////// The 3D content root. /// ////// Important! - Not readonly because CS will silently copy /// for self-modifying methods. (C# Spec 14.5.4) /// private VisualProxy _proxy3D; private Rect3D _bboxChildrenSubgraph3D; private readonly Visual3DCollection _children; private DependencyObject _inheritanceContextForChildren; #endregion Private Fields } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved. //---------------------------------------------------------------------------- // //// Copyright (C) Microsoft Corporation. All rights reserved. // // //--------------------------------------------------------------------------- using MS.Internal; using MS.Internal.Media; using MS.Internal.Media3D; using System; using System.ComponentModel; using System.ComponentModel.Design.Serialization; using System.Diagnostics; using System.Windows; using System.Windows.Media; using System.Windows.Media.Composition; using System.Windows.Markup; using System.Windows.Media.Effects; using MS.Internal.PresentationCore; using SR=MS.Internal.PresentationCore.SR; using SRID=MS.Internal.PresentationCore.SRID; namespace System.Windows.Media.Media3D { ////// The Viewport3DVisual provides the Camera and viewport Rect /// required to project the Visual3Ds into 2D. The Viewport3DVisual /// is the bridge between 2D visuals and 3D. /// [ContentProperty("Children")] public sealed class Viewport3DVisual : Visual, DUCE.IResource, IVisual3DContainer { //----------------------------------------------------- // // Constructors // //----------------------------------------------------- ////// Default constructor /// public Viewport3DVisual() : base(DUCE.ResourceType.TYPE_VIEWPORT3DVISUAL) { _children = new Visual3DCollection(this); } //------------------------------------------------------ // // Public Methods // //----------------------------------------------------- #region Public Methods // ------------------------------------------------------------------------------------------ // Publicly re-exposed VisualTreeHelper interfaces. // // Note that we do not want to expose the Children property on Viewport3DVisual // since the Viewport3DVisual provides its own set of Visual3D children. // ------------------------------------------------------------------------------------------ ////// Re-exposes the Visual base class's corresponding VisualTreeHelper implementation as public method. /// public DependencyObject Parent { get { return base.VisualParent; } } ////// Re-exposes the Visual base class's corresponding VisualTreeHelper implementation as public method. /// public Geometry Clip { get { return base.VisualClip; } set { base.VisualClip = value; } } ////// Re-exposes the Visual base class's corresponding VisualTreeHelper implementation as public method. /// public double Opacity { get { return base.VisualOpacity; } set { base.VisualOpacity = value; } } ////// Re-exposes the Visual base class's corresponding VisualTreeHelper implementation as public method. /// public Brush OpacityMask { get { return base.VisualOpacityMask; } set { base.VisualOpacityMask = value; } } ////// Re-exposes the Visual base class's corresponding VisualTreeHelper implementation as public method. /// [Obsolete(MS.Internal.Media.VisualTreeUtils.BitmapEffectObsoleteMessage)] public BitmapEffect BitmapEffect { get { return base.VisualBitmapEffect; } set { base.VisualBitmapEffect = value; } } ////// Re-exposes the Visual base class's corresponding VisualTreeHelper implementation as public method. /// [Obsolete(MS.Internal.Media.VisualTreeUtils.BitmapEffectObsoleteMessage)] public BitmapEffectInput BitmapEffectInput { get { return base.VisualBitmapEffectInput; } set { base.VisualBitmapEffectInput = value; } } ////// Re-exposes the Visual base class's corresponding VisualTreeHelper implementation as public method. /// new public HitTestResult HitTest(Point point) { return base.HitTest(point); } ////// Re-exposes the Visual base class's corresponding VisualTreeHelper implementation as public method. /// new public void HitTest(HitTestFilterCallback filterCallback, HitTestResultCallback resultCallback, HitTestParameters hitTestParameters) { base.HitTest(filterCallback, resultCallback, hitTestParameters); } ////// VisualContentBounds returns the bounding box for the contents of this Visual. /// public Rect ContentBounds { get { return base.VisualContentBounds; } } ////// Gets or sets the Transform property. /// public Transform Transform { get { return base.VisualTransform; } set { base.VisualTransform = value; } } ////// Gets or sets the Offset property. /// public Vector Offset { get { return base.VisualOffset; } set { base.VisualOffset = value; } } ////// DescendantBounds returns the union of all of the content bounding /// boxes for all of the descendants of the current visual, but not including /// the contents of the current visual. /// public Rect DescendantBounds { get { return base.VisualDescendantBounds; } } #endregion Public Methods //----------------------------------------------------- // // Public Properties // //------------------------------------------------------ #region Public Properties ////// DependencyProperty which backs the ModelVisual3D.Camera property. /// public static readonly DependencyProperty CameraProperty = DependencyProperty.Register( "Camera", /* propertyType = */ typeof(Camera), /* ownerType = */ typeof(Viewport3DVisual), new PropertyMetadata( FreezableOperations.GetAsFrozen(new PerspectiveCamera()), CameraPropertyChanged), (ValidateValueCallback) delegate { return MediaContext.CurrentMediaContext.WriteAccessEnabled; }); private static void CameraPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { Viewport3DVisual owner = ((Viewport3DVisual) d); if (!e.IsASubPropertyChange) { if (e.OldValue != null) { owner.DisconnectAttachedResource( VisualProxyFlags.Viewport3DVisual_IsCameraDirty, ((DUCE.IResource) e.OldValue)); } owner.SetFlagsOnAllChannels(true, VisualProxyFlags.Viewport3DVisual_IsCameraDirty | VisualProxyFlags.IsContentDirty); } owner.ContentsChanged(/* sender = */ owner, EventArgs.Empty); } ////// Camera for this Visual3D. /// public Camera Camera { get { return (Camera) GetValue(CameraProperty); } set { SetValue(CameraProperty, value); } } ////// DependencyProperty which backs the ModelVisual3D.Viewport property. /// public static readonly DependencyProperty ViewportProperty = DependencyProperty.Register( "Viewport", /* propertyType = */ typeof(Rect), /* ownerType = */ typeof(Viewport3DVisual), new PropertyMetadata(Rect.Empty, ViewportPropertyChanged), (ValidateValueCallback) delegate { return MediaContext.CurrentMediaContext.WriteAccessEnabled; }); private static void ViewportPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { Viewport3DVisual owner = ((Viewport3DVisual) d); Debug.Assert(!e.IsASubPropertyChange, "How are we receiving sub property changes from a struct?"); owner.SetFlagsOnAllChannels(true, VisualProxyFlags.Viewport3DVisual_IsViewportDirty | VisualProxyFlags.IsContentDirty); owner.ContentsChanged(/* sender = */ owner, EventArgs.Empty); } ////// Viewport for this Visual3D. /// public Rect Viewport { get { return (Rect) GetValue(ViewportProperty); } set { SetValue(ViewportProperty, value); } } ////// The 3D children to be projected by this Viewport3DVisual. /// [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)] public Visual3DCollection Children { get { return _children; } } #endregion Public Properties //----------------------------------------------------- // // Public Events // //----------------------------------------------------- //----------------------------------------------------- // // Protected Methods // //------------------------------------------------------ //----------------------------------------------------- // // Internal Methods // //------------------------------------------------------ #region Internal Methods // CS0536: Intreface implementation must be public or explicit so we re-expose // the internal methods as an explicit implementation of an internal interface. void IVisual3DContainer.VerifyAPIReadOnly() { this.VerifyAPIReadOnly(); } void IVisual3DContainer.VerifyAPIReadOnly(DependencyObject other) { this.VerifyAPIReadOnly(other); } void IVisual3DContainer.VerifyAPIReadWrite() { this.VerifyAPIReadWrite(); } void IVisual3DContainer.VerifyAPIReadWrite(DependencyObject other) { this.VerifyAPIReadWrite(other); } // NOTE: The code here is highly similar to AddChildCore in ModelVisual3D, // but slightly different because the parent is 2D here. void IVisual3DContainer.AddChild(Visual3D child) { // It is invalid to modify the children collection that we // might be iterating during a property invalidation tree walk. if (IsVisualChildrenIterationInProgress) { throw new InvalidOperationException(SR.Get(SRID.CannotModifyVisualChildrenDuringTreeWalk)); } Debug.Assert(child != null); Debug.Assert(child.InternalVisualParent == null); child.SetParent(this); // set the inheritance context so databinding, etc... work if (_inheritanceContextForChildren != null) { _inheritanceContextForChildren.ProvideSelfAsInheritanceContext(child, null); } SetFlagsOnAllChannels(true, VisualProxyFlags.IsContentDirty); // The child already might be dirty. Hence we need to propagate dirty information // from the parent and from the child. Visual.PropagateFlags( this, VisualFlags.IsSubtreeDirtyForPrecompute | VisualFlags.NodeNeedsBitmapEffectUpdate, VisualProxyFlags.IsSubtreeDirtyForRender); Visual3D.PropagateFlags( child, VisualFlags.IsSubtreeDirtyForPrecompute, VisualProxyFlags.IsSubtreeDirtyForRender); // // Fire notifications OnVisualChildrenChanged(child, /* visualRemoved = */ null); child.FireOnVisualParentChanged(null); } // NOTE: The code here is highly similar to RemoveChildCore in ModelVisual3D, // but slightly different because the parent is 2D here. void IVisual3DContainer.RemoveChild(Visual3D child) { int index = child.ParentIndex; // It is invalid to modify the children collection that we // might be iterating during a property invalidation tree walk. if (IsVisualChildrenIterationInProgress) { throw new InvalidOperationException(SR.Get(SRID.CannotModifyVisualChildrenDuringTreeWalk)); } Debug.Assert(child != null); Debug.Assert(child.InternalVisualParent == this); child.SetParent(/* newParent = */ (Visual) null); // CS0121: Call is ambigious without casting null to Visual. // remove the inheritance context if (_inheritanceContextForChildren != null) { _inheritanceContextForChildren.RemoveSelfAsInheritanceContext(child, null); } // // Remove the child on all channels this visual is marshalled to. // for (int i = 0, limit = _proxy3D.Count; i < limit; i++) { DUCE.Channel channel = _proxy3D.GetChannel(i); if (child.CheckFlagsAnd(channel, VisualProxyFlags.IsConnectedToParent)) { channel.AddToRemoveAndReleaseQueue( this, child); child.SetFlags(channel, false, VisualProxyFlags.IsConnectedToParent); } } SetFlagsOnAllChannels(true, VisualProxyFlags.IsContentDirty); // // Force a full precompute and render pass for this visual. // Visual.PropagateFlags( this, VisualFlags.IsSubtreeDirtyForPrecompute | VisualFlags.NodeNeedsBitmapEffectUpdate, VisualProxyFlags.IsSubtreeDirtyForRender); // child.FireOnVisualParentChanged(this); OnVisualChildrenChanged(/* visualAdded = */ null , child); } ////// Gets the number of Visual3D children that the IVisual3DContainer /// contains. /// int IVisual3DContainer.GetChildrenCount() { return InternalVisual2DOr3DChildrenCount; } ////// Gets the index children of the IVisual3DContainer /// Visual3D IVisual3DContainer.GetChild(int index) { return (Visual3D)InternalGet2DOr3DVisualChild(index); } ////// Returns the number of children of this object (in most cases this will be /// the number of Visuals, but it some cases, Viewport3DVisual for instance, /// this is the number of Visual3Ds). /// /// Used only by VisualTreeHelper. /// internal override int InternalVisual2DOr3DChildrenCount { get { return Children.Count; } } ////// Used only by VisualTreeHelper. /// /// Returns the child at index "index" (in most cases this will be /// a Visual, but it some cases, Viewport3DVisual, for instance, /// this is a Visual3D). /// internal override DependencyObject InternalGet2DOr3DVisualChild(int index) { return Children[index]; } internal override HitTestResultBehavior HitTestPointInternal( HitTestFilterCallback filterCallback, HitTestResultCallback resultCallback, PointHitTestParameters hitTestParameters) { if (_children.Count != 0) { double distanceAdjustment; RayHitTestParameters rayParams = Camera.RayFromViewportPoint( hitTestParameters.HitPoint, Viewport.Size, BBoxSubgraph, out distanceAdjustment); HitTestResultBehavior result = Visual3D.HitTestChildren(filterCallback, rayParams, this); return rayParams.RaiseCallback(resultCallback, filterCallback, result, distanceAdjustment); } return HitTestResultBehavior.Continue; } ////// Viewport3DVisual does not yet support Geometry hit testing. /// protected override GeometryHitTestResult HitTestCore(GeometryHitTestParameters hitTestParameters) { throw new NotSupportedException(SR.Get(SRID.HitTest_Invalid, typeof(GeometryHitTestParameters).Name, this.GetType().Name)); } internal Point WorldToViewport(Point4D point) { double aspectRatio = M3DUtil.GetAspectRatio(Viewport.Size); Camera camera = Camera; if (camera != null) { Matrix3D viewProjMatrix = camera.GetViewMatrix() * camera.GetProjectionMatrix(aspectRatio); point *= viewProjMatrix; Point point2D = new Point(point.X/point.W, point.Y/point.W); point2D *= M3DUtil.GetHomogeneousToViewportTransform(Viewport); return point2D; } else { return new Point(0,0); } } ////// Derived classes return the hit-test bounding box from the /// GetHitTestBounds virtual. Visual uses the bounds to optimize /// hit-testing. /// internal override Rect GetHitTestBounds() { return CalculateSubgraphBoundsInnerSpace(); } internal override Rect CalculateSubgraphBoundsInnerSpace(bool renderBounds) { Camera camera = Camera; if (camera == null) { return Rect.Empty; } // // Cache the 3D bounding box for future use. Here we are relying on // the fact that this method is called by PrecomputeContent(), // which is called prior to all usages of _bboxChildrenSubgraph3D. // _bboxChildrenSubgraph3D = ComputeSubgraphBounds3D(); if (_bboxChildrenSubgraph3D.IsEmpty) { // Attempting to project empty bounds will result in NaNs which // which will ruin descendant bounds for the 2D tree. We handle // this explicitly and early exit with the correct answer. return Rect.Empty; } Rect viewport = Viewport; // Common Case: Viewport3DVisual in a collasped UIElement. if (viewport.IsEmpty) { // Creating a 3D homogenous space to 2D viewport space transform // with an empty rectangle will result in NaNs which ruin the // descendant bounds for the 2D tree. We handle this explicitly // and early exit with the correct answer. // // (See also Windows OS Bugs #1637618) return Rect.Empty; } double aspectRatio = M3DUtil.GetAspectRatio(viewport.Size); Matrix3D viewProjMatrix = camera.GetViewMatrix() * camera.GetProjectionMatrix(aspectRatio); Rect projectedBounds2D = MILUtilities.ProjectBounds(ref viewProjMatrix, ref _bboxChildrenSubgraph3D); Matrix ----ToLocal = M3DUtil.GetHomogeneousToViewportTransform(viewport); MatrixUtil.TransformRect(ref projectedBounds2D, ref ----ToLocal); return projectedBounds2D; } // // NOTE: Must only be called after PrecomputeContent(). // private Rect3D BBoxSubgraph { get { Debug_VerifyCachedSubgraphBounds(); return _bboxChildrenSubgraph3D; } } internal Rect3D ComputeSubgraphBounds3D() { Rect3D bboxChildrenSubgraph3D = Rect3D.Empty; for (int i = 0, count = _children.InternalCount; i < count; i++) { Visual3D child = _children.InternalGetItem(i); bboxChildrenSubgraph3D.Union(child.CalculateSubgraphBoundsOuterSpace()); } return bboxChildrenSubgraph3D; } [Conditional("DEBUG")] private void Debug_VerifyCachedSubgraphBounds() { Rect3D currentBounds = Rect3D.Empty; currentBounds = ComputeSubgraphBounds3D(); Rect3D cachedBounds = _bboxChildrenSubgraph3D; // The funny boolean logic below avoids asserts when the cached // bounds contain NaNs. (NaN != NaN) bool boundsAreEqual = !(cachedBounds.X < currentBounds.X || cachedBounds.X > currentBounds.X) && !(cachedBounds.Y < currentBounds.Y || cachedBounds.Y > currentBounds.Y) && !(cachedBounds.Z < currentBounds.Z || cachedBounds.Z > currentBounds.Z) && !(cachedBounds.SizeX < currentBounds.SizeX || cachedBounds.SizeX > currentBounds.SizeX) && !(cachedBounds.SizeY < currentBounds.SizeY || cachedBounds.SizeY > currentBounds.SizeY) && !(cachedBounds.SizeZ < currentBounds.SizeZ || cachedBounds.SizeZ > currentBounds.SizeZ); if (!boundsAreEqual) { Debug.Fail("Cached bbox subgraph is incorrect!"); } } internal override DUCE.ResourceHandle AddRefOnChannelCore(DUCE.Channel channel) { DUCE.ResourceHandle handle = base.AddRefOnChannelCore(channel); bool created = _proxy3D.CreateOrAddRefOnChannel(channel, DUCE.ResourceType.TYPE_VISUAL3D); Debug.Assert( _proxy.Count == _proxy3D.Count, "Viewport has been marshalled to a different number of channels than the 3D content."); // If we are creating the Viewport3DVisual/Visual3D for the first // time on this channel we need to connect the 3D root. if (created) { DUCE.Viewport3DVisualNode.Set3DChild( handle, _proxy3D.GetHandle(channel), channel); } return handle; } internal override void ReleaseOnChannelCore(DUCE.Channel channel) { Debug.Assert( _proxy.Count == _proxy3D.Count, "Viewport has been marshalled to a different number of channels than the 3D content."); base.ReleaseOnChannelCore(channel); _proxy3D.ReleaseOnChannel(channel); } int DUCE.IResource.GetChannelCount() { return _proxy.Count; } DUCE.Channel DUCE.IResource.GetChannel(int index) { return _proxy.GetChannel(index); } ////// Precompute pass. /// internal override void PrecomputeContent() { base.PrecomputeContent(); // If any of our children root a 3D subtree which uses realization // caches we need to set NodeUsesRealizationCaches on ourselves. // // NOTE: There is no 2D content on Visual so base.PrecomputeContent() // does not initialize this flag. We start with false. bool subTreeUsesRealizationCaches = false; if (_children != null) { for (int i = 0, count = _children.InternalCount; i < count; i++) { Visual3D child = _children.InternalGetItem(i); if (child != null) { // This merely tells the Visual3Ds to update their bounds // caches if necessary. Later on we'll get the cached bounds // from calling Visual3D.CalculateSubgraphBounds Rect3D bboxSubgraphChildIgnored; child.PrecomputeRecursive(out bboxSubgraphChildIgnored); subTreeUsesRealizationCaches |= child.CheckFlagsAnd(VisualFlags.NodeInSubtreeUsesRealizationCaches); } } } // NOTE: We set NodeUseRealizationCaches rather than // NodeInSubtreeUsesRealizationCaches. This is because we // use UpdateRealizations() on the Viewport3DVisual to bridge // the realization walk into the Visual3D tree. SetFlags(subTreeUsesRealizationCaches, VisualFlags.NodeUsesRealizationCaches); // // If realizations are used in the subtree, they could be glyphs // which may induce multiple pathness. // SetFlags(subTreeUsesRealizationCaches, VisualFlags.NodeOrDescendantIntroducesGraphness); } internal override void RenderContent(RenderContext ctx, bool isOnChannel) { DUCE.Channel channel = ctx.Channel; // // At this point, the visual has to be marshalled. Force // marshalling of the camera and viewport in case we have // just created a new visual resource. // Debug.Assert(IsOnChannel(channel)); VisualProxyFlags flags = _proxy.GetFlags(channel); // // Make sure the camera resource is being marshalled properly. // if ((flags & VisualProxyFlags.Viewport3DVisual_IsCameraDirty) != 0) { Camera camera = Camera; if (camera != null) { DUCE.Viewport3DVisualNode.SetCamera( ((DUCE.IResource)this).GetHandle(channel), ((DUCE.IResource)camera).AddRefOnChannel(channel), channel); } else if (isOnChannel) /* camera == null */ { DUCE.Viewport3DVisualNode.SetCamera( ((DUCE.IResource)this).GetHandle(channel), DUCE.ResourceHandle.Null, channel); } SetFlags(channel, false, VisualProxyFlags.Viewport3DVisual_IsCameraDirty); } // // Set the viewport if it's dirty. // if ((flags & VisualProxyFlags.Viewport3DVisual_IsViewportDirty) != 0) { DUCE.Viewport3DVisualNode.SetViewport( ((DUCE.IResource)this).GetHandle(channel), Viewport, channel); SetFlags(channel, false, VisualProxyFlags.Viewport3DVisual_IsViewportDirty); } //we only want to recurse in the children if the visual does not have a bitmap effect //or we are in the BitmapVisualManager render pass // Visit children of this node ------------------------------------------------------------------------ Debug.Assert(!CheckFlagsAnd(channel, VisualProxyFlags.IsContentNodeConnected), "Only HostVisuals are expected to have a content node."); if (_children != null) { for (uint i = 0; i < _children.InternalCount; i++) { Visual3D child = _children.InternalGetItem((int) i); if (child != null) { if (child.CheckFlagsAnd(channel, VisualProxyFlags.IsSubtreeDirtyForRender) || // or the visual is dirty !(child.IsOnChannel(channel))) // or the child has not been marshalled yet. { child.RenderRecursive(ctx); } if (child.IsOnChannel(channel)) { if (!child.CheckFlagsAnd(channel, VisualProxyFlags.IsConnectedToParent)) { DUCE.Visual3DNode.InsertChildAt( _proxy3D.GetHandle(channel), ((DUCE.IResource)child).GetHandle(channel), /* iPosition = */ i, channel); child.SetFlags(channel, true, VisualProxyFlags.IsConnectedToParent); } } } } } } ////// Override this function in derived classes to release unmanaged resources during Dispose /// and during removal of a subtree. /// internal override void FreeContent(DUCE.Channel channel) { Debug.Assert(IsOnChannel(channel)); Camera camera = Camera; if (camera != null) { if (!CheckFlagsAnd(channel, VisualProxyFlags.Viewport3DVisual_IsCameraDirty)) { ((DUCE.IResource)camera).ReleaseOnChannel(channel); SetFlagsOnAllChannels(true, VisualProxyFlags.Viewport3DVisual_IsCameraDirty); } } if (_children != null) { for (int i = 0; i < _children.InternalCount; i++) { Visual3D visual = _children.InternalGetItem(i); ((DUCE.IResource)visual).ReleaseOnChannel(channel); } } SetFlagsOnAllChannels(true, VisualProxyFlags.IsContentDirty); base.FreeContent(channel); } ////// Called by the base class to update realization caches. /// Updates the realization cache on the scene3d. /// internal override void UpdateRealizations(RealizationContext ctx) { Debug.Assert(CheckFlagsAnd(VisualFlags.NodeUsesRealizationCaches)); Camera camera = Camera; if (camera != null) { // Do not call the base class here because that would kick of an // unnecessary realization pass over the render data content of this // Visual. Matrix3DStack stack3D = ctx.Transform3DStack; // PushWithoutAccumulating to enable nested usage of the Transform3DStack. stack3D.PushWithoutAccumulating(M3DUtil.GetWorldToViewportTransform3D(camera, Viewport)); bool wasIn3DMode = ctx.Set3DMode(true); for (int i = 0; i < _children.InternalCount; i++) { Visual3D child = _children.InternalGetItem(i); if (child.CheckFlagsAnd(VisualFlags.NodeInSubtreeUsesRealizationCaches)) { child.UpdateRealizations(ctx); } } ctx.Set3DMode(wasIn3DMode); stack3D.Pop(); // worldToViewport. } } // Notify the Viewport3DVisual that the Visual3D subtree it hosts // has been modified. internal void Visual3DTreeChanged() { // The Visual3D tree is plugged into the 2D Visual tree via the // same extensibility point we use for "content". SetFlagsOnAllChannels(true, VisualProxyFlags.IsContentDirty); ContentsChanged(/* sender = */ this, EventArgs.Empty); } ////// Returns the handle this visual has on the given channel. /// Note: The 3D handle is obtained from _proxy3D. /// DUCE.ResourceHandle DUCE.IResource.Get3DHandle(DUCE.Channel channel) { return _proxy3D.GetHandle(channel); } // Because 2D Visuals and FEs do not participate in inheritance context // we allow this backdoor for a Viewport3D to set itself as the inheritance // context of the Visual3DCollection it exposes as Children. [FriendAccessAllowed] internal void SetInheritanceContextForChildren(DependencyObject inheritanceContextForChildren) { _inheritanceContextForChildren = inheritanceContextForChildren; } #endregion Internal Methods //----------------------------------------------------- // // Private Fields // //------------------------------------------------------ #region Private Fields ////// The 3D content root. /// ////// Important! - Not readonly because CS will silently copy /// for self-modifying methods. (C# Spec 14.5.4) /// private VisualProxy _proxy3D; private Rect3D _bboxChildrenSubgraph3D; private readonly Visual3DCollection _children; private DependencyObject _inheritanceContextForChildren; #endregion Private Fields } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved.
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- ToolboxComponentsCreatingEventArgs.cs
- HiddenFieldPageStatePersister.cs
- BaseCollection.cs
- AnnotationAuthorChangedEventArgs.cs
- InvalidEnumArgumentException.cs
- NotSupportedException.cs
- IdnElement.cs
- DefaultParameterValueAttribute.cs
- DescendantQuery.cs
- VectorValueSerializer.cs
- CompiledIdentityConstraint.cs
- CurrentTimeZone.cs
- SchemaCollectionCompiler.cs
- _TransmitFileOverlappedAsyncResult.cs
- DataBoundControl.cs
- GB18030Encoding.cs
- DEREncoding.cs
- ExternalDataExchangeService.cs
- TypeForwardedToAttribute.cs
- TextTrailingCharacterEllipsis.cs
- MessagePartDescription.cs
- GcSettings.cs
- Visual.cs
- NetMsmqBindingCollectionElement.cs
- XmlBinaryReader.cs
- FormView.cs
- TagPrefixCollection.cs
- HMACSHA512.cs
- GridViewRowPresenterBase.cs
- TogglePatternIdentifiers.cs
- WorkflowView.cs
- AffineTransform3D.cs
- NullableIntMinMaxAggregationOperator.cs
- LowerCaseStringConverter.cs
- FrameworkObject.cs
- ConnectionOrientedTransportManager.cs
- PromptStyle.cs
- SqlServices.cs
- FloatUtil.cs
- EntityTemplateFactory.cs
- CodeTypeReference.cs
- WebPartRestoreVerb.cs
- FixedSOMSemanticBox.cs
- HttpWebResponse.cs
- OleDbPropertySetGuid.cs
- Simplifier.cs
- DesignTimeTemplateParser.cs
- Span.cs
- GetPageCompletedEventArgs.cs
- ComponentEditorForm.cs
- StoryFragments.cs
- SrgsToken.cs
- StatusBarAutomationPeer.cs
- ContentElementAutomationPeer.cs
- Int16Storage.cs
- UnauthorizedWebPart.cs
- WebFormDesignerActionService.cs
- SqlRowUpdatingEvent.cs
- SoapInteropTypes.cs
- EventSinkHelperWriter.cs
- NativeObjectSecurity.cs
- ListControlConvertEventArgs.cs
- RepeatBehaviorConverter.cs
- SessionSwitchEventArgs.cs
- GlyphManager.cs
- TextElementEnumerator.cs
- HtmlShimManager.cs
- CapabilitiesUse.cs
- ProgressBar.cs
- ResourceDefaultValueAttribute.cs
- MulticastDelegate.cs
- diagnosticsswitches.cs
- TextElementCollection.cs
- FileCodeGroup.cs
- unitconverter.cs
- CompilationRelaxations.cs
- HashMembershipCondition.cs
- ArrayWithOffset.cs
- SafeFindHandle.cs
- CacheChildrenQuery.cs
- SamlAuthorizationDecisionClaimResource.cs
- AddInDeploymentState.cs
- Exceptions.cs
- MaskedTextProvider.cs
- RuleProcessor.cs
- xdrvalidator.cs
- TypeName.cs
- XmlElementCollection.cs
- SmiEventStream.cs
- MessageSecurityOverHttp.cs
- ComAdminWrapper.cs
- ReturnValue.cs
- Msec.cs
- XmlSchemaSimpleType.cs
- Expression.DebuggerProxy.cs
- Timeline.cs
- OrderingInfo.cs
- Opcode.cs
- Bold.cs
- ImageSource.cs