using System; using System.Collections.Generic; using System.Text; using SalsaModel.Actions; using SalsaModel.Scheduling; namespace SalsaModel { public class SequenceAttribute : Attribute { public string Name; public SequenceAttribute(string name) { Name = name; } } public class SequenceHandler : ISequence { Dictionary _providers =new Dictionary(); Timing _timing = new Timing(); public Timing Timing { get { return _timing; } } private SalsaMover _Boy; public SalsaMover Boy { get { return _Boy; } set { _Boy = value; } } private SalsaMover _Girl; public SalsaMover Girl { get { return _Girl; } set { _Girl = value; } } TimeLine _timeLine = new TimeLine(); public TimeLine TimeLine { get { return _timeLine; } } public SequenceHandler() { Boy = new SalsaMover(BodyGeometry.Andy(), new Location(5, -BodyGeometry.Andy().LowerArm, 0)); Girl = new SalsaMover(BodyGeometry.Girl(), new Location(-5, BodyGeometry.Girl().LowerArm, 0)); Girl.Model.IsGirl = true; Girl.Flip(); FindSequenceProviders(); // just to get us started CompositeActions.OneBasicWithFollower(_timeLine, 1.0, Boy, Girl, 70); } private void FindSequenceProviders() { foreach (System.Type type in System.Reflection.Assembly.GetCallingAssembly().GetTypes()) { object[] attrs = type.GetCustomAttributes(typeof(SequenceAttribute), true); if (attrs.Length > 0) { // it's a sequence. Construct one, and register it along // with the name from the attribute. if (attrs.Length > 1) { throw new ApplicationException("too many Sequence attributes"); } SequenceAttribute attr = attrs[0] as SequenceAttribute; object provObj = System.Activator.CreateInstance(type); if (provObj == null) { throw new ApplicationException("cannot create object"); } ISequenceProvider prov = provObj as ISequenceProvider; if (prov == null) { throw new ApplicationException("Type " + type.ToString() + " does not implement ISequencePRovider"); } RegisterSequenceProvider(attr.Name, prov); } } } private void RegisterSequenceProvider(string name, ISequenceProvider prov) { _providers.Add(name, prov); } public IEnumerable AvailableSequences { get { return _providers.Keys; } } string _nextSequence = "Basic"; private void SetupTimeLine(double from) { ISequenceProvider prov; if (_providers.TryGetValue(_nextSequence, out prov)) { prov.AddMoves(_timeLine, from, Boy, Girl); } else { throw new ApplicationException("Unknown sequence " + _nextSequence); } } double _prev = -1.0; public void Update() { double now = Timing.GlobalBeat() + Timing.Percent(); _timeLine.RunActions(_prev, now); _prev = now; Boy.AlignKnees(); Boy.CheckPosture(); Girl.AlignKnees(); Girl.CheckPosture(); // assumes that the sequence is 2 bars long // XXX a multiple of 2 bars? -- Andy if (!_timeLine.HasEventsAfter(now)) { if (Timing.Beat() == 8) { SetupTimeLine(Timing.GlobalBeat() + 1.0); } //else if (Timing.Beat() == 1) //{ // is this wise? // no // SetupTimeLine(Timing.GlobalBeat()); //} } } public string Status() { return _nextSequence; } internal void SetNextSequence(string p) { _nextSequence = p; } } }