public Dancer(Dancer from) : this(from.number, from.number_couple, from.gender, from.fillColor, from.tx, GeometryMaker.makeOne(from.geom.geometry(), 0), new List <Movement>()) { clonedFrom = from; // For the sequencer, copy dancer data data.active = from.data.active; }
// Create a context from a formation defined in XML public CallContext(IXmlNode f) { dancers = new List <Dancer>(); var fds = f.SelectNodes("dancer"); for (uint i = 0; i < fds.Count; i++) { var fd = fds.Item(i); // Assume square geometry var m = Matrix.CreateRotation(fd.attr("angle").toDouble() * Math.PI / 180); m = m * Matrix.CreateTranslation(fd.attr("x").toDouble(), fd.attr("y").toDouble()); dancers.Add(new Dancer($"{i * 2 + 1}", $"{i + 1}", genderMap(fd.attr("gender")), Colors.White, m, GeometryMaker.makeOne(GeometryType.SQUARE, 0), new List <Movement>())); dancers.Add(new Dancer($"{i * 2 + 2}", $"{i + 1}", genderMap(fd.attr("gender")), Colors.White, m, GeometryMaker.makeOne(GeometryType.SQUARE, 1), new List <Movement>())); } }
public void resetAnimation() { if (tam != null) { leadin = interactiveDancer < 0 ? 2 : 3; leadout = interactiveDancer < 0 ? 2 : 1; // if (isRunnning) // doneCallback(); isRunning = false; beats = 0.0; var tlist = tam.SelectNodes("formation"); var formation = tlist.Length > 0 ? tlist.First() // formation defined in animation : tam.hasAttr("formation") ? TamUtils.getFormation(tam.attr("formation")) // formation reference to formations.xml : tam; // formation passed in for sequencer var flist = formation.SelectNodes("dancer"); dancers = new Dancer[flist.Length * (int)geometry]; // Except for the phantoms, these are the standard colors // used for teaching callers var dancerColor = geometry == GeometryType.HEXAGON ? new Color[] { Colors.Red, Colors.ForestGreen, Colors.Magenta, Colors.Blue, Colors.Yellow, Colors.Cyan, Colors.LightGray, Colors.LightGray, Colors.LightGray, Colors.LightGray } : new Color[] { Colors.Red, ColorUtilities.ColorFromHex(0xff00c000), Colors.Blue, Colors.Yellow, Colors.LightGray, Colors.LightGray, Colors.LightGray, Colors.LightGray }; // Get numbers for dancers and couples // This fetches any custom numbers that might be defined in // the animation to match a Callerlab or Ceder Chest illustration var paths = tam.SelectNodes("path"); var numbers = geometry == GeometryType.HEXAGON ? new string[] { "A", "E", "I", "B", "F", "J", "C", "G", "K", "D", "H", "L", "u", "v", "w", "x", "y", "z" } : geometry == GeometryType.BIGON || paths.Length == 0 ? new string[] { "1", "2", "3", "4", "5", "6", "7", "8" } : TamUtils.getNumbers(tam); var couples = geometry == GeometryType.HEXAGON ? new string[] { "1", "3", "5", "1", "3", "5", "2", "4", "6", "2", "4", "6", "7", "8", "7", "8", "7", "8" } : geometry == GeometryType.BIGON ? new string[] { "1", "2", "3", "4", "5", "6", "7", "8" } : paths.Length == 0 ? new string[] { "1", "3", "1", "3", "2", "4", "2", "4" } : TamUtils.getCouples(tam); var geoms = GeometryMaker.makeAll(geometry); // Select a random dancer of the correct gender for the interactive dancer var icount = -1; var im = Matrix3x2.Identity; if (interactiveDancer > 0) { var rand = new Random(); var selector = interactiveDancer == (int)Gender.BOY ? "dancer[@gender='boy']" : "dancer[@gender='girl']"; var glist = formation.SelectNodes(selector); icount = rand.Next(glist.Count); // If the animations starts with "Heads" or "Sides" // then select the first dancer. // Otherwise the formation could rotate 90 degrees // which would be confusing var title = tam.attr("title"); if (title.Contains("Heads") || title.Contains("Sides")) { icount = 0; } // Find the angle the interactive dancer faces at start // We want to rotate the formation so that direction is up var iangle = glist.Item((uint)icount).attr("angle").toDouble(); im = Matrix.CreateRotation(-iangle.toRadians()) * im; icount = icount * geoms.Count() + 1; } // Create the dancers and set their starting positions int dnum = 0; for (var i = 0; i < flist.Length; i++) { var fd = flist.ElementAt(i); var x = fd.attr("x").toDouble(); var y = fd.attr("y").toDouble(); var angle = fd.attr("angle").toDouble(); var gender = fd.attr("gender"); var g = gender == "boy" ? Gender.BOY : gender == "girl" ? Gender.GIRL : Gender.PHANTOM; var movelist = paths.Length > i?TamUtils.translatePath(paths.ElementAt(i)) : new List <Movement>(); // Each dancer listed in the formation corresponds to // one, two, or three real dancers depending on the geometry foreach (Geometry geom in geoms) { var m = Matrix3x2.Identity * Matrix.CreateRotation(angle.toRadians()) * Matrix.CreateTranslation(x, y) * im; var nstr = g == Gender.PHANTOM ? " " : numbers[dnum]; var cstr = g == Gender.PHANTOM ? " " : couples[dnum]; var c = g == Gender.PHANTOM ? Colors.LightGray : dancerColor[int.Parse(cstr) - 1]; // add one dancer //icount -= 1; if ((int)g == interactiveDancer && --icount == 0) { idancer = new InteractiveDancer(nstr, cstr, g, c, m, geom.clone(), movelist); dancers[dnum] = idancer; } else { dancers[dnum] = new Dancer(nstr, cstr, g, c, m, geom.clone(), movelist); dancers[dnum].hidden = g == Gender.PHANTOM && !showPhantoms; } beats = Math.Max(dancers[dnum].beats + leadout, beats); dnum++; } } // All dancers added // Initialize other stuff parts = tam.attr("parts") + tam.attr("fractions"); hasParts = tam.attr("parts").Length > 0; isRunning = false; beat = -leadin; prevbeat = -leadin; partbeats = partsValues(); // force a redraw canvas.Invalidate(); // ready callback Callouts.animationReady(); } }
private void doDraw(CanvasDrawingSession ds) { ds.FillRectangle(new Rect(0.0, 0.0, ActualWidth, ActualHeight), Color.FromArgb(255, 255, 240, 224)); // Note loop and dancer speed // ... // For interactive leadin, show countdown // ... // Scale coordinate system to dancer's size var range = Math.Min(ActualWidth, ActualHeight); ds.Transform = Matrix3x2.CreateTranslation(new Vector2((float)ActualWidth / 2, (float)ActualHeight / 2)); var s = range / 13; // Flip and rotate ds.Transform = Matrix.CreateScale(s, -s) * ds.Transform; ds.Transform = Matrix.CreateRotation(Math.PI / 2) * ds.Transform; // Draw grid if on if (showGrid) { GeometryMaker.makeOne(geometry).drawGrid(s, ds); } // Always show bigon center mark if (geometry == GeometryType.BIGON) { ds.DrawLine(0, -0.5f, 0, 0.5f, Colors.Black, 1 / (float)s); ds.DrawLine(-0.5f, 0, 0.5f, 0, Colors.Black, 1 / (float)s); } // Draw paths if requested foreach (Dancer d in dancers) { if (!d.hidden && (showPaths || d.showPath)) { d.drawPath(ds); } } // Draw handholds foreach (Dancer d in dancers) { var loc = d.location; if (d.rightHandVisibility) { if (d.rightdancer == null) // hexagon center { } else if (d.rightdancer.CompareTo(d) < 0) { var loc2 = d.rightdancer.location; ds.DrawLine(loc, loc2, Colors.Orange, 0.05f); ds.FillCircle((loc + loc2) / 2, 0.125f, Colors.Orange); } } if (d.leftHandVisibility) { if (d.leftdancer == null) // hexagon center { } else if (d.leftdancer.CompareTo(d) < 0) { var loc2 = d.leftdancer.location; ds.DrawLine(loc, loc2, Colors.Orange, 0.05f); ds.FillCircle((loc + loc2) / 2, 0.125f, Colors.Orange); } } } // Draw dancers foreach (Dancer d in dancers) { if (!d.hidden) { var txsave = ds.Transform; ds.Transform = d.tx * ds.Transform; d.draw(ds); ds.Transform = txsave; } } }