internal override void ReleaseOnChannelCore(DUCE.Channel channel) { Debug.Assert(_duceResource.IsOnChannel(channel)); if (_duceResource.ReleaseOnChannel(channel)) { Transform3D vTransform = Transform; if (vTransform != null) { ((DUCE.IResource)vTransform).ReleaseOnChannel(channel); } Model3DCollection vChildren = Children; if (vChildren != null) { int count = vChildren.Count; for (int i = 0; i < count; i++) { ((DUCE.IResource)vChildren.Internal_GetItem(i)).ReleaseOnChannel(channel); } } ReleaseOnChannelAnimations(channel); } }
internal override DUCE.ResourceHandle AddRefOnChannelCore(DUCE.Channel channel) { if (_duceResource.CreateOrAddRefOnChannel(this, channel, System.Windows.Media.Composition.DUCE.ResourceType.TYPE_MODEL3DGROUP)) { Transform3D vTransform = Transform; if (vTransform != null) { ((DUCE.IResource)vTransform).AddRefOnChannel(channel); } Model3DCollection vChildren = Children; if (vChildren != null) { int count = vChildren.Count; for (int i = 0; i < count; i++) { ((DUCE.IResource)vChildren.Internal_GetItem(i)).AddRefOnChannel(channel); } } AddRefOnChannelAnimations(channel); UpdateResource(channel, true /* skip "on channel" check - we already know that we're on channel */); } return(_duceResource.GetHandle(channel)); }
//------------------------------------------------------ // // Internal Methods // //------------------------------------------------------ #region Internal Methods internal override void UpdateResource(DUCE.Channel channel, bool skipOnChannelCheck) { // If we're told we can skip the channel check, then we must be on channel Debug.Assert(!skipOnChannelCheck || _duceResource.IsOnChannel(channel)); if (skipOnChannelCheck || _duceResource.IsOnChannel(channel)) { base.UpdateResource(channel, skipOnChannelCheck); // Read values of properties into local variables Transform3D vTransform = Transform; Model3DCollection vChildren = Children; // Obtain handles for properties that implement DUCE.IResource DUCE.ResourceHandle hTransform; if (vTransform == null || Object.ReferenceEquals(vTransform, Transform3D.Identity) ) { hTransform = DUCE.ResourceHandle.Null; } else { hTransform = ((DUCE.IResource)vTransform).GetHandle(channel); } // Store the count of this resource's contained collections in local variables. int ChildrenCount = (vChildren == null) ? 0 : vChildren.Count; // Pack & send command packet DUCE.MILCMD_MODEL3DGROUP data; unsafe { data.Type = MILCMD.MilCmdModel3DGroup; data.Handle = _duceResource.GetHandle(channel); data.htransform = hTransform; data.ChildrenSize = (uint)(sizeof(DUCE.ResourceHandle) * ChildrenCount); channel.BeginCommand( (byte *)&data, sizeof(DUCE.MILCMD_MODEL3DGROUP), (int)(data.ChildrenSize) ); // Copy this collection's elements (or their handles) to reserved data for (int i = 0; i < ChildrenCount; i++) { DUCE.ResourceHandle resource = ((DUCE.IResource)vChildren.Internal_GetItem(i)).GetHandle(channel);; channel.AppendCommandData( (byte *)&resource, sizeof(DUCE.ResourceHandle) ); } channel.EndCommand(); } } }
//------------------------------------------------------ // // Internal Methods // //------------------------------------------------------ #region Internal Methods internal override void RayHitTestCore( RayHitTestParameters rayParams) { Model3DCollection children = Children; if (children == null) { return; } for (int i = children.Count - 1; i >= 0; i--) { Model3D child = children.Internal_GetItem(i); // Perform the hit-test against the child. child.RayHitTest(rayParams); } }
internal override Rect3D CalculateSubgraphBoundsInnerSpace() { Model3DCollection children = Children; if (children == null) { return(Rect3D.Empty); } Rect3D bounds = Rect3D.Empty; for (int i = 0, count = children.Count; i < count; i++) { Model3D child = children.Internal_GetItem(i); // Calls CSBOS rather than Bounds to avoid ReadPreamble. bounds.Union(child.CalculateSubgraphBoundsOuterSpace()); } return(bounds); }
//------------------------------------------------------ // // Public Properties // //------------------------------------------------------ private static void ChildrenPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { // The first change to the default value of a mutable collection property (e.g. GeometryGroup.Children) // will promote the property value from a default value to a local value. This is technically a sub-property // change because the collection was changed and not a new collection set (GeometryGroup.Children. // Add versus GeometryGroup.Children = myNewChildrenCollection). However, we never marshalled // the default value to the compositor. If the property changes from a default value, the new local value // needs to be marshalled to the compositor. We detect this scenario with the second condition // e.OldValueSource != e.NewValueSource. Specifically in this scenario the OldValueSource will be // Default and the NewValueSource will be Local. if (e.IsASubPropertyChange && (e.OldValueSource == e.NewValueSource)) { return; } Model3DGroup target = ((Model3DGroup)d); // If this is both non-null and mutable, we need to unhook the Changed event. Model3DCollection oldCollection = null; Model3DCollection newCollection = null; if ((e.OldValueSource != BaseValueSourceInternal.Default) || e.IsOldValueModified) { oldCollection = (Model3DCollection)e.OldValue; if ((oldCollection != null) && !oldCollection.IsFrozen) { oldCollection.ItemRemoved -= target.ChildrenItemRemoved; oldCollection.ItemInserted -= target.ChildrenItemInserted; } } // If this is both non-null and mutable, we need to hook the Changed event. if ((e.NewValueSource != BaseValueSourceInternal.Default) || e.IsNewValueModified) { newCollection = (Model3DCollection)e.NewValue; if ((newCollection != null) && !newCollection.IsFrozen) { newCollection.ItemInserted += target.ChildrenItemInserted; newCollection.ItemRemoved += target.ChildrenItemRemoved; } } if (oldCollection != newCollection && target.Dispatcher != null) { using (CompositionEngineLock.Acquire()) { DUCE.IResource targetResource = (DUCE.IResource)target; int channelCount = targetResource.GetChannelCount(); for (int channelIndex = 0; channelIndex < channelCount; channelIndex++) { DUCE.Channel channel = targetResource.GetChannel(channelIndex); Debug.Assert(!channel.IsOutOfBandChannel); Debug.Assert(!targetResource.GetHandle(channel).IsNull); // resource shouldn't be null because // 1) If the field is one of our collections, we don't allow null elements // 2) Codegen already made sure the collection contains DUCE.IResources // ... so we'll Assert it if (newCollection != null) { int count = newCollection.Count; for (int i = 0; i < count; i++) { DUCE.IResource resource = newCollection.Internal_GetItem(i) as DUCE.IResource; Debug.Assert(resource != null); resource.AddRefOnChannel(channel); } } if (oldCollection != null) { int count = oldCollection.Count; for (int i = 0; i < count; i++) { DUCE.IResource resource = oldCollection.Internal_GetItem(i) as DUCE.IResource; Debug.Assert(resource != null); resource.ReleaseOnChannel(channel); } } } } } target.PropertyChanged(ChildrenProperty); }