ft2-clone

Fasttracker 2 clone
Log | Files | Refs | README | LICENSE

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 }