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;
 }
Exemple #2
0
        //  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;
                }
            }
        }