public NewSpell_Training_TutorialStage(string label, Focus Focus, bool AutoStart = false) : base(label) { Implement = Focus; Stillness = new StillnessProvider(); SetUpProvider(Stillness); Stillness.StartDisplayLoop(Current, 1000); SpellBeingTrained = Current.SpellBeingTrained; AttitudeProvider = new GravityOrientationProvider(Implement.FrameShift); AttitudeProvider.Activate(); if (AutoStart) { Activate(); } }
public FormSetupStage(string label, FrameShiftedOrientationProvider provider = null, bool Autostart = false) : base(label) { Blade = Current.ThePlayersSword; IsInitialPoseEstimate = (Current.FormBeingTrained.InitialOrientation.IsIdentity); Stillness = new StillnessProvider(); SetUpProvider(Stillness); //AttitudeProvider = provider ?? new OrientationSensorProvider(Android.Hardware.SensorType.GameRotationVector); AttitudeProvider = provider; // If null, we'd bloody well better be planning to set it externally! ?? new FrameShiftedOrientationProvider(Android.Hardware.SensorType.GameRotationVector, Blade.EnGardeOrientation.Average); if (provider == null && Autostart) { throw new ArgumentNullException("provider", "Provider cannot be null if you're planning to automatically start - that only works if you're setting it externally after ctor but before Activate()."); } //if (!AttitudeProvider.IsActive) AttitudeProvider.Activate(); if (Autostart) { Activate(); } }
protected override async Task nextStageActionAsync() { if (Current.setFormNameButton.Text == RetrainEnGardeText) { Current.setFormNameButton.Text = "Random"; // Undoes our little textual flag that lets us retrain the en garde using this button instead of its usual function. } var oldOrientation = Blade.EnGardeOrientation.Average; Blade.EnGardeOrientation.Update(AttitudeProvider.Quaternion); // Subtle trick: we keep averaging the En Garde orientation so it "tracks" the player's shifts in taking it, over time. Log.Debug("EnGarde Stage", $"Updating the prior en garde ({oldOrientation}), using the new one ({AttitudeProvider.Quaternion}," + $" {AttitudeProvider.Quaternion.AngleTo(oldOrientation)} degrees away), producing a new one ({Blade.EnGardeOrientation.Average}," + $" {Blade.EnGardeOrientation.Average.AngleTo(oldOrientation)} degrees away from the prior one)."); //// In order to *pass along* a provider, to an arbitrary Gesture Stage which has already been created and passed to us //// (and which might or might not want to use our provider at all), we use this trick. Activate it in here, and during //// activation, a specific STATIC provider is made available. We lock so that (in theory) two EnGarde Stages which were //// running in separate threads wouldn't end up accessing the static value at the wrong times. //using (await _asyncLock.LockAsync()) //{ // //EngardeProvider = AttitudeProvider; // Can be referenced from inside the prestartAction of the provided stage, if desired. (Not during the ctor... that's already gone by!) // EngardeProvider = new FrameShiftedOrientationProvider(Android.Hardware.SensorType.GameRotationVector); // await Task.WhenAll(EngardeProvider.SetFrameShiftFromCurrent(), Speech.Say(NextStageCue)); // CurrentStage = NextStage; // CurrentStage.Activate(); // EngardeProvider = null; //} // Different approach to solving the above problem. var EngardeProvider = new FrameShiftedOrientationProvider(Android.Hardware.SensorType.GameRotationVector); await Task.WhenAll(EngardeProvider.SetFrameShiftFromCurrent(), Speech.SayAllOf(NextStageCue)); CurrentStage = NextStage; var cStage = CurrentStage as ITakeAnAttitudeProvider; if (cStage != null) { cStage.AttitudeProvider = EngardeProvider; } CurrentStage.Activate(); }