using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Linq; namespace DMX2 { public class SequenceurLineaire : Sequenceur { public class Effet { string _nom; public Effet (string nom, Dictionary valeurs, TimeSpan duree, TimeSpan transition) { _nom = nom; _valeurs = new Dictionary (valeurs); _duree = duree; _transition = transition; } public string Nom { get { return _nom; } set { _nom = value; } } Dictionary _valeurs; public int this [Circuit index] { get { if (!_valeurs.ContainsKey (index)) _valeurs.Add (index, 0); return _valeurs [index]; } } public Dictionary Valeurs { get { return _valeurs; } } public void RetireCircuit (Circuit c) { _valeurs.Remove (c); } TimeSpan _duree = TimeSpan.Zero ; TimeSpan _transition = TimeSpan.Zero; public TimeSpan Duree { get { return _duree; } set { _duree = value; } } public TimeSpan Transition { get { return _transition; } set { _transition = value; } } public void Save (System.Xml.XmlElement parent) { System.Xml.XmlElement el = parent.OwnerDocument.CreateElement ("Effet"); System.Xml.XmlElement xmlVal; parent.AppendChild (el); el.SetAttribute("nom",_nom); el.SetAttribute ("duree", _duree.ToString ()); el.SetAttribute ("transition", _transition.ToString ()); foreach (var valeur in _valeurs) { xmlVal = parent.OwnerDocument.CreateElement("Valeur"); el.AppendChild(xmlVal); xmlVal.SetAttribute("circuit",valeur.Key.ID.ToString()); xmlVal.SetAttribute("valeur",valeur.Value.ToString()); } } public static Effet Load (Conduite conduite, System.Xml.XmlElement el) { Dictionary valeurs = new Dictionary (); foreach (var xv in el.GetElementsByTagName("Valeur")) { System.Xml.XmlElement xval = xv as System.Xml.XmlElement; valeurs.Add( conduite.GetCircuitByID(int.Parse(xval.GetAttribute("circuit"))), int.Parse(xval.GetAttribute("valeur")) ); } return new Effet( el.GetAttribute("nom"),valeurs, TimeSpan.Parse(el.GetAttribute("duree")), TimeSpan.Parse(el.GetAttribute("transition")) ); } } #region EventTargets class circuitEventTarget : IEventTarget { Circuit circuit; Dictionary valeursrecues= new Dictionary(); SequenceurLineaire seq; int max=0, signe=-2; bool attache; public bool Attache { get { return attache; } set { signe=-2; attache = value; } } public circuitEventTarget(SequenceurLineaire _seq, Circuit _c){ seq=_seq; circuit=_c; } bool IEventTarget.FireEvent (EventData data) { valeursrecues[data.id]=data.value; max = valeursrecues.Values.Max(); if (!Attache) { int val = seq.ValeurBruteCircuit (circuit); int cs = Math.Sign (val - max); if (signe == -2) signe=cs; if (cs==0 || cs!=signe) Attache=true; else return true ; } seq.ChangeValeur(circuit,max); return true; } } #endregion TimeSpan timeStamp = TimeSpan.Zero; TimeSpan tempsTransition = TimeSpan.Zero; List circuitsSeq = new List (); List effets = new List (); Effet effetcourrant = null; bool enTransition = false; Dictionary valeurscourantes = new Dictionary (); Dictionary valeursinitiales = new Dictionary (); Dictionary valeurschangees = new Dictionary (); Dictionary targets = new Dictionary(); actionEventTarget masterEventTarget=null; actionEventTarget goNextEventTarget=null; actionEventTarget goBackEventTarget=null; SeqLinUI ui = null; int master = 100; public int Master { get { return master; } set { master = value; } } public SequenceurLineaire () { effetcourrant = new Effet ("",valeurscourantes , TimeSpan.Zero, TimeSpan.Zero); masterEventTarget = new actionEventTarget ( delegate(EventData data) { Master = 100 * data.value / 255; return true; } ); goNextEventTarget = new actionEventTarget ( delegate(EventData data) { if(data.value>0) IndexEffetCourrant++; return true; } ); goBackEventTarget = new actionEventTarget ( delegate(EventData data) { if(data.value>0) IndexEffetCourrant--; return true; } ); } public TimeSpan TimeStamp { get { return timeStamp; } } public ReadOnlyCollection Circuits { get { return circuitsSeq.AsReadOnly (); } } public ReadOnlyCollection Effets { get { return effets.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; valeursinitiales [c] = 0; } void RetireCircuit (Circuit c) { foreach (var ef in effets) { ef.RetireCircuit (c); } circuitsSeq.Remove (c); valeurscourantes.Remove (c); valeursinitiales.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) { lock(this) { 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 void ChangeValeur (Circuit c, int value) { valeurschangees [c] = true; valeurscourantes [c] = value; } public bool EstChange (Circuit c) { return valeurschangees.ContainsKey (c); } public bool EnTransition (Circuit c) { if(!enTransition) return false ; return valeurscourantes [c] != effetcourrant [c]; } public bool EstCapture (Circuit c) { if(!targets.ContainsKey(c)) return false; return targets[c].Attache; } bool paused=false; public bool Paused { get { return paused; } set { paused = value; } } public override void Tick (TimeSpan time) { if (paused) return; timeStamp += time; lock(this) { if (enTransition) { if (timeStamp < tempsTransition) { double progression = timeStamp.TotalMilliseconds / tempsTransition.TotalMilliseconds; foreach (Circuit c in circuitsSeq) { if (valeurscourantes [c] != effetcourrant [c] && !valeurschangees.ContainsKey (c)) { valeurscourantes [c] = (int)(progression * (effetcourrant [c] - valeursinitiales [c]) + valeursinitiales [c]); } } } else { FinDeTransition (); } } if (effetcourrant.Duree != TimeSpan.Zero && timeStamp >= effetcourrant.Duree) { int index = effets.IndexOf (effetcourrant) + 1; if (index < effets.Count) ChangeEffetCourrant (index); } } } public void FinDeTransition () { lock(this) { enTransition = false; foreach (Circuit c in circuitsSeq) if (!valeurschangees.ContainsKey (c)) valeurscourantes [c] = effetcourrant [c]; } } public SequenceurLineaire.Effet EffetCourrant { get { return effetcourrant; } } public int IndexEffetCourrant { get { return effets.IndexOf(effetcourrant); } set { if(value>=0 && value < effets.Count) ChangeEffetCourrant(value); } } void ChangeEffetCourrant (int index) { lock (this) { effetcourrant = effets [index]; valeurschangees.Clear (); valeursinitiales = new Dictionary (valeurscourantes); tempsTransition = effetcourrant.Transition; enTransition = true; timeStamp = TimeSpan.Zero; if (ui != null) ui.EffetChange (); foreach(var t in targets.Values) t.Attache = false; } } public int SauveEffet (string nom, TimeSpan duree, TimeSpan transition) { lock (this) { effets.Add (effetcourrant = new Effet (nom, valeurscourantes, duree, transition)); valeurschangees.Clear (); return effets.Count-1; } } public int InsereEffetApres (int index, string nom, TimeSpan duree, TimeSpan transition) { lock (this) { int pos = index+1; if (pos >= effets.Count) return SauveEffet(nom,duree,transition); effets.Insert (pos,effetcourrant = new Effet (nom, valeurscourantes, duree, transition)); valeurschangees.Clear (); CommandAdd(index); return pos; } } public void RemplaceEffet (int index) { lock (this) { Effet ef = effets[index]; effets[index] = new Effet (ef.Nom, valeurscourantes, ef.Duree, ef.Transition); effetcourrant = effets[index]; valeurschangees.Clear (); } } public void SupprimeEffet (int index) { lock (this) { effets.RemoveAt (index); CommandRemove(index); } } public int MonteEffet (int index) { lock (this) { if (index >= effets.Count || index < 1) return index; Effet ef = effets [index]; effets.RemoveAt (index); effets.Insert (index - 1, ef); CommandSwap (index - 1); return index - 1; } } public int BaisseEffet (int index) { lock (this) { if (index > effets.Count - 2 || index < 0) return index; Effet ef = effets [index]; effets.RemoveAt (index); effets.Insert (index + 1, ef); CommandSwap(index); return index + 1; } } /* private class circEvTarget : IEventTarget{ Circuit c; SequenceurLineaire seq; int s=-2; bool ok=false; public circEvTarget(SequenceurLineaire _seq, Circuit _c){ c=_c; seq=_seq; } #region IEventTarget implementation bool IEventTarget.FireEvent (EventData data) { if (!ok) { int val = seq.ValeurBruteCircuit (c); int cs = Math.Sign (val - data.value); if (s == -2) s =cs; if (cs==0 || cs!=s) ok=true; else return true ; } seq.ChangeValeur(c,data.value); return true; } #endregion } */ public void BindCircuitEvent (Circuit c, string eventId) { if (eventId.Length == 0) { if(!targets.ContainsKey(c)) return; Conduite.Courante.EventManager.Unbind(targets[c]); targets.Remove(c); return; } if(!targets.ContainsKey(c)) targets[c]=new circuitEventTarget(this,c); Conduite.Courante.EventManager.Bind(eventId,targets[c]); } 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 override void Save (System.Xml.XmlElement parent) { System.Xml.XmlElement el = parent.OwnerDocument.CreateElement ("SequenceurLineaire"); System.Xml.XmlElement xmlC; parent.AppendChild (el); el.SetAttribute ("id", ID.ToString ()); el.SetAttribute ("name", Name); el.SetAttribute ("master", master.ToString ()); foreach (Circuit c in circuitsSeq) { el.AppendChild(xmlC = parent.OwnerDocument.CreateElement ("CircuitSeq")); xmlC.SetAttribute("id",c.ID.ToString()); } foreach (Effet ef in effets) { ef.Save(el); } } public override SequenceurUI GetUI () { if (ui == null) { ui = new SeqLinUI (this); ui.Destroyed += UiDestroyed; } return ui; } void UiDestroyed (object sender, EventArgs e) { ui = null; } public static new SequenceurLineaire Load (Conduite conduite, System.Xml.XmlElement el) { SequenceurLineaire seq = new SequenceurLineaire(); 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"); master = int.Parse (el.GetAttribute ("master")); 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("Effet")) effets.Add(Effet.Load(conduite,xe as System.Xml.XmlElement)); } static System.Text.RegularExpressions.Regex regexCommandExec = new System.Text.RegularExpressions.Regex( @"(?\d+)(t(?\d+))?", System.Text.RegularExpressions.RegexOptions.Compiled); static System.Text.RegularExpressions.Regex regexCommandProcess = new System.Text.RegularExpressions.Regex( @"(?\d+)(?(t\d+)?)?", System.Text.RegularExpressions.RegexOptions.Compiled); public override void Command (string command) { lock (this) { var cmd = regexCommandExec.Match(command); if (cmd.Success) { if (cmd.Groups ["effet"].Success) { int effet = int.Parse (cmd.Groups ["effet"].Value) - 1; if (effet < effets.Count) ChangeEffetCourrant (effet); } if (cmd.Groups ["transition"].Success) { int transition = int.Parse (cmd.Groups ["transition"].Value); tempsTransition = TimeSpan.FromMilliseconds( transition *100); } } } } 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 = regexCommandProcess.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 = regexCommandProcess.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 = regexCommandProcess.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); } } } }