private void RenderBurst(CancellationTokenSource tokenSource, WipeDirection direction) { switch (direction) { case WipeDirection.In: case WipeDirection.Out: break; default: throw new InvalidOperationException("the RenderBurst method should only be called for Wipe Directions In and Out"); break; } var burstNodes = TargetNodes.SelectMany(x => x.GetLeafEnumerator()) .Select(s => { var prop = s.Properties.Get(LocationDescriptor._typeId); if (prop != null) { return new Tuple<ElementNode, int, int, int>(s, ((LocationData)prop.ModuleData).X, ((LocationData)prop.ModuleData).Y, ((LocationData)prop.ModuleData).Z); } return new Tuple<ElementNode, int, int, int>(null, -1, -1, -1); //return null }) .Where(s => s.Item2 > 0) // Ignore the pseudo null values .ToList(); if (!burstNodes.Any()) return; var maxX = burstNodes.Max(m => m.Item2); var maxY = burstNodes.Max(m => m.Item3); var minX = burstNodes.Min(m => m.Item2); var minY = burstNodes.Min(m => m.Item3); var Steps = (int)(Math.Max(maxX - minX, maxY - minY) / 2); List<Tuple<int, ElementNode[]>> groups = new List<Tuple<int, ElementNode[]>>(); for (int i = 0; i < Steps; i++) { List<ElementNode> elements = new List<ElementNode>(); var xNodes = burstNodes.Where(x => (x.Item2 == minX + i || x.Item2 == maxX - i) ) .Select(s => s.Item1).ToList(); var yNodes = burstNodes.Where(x => ( x.Item3 == minY + i || x.Item3 == maxY - i) ) .Select(s => s.Item1).ToList(); yNodes.RemoveAll(s => { var prop = s.Properties.Get(LocationDescriptor._typeId); if (prop != null) { return ((LocationData)prop.ModuleData).X < minX + i || ((LocationData)prop.ModuleData).X > maxX - i; } return false; }); xNodes.RemoveAll(s => { var prop = s.Properties.Get(LocationDescriptor._typeId); if (prop != null) { return ((LocationData)prop.ModuleData).Y < minY + i || ((LocationData)prop.ModuleData).Y > maxY - i; } return false; }); elements.AddRange(yNodes); elements.AddRange(xNodes); groups.Add(new Tuple<int, ElementNode[]>(i, elements.ToArray())); } List<ElementNode[]> renderNodes = new List<ElementNode[]>(); switch (direction) { case WipeDirection.In: renderNodes = groups.OrderBy(o => o.Item1).Select(s => s.Item2).ToList(); break; case WipeDirection.Out: renderNodes = groups.OrderByDescending(o => o.Item1).Select(s => s.Item2).ToList(); break; } var pulse = new Pulse.Pulse(); if (renderNodes != null && renderNodes.Any()) { TimeSpan effectTime = TimeSpan.Zero; if (WipeByCount) { int count = 0; double pulseSegment = (TimeSpan.TotalMilliseconds / PassCount) * (PulsePercent / 100); TimeSpan intervalTime = TimeSpan.FromMilliseconds((TimeSpan.TotalMilliseconds - pulseSegment) / (renderNodes.Count() * PassCount)); TimeSpan segmentPulse = TimeSpan.FromMilliseconds(pulseSegment); while (count < PassCount) { foreach (var item in renderNodes) { if (tokenSource != null && tokenSource.IsCancellationRequested) return; EffectIntents result; foreach (ElementNode element in item) { if (tokenSource != null && tokenSource.IsCancellationRequested) return; if (element != null) { pulse.TimeSpan = segmentPulse; pulse.ColorGradient = _data.ColorGradient; pulse.LevelCurve = _data.Curve; pulse.TargetNodes = new ElementNode[] { element }; result = pulse.Render(); result.OffsetAllCommandsByTime(effectTime); _elementData.Add(result); } } effectTime += intervalTime; } count++; } } else { double intervals = (double)PulseTime / (double)renderNodes.Count(); var intervalTime = TimeSpan.FromMilliseconds(intervals); // the calculation above blows up render time/memory as count goes up, try this.. // also fails if intervals is less than half a ms and intervalTime then gets 0 intervalTime = TimeSpan.FromMilliseconds(Math.Max(intervalTime.TotalMilliseconds, 5)); TimeSpan segmentPulse = TimeSpan.FromMilliseconds(PulseTime); while (effectTime < TimeSpan) { foreach (var item in renderNodes) { EffectIntents result; if (tokenSource != null && tokenSource.IsCancellationRequested) return; foreach (ElementNode element in item) { if (element != null) { if (tokenSource != null && tokenSource.IsCancellationRequested) return; pulse.TimeSpan = segmentPulse; pulse.ColorGradient = _data.ColorGradient; pulse.LevelCurve = _data.Curve; pulse.TargetNodes = new ElementNode[] { element }; result = pulse.Render(); result.OffsetAllCommandsByTime(effectTime); _elementData.Add(result); } } effectTime += intervalTime; if (effectTime >= TimeSpan) return; } } } } }
public WipeTransition(WipeDirection direction) : this(direction, TimeSpan.FromSeconds(2)) { }
private void RenderBurst(CancellationTokenSource tokenSource, WipeDirection direction) { switch (direction) { case WipeDirection.In: case WipeDirection.Out: break; default: throw new InvalidOperationException("the RenderBurst method should only be called for Wipe Directions In and Out"); break; } var burstNodes = TargetNodes.SelectMany(x => x.GetLeafEnumerator()) .Select(s => { var prop = s.Properties.Get(LocationDescriptor._typeId); if (prop != null) { return(new Tuple <ElementNode, int, int, int>(s, ((LocationData)prop.ModuleData).X, ((LocationData)prop.ModuleData).Y, ((LocationData)prop.ModuleData).Z)); } return(new Tuple <ElementNode, int, int, int>(null, -1, -1, -1)); //return null }) .Where(s => s.Item2 > 0) // Ignore the pseudo null values .ToList(); if (!burstNodes.Any()) { return; } var maxX = burstNodes.Max(m => m.Item2); var maxY = burstNodes.Max(m => m.Item3); var minX = burstNodes.Min(m => m.Item2); var minY = burstNodes.Min(m => m.Item3); var Steps = (int)(Math.Max(maxX - minX, maxY - minY) / 2); List <Tuple <int, ElementNode[]> > groups = new List <Tuple <int, ElementNode[]> >(); for (int i = 0; i < Steps; i++) { List <ElementNode> elements = new List <ElementNode>(); var xNodes = burstNodes.Where(x => (x.Item2 == minX + i || x.Item2 == maxX - i) ) .Select(s => s.Item1).ToList(); var yNodes = burstNodes.Where(x => ( x.Item3 == minY + i || x.Item3 == maxY - i) ) .Select(s => s.Item1).ToList(); yNodes.RemoveAll(s => { var prop = s.Properties.Get(LocationDescriptor._typeId); if (prop != null) { return(((LocationData)prop.ModuleData).X < minX + i || ((LocationData)prop.ModuleData).X > maxX - i); } return(false); }); xNodes.RemoveAll(s => { var prop = s.Properties.Get(LocationDescriptor._typeId); if (prop != null) { return(((LocationData)prop.ModuleData).Y < minY + i || ((LocationData)prop.ModuleData).Y > maxY - i); } return(false); }); elements.AddRange(yNodes); elements.AddRange(xNodes); groups.Add(new Tuple <int, ElementNode[]>(i, elements.ToArray())); } List <ElementNode[]> renderNodes = new List <ElementNode[]>(); switch (direction) { case WipeDirection.In: renderNodes = groups.OrderBy(o => o.Item1).Select(s => s.Item2).ToList(); break; case WipeDirection.Out: renderNodes = groups.OrderByDescending(o => o.Item1).Select(s => s.Item2).ToList(); break; } //var pulse = new Pulse.Pulse(); if (renderNodes != null && renderNodes.Any()) { TimeSpan effectTime = TimeSpan.Zero; if (WipeByCount) { int count = 0; double pulseSegment = TimeSpan.Ticks / (double)PassCount * (PulsePercent / 100); TimeSpan intervalTime = TimeSpan.FromTicks((long)((TimeSpan.Ticks - pulseSegment) / (renderNodes.Count() * PassCount))); TimeSpan segmentPulse = TimeSpan.FromTicks((long)pulseSegment); while (count < PassCount) { foreach (var item in renderNodes) { if (tokenSource != null && tokenSource.IsCancellationRequested) { return; } EffectIntents result; foreach (ElementNode element in item) { if (tokenSource != null && tokenSource.IsCancellationRequested) { return; } if (element != null) { //pulse.TimeSpan = segmentPulse; //pulse.ColorGradient = _data.ColorGradient; //pulse.LevelCurve = _data.Curve; //pulse.TargetNodes = new ElementNode[] { element }; //result = pulse.Render(); result = PulseRenderer.RenderNode(element, _data.Curve, _data.ColorGradient, segmentPulse, HasDiscreteColors); result.OffsetAllCommandsByTime(effectTime); bool discreteElement = HasDiscreteColors && ColorModule.isElementNodeDiscreteColored(element); _elementData.Add(IntentBuilder.ConvertToStaticArrayIntents(result, TimeSpan, discreteElement)); } } effectTime += intervalTime; } count++; } } else { double intervals = (double)PulseTime / (double)renderNodes.Count(); var intervalTime = TimeSpan.FromMilliseconds(intervals); // the calculation above blows up render time/memory as count goes up, try this.. // also fails if intervals is less than half a ms and intervalTime then gets 0 intervalTime = TimeSpan.FromMilliseconds(Math.Max(intervalTime.TotalMilliseconds, 5)); TimeSpan segmentPulse = TimeSpan.FromMilliseconds(PulseTime); while (effectTime < TimeSpan) { foreach (var item in renderNodes) { EffectIntents result; if (tokenSource != null && tokenSource.IsCancellationRequested) { return; } foreach (ElementNode element in item) { if (element != null) { if (tokenSource != null && tokenSource.IsCancellationRequested) { return; } //pulse.TimeSpan = segmentPulse; //pulse.ColorGradient = _data.ColorGradient; //pulse.LevelCurve = _data.Curve; //pulse.TargetNodes = new ElementNode[] { element }; //result = pulse.Render(); result = PulseRenderer.RenderNode(element, _data.Curve, _data.ColorGradient, segmentPulse, HasDiscreteColors); result.OffsetAllCommandsByTime(effectTime); bool discreteElement = HasDiscreteColors && ColorModule.isElementNodeDiscreteColored(element); _elementData.Add(IntentBuilder.ConvertToStaticArrayIntents(result, TimeSpan, discreteElement)); } } effectTime += intervalTime; if (effectTime >= TimeSpan) { return; } } } } } }
public WipeTransition(WipeDirection direction, TimeSpan duration) { time = duration; this.direction = direction; }
private void MigrateWipeFrom6To7(XElement content) { // This migration deals with changing the Wipe Direction property to reduce the number of options in the Direction and add in reverse option. // Add Wipe movement and movement curve. // Get the standard namespaces that are needed in the sequence var namespaces = GetStandardNamespaces(); XNamespace d2p1 = "http://schemas.datacontract.org/2004/07/VixenModules.Effect.Wipe"; namespaces.AddNamespace("d2p1", d2p1.NamespaceName); //Find the Wipe effects. IEnumerable <XElement> wipeElements = content.XPathSelectElements( "_dataModels/d1p1:anyType[@i:type = 'd2p1:WipeData']", namespaces); var datamodel = content.XPathSelectElement("_dataModels", namespaces); foreach (var wipeElement in wipeElements.ToList()) { XElement direction = wipeElement.XPathSelectElement("d2p1:Direction", namespaces); XElement colorGradient = wipeElement.XPathSelectElement("d2p1:ColorGradient", namespaces); XElement colorHandling = wipeElement.XPathSelectElement("d2p1:ColorHandling", namespaces); XElement passCount = wipeElement.XPathSelectElement("d2p1:PassCount", namespaces); XElement pulsePercent = wipeElement.XPathSelectElement("d2p1:PulsePercent", namespaces); XElement pulseTime = wipeElement.XPathSelectElement("d2p1:PulseTime", namespaces); XElement wipeByCount = wipeElement.XPathSelectElement("d2p1:WipeByCount", namespaces); XElement wipeOn = wipeElement.XPathSelectElement("d2p1:WipeOn", namespaces); XElement wipeOff = wipeElement.XPathSelectElement("d2p1:WipeOff", namespaces); XElement curve = wipeElement.XPathSelectElement("d2p1:Curve", namespaces); XElement moduleInstanceId = wipeElement.XPathSelectElement("ModuleInstanceId", namespaces); XElement moduleTypeId = wipeElement.XPathSelectElement("ModuleTypeId", namespaces); WipeDirection dataDirection = WipeDirection.Burst; bool dataReverseDirection = false; switch (direction.Value) { case "Up": dataDirection = WipeDirection.Vertical; dataReverseDirection = true; break; case "Down": dataDirection = WipeDirection.Vertical; dataReverseDirection = false; break; case "Right": dataDirection = WipeDirection.Horizontal; dataReverseDirection = false; break; case "Left": dataDirection = WipeDirection.Horizontal; dataReverseDirection = true; break; case "In": dataDirection = WipeDirection.Burst; dataReverseDirection = true; break; case "Out": dataDirection = WipeDirection.Burst; dataReverseDirection = false; break; } WipeData data = new WipeData { ColorGradient = new ColorGradient(DeSerializer <ColorGradient>(colorGradient)), ColorHandling = DeSerializer <ColorHandling>(colorHandling), PassCount = DeSerializer <int>(passCount), PulsePercent = DeSerializer <double>(pulsePercent), PulseTime = DeSerializer <int>(pulseTime), WipeMovement = DeSerializer <bool>(wipeByCount) ? WipeMovement.Count : WipeMovement.PulseLength, WipeOn = DeSerializer <bool>(wipeOn), WipeOff = DeSerializer <bool>(wipeOff), ColorAcrossItemPerCount = true, ReverseColorDirection = true, Curve = DeSerializer <Curve>(curve), MovementCurve = new Curve(new PointPairList(new[] { 0.0, 100.0 }, new[] { 0.0, 100.0 })), Direction = dataDirection, ReverseDirection = dataReverseDirection, ModuleInstanceId = DeSerializer <Guid>(moduleInstanceId), ModuleTypeId = DeSerializer <Guid>(moduleTypeId) }; //Remove the old version wipeElement.Remove(); //Build up a temporary container similar to the way sequences are stored to //make all the namespace prefixes line up. IModuleDataModel[] dm = { data }; DataContainer dc = new DataContainer { _dataModels = dm }; //Serialize the object into a xelement XElement glp = Serializer(dc, new[] { typeof(WipeData), typeof(IModuleDataModel[]), typeof(DataContainer) }); //Extract the new data model that we want and insert it in the tree datamodel.Add(glp.XPathSelectElement("//*[local-name()='anyType']", namespaces)); } }