ft2_radiobuttons.c (13718B)
1 // for finding memory leaks in debug mode with Visual Studio 2 #if defined _DEBUG && defined _MSC_VER 3 #include <crtdbg.h> 4 #endif 5 6 #include <stdint.h> 7 #include <stdbool.h> 8 #include "ft2_header.h" 9 #include "ft2_gui.h" 10 #include "ft2_config.h" 11 #include "ft2_help.h" 12 #include "ft2_sample_ed.h" 13 #include "ft2_nibbles.h" 14 #include "ft2_inst_ed.h" 15 #include "ft2_diskop.h" 16 #include "ft2_mouse.h" 17 #include "ft2_wav_renderer.h" 18 #include "ft2_bmp.h" 19 #include "ft2_structs.h" 20 21 radioButton_t radioButtons[NUM_RADIOBUTTONS] = 22 { 23 /* 24 ** -- STRUCT INFO: -- 25 ** x = x position 26 ** y = y position 27 ** w = clickable width in pixels, relative to x 28 ** group = what group the radiobutton belongs to 29 ** funcOnUp = function to call when released 30 */ 31 32 // ------ HELP SCREEN RADIOBUTTONS ------ 33 //x, y, w, group, funcOnUp 34 { 5, 18, 69, RB_GROUP_HELP, rbHelpFeatures }, 35 { 5, 34, 60, RB_GROUP_HELP, rbHelpEffects }, 36 { 5, 50, 86, RB_GROUP_HELP, rbHelpKeybindings }, 37 { 5, 66, 109, RB_GROUP_HELP, rbHelpHowToUseFT2 }, 38 { 5, 82, 101, RB_GROUP_HELP, rbHelpFAQ }, 39 { 5, 98, 86, RB_GROUP_HELP, rbHelpKnownBugs }, 40 41 // ------ NIBBLES SCREEN RADIOBUTTONS ------ 42 //x, y, w, group, funcOnUp 43 { 4, 105, 61, RB_GROUP_NIBBLES_PLAYERS, nibblesSet1Player }, 44 { 4, 119, 68, RB_GROUP_NIBBLES_PLAYERS, nibblesSet2Players }, 45 { 79, 117, 55, RB_GROUP_NIBBLES_DIFFICULTY, nibblesSetNovice }, 46 { 79, 131, 63, RB_GROUP_NIBBLES_DIFFICULTY, nibblesSetAverage }, 47 { 79, 145, 34, RB_GROUP_NIBBLES_DIFFICULTY, nibblesSetPro }, 48 { 79, 159, 50, RB_GROUP_NIBBLES_DIFFICULTY, nibblesSetTriton }, 49 50 // ------ SAMPLER SCREEN RADIOBUTTONS ------ 51 //x, y, w, group, funcOnUp 52 { 357, 351, 58, RB_GROUP_SAMPLE_LOOP, rbSampleNoLoop }, 53 { 357, 368, 62, RB_GROUP_SAMPLE_LOOP, rbSampleForwardLoop }, 54 { 357, 385, 67, RB_GROUP_SAMPLE_LOOP, rbSamplePingpongLoop }, 55 { 431, 368, 44, RB_GROUP_SAMPLE_DEPTH, rbSample8bit }, 56 { 431, 383, 50, RB_GROUP_SAMPLE_DEPTH, rbSample16bit }, 57 58 // ------ INSTRUMENT EDITOR SCREEN RADIOBUTTONS ------ 59 //x, y, w, group, funcOnUp 60 { 442, 279, 25, RB_GROUP_INST_WAVEFORM, rbVibWaveSine }, 61 { 472, 279, 25, RB_GROUP_INST_WAVEFORM, rbVibWaveSquare }, 62 { 502, 279, 25, RB_GROUP_INST_WAVEFORM, rbVibWaveRampDown }, 63 { 532, 279, 25, RB_GROUP_INST_WAVEFORM, rbVibWaveRampUp }, 64 65 // ------ CONFIG SCREEN LEFT RADIOBUTTONS ------ 66 //x, y, w, group, funcOnUp 67 { 5, 18, 48, RB_GROUP_CONFIG_SELECT, rbConfigAudio }, 68 { 5, 34, 57, RB_GROUP_CONFIG_SELECT, rbConfigLayout }, 69 { 5, 50, 97, RB_GROUP_CONFIG_SELECT, rbConfigMiscellaneous }, 70 #ifdef HAS_MIDI 71 { 5, 66, 72, RB_GROUP_CONFIG_SELECT, rbConfigMidiInput }, 72 #endif 73 74 // ------ CONFIG AUDIO ------ 75 76 // audio buffer size 77 //x, y, w, group, funcOnUp 78 { 390, 16, 45, RB_GROUP_CONFIG_SOUND_BUFF_SIZE, rbConfigAudioBuffSmall }, 79 { 390, 30, 112, RB_GROUP_CONFIG_SOUND_BUFF_SIZE, rbConfigAudioBuffMedium }, 80 { 390, 44, 49, RB_GROUP_CONFIG_SOUND_BUFF_SIZE, rbConfigAudioBuffLarge }, 81 82 // audio bit depth 83 //x, y, w, group, funcOnUp 84 { 390, 73, 51, RB_GROUP_CONFIG_AUDIO_BIT_DEPTH, rbConfigAudio16Bit }, 85 { 453, 73, 51, RB_GROUP_CONFIG_AUDIO_BIT_DEPTH, rbConfigAudio32BitFloat }, 86 87 // audio interpolation 88 //x, y, w, group, funcOnUp 89 { 390, 90, 108, RB_GROUP_CONFIG_AUDIO_INTERPOLATION, rbConfigAudioIntrpDisabled }, 90 { 390, 104, 90, RB_GROUP_CONFIG_AUDIO_INTERPOLATION, rbConfigAudioIntrpLinear }, 91 { 390, 118, 109, RB_GROUP_CONFIG_AUDIO_INTERPOLATION, rbConfigAudioIntrpQuadratic }, 92 { 390, 132, 85, RB_GROUP_CONFIG_AUDIO_INTERPOLATION, rbConfigAudioIntrpCubic }, 93 { 390, 146, 94, RB_GROUP_CONFIG_AUDIO_INTERPOLATION, rbConfigAudioIntrpSinc8 }, 94 { 390, 160, 101, RB_GROUP_CONFIG_AUDIO_INTERPOLATION, rbConfigAudioIntrpSinc16 }, 95 96 // audio output frequency 97 //x, y, w, group, funcOnUp 98 { 513, 16, 65, RB_GROUP_CONFIG_AUDIO_FREQ, rbConfigAudio44kHz }, 99 { 513, 30, 65, RB_GROUP_CONFIG_AUDIO_FREQ, rbConfigAudio48kHz }, 100 { 513, 44, 65, RB_GROUP_CONFIG_AUDIO_FREQ, rbConfigAudio96kHz }, 101 102 // audio input frequency 103 //x, y, w, group, funcOnUp 104 { 180, 156, 60, RB_GROUP_CONFIG_AUDIO_INPUT_FREQ, rbConfigAudioInput44kHz }, 105 { 251, 156, 60, RB_GROUP_CONFIG_AUDIO_INPUT_FREQ, rbConfigAudioInput48kHz }, 106 { 322, 156, 60, RB_GROUP_CONFIG_AUDIO_INPUT_FREQ, rbConfigAudioInput96kHz }, 107 108 // frequency slides 109 //x, y, w, group, funcOnUp 110 { 513, 74, 49, RB_GROUP_CONFIG_FREQ_SLIDES, rbConfigFreqSlidesAmiga }, 111 { 513, 88, 107, RB_GROUP_CONFIG_FREQ_SLIDES, rbConfigFreqSlidesLinear }, 112 113 // ------ CONFIG LAYOUT ------ 114 115 // mouse shape 116 //x, y, w, group, funcOnUp 117 { 115, 120, 41, RB_GROUP_CONFIG_MOUSE, rbConfigMouseNice }, 118 { 178, 120, 41, RB_GROUP_CONFIG_MOUSE, rbConfigMouseUgly }, 119 { 115, 134, 47, RB_GROUP_CONFIG_MOUSE, rbConfigMouseAwful }, 120 { 178, 134, 55, RB_GROUP_CONFIG_MOUSE, rbConfigMouseUsable }, 121 122 // mouse busy shape 123 //x, y, w, group, funcOnUp 124 { 115, 159, 51, RB_GROUP_CONFIG_MOUSE_BUSY, rbConfigMouseBusyVogue }, 125 { 178, 159, 45, RB_GROUP_CONFIG_MOUSE_BUSY, rbConfigMouseBusyMrH }, 126 127 // scope style 128 //x, y, w, group, funcOnUp 129 { 305, 145, 38, RB_GROUP_CONFIG_SCOPE, rbConfigScopeStandard }, 130 { 346, 145, 46, RB_GROUP_CONFIG_SCOPE, rbConfigScopeLined }, 131 132 // visible pattern channels 133 //x, y, w, group, funcOnUp 134 { 257, 42, 78, RB_GROUP_CONFIG_PATTERN_CHANS, rbConfigPatt4Chans }, 135 { 257, 56, 78, RB_GROUP_CONFIG_PATTERN_CHANS, rbConfigPatt6Chans }, 136 { 257, 70, 78, RB_GROUP_CONFIG_PATTERN_CHANS, rbConfigPatt8Chans }, 137 { 257, 84, 85, RB_GROUP_CONFIG_PATTERN_CHANS, rbConfigPatt12Chans }, 138 139 // pattern font 140 //x, y, w, group, funcOnUp 141 { 257, 114, 62, RB_GROUP_CONFIG_FONT, rbConfigFontCapitals }, 142 { 323, 114, 68, RB_GROUP_CONFIG_FONT, rbConfigFontLowerCase }, 143 { 257, 129, 54, RB_GROUP_CONFIG_FONT, rbConfigFontFuture }, 144 { 323, 129, 40, RB_GROUP_CONFIG_FONT, rbConfigFontBold }, 145 146 // palette entries 147 //x, y, w, group, funcOnUp 148 { 399, 2, 88, RB_GROUP_CONFIG_PAL_ENTRIES, rbConfigPalPatternText }, 149 { 399, 16, 79, RB_GROUP_CONFIG_PAL_ENTRIES, rbConfigPalBlockMark }, 150 { 399, 30, 97, RB_GROUP_CONFIG_PAL_ENTRIES, rbConfigPalTextOnBlock }, 151 { 399, 44, 52, RB_GROUP_CONFIG_PAL_ENTRIES, rbConfigPalMouse }, 152 { 399, 58, 63, RB_GROUP_CONFIG_PAL_ENTRIES, rbConfigPalDesktop }, 153 { 399, 72, 61, RB_GROUP_CONFIG_PAL_ENTRIES, rbConfigPalButttons }, 154 155 // palette presets 156 //x, y, w, group, funcOnUp 157 { 399, 89, 50, RB_GROUP_CONFIG_PAL_PRESET, rbConfigPalArctic }, 158 { 512, 89, 81, RB_GROUP_CONFIG_PAL_PRESET, rbConfigPalLitheDark }, 159 { 399, 103, 105, RB_GROUP_CONFIG_PAL_PRESET, rbConfigPalAuroraBorealis }, 160 { 512, 103, 45, RB_GROUP_CONFIG_PAL_PRESET, rbConfigPalRose }, 161 { 399, 117, 47, RB_GROUP_CONFIG_PAL_PRESET, rbConfigPalBlues }, 162 { 512, 117, 77, RB_GROUP_CONFIG_PAL_PRESET, rbConfigPalDarkMode }, 163 { 399, 131, 40, RB_GROUP_CONFIG_PAL_PRESET, rbConfigPalGold }, 164 { 512, 131, 56, RB_GROUP_CONFIG_PAL_PRESET, rbConfigPalViolent }, 165 { 399, 145, 87, RB_GROUP_CONFIG_PAL_PRESET, rbConfigPalHeavyMetal }, 166 { 512, 145, 87, RB_GROUP_CONFIG_PAL_PRESET, rbConfigPalWhyColors }, 167 { 399, 159, 54, RB_GROUP_CONFIG_PAL_PRESET, rbConfigPalJungle }, 168 { 512, 159, 90, RB_GROUP_CONFIG_PAL_PRESET, rbConfigPalUserDefined }, 169 170 // ------ CONFIG MISCELLANEOUS ------ 171 172 // FILENAME SORTING 173 //x, y, w, group, funcOnUp 174 { 114, 15, 40, RB_GROUP_CONFIG_FILESORT, rbFileSortExt }, 175 { 114, 29, 48, RB_GROUP_CONFIG_FILESORT, rbFileSortName }, 176 177 // WINDOW SIZE 178 //x, y, w, group, funcOnUp 179 { 114, 58, 60, RB_GROUP_CONFIG_WIN_SIZE, rbWinSizeAuto }, 180 { 114, 72, 31, RB_GROUP_CONFIG_WIN_SIZE, rbWinSize1x }, 181 { 156, 72, 31, RB_GROUP_CONFIG_WIN_SIZE, rbWinSize3x }, 182 { 114, 86, 31, RB_GROUP_CONFIG_WIN_SIZE, rbWinSize2x }, 183 { 156, 86, 31, RB_GROUP_CONFIG_WIN_SIZE, rbWinSize4x }, 184 185 // ------ DISK OP. ------ 186 187 // FILENAME SORTING 188 //x, y, w, group, funcOnUp 189 { 4, 16, 55, RB_GROUP_DISKOP_ITEM, rbDiskOpModule }, 190 { 4, 30, 45, RB_GROUP_DISKOP_ITEM, rbDiskOpInstr }, 191 { 4, 44, 56, RB_GROUP_DISKOP_ITEM, rbDiskOpSample }, 192 { 4, 58, 59, RB_GROUP_DISKOP_ITEM, rbDiskOpPattern }, 193 { 4, 72, 50, RB_GROUP_DISKOP_ITEM, rbDiskOpTrack }, 194 195 // MODULE SAVE AS FORMATS 196 //x, y, w, group, funcOnUp 197 { 4, 100, 40, RB_GROUP_DISKOP_MOD_SAVEAS, rbDiskOpModSaveMod }, 198 { 4, 114, 33, RB_GROUP_DISKOP_MOD_SAVEAS, rbDiskOpModSaveXm }, 199 { 4, 128, 40, RB_GROUP_DISKOP_MOD_SAVEAS, rbDiskOpModSaveWav }, 200 201 // INSTRUMENT SAVE AS FORMATS 202 //x, y, w, group, funcOnUp 203 { 4, 100, 29, RB_GROUP_DISKOP_INS_SAVEAS, NULL }, 204 205 // SAMPLE SAVE AS FORMATS 206 //x, y, w, group, funcOnUp 207 { 4, 100, 40, RB_GROUP_DISKOP_SMP_SAVEAS, rbDiskOpSmpSaveRaw }, 208 { 4, 114, 34, RB_GROUP_DISKOP_SMP_SAVEAS, rbDiskOpSmpSaveIff }, 209 { 4, 128, 40, RB_GROUP_DISKOP_SMP_SAVEAS, rbDiskOpSmpSaveWav }, 210 211 // PATTERN SAVE AS FORMATS 212 //x, y, w, group, funcOnUp 213 { 4, 100, 33, RB_GROUP_DISKOP_PAT_SAVEAS, NULL }, 214 215 // TRACK SAVE AS FORMATS 216 //x, y, w, group, funcOnUp 217 { 4, 100, 31, RB_GROUP_DISKOP_TRK_SAVEAS, NULL }, 218 219 // WAV RENDERER BITDEPTH 220 //x, y, w, group, funcOnUp 221 { 130, 95, 52, RB_GROUP_WAV_RENDER_BITDEPTH, rbWavRenderBitDepth16 }, 222 { 195, 95, 93, RB_GROUP_WAV_RENDER_BITDEPTH, rbWavRenderBitDepth32 } 223 }; 224 225 void drawRadioButton(uint16_t radioButtonID) 226 { 227 assert(radioButtonID < NUM_RADIOBUTTONS); 228 radioButton_t *radioButton = &radioButtons[radioButtonID]; 229 if (!radioButton->visible) 230 return; 231 232 assert(radioButton->x < SCREEN_W && radioButton->y < SCREEN_H); 233 234 const uint8_t *gfxPtr = &bmp.radiobuttonGfx[radioButton->state*(RADIOBUTTON_W*RADIOBUTTON_H)]; 235 blitFast(radioButton->x, radioButton->y, gfxPtr, RADIOBUTTON_W, RADIOBUTTON_H); 236 } 237 238 void showRadioButton(uint16_t radioButtonID) 239 { 240 assert(radioButtonID < NUM_RADIOBUTTONS); 241 radioButtons[radioButtonID].visible = true; 242 drawRadioButton(radioButtonID); 243 } 244 245 void hideRadioButton(uint16_t radioButtonID) 246 { 247 assert(radioButtonID < NUM_RADIOBUTTONS); 248 radioButtons[radioButtonID].state = 0; 249 radioButtons[radioButtonID].visible = false; 250 } 251 252 void checkRadioButton(uint16_t radioButtonID) 253 { 254 assert(radioButtonID < NUM_RADIOBUTTONS); 255 const uint16_t testGroup = radioButtons[radioButtonID].group; 256 257 radioButton_t *radioButton = radioButtons; 258 for (uint16_t i = 0; i < NUM_RADIOBUTTONS; i++, radioButton++) 259 { 260 if (radioButton->group == testGroup && radioButton->state == RADIOBUTTON_CHECKED) 261 { 262 radioButton->state = RADIOBUTTON_UNCHECKED; 263 drawRadioButton(i); 264 break; 265 } 266 } 267 268 radioButtons[radioButtonID].state = RADIOBUTTON_CHECKED; 269 drawRadioButton(radioButtonID); 270 } 271 272 void uncheckRadioButtonGroup(uint16_t radioButtonGroup) 273 { 274 radioButton_t *radioButton = radioButtons; 275 for (uint16_t i = 0; i < NUM_RADIOBUTTONS; i++, radioButton++) 276 { 277 if (radioButton->group == radioButtonGroup) 278 radioButton->state = RADIOBUTTON_UNCHECKED; 279 } 280 } 281 282 void showRadioButtonGroup(uint16_t radioButtonGroup) 283 { 284 radioButton_t *radioButton = radioButtons; 285 for (uint16_t i = 0; i < NUM_RADIOBUTTONS; i++, radioButton++) 286 { 287 if (radioButton->group == radioButtonGroup) 288 showRadioButton(i); 289 } 290 } 291 292 void hideRadioButtonGroup(uint16_t radioButtonGroup) 293 { 294 radioButton_t *radioButton = radioButtons; 295 for (uint16_t i = 0; i < NUM_RADIOBUTTONS; i++, radioButton++) 296 { 297 if (radioButton->group == radioButtonGroup) 298 hideRadioButton(i); 299 } 300 } 301 302 void handleRadioButtonsWhileMouseDown(void) 303 { 304 assert(mouse.lastUsedObjectID >= 0 && mouse.lastUsedObjectID < NUM_RADIOBUTTONS); 305 radioButton_t *radioButton = &radioButtons[mouse.lastUsedObjectID]; 306 if (!radioButton->visible || radioButton->state == RADIOBUTTON_CHECKED) 307 return; 308 309 radioButton->state = RADIOBUTTON_UNCHECKED; 310 if (mouse.x >= radioButton->x && mouse.x < radioButton->x+radioButton->clickAreaWidth && 311 mouse.y >= radioButton->y && mouse.y < radioButton->y+(RADIOBUTTON_H+1)) 312 { 313 radioButton->state = RADIOBUTTON_PRESSED; 314 } 315 316 if (mouse.lastX != mouse.x || mouse.lastY != mouse.y) 317 { 318 mouse.lastX = mouse.x; 319 mouse.lastY = mouse.y; 320 321 drawRadioButton(mouse.lastUsedObjectID); 322 } 323 } 324 325 bool testRadioButtonMouseDown(void) 326 { 327 if (ui.sysReqShown) 328 return false; 329 330 const int32_t mx = mouse.x; 331 const int32_t my = mouse.y; 332 333 radioButton_t *radioButton = radioButtons; 334 for (uint16_t i = 0; i < NUM_RADIOBUTTONS; i++, radioButton++) 335 { 336 if (!radioButton->visible || radioButton->state == RADIOBUTTON_CHECKED) 337 continue; 338 339 if (mx >= radioButton->x && mx < radioButton->x+radioButton->clickAreaWidth && 340 my >= radioButton->y && my < radioButton->y+(RADIOBUTTON_H+1)) 341 { 342 mouse.lastUsedObjectID = i; 343 mouse.lastUsedObjectType = OBJECT_RADIOBUTTON; 344 return true; 345 } 346 } 347 348 return false; 349 } 350 351 void testRadioButtonMouseRelease(void) 352 { 353 if (mouse.lastUsedObjectType != OBJECT_RADIOBUTTON || mouse.lastUsedObjectID == OBJECT_ID_NONE) 354 return; 355 356 assert(mouse.lastUsedObjectID < NUM_RADIOBUTTONS); 357 radioButton_t *radioButton = &radioButtons[mouse.lastUsedObjectID]; 358 if (!radioButton->visible || radioButton->state == RADIOBUTTON_CHECKED) 359 return; 360 361 if (mouse.x >= radioButton->x && mouse.x < radioButton->x+radioButton->clickAreaWidth && 362 mouse.y >= radioButton->y && mouse.y < radioButton->y+(RADIOBUTTON_H+1)) 363 { 364 radioButton->state = RADIOBUTTON_UNCHECKED; 365 drawRadioButton(mouse.lastUsedObjectID); 366 367 if (radioButton->callbackFunc != NULL) 368 radioButton->callbackFunc(); 369 } 370 }