private void setAnimation() { var tam = alltams.ElementAt(animnum); Callouts.SetTitle(tam.attr("title")); animationView.setAnimation(tam); sliderTicView.setTics(animationView.totalBeats, animationView.parts, isParts: animationView.hasParts); Callouts.progressCallback = (double beat) => { // Set slider to the current beat userDrag = false; slider.Value = beat * 100 / animationView.totalBeats; userDrag = true; // Fade out any Taminator text // Win wants an "opacity" value from 1 to 0 var a = Math.Max((2.0 - beat) / 2.01, 0.0); saysPanel.Opacity = a; }; var taminator = tam.SelectSingleNode("taminator"); if (taminator != null) { saysText.Text = taminator.FirstChild.NodeValue.ToString().Trim().ReplaceAll("\\s+", " "); } animnumText.Text = $"{animnum+1} of {animtot}"; readSettings(); }
private void Level_Tapped(object sender, TappedRoutedEventArgs e) { var grid = (Grid)sender; Callouts.LevelButtonAction(grid.Name); e.Handled = true; }
public AnimationPage() { this.InitializeComponent(); var link = this.Intent()["link"]; var tamdoc = TamUtils.getXMLAsset(this.Intent()["link"]); alltams = TamUtils.tamList(tamdoc).Where(t => t.attr("display") != "none"); animtot = alltams.Count(); animnum = int.Parse(this.Intent()["anim"]); Callouts.SetLevel(link); setAnimation(); Callouts.AnimationFinished = () => { PlayPath.Fill = new SolidColorBrush(Colors.Black); PausePath.Fill = new SolidColorBrush(Colors.Transparent); playing = false; }; ManipulationMode = ManipulationModes.TranslateX; ManipulationStarted += (x, e) => x1 = (int)e.Position.X; ManipulationCompleted += (x, e) => { x2 = (int)e.Position.X; if (x1 - x2 > animationView.ActualWidth / 2 && animnum + 1 < animtot) { // swipe left animnum++; setAnimation(); } else if (x2 - x1 > animationView.ActualWidth / 2 && animnum > 0) { // swipe right animnum--; setAnimation(); } }; }
public SettingsPage() { this.InitializeComponent(); Callouts.SetTitle("Settings"); switch (settings.Values["speed"]?.ToString()) { case "Fast": speedFastRB.IsChecked = true; break; case "Slow": speedSlowRB.IsChecked = true; break; default: speedNormalRB.IsChecked = true; break; } switch (settings.Values["numbers"]?.ToString()) { case "1-8": numbersDancersRB.IsChecked = true; break; case "1-4": numbersCouplesRB.IsChecked = true; break; default: numbersNoneRB.IsChecked = true; break; } switch (settings.Values["geometry"]?.ToString()) { case "Hexagon": geometryHexagonRB.IsChecked = true; break; case "Bigon": geometryBigonRB.IsChecked = true; break; default: geometrySquareRB.IsChecked = true; break; } gridSwitch.IsOn = settings.Values["grid"]?.ToString() == "On"; loopSwitch.IsOn = settings.Values["loop"]?.ToString() == "On"; pathsSwitch.IsOn = settings.Values["paths"]?.ToString() == "On"; phantomsSwitch.IsOn = settings.Values["phantoms"]?.ToString() == "On"; }
private void AnimList_SelectionChanged(object sender, SelectionChangedEventArgs e) { var item = (AnimListItem)AnimList.SelectedItem; if (item.animnumber >= 0) { item.isSelected = true; Callouts.AnimationSelected(item); } }
public void reset(string level) { LevelData d = LevelData.find(level); var isIndex = d.dir == "all"; XmlDocument calldoc = TamUtils.getXMLAsset(isIndex ? "src\\callindex.xml" : "src\\calls.xml"); Callouts.SetTitle(d.name); calls = calldoc.SelectNodes(isIndex ? "/calls/call" : $"/calls/call[@{d.selector}]"); searchCallList(""); }
public LevelPage() { this.InitializeComponent(); var screenSize = MainPage.ScreenSize(); if (screenSize.Length() < 6) { DisplayInformation.AutoRotationPreferences = DisplayOrientations.Portrait; } Callouts.SetTitle("Taminations"); }
public DefinitionPage() { this.InitializeComponent(); var link = this.Intent()["link"].ReplaceAll(@"\..*", "") + ".html"; Callouts.SetLevel(link); Uri url = webview.BuildLocalStreamUri("assets", link.ReplaceAll("ms/", "ms0/")); webview.NavigationCompleted += navigationCompleted; webview.NavigateToLocalStreamUri(url, this); // if (!Regex.Match(link, "^(b1|b2|ms0)").Success) // AbbrevFullPanel.Visibility = Visibility.Collapsed; Callouts.AnimationPart = async(int part) => { await webview.InvokeScriptAsync("eval", new string[] { $"setPart({part})" }); }; }
public override void nextAnimation() { if (tutnum >= tutdata.Length) tutnum = 0; var tamdoc = TamUtils.getXMLAsset("src/tutorial.xml"); var gender = settings.Values["gender"]?.ToString() == "Girl" ? Gender.GIRL : Gender.BOY; var offset = gender == Gender.BOY ? 0 : 1; var tamlist = tamdoc.SelectNodes("/tamination/tam"); var tam = tamlist[tutnum * 2 + offset]; Callouts.SetTitle(tam.attr("title")); page.Animation.setAnimation(tam,(int)gender); switch (settings.Values["practicespeed"]?.ToString()) { case "Normal": page.Animation.setSpeed("Normal"); break; case "Moderate": page.Animation.setSpeed("Moderate"); break; default: page.Animation.setSpeed("Slow"); break; } showInstructions(); }
// This is called by the system to redraw the animation private void canvas_Draw(CanvasControl sender, CanvasDrawEventArgs args) { if (tam != null) { // Update the animation time var now = DateTime.Now; var diff = now.Subtract(lastTime).Milliseconds; if (isRunning) { beat = beat + diff / speed; } lastTime = now; // Move the dancers updateDancers(); // Draw the dancers doDraw(args.DrawingSession); // Remember time of this update, and handle loop and end prevbeat = beat; if (beat >= beats) { if (looping && isRunning) { prevbeat = -leadin; beat = -leadin; } else if (isRunning) { isRunning = false; Callouts.AnimationFinished(); } } Callouts.progressCallback(beat + leadin); // Continually epeat by telling the system to re-draw if (isRunning) { canvas.Invalidate(); } } }
public virtual void nextAnimation() { var calldoc = TamUtils.getXMLAsset("src/calls.xml"); var selector = LevelData.find(page.Intent()["level"]).selector; var calls = calldoc.SelectNodes($"/calls/call[@{selector}]"); IXmlNode tam = null; var rand = new Random(); while (tam == null) { var e = calls[rand.Next((int)calls.Length)]; // Remember link for definition link = e.attr("link"); var tamdoc = TamUtils.getXMLAsset(link); var tams = tamdoc.SelectNodes("/tamination/tam") // For now, skip any "difficult" animations .Where((IXmlNode x) => { return(x.attr("difficulty") != "3"); }) // Skip any call with parens in the title - it could be a cross-reference // to a concept call from a higher level .Where((IXmlNode x) => { return(!x.attr("title").Contains("(")); }); if (tams.Count() > 0) { tam = tams.ElementAt(rand.Next(tams.Count())); var gender = settings.Values["practicegender"]?.ToString() == "Boy" ? (int)Gender.BOY : (int)Gender.GIRL; page.Animation.setAnimation(tam, gender); switch (settings.Values["practicespeed"]?.ToString()) { case "Normal": page.Animation.setSpeed("Normal"); break; case "Moderate": page.Animation.setSpeed("Moderate"); break; default: page.Animation.setSpeed("Slow"); break; } Callouts.SetTitle(tam.attr("title")); } } }
public AboutPage() { this.InitializeComponent(); Callouts.SetTitle("About Taminations"); }
private void CallList_SelectionChanged(object sender, SelectionChangedEventArgs e) { var item = (CallListItem)CallList.SelectedItem; Callouts.CallSelected(item.Link); }
public void reset() { // Fetch the list of animations and build the table var prevtitle = ""; var prevgroup = ""; link = this.Intent()["link"]; Callouts.SetLevel(link); XmlDocument tamdoc = TamUtils.getXMLAsset(link); var title = tamdoc.SelectSingleNode("/tamination").attr("title"); Callouts.SetTitle(title); var tams = TamUtils.tamList(tamdoc); var diffsum = 0; var firstanim = -1; var i = 0; foreach (IXmlNode tam in tams) { if (tam.attr("display") == "none") { continue; } var tamtitle = tam.attr("title"); var from = TamUtils.tamXref(tam).attr("from"); var group = tam.attr("group"); var diffstr = TamUtils.tamXref(tam).attr("difficulty"); var diff = diffstr.Length > 0 ? int.Parse(diffstr) : 0; diffsum += diff; if (group.Length > 0) { // Add header for new group as needed if (group != prevgroup) { if (Regex.Match(group, @"^\s+$").Success) { // Blank group, for calls with no common starting phrase // Add a green separator unless it's the first group if (anims.Count > 0) { anims.Add(new AnimListItem() { celltype = CellType.Separator }); } } else { // Named group e.g. "As Couples.." // Add a header with the group name, which starts // each call in the group anims.Add(new AnimListItem() { celltype = CellType.Header, name = group }); } } from = tamtitle.Replace(group, " ").Trim(); } else if (tamtitle != prevtitle) { // Not a group but a different call // Put out a header with this call anims.Add(new AnimListItem() { celltype = CellType.Header, name = tamtitle + " from" }); } // Build list item for this animation prevtitle = tamtitle; prevgroup = group; // TODO posanim(av.getCount) = i // Remember where the first real animation is in the list if (firstanim < 0) { firstanim = anims.Count; } // TODO selectanim and weblink // ... // Put out a selectable item anims.Add(new AnimListItem() { celltype = Regex.Match(group, @"^\s+$").Success ? CellType.Plain : CellType.Indented, title = tamtitle, name = from, group = group.Length > 0 ? group : tamtitle + " from", animnumber = i, difficulty = diff }); i = i + 1; } if (diffsum <= 0) { DifficultyLegend.Visibility = Visibility.Collapsed; } AnimList.ItemsSource = anims; if (firstanim >= 0) { Callouts.FirstAnimationReady(anims[firstanim]); } }
private void Settings_Tapped(object sender, TappedRoutedEventArgs e) { Callouts.LevelSettingsAction(); }
private void About_Tapped(object sender, TappedRoutedEventArgs e) { Callouts.AboutAction(); }
private void Sequencer_Tapped(object sender, TappedRoutedEventArgs e) { Callouts.SequencerAction(); }
private void Practice_Tapped(object sender, TappedRoutedEventArgs e) { Callouts.StartPracticeAction(); }
/** * Updates dancers positions based on the passage of realtime. */ private void updateDancers() { // Move dancers // For big jumps, move incrementally - // this helps hexagon and bigon compute the right location var delta = beat - prevbeat; var incs = (int)Math.Ceiling(Math.Abs(delta)); for (int j = 1; j <= incs; j++) { foreach (Dancer d in dancers) { d.animate(prevbeat + j * delta / incs); } } // Find the current part, and send a message if it's changed var thispart = 0; if (beat >= 0 && beat <= beats) { for (var i = 0; i < partbeats.Length; i++) { if (partbeats[i] < beat) { thispart = i; } } } if (thispart != currentPart) { currentPart = thispart; Callouts.AnimationPart(currentPart); } // Compute handholds var hhlist = new List <Handhold>(); foreach (Dancer d0 in dancers) { d0.rightdancer = null; d0.leftdancer = null; d0.rightHandVisibility = false; d0.leftHandVisibility = false; } for (int i1 = 0; i1 < dancers.Count() - 1; i1++) { var d1 = dancers[i1]; if (!d1.isPhantom || showPhantoms) { for (int i2 = i1 + 1; i2 < dancers.Count(); i2++) { var d2 = dancers[i2]; if (!d2.isPhantom || showPhantoms) { var hh = Handhold.Create(d1, d2, geometry); if (hh != null) { hhlist.Add(hh); } } } } } // Sort the array to put best scores first var hharr = hhlist.ToArray(); Array.Sort(hharr); // Apply the handholds in order from best to worst // so that if a dancer has a choice it gets the best handhold foreach (Handhold hh in hharr) { // Check that the hands aren't already used var incenter = geometry == GeometryType.HEXAGON && hh.inCenter; if (incenter || (hh.hold1 == Hands.RIGHTHAND && hh.dancer1.rightdancer == null || hh.hold1 == Hands.LEFTHAND && hh.dancer1.leftdancer == null) && (hh.hold2 == Hands.RIGHTHAND && hh.dancer2.rightdancer == null || hh.hold2 == Hands.LEFTHAND && hh.dancer2.leftdancer == null)) { // Make the handhold visible // Scale should be 1 if distance is 2 // float scale = hh.distance/2f; if (hh.hold1 == Hands.RIGHTHAND || hh.hold1 == Hands.GRIPRIGHT) { hh.dancer1.rightHandVisibility = true; hh.dancer1.rightHandNewVisibility = true; } if (hh.hold1 == Hands.LEFTHAND || hh.hold1 == Hands.GRIPLEFT) { hh.dancer1.leftHandVisibility = true; hh.dancer1.leftHandNewVisibility = true; } if (hh.hold2 == Hands.RIGHTHAND || hh.hold2 == Hands.GRIPRIGHT) { hh.dancer2.rightHandVisibility = true; hh.dancer2.rightHandNewVisibility = true; } if (hh.hold2 == Hands.LEFTHAND || hh.hold2 == Hands.GRIPLEFT) { hh.dancer2.leftHandVisibility = true; hh.dancer2.leftHandNewVisibility = true; } if (!incenter) { if (hh.hold1 == Hands.RIGHTHAND) { hh.dancer1.rightdancer = hh.dancer2; if ((hh.dancer1.hands & Hands.GRIPRIGHT) == Hands.GRIPRIGHT) { hh.dancer1.rightgrip = hh.dancer2; } } else { hh.dancer1.leftdancer = hh.dancer2; if ((hh.dancer1.hands & Hands.GRIPLEFT) == Hands.GRIPLEFT) { hh.dancer1.leftgrip = hh.dancer2; } } if (hh.hold2 == Hands.RIGHTHAND) { hh.dancer2.rightdancer = hh.dancer1; if ((hh.dancer2.hands & Hands.GRIPRIGHT) == Hands.GRIPRIGHT) { hh.dancer2.rightgrip = hh.dancer1; } } else { hh.dancer2.leftdancer = hh.dancer1; if ((hh.dancer2.hands & Hands.GRIPLEFT) == Hands.GRIPLEFT) { hh.dancer2.leftgrip = hh.dancer1; } } } } } // Clear handholds no longer visible foreach (Dancer d in dancers) { if (d.leftHandVisibility && !d.leftHandNewVisibility) { d.leftHandVisibility = false; } if (d.rightHandVisibility && !d.rightHandNewVisibility) { d.rightHandVisibility = false; } } // Update interactive dancer score if (idancer != null && beat > 0.0 && beat < beats - leadout) { idancer.onTrack = isInteractiveDancerOnTrack(); if (idancer.onTrack) { iscore += (beat - Math.Max(prevbeat, 0)) * 10; } } }
private void pathsSwitch_Toggled(object sender, RoutedEventArgs e) { settings.Values["paths"] = (sender as ToggleSwitch).IsOn ? "On" : "Off"; Callouts.settingsChanged(); }
private void speedFastRB_Checked(object sender, RoutedEventArgs e) { settings.Values["speed"] = "Fast"; Callouts.settingsChanged(); }
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 geometryBigonRB_Tapped(object sender, TappedRoutedEventArgs e) { settings.Values["geometry"] = "Bigon"; Callouts.settingsChanged(); }
private void numbersCouplesRB_Tapped(object sender, TappedRoutedEventArgs e) { settings.Values["numbers"] = "1-4"; Callouts.settingsChanged(); }
private void Definition_Tapped(object sender, TappedRoutedEventArgs e) { Callouts.AnimationDefinitionAction(this.Intent()["link"]); }