using System; using System.Collections.Generic; using System.Xml; using System.Collections.ObjectModel; namespace DMX2 { public class SequenceurMacro : Sequenceur { public class Ligne { public Ligne(){} string nom = string.Empty; TimeSpan top = TimeSpan.MinValue; string circuits = string.Empty; int valeur; TimeSpan temps = TimeSpan.Zero; public string Nom { get { return nom; } set { nom = value; } } public TimeSpan Top { get { return top; } set { top = value; } } public string Circuits { get { return circuits; } set { circuits = value; } } public int Valeur { get { return valeur; } set { valeur = value; } } public TimeSpan Temps { get { return temps; } set { temps = value; } } public void Save (XmlElement parent) { XmlElement el = parent.OwnerDocument.CreateElement ("Ligne"); parent.AppendChild (el); el.SetAttribute ("nom", nom); el.SetAttribute ("top", top.ToString ()); el.SetAttribute ("circuits", circuits); el.SetAttribute ("valeur", valeur.ToString ()); el.SetAttribute ("temps", temps.ToString ()); } public static Ligne Load (Conduite c, XmlElement el) { Ligne l = new Ligne(); l.nom = el.GetAttribute ("nom"); l.top = TimeSpan.Parse(el.GetAttribute("top")); l.circuits = el.GetAttribute ("circuits"); l.valeur = int.Parse(el.GetAttribute("valeur")); l.temps = TimeSpan.Parse(el.GetAttribute("temps")); return l; } } public class EffetMacro { public EffetMacro( TimeSpan tempsTransition, int valeurInitiale, int valeurFinale) { TempsPasse = TimeSpan.Zero; TempsTransition = tempsTransition; ValeurInitiale= valeurInitiale; ValeurFinale = valeurFinale; } public TimeSpan TempsPasse { get; set; } public TimeSpan TempsTransition { get; set; } public int ValeurInitiale { get; set; } public int ValeurFinale { get; set; } public bool Incremente (TimeSpan delta) { TempsPasse += delta; if (TempsPasse > TempsTransition) { TempsPasse = TempsTransition; return true; } return false; } public int ValeurCourante() { double progression = TempsPasse.TotalMilliseconds/TempsTransition.TotalMilliseconds; return (int)( progression * (ValeurFinale - ValeurInitiale) + ValeurInitiale ); } } List lignes = new List(); Ligne aSuivre = null; Ligne enCours = null; Ligne ligneMaitre = null; TimeSpan timeStamp = TimeSpan.Zero; TimeSpan topSuivant = TimeSpan.Zero; bool topPresent = false; List circuitsSeq = new List (); Dictionary valeurscourantes = new Dictionary (); Dictionary effetsEnCours = new Dictionary(); actionEventTarget masterEventTarget=null; actionEventTarget goNextEventTarget=null; actionEventTarget goBackEventTarget=null; SeqMacroUI ui = null; bool change = false; int master = 100; public int Master { get { return master; } set { master = value; } } bool paused=false; public bool Paused { get { return paused; } set { paused = value; } } public SequenceurMacro () { masterEventTarget = new actionEventTarget ( delegate(EventData data) { Master = 100 * data.value / 255; return true; } ); goNextEventTarget = new actionEventTarget ( delegate(EventData data) { if(data.value>0) LigneSuivante(); return true; } ); goBackEventTarget = new actionEventTarget ( delegate(EventData data) { if(data.value>0){ if (IndexLigneEnCours > 0) { IndexLigneaSuivre = IndexLigneEnCours - 1; LigneSuivante (); } } return true; } ); } public int IndexLigneEnCours { get { if (enCours == null) return -1; return lignes.IndexOf(enCours); } } public int IndexLigneaSuivre { get { if (aSuivre == null) return -1; return lignes.IndexOf (aSuivre); } set { aSuivre = lignes[value]; } } public int AjoutLigne (int pos) { lock (this) { lignes.Insert (pos, new Ligne ()); CommandAdd(pos); return pos; } } public void RetireLigne (int pos) { lock (this) { if (lignes [pos] == enCours) { enCours = null; if (pos + 1 < lignes.Count) aSuivre = lignes [pos + 1]; } if (lignes [pos] == aSuivre) aSuivre = null; lignes.RemoveAt (pos); CommandRemove(pos); } } public TimeSpan TimeStamp { get { return timeStamp; } } public ReadOnlyCollection Lignes { get { return lignes.AsReadOnly(); } } public ReadOnlyCollection Circuits { get { return circuitsSeq.AsReadOnly (); } } public void ChangeCircuits (System.Collections.Generic.List list) { foreach (var c in circuitsSeq.ToArray()) { if (!list.Contains (c)) lock (this) RetireCircuit (c); } foreach (var c in list) if (!circuitsSeq.Contains (c)) lock (this) AjouteCircuit (c); circuitsSeq = list; } void AjouteCircuit (Circuit c) { valeurscourantes [c] = 0; } void RetireCircuit (Circuit c) { circuitsSeq.Remove (c); valeurscourantes.Remove (c); } /*public override void MajCircuitsSupprimes () { lock (this) { foreach (var c in circuitsSeq.ToArray()) { if (!Conduite.Courante.Circuits.Contains (c)) RetireCircuit (c); } } }*/ public override int ValeurCircuit (Circuit c) { if (!circuitsSeq.Contains (c)) return 0; if(master !=100) return valeurscourantes [c] * master /100; return valeurscourantes [c]; } public int ValeurBruteCircuit (Circuit c) { if (!circuitsSeq.Contains (c)) return 0; return valeurscourantes [c]; } public override void Tick (TimeSpan time) { if (paused) return; timeStamp += time; lock (this) { List circuits = new List (effetsEnCours.Keys); foreach (Circuit c in circuits) { if (effetsEnCours [c].Incremente (time)) { valeurscourantes [c] = effetsEnCours [c].ValeurFinale; effetsEnCours.Remove (c); } else { valeurscourantes [c] = effetsEnCours [c].ValeurCourante (); } } } if (topPresent) { if (timeStamp > topSuivant){ LigneSuivante(); } } } public void LigneSuivante () { lock (this) { if(lignes.Count==0) return; int index; change = true; topPresent = false; if(aSuivre==null) // selection souris { index = IndexLigneEnCours +1; // Premier effet si aucun précédement if(index>= lignes.Count) index = 0; // Boucle si arrivé à la fin enCours = lignes[index]; // Gestion de la Reprise if(enCours.Circuits.Equals("R") && ligneMaitre != null) enCours = ligneMaitre; if(enCours.Nom.Length!=0) { ligneMaitre = enCours; timeStamp = TimeSpan.Zero; } } else { enCours = aSuivre; ligneMaitre = enCours; timeStamp = TimeSpan.Zero; } index = IndexLigneEnCours+1; if(index= TimeSpan.Zero) { topPresent = true; topSuivant= lignes[index].Top; } } aSuivre = null; LanceEffetsMacro(false,TimeSpan.Zero); if(ui!=null) ui.EffetChange(); } } void LanceEffetsMacro (bool ecrase, TimeSpan tempsMatrice) { lock (this) { if (ecrase) LanceEffetsMacro (enCours.Circuits, enCours.Valeur, tempsMatrice); else LanceEffetsMacro (enCours.Circuits, enCours.Valeur, enCours.Temps); } } void LanceEffetsMacro (string circuits, int valeurCible, TimeSpan temps) { if(circuits==null)return; string[] blocs = circuits.Split(','); foreach (string bloc in blocs) { string[] circ = bloc.Split('-'); int start, end; if(! int.TryParse(circ[0], out start)) continue; if(circ.Length > 1) // on a affaire a un bloc (de plusieurs) { if(! int.TryParse(circ[1], out end)) continue; } else end= start; for( int i = start; i<=end; i++) { Circuit c = Conduite.Courante.GetCircuitByID(i); if(circuitsSeq.Contains(c)) { effetsEnCours[c] = new EffetMacro(temps,valeurscourantes[c],valeurCible); } } } } public bool LigneChange () { if (change) { change = false; return true; } return false; } public override void Save (System.Xml.XmlElement parent) { System.Xml.XmlElement el = parent.OwnerDocument.CreateElement ("SequenceurMacro"); System.Xml.XmlElement xmlEl; parent.AppendChild (el); el.SetAttribute ("id", ID.ToString ()); el.SetAttribute ("name", Name); //el.SetAttribute ("master", master.ToString ()); el.AppendChild(xmlEl = parent.OwnerDocument.CreateElement ("Master")); xmlEl.SetAttribute("value",master.ToString()); Conduite.Courante.EventManager.SaveBindings(xmlEl,masterEventTarget); xmlEl = parent.OwnerDocument.CreateElement ("EffetSuivant"); if(Conduite.Courante.EventManager.SaveBindings(xmlEl,goNextEventTarget )) el.AppendChild(xmlEl); xmlEl = parent.OwnerDocument.CreateElement ("EffetPrecedent"); if(Conduite.Courante.EventManager.SaveBindings(xmlEl,goBackEventTarget )) el.AppendChild(xmlEl); foreach (Circuit c in circuitsSeq) { el.AppendChild(xmlEl = parent.OwnerDocument.CreateElement ("CircuitSeq")); xmlEl.SetAttribute("id",c.ID.ToString()); } foreach (Ligne li in lignes) { li.Save(el); } } public override SequenceurUI GetUI () { if (ui == null) { ui = new SeqMacroUI (this); ui.Destroyed += UiDestroyed; } return ui; } void UiDestroyed (object sender, EventArgs e) { ui = null; } public void BindMasterEvent (string eventId) { if(eventId.Length==0) { Conduite.Courante.EventManager.Unbind(masterEventTarget); return; } Conduite.Courante.EventManager.Bind(eventId,masterEventTarget); } public void BindEffetSuivantEvent (string eventId) { if (eventId.Length == 0) { Conduite.Courante.EventManager.Unbind (goNextEventTarget); return; } Conduite.Courante.EventManager.Bind(eventId,goNextEventTarget); } public void BindEffetPrecedentEvent (string eventId) { if (eventId.Length == 0) { Conduite.Courante.EventManager.Unbind (goBackEventTarget); return; } Conduite.Courante.EventManager.Bind(eventId,goBackEventTarget); } public static new SequenceurMacro Load (Conduite conduite, System.Xml.XmlElement el) { SequenceurMacro seq = new SequenceurMacro(); seq.LoadSeq(conduite,el); return seq; } private void LoadSeq (Conduite conduite, System.Xml.XmlElement el) { ID = int.Parse (el.GetAttribute ("id")); Name = el.GetAttribute ("name"); XmlElement xmlE; if ((xmlE = el["Master"]) != null) { master = int.Parse (xmlE.TryGetAttribute("value","100")); foreach(string id in EventManager.LoadBindings(xmlE)) BindMasterEvent(id); } else master = int.Parse (el.TryGetAttribute("master","100")); if ((xmlE = el["EffetSuivant"])!= null) foreach(string id in EventManager.LoadBindings(xmlE)) BindEffetSuivantEvent(id); if ((xmlE = el["EffetPrecedent"])!= null) foreach(string id in EventManager.LoadBindings(xmlE)) BindEffetPrecedentEvent(id); foreach (var xc in el.GetElementsByTagName("CircuitSeq")) { System.Xml.XmlElement xcir = xc as System.Xml.XmlElement; Circuit c = conduite.GetCircuitByID (int.Parse (xcir.GetAttribute ("id"))); circuitsSeq.Add (c); AjouteCircuit (c); } foreach (var xe in el.GetElementsByTagName("Ligne")) lignes.Add(Ligne.Load(conduite,xe as System.Xml.XmlElement)); } static System.Text.RegularExpressions.Regex regexCommandeDirecte = new System.Text.RegularExpressions.Regex( @"(?[\d,-]+) (?\d+) (?\d+)", System.Text.RegularExpressions.RegexOptions.Compiled); public void CommandDirecte (string text) { var cmd = regexCommandeDirecte.Match (text); if (cmd.Success) { string circuits = cmd.Groups["circuits"].Value; int valeur = int.Parse(cmd.Groups["valeur"].Value); TimeSpan temps = TimeSpan.FromMilliseconds(100* int.Parse(cmd.Groups["temps"].Value)); LanceEffetsMacro(circuits,valeur,temps); } } static System.Text.RegularExpressions.Regex regexCommand1 = new System.Text.RegularExpressions.Regex( @"(?\d+)(t(?\d+))?", System.Text.RegularExpressions.RegexOptions.Compiled); static System.Text.RegularExpressions.Regex regexCommand2 = new System.Text.RegularExpressions.Regex( @"(?\d+)(?(t\d+)?)?", System.Text.RegularExpressions.RegexOptions.Compiled); public override void Command (string command) { lock (this) { var cmd = regexCommand1.Match(command); if (cmd.Success) { if (cmd.Groups ["effet"].Success) { int effet = int.Parse (cmd.Groups ["effet"].Value) - 1; int transition=-1; if(effet>=lignes.Count) return; enCours = lignes[effet]; ligneMaitre = enCours; timeStamp = TimeSpan.Zero; topPresent = false; int index = IndexLigneEnCours+1; if(index= TimeSpan.Zero) { topPresent = true; topSuivant= lignes[index].Top; } } aSuivre = null; if (cmd.Groups ["transition"].Success) { transition = int.Parse (cmd.Groups ["transition"].Value); LanceEffetsMacro(true, TimeSpan.FromMilliseconds(transition *100)); } else LanceEffetsMacro(false,TimeSpan.Zero); if(ui!=null) ui.EffetChange(); } } } } void CommandAdd (int index) { lock (Conduite.Courante.SequenceurMaitre) { string[] commands = Conduite.Courante.SequenceurMaitre.GetCommands (this); for (int i = 0; i < commands.Length; i++) { var cmd = regexCommand2.Match(commands[i]); if(cmd.Success){ int ef = int.Parse(cmd.Groups["effet"].Value); if (ef-1>index) { ef++; commands[i] = ef.ToString() + cmd.Groups["params"].Value; } } } Conduite.Courante.SequenceurMaitre.SetCommands(this,commands); } } void CommandRemove (int index) { lock (Conduite.Courante.SequenceurMaitre) { string[] commands = Conduite.Courante.SequenceurMaitre.GetCommands (this); for (int i = 0; i < commands.Length; i++) { var cmd = regexCommand2.Match(commands[i]); if(cmd.Success){ int ef = int.Parse(cmd.Groups["effet"].Value); if (ef-1 == index) commands[i] = string.Empty; else if (ef-1>index) { ef--; commands[i] = ef.ToString() + cmd.Groups["params"].Value; } } } Conduite.Courante.SequenceurMaitre.SetCommands(this,commands); } } void CommandSwap (int index) { lock (Conduite.Courante.SequenceurMaitre) { string[] commands = Conduite.Courante.SequenceurMaitre.GetCommands (this); // numeros a swapper int a = index+1; int b = index+2; for (int i = 0; i < commands.Length; i++) { var cmd = regexCommand2.Match(commands[i]); if(cmd.Success){ int ef = int.Parse(cmd.Groups["effet"].Value); if (ef == a) commands[i] = b.ToString() + cmd.Groups["params"].Value; if (ef == b) commands[i] = a.ToString() + cmd.Groups["params"].Value; } } Conduite.Courante.SequenceurMaitre.SetCommands(this,commands); } } } }