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