Advertisement
Sabersense

Array Merge Prop

Dec 1st, 2024
34
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 31.47 KB | None | 0 0
  1.  
  2. #ifndef PROPS_SABER_SABERSENSE_BUTTONS_H
  3. #define PROPS_SABER_SABERSENSE_BUTTONS_H
  4.  
  5.  
  6. #ifdef SABERSENSE_ARRAY_SELECTOR
  7. #ifndef SABERSENSE_NUM_ARRAYS // No default number of arrays - must be defined in config.
  8. #error "SABERSENSE_NUM_ARRAYS x must be defined in the config file."
  9. #endif
  10.  
  11. #ifdef SABERSENSE_BLADE_ID // Only one Sabersense BladeID standard permitted.
  12. #error "SABERSENSE_ARRAY_SELECTOR and SABERSENSE_BLADE_ID cannot be defined at the same time."
  13. #endif
  14.  
  15. // Function to play the corresponding sound.
  16. void PlaySound(const char* sound) {
  17. RefPtr<BufferedWavPlayer> player = GetFreeWavPlayer();
  18. if (player) {
  19. if (!player->PlayInCurrentDir(sound)) {
  20. player->Play(sound);
  21. }
  22. }
  23. }
  24.  
  25. struct SabersenseArraySelector {
  26. static int return_value; // Tracks the current array index.
  27. static const int sabersense_num_arrays = SABERSENSE_NUM_ARRAYS;
  28. static bool shouldPlaySound; // Flag to control if sound should be played.
  29. static unsigned long lastSwitchTime; // Track time of the last array switch.
  30. static const unsigned long soundDelay = 50; // Delay in ms before playing sound after switch.
  31. static bool isSwitchingInProgress; // Flag to indicate if array switch is in progress.
  32.  
  33. float id() {
  34. return return_value;
  35. }
  36.  
  37. // Forward cycle through arrays...
  38. static void cycleForward() {
  39. isSwitchingInProgress = true; // Mark that the switch is in progress.
  40. return_value = (return_value + 1) % sabersense_num_arrays;
  41. shouldPlaySound = true;
  42. lastSwitchTime = millis();
  43. isSwitchingInProgress = false; // Mark that the switch is complete.
  44. }
  45.  
  46. // Backward cycle through arrays.
  47. static void cycleBackward() {
  48. isSwitchingInProgress = true; // Mark that the switch is in progress
  49. return_value = (return_value - 1 + sabersense_num_arrays) % sabersense_num_arrays; // Ensures wrap.
  50. shouldPlaySound = true;
  51. lastSwitchTime = millis();
  52. isSwitchingInProgress = false; // Mark that the switch is complete.
  53. }
  54.  
  55. // Function to play corresponding sound file based on array index.
  56. static void playArraySound(int arrayIndex) {
  57. const char* soundFile = nullptr;
  58. switch (arrayIndex) {
  59. // Maximum of eight arrays possible.
  60. case 0: soundFile = "array1.wav"; break;
  61. case 1: soundFile = "array2.wav"; break;
  62. case 2: soundFile = "array3.wav"; break;
  63. case 3: soundFile = "array4.wav"; break;
  64. case 4: soundFile = "array5.wav"; break;
  65. case 5: soundFile = "array6.wav"; break;
  66. case 6: soundFile = "array7.wav"; break;
  67. case 7: soundFile = "array8.wav"; break;
  68. default: return; // No sound for invalid array index.
  69. }
  70. PlaySound(soundFile); // Calls custom PlaySound function.
  71. }
  72.  
  73. // Function to check enough time has passed to play the sound.
  74. static void checkAndPlaySound() {
  75. if (shouldPlaySound && !isSwitchingInProgress && (millis() - lastSwitchTime >= soundDelay)) {
  76. playArraySound(return_value); // Play sound for the current array.
  77. shouldPlaySound = false; // Reset flag after sound is played.
  78. }
  79. }
  80.  
  81. // Loop function, needs to be called periodically.
  82. static void loop() {
  83. checkAndPlaySound(); // Check if sound should be played after switching arrays.
  84. }
  85.  
  86. // This update function is a more explicit name for the periodic call.
  87. static void update() {
  88. // The `update` method is meant to be called periodically in your main loop
  89. // and will invoke the `loop()` method internally.
  90. loop(); // This ensures periodic checks for sound playing.
  91. }
  92. };
  93.  
  94. // Static member initialization
  95. int SabersenseArraySelector::return_value = 0; // Start with the first array (index 0).
  96. bool SabersenseArraySelector::shouldPlaySound = false; // Flag to control sound playback.
  97. unsigned long SabersenseArraySelector::lastSwitchTime = 0; // Track time of array switch.
  98. bool SabersenseArraySelector::isSwitchingInProgress = false; // Flag for switch status.
  99.  
  100. #undef BLADE_ID_CLASS_INTERNAL
  101. #define BLADE_ID_CLASS_INTERNAL SabersenseArraySelector
  102. #undef BLADE_ID_CLASS
  103. #define BLADE_ID_CLASS SabersenseArraySelector
  104. #endif
  105.  
  106.  
  107.  
  108.  
  109.  
  110.  
  111.  
  112.  
  113.  
  114.  
  115.  
  116.  
  117.  
  118.  
  119.  
  120. #include "prop_base.h"
  121. #include "../sound/hybrid_font.h"
  122.  
  123. #undef PROP_TYPE
  124. #define PROP_TYPE SabersenseButtons
  125.  
  126. #ifndef MOTION_TIMEOUT
  127. #define MOTION_TIMEOUT 60 * 15 * 1000
  128. #endif
  129.  
  130. #ifndef SABERSENSE_SWING_ON_SPEED
  131. #define SABERSENSE_SWING_ON_SPEED 250
  132. #endif
  133.  
  134. #ifndef SABERSENSE_LOCKUP_DELAY
  135. #define SABERSENSE_LOCKUP_DELAY 200
  136. #endif
  137.  
  138. #ifndef SABERSENSE_FORCE_PUSH_LENGTH
  139. #define SABERSENSE_FORCE_PUSH_LENGTH 5
  140. #endif
  141.  
  142. #ifndef BUTTON_DOUBLE_CLICK_TIMEOUT
  143. #define BUTTON_DOUBLE_CLICK_TIMEOUT 300
  144. #endif
  145.  
  146. #ifndef BUTTON_SHORT_CLICK_TIMEOUT
  147. #define BUTTON_SHORT_CLICK_TIMEOUT 300
  148. #endif
  149.  
  150. #ifndef BUTTON_HELD_TIMEOUT
  151. #define BUTTON_HELD_TIMEOUT 300
  152. #endif
  153.  
  154. #ifndef BUTTON_HELD_MEDIUM_TIMEOUT
  155. #define BUTTON_HELD_MEDIUM_TIMEOUT 1000
  156. #endif
  157.  
  158. #ifndef BUTTON_HELD_LONG_TIMEOUT
  159. #define BUTTON_HELD_LONG_TIMEOUT 2000
  160. #endif
  161.  
  162. #ifdef SABERSENSE_SWING_ON
  163. #define SABERSENSE_SWING_GESTURE
  164. #endif
  165.  
  166. #ifdef SABERSENSE_STAB_ON
  167. #define SABERSENSE_STAB_GESTURE
  168. #endif
  169.  
  170. #ifdef SABERSENSE_TWIST_ON
  171. #define SABERSENSE_TWIST_GESTURE
  172. #endif
  173.  
  174. #ifdef SABERSENSE_THRUST_ON
  175. #define SABERSENSE_THRUST_GESTURE
  176. #endif
  177.  
  178. EFFECT(dim); // for EFFECT_POWERSAVE
  179. EFFECT(battery); // for EFFECT_BATTERY_LEVEL
  180. EFFECT(vmbegin); // for Begin Volume Menu
  181. EFFECT(vmend); // for End Volume Menu
  182. EFFECT(volup); // for increse volume
  183. EFFECT(voldown); // for decrease volume
  184. EFFECT(volmin); // for minimum volume reached
  185. EFFECT(volmax); // for maximum volume reached
  186. EFFECT(faston); // for EFFECT_FAST_ON
  187. EFFECT(blstbgn); // for Begin Multi-Blast
  188. EFFECT(blstend); // for End Multi-Blast
  189. EFFECT(array); // for playing array idents
  190. #ifdef SABERSENSE_OS7_LEGACY_SUPPORT
  191. EFFECT(quote); // for playing quotes. Required for ProffieOS 7.x.
  192. #endif
  193.  
  194.  
  195.  
  196. // The Saber class implements the basic states and actions
  197. // for the saber.
  198. class SabersenseButtons : public PROP_INHERIT_PREFIX PropBase {
  199. public:
  200. SabersenseButtons() : PropBase() {}
  201. const char* name() override { return "SabersenseButtons"; }
  202.  
  203.  
  204.  
  205. #ifdef SABERSENSE_BLADE_ID
  206. void TriggerBladeID() {
  207. size_t detected_best_config = FindBestConfig(false);
  208. current_config = blades + detected_best_config;
  209. FakeFindBladeAgain();
  210. // option if no array.wavs used, play font.wav instead
  211. // SaberBase::DoNewFont();
  212. SFX_array.Select(detected_best_config);
  213. hybrid_font.PlayCommon(&SFX_array);
  214. }
  215.  
  216. void NextBladeArray() {
  217. current_config = blades + (current_config - blades + 1) % NELEM(blades);
  218. FakeFindBladeAgain();
  219. // option if no array.wavs used, play font.wav instead
  220. // SaberBase::DoNewFont();
  221. SFX_array.Select(current_config - blades);
  222. hybrid_font.PlayCommon(&SFX_array);
  223. }
  224.  
  225. // Manual Blade Array Selection version of FindBladeAgain()
  226. void FakeFindBladeAgain() {
  227. // Do everything FindBladeAgain() and FindBlade() do, except for recalculating best_config
  228. ONCEPERBLADE(UNSET_BLADE_STYLE)
  229.  
  230. #undef DEACTIVATE
  231. #define DEACTIVATE(N) do { \
  232. if (current_config->blade##N) \
  233. current_config->blade##N->Deactivate(); \
  234. } while(0);
  235.  
  236. ONCEPERBLADE(DEACTIVATE);
  237. SaveVolumeIfNeeded();
  238.  
  239. #undef ACTIVATE
  240. #define ACTIVATE(N) do { \
  241. if (!current_config->blade##N) { \
  242. goto bad_blade; \
  243. } \
  244. current_config->blade##N->Activate(N); \
  245. } while(0);
  246.  
  247. ONCEPERBLADE(ACTIVATE);
  248. RestoreGlobalState();
  249.  
  250. #ifdef SAVE_PRESET
  251. ResumePreset();
  252. #else
  253. SetPreset(0, false);
  254. #endif // SAVE_PRESET
  255. return;
  256.  
  257. #if NUM_BLADES != 0
  258. bad_blade:
  259. ProffieOSErrors::error_in_blade_array();
  260. #endif
  261. }
  262.  
  263. #endif
  264.  
  265.  
  266.  
  267. void Loop() override {
  268. PropBase::Loop();
  269. DetectTwist();
  270. Vec3 mss = fusor.mss();
  271. if (SaberBase::IsOn()) {
  272. DetectSwing();
  273. if (auto_lockup_on_ &&
  274. !swinging_ &&
  275. fusor.swing_speed() > 120 &&
  276. millis() - clash_impact_millis_ > SABERSENSE_LOCKUP_DELAY &&
  277. SaberBase::Lockup()) {
  278. SaberBase::DoEndLockup();
  279. SaberBase::SetLockup(SaberBase::LOCKUP_NONE);
  280. auto_lockup_on_ = false;
  281. }
  282. if (auto_melt_on_ &&
  283. !swinging_ &&
  284. fusor.swing_speed() > 60 &&
  285. millis() - clash_impact_millis_ > SABERSENSE_LOCKUP_DELAY &&
  286. SaberBase::Lockup()) {
  287. SaberBase::DoEndLockup();
  288. SaberBase::SetLockup(SaberBase::LOCKUP_NONE);
  289. auto_melt_on_ = false;
  290. }
  291.  
  292. // EVENT_PUSH
  293. if (fabs(mss.x) < 3.0 &&
  294. mss.y * mss.y + mss.z * mss.z > 70 &&
  295. fusor.swing_speed() < 30 &&
  296. fabs(fusor.gyro().x) < 10) {
  297. if (millis() - push_begin_millis_ > SABERSENSE_FORCE_PUSH_LENGTH) {
  298. Event(BUTTON_NONE, EVENT_PUSH);
  299. push_begin_millis_ = millis();
  300. }
  301. } else {
  302. push_begin_millis_ = millis();
  303. }
  304. } else {
  305. // EVENT_SWING - Swing On gesture control to allow fine tuning of speed needed to ignite
  306. if (millis() - saber_off_time_ < MOTION_TIMEOUT) {
  307. SaberBase::RequestMotion();
  308. if (swinging_ && fusor.swing_speed() < 90) {
  309. swinging_ = false;
  310. }
  311. if (!swinging_ && fusor.swing_speed() > SABERSENSE_SWING_ON_SPEED) {
  312. swinging_ = true;
  313. Event(BUTTON_NONE, EVENT_SWING);
  314. }
  315. }
  316. // EVENT_THRUST
  317. if (mss.y * mss.y + mss.z * mss.z < 16.0 &&
  318. mss.x > 14 &&
  319. fusor.swing_speed() < 150) {
  320. if (millis() - thrust_begin_millis_ > 15) {
  321. Event(BUTTON_NONE, EVENT_THRUST);
  322. thrust_begin_millis_ = millis();
  323. }
  324. } else {
  325. thrust_begin_millis_ = millis();
  326. }
  327. }
  328. }
  329.  
  330. // Volume Menu
  331. void VolumeUp() {
  332. STDOUT.println("Volume up");
  333. if (dynamic_mixer.get_volume() < VOLUME) {
  334. dynamic_mixer.set_volume(std::min<int>(VOLUME + VOLUME * 0.1,
  335. dynamic_mixer.get_volume() + VOLUME * 0.10));
  336. if (SFX_volup) {
  337. hybrid_font.PlayCommon(&SFX_volup);
  338. } else {
  339. beeper.Beep(0.5, 2000);
  340. }
  341. STDOUT.print("Volume Up - Current Volume: ");
  342. STDOUT.println(dynamic_mixer.get_volume());
  343. } else {
  344. // Cycle through ends of Volume Menu option
  345. #ifdef VOLUME_MENU_CYCLE
  346. if (!max_vol_reached_) {
  347. if (SFX_volmax) {
  348. hybrid_font.PlayCommon(&SFX_volmax);
  349. } else {
  350. beeper.Beep(0.5, 3000);
  351. }
  352. STDOUT.print("Maximum Volume: ");
  353. max_vol_reached_ = true;
  354. } else {
  355. dynamic_mixer.set_volume(std::max<int>(VOLUME * 0.1,
  356. dynamic_mixer.get_volume() - VOLUME * 0.90));
  357. if (SFX_volmin) {
  358. hybrid_font.PlayCommon(&SFX_volmin);
  359. } else {
  360. beeper.Beep(0.5, 1000);
  361. }
  362. STDOUT.print("Minimum Volume: ");
  363. max_vol_reached_ = false;
  364. }
  365. #else
  366. if (SFX_volmax) {
  367. hybrid_font.PlayCommon(&SFX_volmax);
  368. } else {
  369. beeper.Beep(0.5, 3000);
  370. }
  371. STDOUT.print("Maximum Volume: ");
  372. #endif
  373. }
  374. }
  375.  
  376. void VolumeDown() {
  377. STDOUT.println("Volume Down");
  378. if (dynamic_mixer.get_volume() > (0.10 * VOLUME)) {
  379. dynamic_mixer.set_volume(std::max<int>(VOLUME * 0.1,
  380. dynamic_mixer.get_volume() - VOLUME * 0.10));
  381. if (SFX_voldown) {
  382. hybrid_font.PlayCommon(&SFX_voldown);
  383. } else {
  384. beeper.Beep(0.5, 2000);
  385. }
  386. STDOUT.print("Volume Down - Current Volume: ");
  387. STDOUT.println(dynamic_mixer.get_volume());
  388. } else {
  389. #ifdef VOLUME_MENU_CYCLE
  390. if (!min_vol_reached_) {
  391. if (SFX_volmin) {
  392. hybrid_font.PlayCommon(&SFX_volmin);
  393. } else {
  394. beeper.Beep(0.5, 1000);
  395. }
  396. STDOUT.print("Minimum Volume: ");
  397. min_vol_reached_ = true;
  398. } else {
  399. dynamic_mixer.set_volume(VOLUME);
  400. if (SFX_volmax) {
  401. hybrid_font.PlayCommon(&SFX_volmax);
  402. } else {
  403. beeper.Beep(0.5, 3000);
  404. }
  405. STDOUT.print("Maximum Volume: ");
  406. min_vol_reached_ = false;
  407. }
  408. #else
  409. if (SFX_volmin) {
  410. hybrid_font.PlayCommon(&SFX_volmin);
  411. } else {
  412. beeper.Beep(0.5, 1000);
  413. }
  414. STDOUT.print("Minimum Volume: ");
  415. #endif
  416.  
  417. }
  418. }
  419.  
  420. void PlaySound(const char* sound) {
  421. RefPtr<BufferedWavPlayer> player = GetFreeWavPlayer();
  422. if (player) {
  423. if (!player->PlayInCurrentDir(sound)) player->Play(sound);
  424. }
  425. }
  426.  
  427. bool Event2(enum BUTTON button, EVENT event, uint32_t modifiers) override {
  428. switch (EVENTID(button, event, modifiers)) {
  429. case EVENTID(BUTTON_POWER, EVENT_PRESSED, MODE_ANY_BUTTON | MODE_ON):
  430. case EVENTID(BUTTON_POWER, EVENT_PRESSED, MODE_ANY_BUTTON | MODE_OFF):
  431. case EVENTID(BUTTON_AUX, EVENT_PRESSED, MODE_ANY_BUTTON | MODE_ON):
  432. case EVENTID(BUTTON_AUX, EVENT_PRESSED, MODE_ANY_BUTTON | MODE_OFF):
  433. SaberBase::RequestMotion();
  434. #ifdef SABERSENSE_BUTTON_CLICKER
  435. // Intended for Scavenger hilt where wheel makes tactile feel difficult.
  436. PlaySound("press.wav"); // Requires press.wav file to work.
  437. #endif
  438. return false;
  439. case EVENTID(BUTTON_POWER, EVENT_RELEASED, MODE_ANY_BUTTON | MODE_ON):
  440. case EVENTID(BUTTON_POWER, EVENT_RELEASED, MODE_ANY_BUTTON | MODE_OFF):
  441. case EVENTID(BUTTON_AUX, EVENT_RELEASED, MODE_ANY_BUTTON | MODE_ON):
  442. case EVENTID(BUTTON_AUX, EVENT_RELEASED, MODE_ANY_BUTTON | MODE_OFF):
  443. #ifdef SABERSENSE_BUTTON_CLICKER
  444. // Intended for Scavenger hilt where wheel makes tactile feel difficult.
  445. PlaySound("release.wav"); // Requires release.wav file to work.
  446. #endif
  447. if (SaberBase::Lockup()) {
  448. SaberBase::DoEndLockup();
  449. SaberBase::SetLockup(SaberBase::LOCKUP_NONE);
  450. return true;
  451. } else {
  452. return false;
  453. }
  454.  
  455. case EVENTID(BUTTON_AUX, EVENT_PRESSED, MODE_ON):
  456. case EVENTID(BUTTON_AUX2, EVENT_PRESSED, MODE_ON):
  457. if (accel_.x < -0.15) {
  458. pointing_down_ = true;
  459. } else {
  460. pointing_down_ = false;
  461. }
  462. return true;
  463.  
  464. // Gesture Controls
  465. #ifdef SABERSENSE_SWING_ON
  466. case EVENTID(BUTTON_NONE, EVENT_SWING, MODE_OFF):
  467. // Due to motion chip startup on boot creating false ignition we delay Swing On at boot for 3000ms
  468. if (millis() > 3000) {
  469. FastOn();
  470. }
  471. return true;
  472. #endif
  473.  
  474. #ifdef SABERSENSE_TWIST_ON
  475. case EVENTID(BUTTON_NONE, EVENT_TWIST, MODE_OFF):
  476. // Delay twist events to prevent false trigger from over twisting
  477. if (millis() - last_twist_ > 2000 &&
  478. millis() - saber_off_time_ > 1000) {
  479. FastOn();
  480. last_twist_ = millis();
  481. }
  482. return true;
  483. #endif
  484.  
  485. #ifdef SABERSENSE_TWIST_OFF
  486. case EVENTID(BUTTON_NONE, EVENT_TWIST, MODE_ON):
  487. // Delay twist events to prevent false trigger from over twisting
  488. if (millis() - last_twist_ > 3000) {
  489. Off();
  490. last_twist_ = millis();
  491. saber_off_time_ = millis();
  492. }
  493. return true;
  494. #endif
  495.  
  496. #ifdef SABERSENSE_STAB_ON
  497. case EVENTID(BUTTON_NONE, EVENT_STAB, MODE_OFF):
  498. if (millis() - saber_off_time_ > 1000) {
  499. FastOn();
  500. }
  501. return true;
  502. #endif
  503.  
  504. #ifdef SABERSENSE_THRUST_ON
  505. case EVENTID(BUTTON_NONE, EVENT_THRUST, MODE_OFF):
  506. if (millis() - saber_off_time_ > 1000) {
  507. FastOn();
  508. }
  509. return true;
  510. #endif
  511.  
  512. // Multiple Skips only available with 2 button installs.
  513. // Skips forward five fonts if pointing up, skips back five fonts if pointing down.
  514. case EVENTID(BUTTON_AUX, EVENT_SECOND_SAVED_CLICK_SHORT, MODE_OFF):
  515. // backwards if pointing down
  516. SetPreset(current_preset_.preset_num + (fusor.angle1() < -M_PI / 4 ? -5 : 5), true);
  517. #ifdef SAVE_PRESET
  518. SaveState(current_preset_.preset_num);
  519. #endif
  520. return true;
  521.  
  522. // Skips forward ten fonts if pointing up, skips back ten fonts if pointing down.
  523. case EVENTID(BUTTON_AUX, EVENT_THIRD_SAVED_CLICK_SHORT, MODE_OFF):
  524. // backwards if pointing down
  525. SetPreset(current_preset_.preset_num + (fusor.angle1() < -M_PI / 4 ? -10 : 10), true);
  526. #ifdef SAVE_PRESET
  527. SaveState(current_preset_.preset_num);
  528. #endif
  529. return true;
  530.  
  531. // Saber ON AND Volume Adjust.
  532. case EVENTID(BUTTON_POWER, EVENT_FIRST_SAVED_CLICK_SHORT, MODE_OFF):
  533. IgnoreClash(50); // Hopefully prevents false clashes due to 'clicky' button.
  534. // Low threshold so as not to conflict with 1-button lockup or volume menu.
  535. if (!mode_volume_) {
  536. On();
  537. } else {
  538. if (fusor.angle1() > 0) {
  539. VolumeUp();
  540. } else {
  541. VolumeDown();
  542. }
  543. }
  544. return true;
  545.  
  546. // Modified 2 button 'next/previous preset' AND volume down,
  547. // to align with multiple skips above.
  548. // Forward one font pointing up, back one font pointing down.
  549. case EVENTID(BUTTON_AUX, EVENT_FIRST_SAVED_CLICK_SHORT, MODE_OFF):
  550. // backwards if pointing down
  551. if (!mode_volume_) {
  552. SetPreset(current_preset_.preset_num + (fusor.angle1() < -M_PI / 4 ? -1 : 1), true);
  553. } else {
  554. VolumeDown();
  555. }
  556. #ifdef SAVE_PRESET
  557. SaveState(current_preset_.preset_num);
  558. #endif
  559. return true;
  560.  
  561. // 1 button 'next/previous preset' command.
  562. // Forward one font pointing up, back one font pointing down.
  563. #if NUM_BUTTONS == 1
  564. #ifndef SABERSENSE_SWAP_PRESET_MUTE
  565. case EVENTID(BUTTON_POWER, EVENT_SECOND_HELD, MODE_OFF):
  566. #else
  567. case EVENTID(BUTTON_POWER, EVENT_FIRST_CLICK_LONG, MODE_OFF):
  568. #endif
  569. // backwards if pointing down
  570. if (!mode_volume_) {
  571. SetPreset(current_preset_.preset_num + (fusor.angle1() < -M_PI / 4 ? -1 : 1), true);
  572. } else {
  573. VolumeDown();
  574. }
  575. #ifdef SAVE_PRESET
  576. SaveState(current_preset_.preset_num);
  577. #endif
  578. return true;
  579. #endif
  580.  
  581.  
  582. // 1 Button skips to first preset (up) or last preset (down)
  583. // or middle preset if horizontal:
  584. #if NUM_BUTTONS == 2
  585. case EVENTID(BUTTON_AUX, EVENT_FIRST_HELD_LONG, MODE_OFF):
  586. #endif
  587. case EVENTID(BUTTON_POWER, EVENT_FIRST_HELD_LONG, MODE_OFF):
  588. #define DEGREES_TO_RADIANS (M_PI / 180)
  589. if (fusor.angle1() > 45 * DEGREES_TO_RADIANS) {
  590. // If pointing up
  591. SetPreset(0, true);
  592. } else if (fusor.angle1() < -45 * DEGREES_TO_RADIANS) {
  593. // If pointing down
  594. SetPreset(-1, true);
  595. } else {
  596. // If horizontal
  597. CurrentPreset tmp;
  598. tmp.SetPreset(-1);
  599. SetPreset(tmp.preset_num / 2, true);
  600. }
  601. #ifdef SAVE_PRESET
  602. SaveState(current_preset_.preset_num);
  603. #endif
  604. return true;
  605.  
  606. // 1 and 2 button: Previous Preset, retained legacy control.
  607. #if NUM_BUTTONS == 2
  608. case EVENTID(BUTTON_POWER, EVENT_CLICK_SHORT, MODE_OFF | BUTTON_AUX):
  609. #endif
  610. if (!mode_volume_) {
  611. previous_preset();
  612. }
  613. return true;
  614.  
  615. // Skips to first preset (up) or last (battery or charge) preset (down)
  616. // or middle preset if horizontal:
  617. #if NUM_BUTTONS == 2
  618. // 2 button: First Preset
  619. case EVENTID(BUTTON_AUX, EVENT_HELD_LONG, MODE_OFF):
  620. #endif
  621. #define DEGREES_TO_RADIANS (M_PI / 180)
  622. if (fusor.angle1() > 45 * DEGREES_TO_RADIANS) {
  623. // If pointing up
  624. SetPreset(0, true);
  625. } else if (fusor.angle1() < -45 * DEGREES_TO_RADIANS) {
  626. // If pointing down
  627. SetPreset(-1, true);
  628. } else {
  629. // If horizontal
  630. CurrentPreset tmp;
  631. tmp.SetPreset(-1);
  632. SetPreset(tmp.preset_num / 2, true);
  633. }
  634. #ifdef SAVE_PRESET
  635. SaveState(current_preset_.preset_num);
  636. #endif
  637. return true;
  638.  
  639. // Manual blade array selector.
  640. #ifdef SABERSENSE_ARRAY_SELECTOR
  641. case EVENTID(BUTTON_POWER, EVENT_THIRD_SAVED_CLICK_SHORT, MODE_OFF):
  642. // Cycles through blade arrays regardless of BladeID status.
  643. if (fusor.angle1() > 0) {
  644. // Cycles forward...
  645. SabersenseArraySelector::cycleForward();
  646. } else {
  647. // Cycles backward.
  648. SabersenseArraySelector::cycleBackward();
  649. }
  650. FindBladeAgain();
  651. SabersenseArraySelector::checkAndPlaySound();
  652. return true;
  653. #endif
  654. /*
  655. #ifdef SABERSENSE_BLADE_ID
  656. case EVENTID(BUTTON_POWER, EVENT_THIRD_SAVED_CLICK_SHORT, MODE_OFF):
  657. FindBladeAgain(); // Perform the scan and find the blade ID
  658. Serial.println("Switching blade...");
  659. SabersenseBladeID::switchBlade(SabersenseBladeID::return_value); // Directly switch the blade and play the sound
  660. return true;
  661. #endif
  662. */
  663.  
  664.  
  665.  
  666.  
  667.  
  668.  
  669.  
  670. #ifdef SABERSENSE_BLADE_ID
  671. case EVENTID(BUTTON_POWER, EVENT_THIRD_SAVED_CLICK_SHORT, MODE_OFF):
  672. // NextBladeArray();
  673. TriggerBladeID();
  674. return true;
  675. #endif
  676.  
  677.  
  678.  
  679.  
  680.  
  681.  
  682.  
  683.  
  684.  
  685.  
  686.  
  687.  
  688.  
  689.  
  690.  
  691.  
  692.  
  693.  
  694. // Activate Muted 1 Button
  695. #if NUM_BUTTONS == 1
  696. #ifndef SABERSENSE_SWAP_PRESET_MUTE
  697. case EVENTID(BUTTON_POWER, EVENT_FIRST_CLICK_LONG, MODE_OFF):
  698. #else
  699. case EVENTID(BUTTON_POWER, EVENT_SECOND_HELD, MODE_OFF):
  700. #endif
  701. if (SetMute(true)) {
  702. unmute_on_deactivation_ = true;
  703. On();
  704. }
  705. return true;
  706. #endif
  707.  
  708. // Activate Muted 2 Button
  709. #if NUM_BUTTONS == 2
  710. case EVENTID(BUTTON_POWER, EVENT_FIRST_CLICK_LONG, MODE_OFF):
  711. if (SetMute(true)) {
  712. unmute_on_deactivation_ = true;
  713. On();
  714. }
  715. return true;
  716. #endif
  717.  
  718. // Turn Blade OFF
  719. // #if NUM_BUTTONS > 1
  720. // 2 button
  721. case EVENTID(BUTTON_POWER, EVENT_FIRST_HELD_MEDIUM, MODE_ON):
  722. // #else
  723. // 1 button
  724. // case EVENTID(BUTTON_POWER, EVENT_FIRST_HELD_LONG, MODE_ON):
  725. // #endif
  726. if (!SaberBase::Lockup()) {
  727. #ifndef DISABLE_COLOR_CHANGE
  728. if (SaberBase::GetColorChangeMode() != SaberBase::COLOR_CHANGE_MODE_NONE) {
  729. // Just exit color change mode.
  730. // Don't turn saber off.
  731. ToggleColorChangeMode();
  732. } else {
  733. Off();
  734. }
  735. }
  736. saber_off_time_ = millis();
  737. swing_blast_ = false;
  738. return true;
  739. #endif
  740.  
  741. // Character Quote and Force Effect, Blade ON.
  742. // Hilt pointed UP for Character Quote, plays sequentially,
  743. // Hilt pointed DOWN for Force Effect, plays randomly.
  744. case EVENTID(BUTTON_POWER, EVENT_SECOND_SAVED_CLICK_SHORT, MODE_ON):
  745. #ifndef SABERSENSE_FLIP_AUDIO_PLAYERS
  746. // Define reverses UP/DOWN options for QUOTE/FORCE/TRACK audio player.
  747. // Quote player points upwards.
  748. if (SFX_quote) {
  749. if (fusor.angle1() > 0) {
  750. SFX_quote.SelectNext();
  751. SaberBase::DoEffect(EFFECT_QUOTE, 0);
  752. } else {
  753. SaberBase::DoForce(); // Force effect for hilt pointed DOWN.
  754. }
  755. } else {
  756. SaberBase::DoForce(); // Fallback: play force effect if no quotes are available.
  757. }
  758. return true;
  759. #else
  760. // Quote player points downwards.
  761. if (SFX_quote) {
  762. if (fusor.angle1() < 0) {
  763. SFX_quote.SelectNext();
  764. SaberBase::DoEffect(EFFECT_QUOTE, 0);
  765. } else {
  766. SaberBase::DoForce(); // Force effect for hilt pointed DOWN.
  767. }
  768. } else {
  769. SaberBase::DoForce(); // Fallback: play force effect if no quotes are available.
  770. }
  771. return true;
  772. #endif
  773.  
  774. // Character Quote and Music Track, Blade OFF.
  775. // Play sequential quote pointing up, play music track pointing down.
  776. case EVENTID(BUTTON_POWER, EVENT_SECOND_SAVED_CLICK_SHORT, MODE_OFF):
  777. #ifndef SABERSENSE_FLIP_AUDIO_PLAYERS
  778. // Define reverses UP/DOWN options for QUOTE/FORCE/TRACK audio players.
  779. // Quote player points upwards.
  780. if (SFX_quote) {
  781. if (fusor.angle1() > 0) {
  782. SFX_quote.SelectNext();
  783. SaberBase::DoEffect(EFFECT_QUOTE, 0);
  784. } else {
  785. StartOrStopTrack(); // Play track for hilt pointed DOWN.
  786. }
  787. } else {
  788. StartOrStopTrack(); // Fallback: play track if no quotes are available.
  789. }
  790. return true;
  791. #else
  792. // Quote player points downwards.
  793. if (SFX_quote) {
  794. if (fusor.angle1() < 0) {
  795. SFX_quote.SelectNext();
  796. SaberBase::DoEffect(EFFECT_QUOTE, 0);
  797. } else {
  798. StartOrStopTrack(); // Play track for hilt pointed DOWN.
  799. }
  800. } else {
  801. StartOrStopTrack(); // Fallback: play track if no quotes are available.
  802. }
  803. return true;
  804. #endif
  805.  
  806. // Colour Change.
  807. // 1 and 2 button modes.
  808. #ifndef DISABLE_COLOR_CHANGE
  809. case EVENTID(BUTTON_POWER, EVENT_THIRD_SAVED_CLICK_SHORT, MODE_ON):
  810. ToggleColorChangeMode();
  811. return true;
  812. // 2 button mode only.
  813. #if NUM_BUTTONS == 2
  814. case EVENTID(BUTTON_AUX, EVENT_CLICK_SHORT, MODE_ON | BUTTON_POWER):
  815. ToggleColorChangeMode();
  816. return true;
  817. #endif
  818. #endif
  819.  
  820. // Blaster Deflection
  821. #if NUM_BUTTONS == 1
  822. // 1 button
  823. case EVENTID(BUTTON_POWER, EVENT_FIRST_SAVED_CLICK_SHORT, MODE_ON):
  824. #else
  825. // 2 button
  826. case EVENTID(BUTTON_AUX, EVENT_CLICK_SHORT, MODE_ON):
  827. case EVENTID(BUTTON_AUX, EVENT_FIRST_SAVED_CLICK_SHORT, MODE_ON):
  828. #endif
  829. swing_blast_ = false;
  830. SaberBase::DoBlast();
  831. return true;
  832.  
  833. // Multi-Blaster Deflection mode
  834. case EVENTID(BUTTON_NONE, EVENT_SWING, MODE_ON | BUTTON_POWER):
  835. swing_blast_ = !swing_blast_;
  836. if (swing_blast_) {
  837. if (SFX_blstbgn) {
  838. hybrid_font.PlayCommon(&SFX_blstbgn);
  839. } else {
  840. hybrid_font.SB_Effect(EFFECT_BLAST, 0);
  841. }
  842. } else {
  843. if (SFX_blstend) {
  844. hybrid_font.PlayCommon(&SFX_blstend);
  845. } else {
  846. hybrid_font.SB_Effect(EFFECT_BLAST, 0);
  847. }
  848. }
  849. return true;
  850.  
  851. case EVENTID(BUTTON_NONE, EVENT_SWING, MODE_ON):
  852. if (swing_blast_) {
  853. SaberBase::DoBlast();
  854. }
  855. return true;
  856.  
  857. // Lockup
  858. #if NUM_BUTTONS == 1
  859. // 1 button lockup
  860. case EVENTID(BUTTON_NONE, EVENT_CLASH, MODE_ON | BUTTON_POWER):
  861. #else
  862. #ifndef SABERSENSE_NO_LOCKUP_HOLD
  863. // 2 button lockup
  864. case EVENTID(BUTTON_AUX, EVENT_FIRST_HELD, MODE_ON):
  865. #else
  866. case EVENTID(BUTTON_NONE, EVENT_CLASH, MODE_ON | BUTTON_AUX):
  867. #endif
  868. #endif
  869. if (accel_.x < -0.15) {
  870. SaberBase::SetLockup(SaberBase::LOCKUP_DRAG);
  871. } else {
  872. SaberBase::SetLockup(SaberBase::LOCKUP_NORMAL);
  873. }
  874. swing_blast_ = false;
  875. SaberBase::DoBeginLockup();
  876. return true;
  877. break;
  878.  
  879. // Lightning Block, 1 and 2 button.
  880. case EVENTID(BUTTON_POWER, EVENT_SECOND_HELD, MODE_ON):
  881. SaberBase::SetLockup(SaberBase::LOCKUP_LIGHTNING_BLOCK);
  882. swing_blast_ = false;
  883. SaberBase::DoBeginLockup();
  884. return true;
  885. break;
  886.  
  887. // Melt
  888. case EVENTID(BUTTON_NONE, EVENT_STAB, MODE_ON | BUTTON_POWER):
  889. SaberBase::SetLockup(SaberBase::LOCKUP_MELT);
  890. swing_blast_ = false;
  891. SaberBase::DoBeginLockup();
  892. return true;
  893. break;
  894.  
  895. case EVENTID(BUTTON_AUX2, EVENT_PRESSED, MODE_OFF):
  896. SaberBase::RequestMotion();
  897. return true;
  898.  
  899. // Enter Volume MENU
  900. #if NUM_BUTTONS == 1
  901. // 1 button
  902. case EVENTID(BUTTON_NONE, EVENT_CLASH, MODE_OFF | BUTTON_POWER):
  903. #else
  904. // 2 button
  905. case EVENTID(BUTTON_AUX, EVENT_CLICK_SHORT, MODE_OFF | BUTTON_POWER):
  906.  
  907. #endif
  908. if (!mode_volume_) {
  909. mode_volume_ = true;
  910. if (SFX_vmbegin) {
  911. hybrid_font.PlayCommon(&SFX_vmbegin);
  912. } else {
  913. beeper.Beep(0.5, 3000);
  914. }
  915. STDOUT.println("Enter Volume Menu");
  916. } else {
  917. mode_volume_ = false;
  918. if (SFX_vmend) {
  919. hybrid_font.PlayCommon(&SFX_vmend);
  920. } else {
  921. beeper.Beep(0.5, 3000);
  922. }
  923. STDOUT.println("Exit Volume Menu");
  924. }
  925. return true;
  926.  
  927. // Battery level
  928. case EVENTID(BUTTON_POWER, EVENT_FOURTH_SAVED_CLICK_SHORT, MODE_OFF):
  929. #if NUM_BUTTONS == 2
  930. case EVENTID(BUTTON_AUX, EVENT_FIRST_CLICK_LONG, MODE_OFF):
  931. #endif
  932. talkie.SayDigit((int)floorf(battery_monitor.battery()));
  933. talkie.Say(spPOINT);
  934. talkie.SayDigit(((int)floorf(battery_monitor.battery() * 10)) % 10);
  935. talkie.SayDigit(((int)floorf(battery_monitor.battery() * 100)) % 10);
  936. talkie.Say(spVOLTS);
  937. SaberBase::DoEffect(EFFECT_BATTERY_LEVEL, 0);
  938. return true;
  939.  
  940. #ifdef BLADE_DETECT_PIN
  941. case EVENTID(BUTTON_BLADE_DETECT, EVENT_LATCH_ON, MODE_ANY_BUTTON | MODE_ON):
  942. case EVENTID(BUTTON_BLADE_DETECT, EVENT_LATCH_ON, MODE_ANY_BUTTON | MODE_OFF):
  943. // Might need to do something cleaner, but let's try this for now.
  944. blade_detected_ = true;
  945. FindBladeAgain();
  946. SaberBase::DoBladeDetect(true);
  947. return true;
  948.  
  949. case EVENTID(BUTTON_BLADE_DETECT, EVENT_LATCH_OFF, MODE_ANY_BUTTON | MODE_ON):
  950. case EVENTID(BUTTON_BLADE_DETECT, EVENT_LATCH_OFF, MODE_ANY_BUTTON | MODE_OFF):
  951. // Might need to do something cleaner, but let's try this for now.
  952. blade_detected_ = false;
  953. FindBladeAgain();
  954. SaberBase::DoBladeDetect(false);
  955. return true;
  956. #endif
  957.  
  958. // Events that needs to be handled regardless of what other buttons are pressed.
  959. case EVENTID(BUTTON_AUX2, EVENT_RELEASED, MODE_ANY_BUTTON | MODE_ON):
  960. if (SaberBase::Lockup()) {
  961. SaberBase::DoEndLockup();
  962. SaberBase::SetLockup(SaberBase::LOCKUP_NONE);
  963. return true;
  964. }
  965. }
  966. return false;
  967. }
  968.  
  969. #ifdef SABERSENSE_OS7_LEGACY_SUPPORT
  970. void SB_Effect(EffectType effect, float location) override { // Required for ProffieOS 7.x.
  971. #else
  972. void SB_Effect(EffectType effect, EffectLocation location) override { // Required for ProffieOS 8.x.
  973. #endif
  974. switch (effect) {
  975. case EFFECT_QUOTE: hybrid_font.PlayCommon(&SFX_quote); return;
  976. case EFFECT_POWERSAVE:
  977. if (SFX_dim) {
  978. hybrid_font.PlayCommon(&SFX_dim);
  979. } else {
  980. beeper.Beep(0.5, 3000);
  981. }
  982. return;
  983. case EFFECT_BATTERY_LEVEL:
  984. if (SFX_battery) {
  985. hybrid_font.PlayCommon(&SFX_battery);
  986. } else {
  987. beeper.Beep(0.5, 3000);
  988. }
  989. return;
  990. case EFFECT_FAST_ON:
  991. if (SFX_faston) {
  992. hybrid_font.PlayCommon(&SFX_faston);
  993. }
  994. return;
  995.  
  996. default: break; // avoids compiler warning
  997. }
  998. }
  999.  
  1000. private:
  1001. bool pointing_down_ = false;
  1002. bool swing_blast_ = false;
  1003. bool mode_volume_ = false;
  1004. bool auto_lockup_on_ = false;
  1005. bool auto_melt_on_ = false;
  1006. bool max_vol_reached_ = false;
  1007. bool min_vol_reached_ = false;
  1008. uint32_t thrust_begin_millis_ = millis();
  1009. uint32_t push_begin_millis_ = millis();
  1010. uint32_t clash_impact_millis_ = millis();
  1011. uint32_t last_twist_ = millis();
  1012. uint32_t last_push_ = millis();
  1013. uint32_t saber_off_time_ = millis();
  1014. };
  1015.  
  1016. #endif
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement