Viewport3DVisual.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / wpf / src / Core / CSharp / System / Windows / Media3D / Viewport3DVisual.cs / 1305600 / 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,
                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)) 
                {
                    child.SetFlags(channel, false, VisualProxyFlags.IsConnectedToParent);
                    DUCE.IResource childResource = (DUCE.IResource)child;
                    childResource.RemoveChildFromParent(this, channel); 
                    childResource.ReleaseOnChannel(channel);
                } 
            } 

            SetFlagsOnAllChannels(true, VisualProxyFlags.IsContentDirty); 

            //
            // Force a full precompute and render pass for this visual.
            // 

            Visual.PropagateFlags( 
                this, 
                VisualFlags.IsSubtreeDirtyForPrecompute,
                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(this, 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 (_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);
                    } 
                }
            } 
        } 

        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); 
        } 

        // 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

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK