internal Enumerator(MaterialCollection list) { Debug.Assert(list != null, "list may not be null."); _list = list; _version = list._version; _index = -1; _current = default(Material); }
/// <summary> /// Implementation of Freezable.GetCurrentValueAsFrozenCore() /// </summary> protected override void GetCurrentValueAsFrozenCore(Freezable source) { MaterialCollection sourceMaterialCollection = (MaterialCollection)source; base.GetCurrentValueAsFrozenCore(source); int count = sourceMaterialCollection._collection.Count; _collection = new FrugalStructList <Material>(count); for (int i = 0; i < count; i++) { Material newValue = (Material)sourceMaterialCollection._collection[i].GetCurrentValueAsFrozen(); OnFreezablePropertyChanged(/* oldValue = */ null, newValue); _collection.Add(newValue); OnInsert(newValue); } }
//------------------------------------------------------ // // 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 MaterialCollection vChildren = Children; // 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_MATERIALGROUP data; unsafe { data.Type = MILCMD.MilCmdMaterialGroup; data.Handle = _duceResource.GetHandle(channel); data.ChildrenSize = (uint)(sizeof(DUCE.ResourceHandle) * ChildrenCount); channel.BeginCommand( (byte *)&data, sizeof(DUCE.MILCMD_MATERIALGROUP), (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 override void ReleaseOnChannelCore(DUCE.Channel channel) { Debug.Assert(_duceResource.IsOnChannel(channel)); if (_duceResource.ReleaseOnChannel(channel)) { MaterialCollection 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_MATERIALGROUP)) { MaterialCollection 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)); }
//------------------------------------------------------ // // 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; } MaterialGroup target = ((MaterialGroup)d); // If this is both non-null and mutable, we need to unhook the Changed event. MaterialCollection oldCollection = null; MaterialCollection newCollection = null; if ((e.OldValueSource != BaseValueSourceInternal.Default) || e.IsOldValueModified) { oldCollection = (MaterialCollection)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 = (MaterialCollection)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); }
/// <summary> /// Replaces any instances of the sentinal brush with the internal brush /// </summary> /// <param name="material">The material to look through</param> private void SwapInCyclicBrush(Material material) { int numMaterialsSwapped = 0; Stack <Material> materialStack = new Stack <Material>(); materialStack.Push(material); Brush internalBrush = (CacheMode as BitmapCache != null) ? (Brush)InternalBitmapCacheBrush : (Brush)InternalVisualBrush; while (materialStack.Count > 0) { Material currMaterial = materialStack.Pop(); if (currMaterial is DiffuseMaterial) { DiffuseMaterial diffMaterial = (DiffuseMaterial)currMaterial; if ((Boolean)diffMaterial.GetValue(Viewport2DVisual3D.IsVisualHostMaterialProperty)) { diffMaterial.Brush = internalBrush; numMaterialsSwapped++; } } else if (currMaterial is EmissiveMaterial) { EmissiveMaterial emmMaterial = (EmissiveMaterial)currMaterial; if ((Boolean)emmMaterial.GetValue(Viewport2DVisual3D.IsVisualHostMaterialProperty)) { emmMaterial.Brush = internalBrush; numMaterialsSwapped++; } } else if (currMaterial is SpecularMaterial) { SpecularMaterial specMaterial = (SpecularMaterial)currMaterial; if ((Boolean)specMaterial.GetValue(Viewport2DVisual3D.IsVisualHostMaterialProperty)) { specMaterial.Brush = internalBrush; numMaterialsSwapped++; } } else if (currMaterial is MaterialGroup) { MaterialGroup matGroup = (MaterialGroup)currMaterial; // the IsVisualHostMaterialProperty should not be set on a MaterialGroup - verify that if ((Boolean)matGroup.GetValue(Viewport2DVisual3D.IsVisualHostMaterialProperty)) { throw new ArgumentException(SR.Get(SRID.Viewport2DVisual3D_MaterialGroupIsInteractiveMaterial), "material"); } // iterate over the children and put them on the stack of materials to modify MaterialCollection children = matGroup.Children; if (children != null) { for (int i = 0, count = children.Count; i < count; i++) { Material m = children[i]; materialStack.Push(m); } } } else { Invariant.Assert(true, "Unexpected Material type encountered. V2DV3D handles DiffuseMaterial, EmissiveMaterial, SpecularMaterial, and MaterialGroup."); } } // throw if there is more than 1 interactive material if (numMaterialsSwapped > 1) { throw new ArgumentException(SR.Get(SRID.Viewport2DVisual3D_MultipleInteractiveMaterials), "material"); } }