609 lines
13 KiB
C#
609 lines
13 KiB
C#
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<Ligne> lignes = new List<Ligne>();
|
|
|
|
|
|
|
|
TimeSpan timeStamp = TimeSpan.Zero;
|
|
TimeSpan topSuivant = TimeSpan.Zero;
|
|
bool topPresent = false;
|
|
|
|
List<Circuit> circuitsSeq = new List<Circuit> ();
|
|
|
|
|
|
Dictionary<Circuit,int> valeurscourantes = new Dictionary<Circuit, int> ();
|
|
Dictionary<Circuit,EffetMacro> effetsEnCours = new Dictionary<Circuit, EffetMacro>();
|
|
|
|
SeqMacroUI ui = null;
|
|
bool change = false;
|
|
int master = 100;
|
|
|
|
public int Master {
|
|
get {
|
|
return master;
|
|
}
|
|
set {
|
|
master = value;
|
|
}
|
|
}
|
|
|
|
public SequenceurMacro ()
|
|
{
|
|
|
|
}
|
|
|
|
|
|
public int IndexLigneEnCours
|
|
{
|
|
get {
|
|
if (enCours == null) return -1;
|
|
return lignes.IndexOf(enCours);
|
|
}
|
|
}
|
|
|
|
Ligne aSuivre = null;
|
|
Ligne enCours = null;
|
|
Ligne ligneMaitre = null;
|
|
|
|
|
|
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) {
|
|
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<Ligne> Lignes {
|
|
get {
|
|
return lignes.AsReadOnly();
|
|
}
|
|
}
|
|
|
|
|
|
public ReadOnlyCollection<Circuit> Circuits {
|
|
get {
|
|
return circuitsSeq.AsReadOnly ();
|
|
}
|
|
}
|
|
|
|
public void ChangeCircuits (System.Collections.Generic.List<Circuit> list)
|
|
{
|
|
lock (this) {
|
|
foreach (var c in circuitsSeq.ToArray()) {
|
|
if (!list.Contains (c))
|
|
RetireCircuit (c);
|
|
}
|
|
foreach (var c in list)
|
|
if (!circuitsSeq.Contains (c))
|
|
AjouteCircuit (c);
|
|
circuitsSeq = list;
|
|
}
|
|
}
|
|
|
|
void AjouteCircuit (Circuit c)
|
|
{
|
|
valeurscourantes [c] = 0;
|
|
}
|
|
|
|
private 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];
|
|
}
|
|
|
|
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) {
|
|
List<Circuit> circuits = new List<Circuit> (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<lignes.Count)
|
|
{
|
|
// Si top présent - non negatif
|
|
if(lignes[index].Top>= 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))
|
|
{
|
|
if(effetsEnCours.ContainsKey(c)) effetsEnCours.Remove(c);
|
|
effetsEnCours.Add(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 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 (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 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");
|
|
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("Ligne"))
|
|
lignes.Add(Ligne.Load(conduite,xe as System.Xml.XmlElement));
|
|
}
|
|
|
|
static System.Text.RegularExpressions.Regex regexCommandeDirecte = new System.Text.RegularExpressions.Regex(
|
|
@"(?<circuits>[\d,-]+) (?<valeur>\d+) (?<temps>\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);
|
|
}
|
|
}
|
|
|
|
// TODO : implementer commandes seqmaitre
|
|
static System.Text.RegularExpressions.Regex regexCommand1 = new System.Text.RegularExpressions.Regex(
|
|
@"(?<effet>\d+)(t(?<transition>\d+))?",
|
|
System.Text.RegularExpressions.RegexOptions.Compiled);
|
|
|
|
static System.Text.RegularExpressions.Regex regexCommand2 = new System.Text.RegularExpressions.Regex(
|
|
@"(?<effet>\d+)(?<params>(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;
|
|
|
|
|
|
int index = IndexLigneEnCours+1;
|
|
if(index<lignes.Count)
|
|
{
|
|
// Si top présent - non negatif
|
|
if(lignes[index].Top>= 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);
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|