2022-01-17 23:18:28 +00:00
# define _USE_MATH_DEFINES
2021-12-11 07:10:09 +00:00
# include "gui.h"
2022-01-27 05:29:16 +00:00
# include "debug.h"
2021-12-19 07:12:19 +00:00
# include "SDL_clipboard.h"
2021-12-12 09:21:09 +00:00
# include "SDL_events.h"
2021-12-15 05:37:27 +00:00
# include "SDL_keycode.h"
2021-12-13 22:09:46 +00:00
# include "SDL_render.h"
2021-12-12 09:21:09 +00:00
# include "SDL_video.h"
2021-12-11 08:11:40 +00:00
# include "fonts.h"
2022-01-07 08:29:56 +00:00
# include "icon.h"
2021-12-11 08:11:40 +00:00
# include "../ta-log.h"
2022-01-20 10:04:03 +00:00
# include "../fileutils.h"
2021-12-11 08:11:40 +00:00
# include "imgui.h"
2021-12-19 21:01:24 +00:00
# include "imgui_impl_sdl.h"
# include "imgui_impl_sdlrenderer.h"
2021-12-13 07:03:36 +00:00
# include "imgui_internal.h"
2021-12-15 05:37:27 +00:00
# include "ImGuiFileDialog.h"
2021-12-21 05:30:55 +00:00
# include "IconsFontAwesome4.h"
2021-12-18 22:54:26 +00:00
# include "plot_nolerp.h"
2021-12-11 22:41:32 +00:00
# include "misc/cpp/imgui_stdlib.h"
2022-01-18 02:08:14 +00:00
# include <stdint.h>
2021-12-15 19:15:44 +00:00
# include <zlib.h>
2021-12-11 21:44:02 +00:00
# include <fmt/printf.h>
2021-12-14 22:45:37 +00:00
# include <stdexcept>
2021-12-11 07:10:09 +00:00
2022-01-22 21:34:44 +00:00
# ifdef __APPLE__
# define CMD_MODIFIER KMOD_GUI
# define CMD_MODIFIER_NAME "Cmd-"
# define SHIFT_MODIFIER_NAME "Shift-"
2022-02-08 07:04:23 +00:00
extern " C " {
# include "macstuff.h"
}
2022-01-22 21:34:44 +00:00
# else
# define CMD_MODIFIER KMOD_CTRL
# define CMD_MODIFIER_NAME "Ctrl-"
# define SHIFT_MODIFIER_NAME "Shift-"
# endif
2021-12-15 05:37:27 +00:00
# ifdef _WIN32
# include <windows.h>
2022-01-19 10:44:19 +00:00
# include <shlobj.h>
# include <shlwapi.h>
# include "../utfutils.h"
2021-12-19 08:16:24 +00:00
# define LAYOUT_INI "\\layout.ini"
2021-12-15 05:37:27 +00:00
# else
# include <unistd.h>
2021-12-31 03:34:42 +00:00
# include <pwd.h>
2022-01-19 10:44:19 +00:00
# include <sys/stat.h>
2021-12-19 08:16:24 +00:00
# define LAYOUT_INI " / layout.ini"
2021-12-15 05:37:27 +00:00
# endif
2021-12-11 22:41:32 +00:00
const int _ZERO = 0 ;
2021-12-12 09:21:09 +00:00
const int _ONE = 1 ;
2021-12-11 22:41:32 +00:00
const int _THREE = 3 ;
const int _SEVEN = 7 ;
2021-12-17 08:33:12 +00:00
const int _TEN = 10 ;
2021-12-12 23:19:43 +00:00
const int _FIFTEEN = 15 ;
2021-12-11 22:41:32 +00:00
const int _THIRTY_ONE = 31 ;
2021-12-12 23:19:43 +00:00
const int _SIXTY_FOUR = 64 ;
const int _ONE_HUNDRED = 100 ;
2021-12-11 22:41:32 +00:00
const int _ONE_HUNDRED_TWENTY_SEVEN = 127 ;
2022-01-09 22:00:52 +00:00
const int _TWO_THOUSAND_FORTY_SEVEN = 2047 ;
const int _FOUR_THOUSAND_NINETY_FIVE = 4095 ;
2022-01-13 06:03:57 +00:00
const int _MINUS_ONE_HUNDRED_TWENTY_SEVEN = - 127 ;
2021-12-11 22:41:32 +00:00
2021-12-13 22:09:46 +00:00
const FurnaceGUIColors fxColors [ 16 ] = {
GUI_COLOR_PATTERN_EFFECT_MISC , // 00
GUI_COLOR_PATTERN_EFFECT_PITCH , // 01
GUI_COLOR_PATTERN_EFFECT_PITCH , // 02
GUI_COLOR_PATTERN_EFFECT_PITCH , // 03
GUI_COLOR_PATTERN_EFFECT_PITCH , // 04
GUI_COLOR_PATTERN_EFFECT_VOLUME , // 05
GUI_COLOR_PATTERN_EFFECT_VOLUME , // 06
GUI_COLOR_PATTERN_EFFECT_VOLUME , // 07
GUI_COLOR_PATTERN_EFFECT_PANNING , // 08
GUI_COLOR_PATTERN_EFFECT_SPEED , // 09
GUI_COLOR_PATTERN_EFFECT_VOLUME , // 0A
GUI_COLOR_PATTERN_EFFECT_SONG , // 0B
GUI_COLOR_PATTERN_EFFECT_TIME , // 0C
GUI_COLOR_PATTERN_EFFECT_SONG , // 0D
GUI_COLOR_PATTERN_EFFECT_INVALID , // 0E
GUI_COLOR_PATTERN_EFFECT_SPEED , // 0F
} ;
const FurnaceGUIColors extFxColors [ 16 ] = {
GUI_COLOR_PATTERN_EFFECT_MISC , // E0
GUI_COLOR_PATTERN_EFFECT_PITCH , // E1
GUI_COLOR_PATTERN_EFFECT_PITCH , // E2
GUI_COLOR_PATTERN_EFFECT_MISC , // E3
GUI_COLOR_PATTERN_EFFECT_MISC , // E4
GUI_COLOR_PATTERN_EFFECT_PITCH , // E5
GUI_COLOR_PATTERN_EFFECT_INVALID , // E6
GUI_COLOR_PATTERN_EFFECT_INVALID , // E7
GUI_COLOR_PATTERN_EFFECT_INVALID , // E8
GUI_COLOR_PATTERN_EFFECT_INVALID , // E9
GUI_COLOR_PATTERN_EFFECT_MISC , // EA
GUI_COLOR_PATTERN_EFFECT_MISC , // EB
GUI_COLOR_PATTERN_EFFECT_TIME , // EC
GUI_COLOR_PATTERN_EFFECT_TIME , // ED
GUI_COLOR_PATTERN_EFFECT_SONG , // EE
GUI_COLOR_PATTERN_EFFECT_SONG , // EF
} ;
2021-12-11 22:41:32 +00:00
const int opOrder [ 4 ] = {
0 , 2 , 1 , 3
} ;
2022-01-18 21:55:32 +00:00
const char * noteNames [ 180 ] = {
" c_5 " , " c+5 " , " d_5 " , " d+5 " , " e_5 " , " f_5 " , " f+5 " , " g_5 " , " g+5 " , " a_5 " , " a+5 " , " b_5 " ,
" c_4 " , " c+4 " , " d_4 " , " d+4 " , " e_4 " , " f_4 " , " f+4 " , " g_4 " , " g+4 " , " a_4 " , " a+4 " , " b_4 " ,
" c_3 " , " c+3 " , " d_3 " , " d+3 " , " e_3 " , " f_3 " , " f+3 " , " g_3 " , " g+3 " , " a_3 " , " a+3 " , " b_3 " ,
" c_2 " , " c+2 " , " d_2 " , " d+2 " , " e_2 " , " f_2 " , " f+2 " , " g_2 " , " g+2 " , " a_2 " , " a+2 " , " b_2 " ,
" c_1 " , " c+1 " , " d_1 " , " d+1 " , " e_1 " , " f_1 " , " f+1 " , " g_1 " , " g+1 " , " a_1 " , " a+1 " , " b_1 " ,
2021-12-13 07:03:36 +00:00
" C-0 " , " C#0 " , " D-0 " , " D#0 " , " E-0 " , " F-0 " , " F#0 " , " G-0 " , " G#0 " , " A-0 " , " A#0 " , " B-0 " ,
" C-1 " , " C#1 " , " D-1 " , " D#1 " , " E-1 " , " F-1 " , " F#1 " , " G-1 " , " G#1 " , " A-1 " , " A#1 " , " B-1 " ,
" C-2 " , " C#2 " , " D-2 " , " D#2 " , " E-2 " , " F-2 " , " F#2 " , " G-2 " , " G#2 " , " A-2 " , " A#2 " , " B-2 " ,
" C-3 " , " C#3 " , " D-3 " , " D#3 " , " E-3 " , " F-3 " , " F#3 " , " G-3 " , " G#3 " , " A-3 " , " A#3 " , " B-3 " ,
" C-4 " , " C#4 " , " D-4 " , " D#4 " , " E-4 " , " F-4 " , " F#4 " , " G-4 " , " G#4 " , " A-4 " , " A#4 " , " B-4 " ,
" C-5 " , " C#5 " , " D-5 " , " D#5 " , " E-5 " , " F-5 " , " F#5 " , " G-5 " , " G#5 " , " A-5 " , " A#5 " , " B-5 " ,
" C-6 " , " C#6 " , " D-6 " , " D#6 " , " E-6 " , " F-6 " , " F#6 " , " G-6 " , " G#6 " , " A-6 " , " A#6 " , " B-6 " ,
" C-7 " , " C#7 " , " D-7 " , " D#7 " , " E-7 " , " F-7 " , " F#7 " , " G-7 " , " G#7 " , " A-7 " , " A#7 " , " B-7 " ,
" C-8 " , " C#8 " , " D-8 " , " D#8 " , " E-8 " , " F-8 " , " F#8 " , " G-8 " , " G#8 " , " A-8 " , " A#8 " , " B-8 " ,
" C-9 " , " C#9 " , " D-9 " , " D#9 " , " E-9 " , " F-9 " , " F#9 " , " G-9 " , " G#9 " , " A-9 " , " A#9 " , " B-9 "
} ;
2022-02-03 19:40:09 +00:00
const char * noteNamesG [ 180 ] = {
" c_5 " , " c+5 " , " d_5 " , " d+5 " , " e_5 " , " f_5 " , " f+5 " , " g_5 " , " g+5 " , " a_5 " , " a+5 " , " h_5 " ,
" c_4 " , " c+4 " , " d_4 " , " d+4 " , " e_4 " , " f_4 " , " f+4 " , " g_4 " , " g+4 " , " a_4 " , " a+4 " , " h_4 " ,
" c_3 " , " c+3 " , " d_3 " , " d+3 " , " e_3 " , " f_3 " , " f+3 " , " g_3 " , " g+3 " , " a_3 " , " a+3 " , " h_3 " ,
" c_2 " , " c+2 " , " d_2 " , " d+2 " , " e_2 " , " f_2 " , " f+2 " , " g_2 " , " g+2 " , " a_2 " , " a+2 " , " h_2 " ,
" c_1 " , " c+1 " , " d_1 " , " d+1 " , " e_1 " , " f_1 " , " f+1 " , " g_1 " , " g+1 " , " a_1 " , " a+1 " , " h_1 " ,
" C-0 " , " C#0 " , " D-0 " , " D#0 " , " E-0 " , " F-0 " , " F#0 " , " G-0 " , " G#0 " , " A-0 " , " A#0 " , " H-0 " ,
" C-1 " , " C#1 " , " D-1 " , " D#1 " , " E-1 " , " F-1 " , " F#1 " , " G-1 " , " G#1 " , " A-1 " , " A#1 " , " H-1 " ,
" C-2 " , " C#2 " , " D-2 " , " D#2 " , " E-2 " , " F-2 " , " F#2 " , " G-2 " , " G#2 " , " A-2 " , " A#2 " , " H-2 " ,
" C-3 " , " C#3 " , " D-3 " , " D#3 " , " E-3 " , " F-3 " , " F#3 " , " G-3 " , " G#3 " , " A-3 " , " A#3 " , " H-3 " ,
" C-4 " , " C#4 " , " D-4 " , " D#4 " , " E-4 " , " F-4 " , " F#4 " , " G-4 " , " G#4 " , " A-4 " , " A#4 " , " H-4 " ,
" C-5 " , " C#5 " , " D-5 " , " D#5 " , " E-5 " , " F-5 " , " F#5 " , " G-5 " , " G#5 " , " A-5 " , " A#5 " , " H-5 " ,
" C-6 " , " C#6 " , " D-6 " , " D#6 " , " E-6 " , " F-6 " , " F#6 " , " G-6 " , " G#6 " , " A-6 " , " A#6 " , " H-6 " ,
" C-7 " , " C#7 " , " D-7 " , " D#7 " , " E-7 " , " F-7 " , " F#7 " , " G-7 " , " G#7 " , " A-7 " , " A#7 " , " H-7 " ,
" C-8 " , " C#8 " , " D-8 " , " D#8 " , " E-8 " , " F-8 " , " F#8 " , " G-8 " , " G#8 " , " A-8 " , " A#8 " , " H-8 " ,
" C-9 " , " C#9 " , " D-9 " , " D#9 " , " E-9 " , " F-9 " , " F#9 " , " G-9 " , " G#9 " , " A-9 " , " A#9 " , " H-9 "
} ;
2021-12-17 08:33:12 +00:00
const char * pitchLabel [ 11 ] = {
" 1/6 " , " 1/5 " , " 1/4 " , " 1/3 " , " 1/2 " , " 1x " , " 2x " , " 3x " , " 4x " , " 5x " , " 6x "
} ;
2022-01-19 10:44:19 +00:00
String getHomeDir ( ) ;
2021-12-11 07:10:09 +00:00
void FurnaceGUI : : bindEngine ( DivEngine * eng ) {
e = eng ;
}
2022-02-03 19:40:09 +00:00
const char * noteNameNormal ( short note , short octave ) {
2022-02-08 08:50:42 +00:00
if ( note = = 100 ) { // note cut
2022-02-03 19:40:09 +00:00
return " OFF " ;
2022-02-08 08:50:42 +00:00
} else if ( note = = 101 ) { // note off and envelope release
return " === " ;
} else if ( note = = 102 ) { // envelope release only
return " REL " ;
2022-02-03 19:40:09 +00:00
} else if ( octave = = 0 & & note = = 0 ) {
return " ... " ;
}
int seek = ( note + ( signed char ) octave * 12 ) + 60 ;
if ( seek < 0 | | seek > = 180 ) {
return " ??? " ;
}
return noteNames [ seek ] ;
}
2021-12-13 07:03:36 +00:00
const char * FurnaceGUI : : noteName ( short note , short octave ) {
if ( note = = 100 ) {
return " OFF " ;
2022-02-08 08:50:42 +00:00
} else if ( note = = 101 ) { // note off and envelope release
return " === " ;
} else if ( note = = 102 ) { // envelope release only
return " REL " ;
2021-12-13 07:03:36 +00:00
} else if ( octave = = 0 & & note = = 0 ) {
return " ... " ;
}
2022-01-18 21:55:32 +00:00
int seek = ( note + ( signed char ) octave * 12 ) + 60 ;
if ( seek < 0 | | seek > = 180 ) {
return " ??? " ;
}
2022-02-03 19:40:09 +00:00
if ( settings . germanNotation ) return noteNamesG [ seek ] ;
2021-12-13 07:03:36 +00:00
return noteNames [ seek ] ;
}
2021-12-19 07:12:19 +00:00
bool FurnaceGUI : : decodeNote ( const char * what , short & note , short & octave ) {
if ( strlen ( what ) ! = 3 ) return false ;
if ( strcmp ( what , " ... " ) = = 0 ) {
note = 0 ;
octave = 0 ;
return true ;
}
if ( strcmp ( what , " ??? " ) = = 0 ) {
note = 0 ;
octave = 0 ;
return true ;
}
if ( strcmp ( what , " OFF " ) = = 0 ) {
note = 100 ;
octave = 0 ;
return true ;
}
2022-01-20 02:53:21 +00:00
for ( int i = 0 ; i < 180 ; i + + ) {
2021-12-19 07:12:19 +00:00
if ( strcmp ( what , noteNames [ i ] ) = = 0 ) {
if ( ( i % 12 ) = = 0 ) {
note = 12 ;
2022-01-19 09:32:40 +00:00
octave = ( unsigned char ) ( ( i / 12 ) - 6 ) ;
2021-12-19 07:12:19 +00:00
} else {
note = i % 12 ;
2022-01-19 09:32:40 +00:00
octave = ( unsigned char ) ( ( i / 12 ) - 5 ) ;
2021-12-19 07:12:19 +00:00
}
return true ;
}
}
return false ;
}
2022-02-08 08:50:42 +00:00
void FurnaceGUI : : encodeMMLStr ( String & target , unsigned char * macro , unsigned char macroLen , signed char macroLoop , signed char macroRel ) {
2022-01-26 22:22:29 +00:00
target = " " ;
char buf [ 32 ] ;
for ( int i = 0 ; i < macroLen ; i + + ) {
if ( i = = macroLoop ) target + = " | " ;
2022-02-08 08:50:42 +00:00
if ( i = = macroRel ) target + = " / " ;
2022-01-26 22:22:29 +00:00
if ( i = = macroLen - 1 ) {
snprintf ( buf , 31 , " %d " , macro [ i ] ) ;
} else {
snprintf ( buf , 31 , " %d " , macro [ i ] ) ;
}
target + = buf ;
}
}
2022-02-08 08:50:42 +00:00
void FurnaceGUI : : encodeMMLStr ( String & target , int * macro , int macroLen , int macroLoop , int macroRel ) {
2022-01-26 18:13:17 +00:00
target = " " ;
char buf [ 32 ] ;
for ( int i = 0 ; i < macroLen ; i + + ) {
if ( i = = macroLoop ) target + = " | " ;
2022-02-08 08:50:42 +00:00
if ( i = = macroRel ) target + = " / " ;
2022-01-26 18:13:17 +00:00
if ( i = = macroLen - 1 ) {
snprintf ( buf , 31 , " %d " , macro [ i ] ) ;
} else {
snprintf ( buf , 31 , " %d " , macro [ i ] ) ;
}
target + = buf ;
}
}
2022-01-26 21:29:49 +00:00
void FurnaceGUI : : decodeMMLStrW ( String & source , int * macro , int & macroLen , int macroMax ) {
int buf = 0 ;
bool negaBuf = false ;
bool hasVal = false ;
macroLen = 0 ;
for ( char & i : source ) {
switch ( i ) {
case ' 0 ' : case ' 1 ' : case ' 2 ' : case ' 3 ' : case ' 4 ' :
case ' 5 ' : case ' 6 ' : case ' 7 ' : case ' 8 ' : case ' 9 ' :
hasVal = true ;
buf * = 10 ;
buf + = i - ' 0 ' ;
break ;
case ' - ' :
if ( ! hasVal ) {
hasVal = true ;
negaBuf = true ;
}
break ;
case ' ' :
if ( hasVal ) {
hasVal = false ;
negaBuf = false ;
macro [ macroLen ] = negaBuf ? - buf : buf ;
if ( macro [ macroLen ] < 0 ) macro [ macroLen ] = 0 ;
if ( macro [ macroLen ] > macroMax ) macro [ macroLen ] = macroMax ;
macroLen + + ;
buf = 0 ;
}
break ;
}
if ( macroLen > = 256 ) break ;
}
if ( hasVal & & macroLen < 256 ) {
hasVal = false ;
negaBuf = false ;
macro [ macroLen ] = negaBuf ? - buf : buf ;
if ( macro [ macroLen ] < 0 ) macro [ macroLen ] = 0 ;
if ( macro [ macroLen ] > macroMax ) macro [ macroLen ] = macroMax ;
macroLen + + ;
buf = 0 ;
}
}
2022-02-08 08:50:42 +00:00
void FurnaceGUI : : decodeMMLStr ( String & source , unsigned char * macro , unsigned char & macroLen , signed char & macroLoop , int macroMin , int macroMax , signed char & macroRel ) {
2022-01-26 22:22:29 +00:00
int buf = 0 ;
bool hasVal = false ;
macroLen = 0 ;
macroLoop = - 1 ;
for ( char & i : source ) {
switch ( i ) {
case ' 0 ' : case ' 1 ' : case ' 2 ' : case ' 3 ' : case ' 4 ' :
case ' 5 ' : case ' 6 ' : case ' 7 ' : case ' 8 ' : case ' 9 ' :
hasVal = true ;
buf * = 10 ;
buf + = i - ' 0 ' ;
break ;
case ' ' :
if ( hasVal ) {
hasVal = false ;
macro [ macroLen ] = buf ;
if ( macro [ macroLen ] < macroMin ) macro [ macroLen ] = macroMin ;
if ( macro [ macroLen ] > macroMax ) macro [ macroLen ] = macroMax ;
macroLen + + ;
buf = 0 ;
}
break ;
case ' | ' :
if ( macroLoop = = - 1 ) {
macroLoop = macroLen ;
}
break ;
2022-02-08 08:50:42 +00:00
case ' / ' :
if ( macroRel = = - 1 ) {
macroRel = macroLen ;
}
break ;
2022-01-26 22:22:29 +00:00
}
if ( macroLen > = 128 ) break ;
}
if ( hasVal & & macroLen < 128 ) {
hasVal = false ;
macro [ macroLen ] = buf ;
if ( macro [ macroLen ] < macroMin ) macro [ macroLen ] = macroMin ;
if ( macro [ macroLen ] > macroMax ) macro [ macroLen ] = macroMax ;
macroLen + + ;
buf = 0 ;
}
}
2022-02-08 08:50:42 +00:00
void FurnaceGUI : : decodeMMLStr ( String & source , int * macro , unsigned char & macroLen , signed char & macroLoop , int macroMin , int macroMax , signed char & macroRel ) {
2022-01-26 18:13:17 +00:00
int buf = 0 ;
bool negaBuf = false ;
bool hasVal = false ;
macroLen = 0 ;
macroLoop = - 1 ;
for ( char & i : source ) {
switch ( i ) {
case ' 0 ' : case ' 1 ' : case ' 2 ' : case ' 3 ' : case ' 4 ' :
case ' 5 ' : case ' 6 ' : case ' 7 ' : case ' 8 ' : case ' 9 ' :
hasVal = true ;
buf * = 10 ;
buf + = i - ' 0 ' ;
break ;
case ' - ' :
if ( ! hasVal ) {
hasVal = true ;
negaBuf = true ;
}
break ;
case ' ' :
if ( hasVal ) {
hasVal = false ;
macro [ macroLen ] = negaBuf ? - buf : buf ;
2022-02-04 20:51:25 +00:00
negaBuf = false ;
2022-01-26 18:13:17 +00:00
if ( macro [ macroLen ] < macroMin ) macro [ macroLen ] = macroMin ;
if ( macro [ macroLen ] > macroMax ) macro [ macroLen ] = macroMax ;
macroLen + + ;
buf = 0 ;
}
break ;
case ' | ' :
if ( macroLoop = = - 1 ) {
macroLoop = macroLen ;
}
break ;
2022-02-08 08:50:42 +00:00
case ' / ' :
if ( macroRel = = - 1 ) {
macroRel = macroLen ;
}
break ;
2022-01-26 18:13:17 +00:00
}
if ( macroLen > = 128 ) break ;
}
if ( hasVal & & macroLen < 128 ) {
hasVal = false ;
macro [ macroLen ] = negaBuf ? - buf : buf ;
2022-02-04 20:51:25 +00:00
negaBuf = false ;
2022-01-26 18:13:17 +00:00
if ( macro [ macroLen ] < macroMin ) macro [ macroLen ] = macroMin ;
if ( macro [ macroLen ] > macroMax ) macro [ macroLen ] = macroMax ;
macroLen + + ;
buf = 0 ;
}
}
2022-01-28 08:17:35 +00:00
const char * FurnaceGUI : : getSystemName ( DivSystem which ) {
if ( settings . chipNames ) {
return e - > getSystemChips ( which ) ;
}
return e - > getSystemName ( which ) ;
}
2021-12-13 22:09:46 +00:00
void FurnaceGUI : : updateScroll ( int amount ) {
2022-01-22 08:15:43 +00:00
float lineHeight = ( patFont - > FontSize + 2 * dpiScale ) ;
2021-12-13 22:09:46 +00:00
nextScroll = lineHeight * amount ;
}
2021-12-24 03:14:59 +00:00
void FurnaceGUI : : addScroll ( int amount ) {
2022-01-22 08:15:43 +00:00
float lineHeight = ( patFont - > FontSize + 2 * dpiScale ) ;
2021-12-24 03:14:59 +00:00
nextAddScroll = lineHeight * amount ;
}
2022-02-02 06:14:21 +00:00
void FurnaceGUI : : setFileName ( String name ) {
# ifdef _WIN32
wchar_t ret [ 4096 ] ;
WString ws = utf8To16 ( name . c_str ( ) ) ;
int index = 0 ;
for ( wchar_t & i : ws ) {
ret [ index + + ] = i ;
if ( index > = 4095 ) break ;
}
ret [ index ] = 0 ;
if ( GetFullPathNameW ( ws . c_str ( ) , 4095 , ret , NULL ) = = 0 ) {
curFileName = name ;
} else {
curFileName = utf16To8 ( ret ) ;
}
# else
char ret [ 4096 ] ;
if ( realpath ( name . c_str ( ) , ret ) = = NULL ) {
curFileName = name ;
} else {
curFileName = ret ;
}
# endif
}
2021-12-15 22:32:08 +00:00
void FurnaceGUI : : updateWindowTitle ( ) {
2022-01-28 08:17:35 +00:00
String type = getSystemName ( e - > song . system [ 0 ] ) ;
2022-01-08 08:02:04 +00:00
if ( e - > song . systemLen > 1 ) type = " multi-system " ;
2021-12-15 22:32:08 +00:00
if ( e - > song . name . empty ( ) ) {
2022-01-08 08:02:04 +00:00
SDL_SetWindowTitle ( sdlWin , fmt : : sprintf ( " Furnace (%s) " , type ) . c_str ( ) ) ;
2021-12-15 22:32:08 +00:00
} else {
2022-01-08 08:02:04 +00:00
SDL_SetWindowTitle ( sdlWin , fmt : : sprintf ( " %s - Furnace (%s) " , e - > song . name , type ) . c_str ( ) ) ;
2021-12-15 22:32:08 +00:00
}
}
2021-12-19 21:01:24 +00:00
const char * defaultLayout = " [Window][DockSpaceViewport_11111111] \n \
Pos = 0 , 24 \ n \
2022-01-30 23:17:46 +00:00
Size = 1280 , 731 \ n \
2021-12-19 21:01:24 +00:00
Collapsed = 0 \ n \
\ n \
[ Window ] [ Debug # # Default ] \ n \
Pos = 60 , 60 \ n \
Size = 400 , 400 \ n \
Collapsed = 0 \ n \
\ n \
[ Window ] [ Play / Edit Controls ] \ n \
2022-01-30 23:17:46 +00:00
Pos = 390 , 24 \ n \
Size = 243 , 177 \ n \
2021-12-19 21:01:24 +00:00
Collapsed = 0 \ n \
2022-01-30 23:17:46 +00:00
DockId = 0x00000009 , 0 \ n \
2021-12-19 21:01:24 +00:00
\ n \
[ Window ] [ Song Information ] \ n \
2022-01-30 23:17:46 +00:00
Pos = 951 , 24 \ n \
Size = 329 , 240 \ n \
2021-12-19 21:01:24 +00:00
Collapsed = 0 \ n \
DockId = 0x00000004 , 0 \ n \
\ n \
[ Window ] [ Orders ] \ n \
Pos = 0 , 24 \ n \
2022-01-30 23:17:46 +00:00
Size = 388 , 240 \ n \
2021-12-19 21:01:24 +00:00
Collapsed = 0 \ n \
DockId = 0x00000005 , 0 \ n \
\ n \
[ Window ] [ Instruments ] \ n \
2022-01-30 23:17:46 +00:00
Pos = 635 , 24 \ n \
Size = 314 , 240 \ n \
2021-12-19 21:01:24 +00:00
Collapsed = 0 \ n \
DockId = 0x00000008 , 1 \ n \
\ n \
[ Window ] [ Wavetables ] \ n \
2022-01-30 23:17:46 +00:00
Pos = 635 , 24 \ n \
Size = 314 , 240 \ n \
2021-12-19 21:01:24 +00:00
Collapsed = 0 \ n \
DockId = 0x00000008 , 2 \ n \
\ n \
[ Window ] [ Samples ] \ n \
2022-01-30 23:17:46 +00:00
Pos = 635 , 24 \ n \
Size = 314 , 240 \ n \
2021-12-19 21:01:24 +00:00
Collapsed = 0 \ n \
DockId = 0x00000008 , 0 \ n \
\ n \
[ Window ] [ Pattern ] \ n \
2022-01-30 23:17:46 +00:00
Pos = 0 , 266 \ n \
Size = 1246 , 489 \ n \
2021-12-19 21:01:24 +00:00
Collapsed = 0 \ n \
2022-01-30 23:17:46 +00:00
DockId = 0x0000000B , 0 \ n \
2021-12-19 21:01:24 +00:00
\ n \
2022-01-30 23:17:46 +00:00
[ Window ] [ Open File # # FileDialog ] \ n \
Pos = 213 , 99 \ n \
Size = 853 , 557 \ n \
Collapsed = 0 \ n \
\ n \
[ Window ] [ Instrument Editor ] \ n \
Pos = 324 , 130 \ n \
Size = 951 , 623 \ n \
Collapsed = 0 \ n \
\ n \
[ Window ] [ Warning ] \ n \
Pos = 516 , 339 \ n \
Size = 346 , 71 \ n \
Collapsed = 0 \ n \
\ n \
[ Window ] [ Load Sample # # FileDialog ] \ n \
Pos = 340 , 177 \ n \
Size = 600 , 400 \ n \
Collapsed = 0 \ n \
\ n \
[ Window ] [ Sample Editor ] \ n \
Pos = 238 , 298 \ n \
Size = 551 , 286 \ n \
Collapsed = 0 \ n \
\ n \
[ Window ] [ About Furnace ] \ n \
Size = 1280 , 755 \ n \
Collapsed = 0 \ n \
\ n \
[ Window ] [ Save File # # FileDialog ] \ n \
Pos = 340 , 177 \ n \
Size = 600 , 400 \ n \
Collapsed = 0 \ n \
\ n \
[ Window ] [ Load Wavetable # # FileDialog ] \ n \
Pos = 340 , 177 \ n \
Size = 600 , 400 \ n \
Collapsed = 0 \ n \
\ n \
[ Window ] [ Wavetable Editor ] \ n \
Pos = 228 , 81 \ n \
Size = 580 , 368 \ n \
Collapsed = 0 \ n \
2021-12-19 21:01:24 +00:00
\ n \
2022-01-30 23:17:46 +00:00
[ Window ] [ Save Wavetable # # FileDialog ] \ n \
Pos = 340 , 177 \ n \
Size = 600 , 400 \ n \
Collapsed = 0 \ n \
\ n \
[ Window ] [ Settings ] \ n \
Pos = 495 , 97 \ n \
Size = 552 , 559 \ n \
Collapsed = 0 \ n \
\ n \
[ Window ] [ Error ] \ n \
Pos = 488 , 342 \ n \
Size = 304 , 71 \ n \
Collapsed = 0 \ n \
\ n \
[ Window ] [ Export VGM # # FileDialog ] \ n \
Pos = 340 , 177 \ n \
Size = 600 , 400 \ n \
Collapsed = 0 \ n \
\ n \
[ Window ] [ Mixer ] \ n \
Pos = 60 , 60 \ n \
Size = 450 , 215 \ n \
Collapsed = 0 \ n \
\ n \
[ Window ] [ Oscilloscope ] \ n \
Pos = 390 , 203 \ n \
Size = 243 , 61 \ n \
Collapsed = 0 \ n \
DockId = 0x0000000A , 0 \ n \
\ n \
[ Window ] [ Volume Meter ] \ n \
Pos = 1248 , 266 \ n \
Size = 32 , 489 \ n \
Collapsed = 0 \ n \
DockId = 0x0000000C , 0 \ n \
\ n \
[ Window ] [ Debug ] \ n \
Pos = 38 , 96 \ n \
Size = 1243 , 574 \ n \
Collapsed = 0 \ n \
\ n \
[ Docking ] [ Data ] \ n \
DockSpace ID = 0x8B93E3BD Window = 0xA787BDB4 Pos = 0 , 24 Size = 1280 , 731 Split = Y Selected = 0x6C01C512 \ n \
DockNode ID = 0x00000001 Parent = 0x8B93E3BD SizeRef = 1280 , 240 Split = X Selected = 0xF3094A52 \ n \
DockNode ID = 0x00000003 Parent = 0x00000001 SizeRef = 949 , 231 Split = X Selected = 0x65CC51DC \ n \
DockNode ID = 0x00000005 Parent = 0x00000003 SizeRef = 388 , 231 Selected = 0xE283F8D8 \ n \
DockNode ID = 0x00000006 Parent = 0x00000003 SizeRef = 559 , 231 Split = X Selected = 0x756E3877 \ n \
DockNode ID = 0x00000007 Parent = 0x00000006 SizeRef = 243 , 231 Split = Y Selected = 0xD2BA8AA2 \ n \
DockNode ID = 0x00000009 Parent = 0x00000007 SizeRef = 220 , 177 Selected = 0xD2BA8AA2 \ n \
DockNode ID = 0x0000000A Parent = 0x00000007 SizeRef = 220 , 61 HiddenTabBar = 1 Selected = 0x608FDEB4 \ n \
DockNode ID = 0x00000008 Parent = 0x00000006 SizeRef = 314 , 231 Selected = 0xD62F6EEB \ n \
DockNode ID = 0x00000004 Parent = 0x00000001 SizeRef = 329 , 231 Selected = 0xF3094A52 \ n \
DockNode ID = 0x00000002 Parent = 0x8B93E3BD SizeRef = 1280 , 489 Split = X Selected = 0x6C01C512 \ n \
DockNode ID = 0x0000000B Parent = 0x00000002 SizeRef = 1246 , 503 CentralNode = 1 Selected = 0x6C01C512 \ n \
DockNode ID = 0x0000000C Parent = 0x00000002 SizeRef = 32 , 503 HiddenTabBar = 1 Selected = 0xD67E3EB0 \ n \
2021-12-19 21:01:24 +00:00
" ;
void FurnaceGUI : : prepareLayout ( ) {
FILE * check ;
2022-01-20 10:04:03 +00:00
check = ps_fopen ( finalLayoutPath , " r " ) ;
2021-12-19 21:01:24 +00:00
if ( check ! = NULL ) {
fclose ( check ) ;
return ;
}
// copy initial layout
logI ( " loading default layout. \n " ) ;
2022-01-20 10:04:03 +00:00
check = ps_fopen ( finalLayoutPath , " w " ) ;
2021-12-19 21:01:24 +00:00
if ( check = = NULL ) {
logW ( " could not write default layout! \n " ) ;
return ;
}
fwrite ( defaultLayout , 1 , strlen ( defaultLayout ) , check ) ;
fclose ( check ) ;
}
2021-12-15 22:32:08 +00:00
void FurnaceGUI : : drawEditControls ( ) {
if ( ! editControlsOpen ) return ;
2022-02-05 04:21:00 +00:00
switch ( settings . controlLayout ) {
case 0 : // classic
if ( ImGui : : Begin ( " Play/Edit Controls " , & editControlsOpen ) ) {
ImGui : : Text ( " Octave " ) ;
ImGui : : SameLine ( ) ;
if ( ImGui : : InputInt ( " ##Octave " , & curOctave , 1 , 1 ) ) {
if ( curOctave > 6 ) curOctave = 6 ;
if ( curOctave < - 5 ) curOctave = - 5 ;
for ( size_t i = 0 ; i < activeNotes . size ( ) ; i + + ) {
e - > noteOff ( activeNotes [ i ] . chan ) ;
}
activeNotes . clear ( ) ;
}
ImGui : : Text ( " Edit Step " ) ;
ImGui : : SameLine ( ) ;
if ( ImGui : : InputInt ( " ##EditStep " , & editStep , 1 , 1 ) ) {
if ( editStep > = e - > song . patLen ) editStep = e - > song . patLen - 1 ;
if ( editStep < 0 ) editStep = 0 ;
}
if ( ImGui : : Button ( ICON_FA_PLAY " ##Play " ) ) {
play ( ) ;
}
ImGui : : SameLine ( ) ;
if ( ImGui : : Button ( ICON_FA_STOP " ##Stop " ) ) {
stop ( ) ;
}
ImGui : : SameLine ( ) ;
ImGui : : Checkbox ( " Edit " , & edit ) ;
ImGui : : SameLine ( ) ;
bool metro = e - > getMetronome ( ) ;
if ( ImGui : : Checkbox ( " Metronome " , & metro ) ) {
e - > setMetronome ( metro ) ;
}
ImGui : : Text ( " Follow " ) ;
ImGui : : SameLine ( ) ;
ImGui : : Checkbox ( " Orders " , & followOrders ) ;
ImGui : : SameLine ( ) ;
ImGui : : Checkbox ( " Pattern " , & followPattern ) ;
bool repeatPattern = e - > getRepeatPattern ( ) ;
if ( ImGui : : Checkbox ( " Repeat pattern " , & repeatPattern ) ) {
e - > setRepeatPattern ( repeatPattern ) ;
}
2022-02-06 05:42:07 +00:00
ImGui : : SameLine ( ) ;
if ( ImGui : : Button ( ICON_FA_ARROW_DOWN " ##StepOne " ) ) {
e - > stepOne ( cursor . y ) ;
}
2022-02-01 08:28:36 +00:00
}
2022-02-05 04:21:00 +00:00
if ( ImGui : : IsWindowFocused ( ImGuiFocusedFlags_ChildWindows ) ) curWindow = GUI_WINDOW_EDIT_CONTROLS ;
ImGui : : End ( ) ;
break ;
case 1 : // compact
if ( ImGui : : Begin ( " Play/Edit Controls " , & editControlsOpen , ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse ) ) {
if ( ImGui : : Button ( ICON_FA_STOP " ##Stop " ) ) {
stop ( ) ;
}
ImGui : : SameLine ( ) ;
if ( ImGui : : Button ( ICON_FA_PLAY " ##Play " ) ) {
play ( ) ;
}
2022-02-06 05:42:07 +00:00
ImGui : : SameLine ( ) ;
if ( ImGui : : Button ( ICON_FA_ARROW_DOWN " ##StepOne " ) ) {
e - > stepOne ( cursor . y ) ;
}
2021-12-15 22:32:08 +00:00
2022-02-05 04:21:00 +00:00
ImGui : : SameLine ( ) ;
bool repeatPattern = e - > getRepeatPattern ( ) ;
ImGui : : PushStyleColor ( ImGuiCol_Button , ImVec4 ( 0.2f , ( repeatPattern ) ? 0.6f : 0.2f , 0.2f , 1.0f ) ) ;
if ( ImGui : : Button ( ICON_FA_REPEAT " ##RepeatPattern " ) ) {
e - > setRepeatPattern ( ! repeatPattern ) ;
}
ImGui : : PopStyleColor ( ) ;
2021-12-16 07:21:43 +00:00
2022-02-05 04:21:00 +00:00
ImGui : : SameLine ( ) ;
ImGui : : PushStyleColor ( ImGuiCol_Button , ImVec4 ( 0.2f , ( edit ) ? 0.6f : 0.2f , 0.2f , 1.0f ) ) ;
if ( ImGui : : Button ( ICON_FA_CIRCLE " ##Edit " ) ) {
edit = ! edit ;
}
ImGui : : PopStyleColor ( ) ;
2021-12-21 22:42:27 +00:00
2022-02-05 04:21:00 +00:00
ImGui : : SameLine ( ) ;
bool metro = e - > getMetronome ( ) ;
ImGui : : PushStyleColor ( ImGuiCol_Button , ImVec4 ( 0.2f , ( metro ) ? 0.6f : 0.2f , 0.2f , 1.0f ) ) ;
if ( ImGui : : Button ( ICON_FA_BELL_O " ##Metronome " ) ) {
e - > setMetronome ( ! metro ) ;
}
ImGui : : PopStyleColor ( ) ;
2021-12-21 22:42:27 +00:00
2022-02-05 04:21:00 +00:00
ImGui : : SameLine ( ) ;
ImGui : : Text ( " Octave " ) ;
ImGui : : SameLine ( ) ;
ImGui : : SetNextItemWidth ( 96.0f * dpiScale ) ;
if ( ImGui : : InputInt ( " ##Octave " , & curOctave , 1 , 1 ) ) {
if ( curOctave > 6 ) curOctave = 6 ;
if ( curOctave < - 5 ) curOctave = - 5 ;
for ( size_t i = 0 ; i < activeNotes . size ( ) ; i + + ) {
e - > noteOff ( activeNotes [ i ] . chan ) ;
}
activeNotes . clear ( ) ;
}
ImGui : : SameLine ( ) ;
ImGui : : Text ( " Edit Step " ) ;
ImGui : : SameLine ( ) ;
ImGui : : SetNextItemWidth ( 96.0f * dpiScale ) ;
if ( ImGui : : InputInt ( " ##EditStep " , & editStep , 1 , 1 ) ) {
if ( editStep > = e - > song . patLen ) editStep = e - > song . patLen - 1 ;
if ( editStep < 0 ) editStep = 0 ;
}
ImGui : : SameLine ( ) ;
ImGui : : Text ( " Follow " ) ;
ImGui : : SameLine ( ) ;
ImGui : : Checkbox ( " Orders " , & followOrders ) ;
ImGui : : SameLine ( ) ;
ImGui : : Checkbox ( " Pattern " , & followPattern ) ;
}
if ( ImGui : : IsWindowFocused ( ImGuiFocusedFlags_ChildWindows ) ) curWindow = GUI_WINDOW_EDIT_CONTROLS ;
ImGui : : End ( ) ;
break ;
case 2 : // compact vertical
if ( ImGui : : Begin ( " Play/Edit Controls " , & editControlsOpen , ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse ) ) {
if ( ImGui : : Button ( ICON_FA_PLAY " ##Play " ) ) {
play ( ) ;
}
if ( ImGui : : Button ( ICON_FA_STOP " ##Stop " ) ) {
stop ( ) ;
}
2022-02-06 05:42:07 +00:00
if ( ImGui : : Button ( ICON_FA_ARROW_DOWN " ##StepOne " ) ) {
e - > stepOne ( cursor . y ) ;
}
2022-02-05 04:21:00 +00:00
bool repeatPattern = e - > getRepeatPattern ( ) ;
ImGui : : PushStyleColor ( ImGuiCol_Button , ImVec4 ( 0.2f , ( repeatPattern ) ? 0.6f : 0.2f , 0.2f , 1.0f ) ) ;
if ( ImGui : : Button ( ICON_FA_REPEAT " ##RepeatPattern " ) ) {
e - > setRepeatPattern ( ! repeatPattern ) ;
}
ImGui : : PopStyleColor ( ) ;
ImGui : : PushStyleColor ( ImGuiCol_Button , ImVec4 ( 0.2f , ( edit ) ? 0.6f : 0.2f , 0.2f , 1.0f ) ) ;
if ( ImGui : : Button ( ICON_FA_CIRCLE " ##Edit " ) ) {
edit = ! edit ;
}
ImGui : : PopStyleColor ( ) ;
bool metro = e - > getMetronome ( ) ;
ImGui : : PushStyleColor ( ImGuiCol_Button , ImVec4 ( 0.2f , ( metro ) ? 0.6f : 0.2f , 0.2f , 1.0f ) ) ;
if ( ImGui : : Button ( ICON_FA_BELL_O " ##Metronome " ) ) {
e - > setMetronome ( ! metro ) ;
}
ImGui : : PopStyleColor ( ) ;
ImGui : : Text ( " Oct. " ) ;
float avail = ImGui : : GetContentRegionAvail ( ) . x ;
ImGui : : SetNextItemWidth ( avail ) ;
if ( ImGui : : InputInt ( " ##Octave " , & curOctave , 0 , 0 ) ) {
if ( curOctave > 6 ) curOctave = 6 ;
if ( curOctave < - 5 ) curOctave = - 5 ;
for ( size_t i = 0 ; i < activeNotes . size ( ) ; i + + ) {
e - > noteOff ( activeNotes [ i ] . chan ) ;
}
activeNotes . clear ( ) ;
}
ImGui : : Text ( " Step " ) ;
ImGui : : SetNextItemWidth ( avail ) ;
if ( ImGui : : InputInt ( " ##EditStep " , & editStep , 0 , 0 ) ) {
if ( editStep > = e - > song . patLen ) editStep = e - > song . patLen - 1 ;
if ( editStep < 0 ) editStep = 0 ;
}
ImGui : : Text ( " Foll. " ) ;
ImGui : : PushStyleColor ( ImGuiCol_Button , ImVec4 ( 0.2f , ( followOrders ) ? 0.6f : 0.2f , 0.2f , 1.0f ) ) ;
if ( ImGui : : SmallButton ( " Ord##FollowOrders " ) ) {
followOrders = ! followOrders ;
}
ImGui : : PopStyleColor ( ) ;
ImGui : : PushStyleColor ( ImGuiCol_Button , ImVec4 ( 0.2f , ( followPattern ) ? 0.6f : 0.2f , 0.2f , 1.0f ) ) ;
if ( ImGui : : SmallButton ( " Pat##FollowPattern " ) ) {
followPattern = ! followPattern ;
}
ImGui : : PopStyleColor ( ) ;
}
if ( ImGui : : IsWindowFocused ( ImGuiFocusedFlags_ChildWindows ) ) curWindow = GUI_WINDOW_EDIT_CONTROLS ;
ImGui : : End ( ) ;
break ;
case 3 : // split
if ( ImGui : : Begin ( " Play Controls " , & editControlsOpen , ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse ) ) {
if ( e - > isPlaying ( ) ) {
if ( ImGui : : Button ( ICON_FA_STOP " ##Stop " ) ) {
stop ( ) ;
}
} else {
if ( ImGui : : Button ( ICON_FA_PLAY " ##Play " ) ) {
play ( ) ;
}
}
ImGui : : SameLine ( ) ;
if ( ImGui : : Button ( ICON_FA_PLAY_CIRCLE " ##PlayAgain " ) ) {
play ( ) ;
}
2022-02-06 05:42:07 +00:00
ImGui : : SameLine ( ) ;
if ( ImGui : : Button ( ICON_FA_ARROW_DOWN " ##StepOne " ) ) {
e - > stepOne ( cursor . y ) ;
}
2022-02-05 04:21:00 +00:00
ImGui : : SameLine ( ) ;
ImGui : : PushStyleColor ( ImGuiCol_Button , ImVec4 ( 0.2f , ( edit ) ? 0.6f : 0.2f , 0.2f , 1.0f ) ) ;
if ( ImGui : : Button ( ICON_FA_CIRCLE " ##Edit " ) ) {
edit = ! edit ;
}
ImGui : : PopStyleColor ( ) ;
bool metro = e - > getMetronome ( ) ;
ImGui : : SameLine ( ) ;
ImGui : : PushStyleColor ( ImGuiCol_Button , ImVec4 ( 0.2f , ( metro ) ? 0.6f : 0.2f , 0.2f , 1.0f ) ) ;
if ( ImGui : : Button ( ICON_FA_BELL_O " ##Metronome " ) ) {
e - > setMetronome ( ! metro ) ;
}
ImGui : : PopStyleColor ( ) ;
ImGui : : SameLine ( ) ;
bool repeatPattern = e - > getRepeatPattern ( ) ;
ImGui : : PushStyleColor ( ImGuiCol_Button , ImVec4 ( 0.2f , ( repeatPattern ) ? 0.6f : 0.2f , 0.2f , 1.0f ) ) ;
if ( ImGui : : Button ( ICON_FA_REPEAT " ##RepeatPattern " ) ) {
e - > setRepeatPattern ( ! repeatPattern ) ;
}
ImGui : : PopStyleColor ( ) ;
}
if ( ImGui : : IsWindowFocused ( ImGuiFocusedFlags_ChildWindows ) ) curWindow = GUI_WINDOW_EDIT_CONTROLS ;
ImGui : : End ( ) ;
if ( ImGui : : Begin ( " Edit Controls " , & editControlsOpen ) ) {
ImGui : : Columns ( 2 ) ;
ImGui : : Text ( " Octave " ) ;
ImGui : : SameLine ( ) ;
float cursor = ImGui : : GetCursorPosX ( ) ;
float avail = ImGui : : GetContentRegionAvail ( ) . x ;
ImGui : : SetNextItemWidth ( avail ) ;
if ( ImGui : : InputInt ( " ##Octave " , & curOctave , 1 , 1 ) ) {
if ( curOctave > 6 ) curOctave = 6 ;
if ( curOctave < - 5 ) curOctave = - 5 ;
for ( size_t i = 0 ; i < activeNotes . size ( ) ; i + + ) {
e - > noteOff ( activeNotes [ i ] . chan ) ;
}
activeNotes . clear ( ) ;
}
ImGui : : Text ( " Step " ) ;
ImGui : : SameLine ( ) ;
ImGui : : SetCursorPosX ( cursor ) ;
ImGui : : SetNextItemWidth ( avail ) ;
if ( ImGui : : InputInt ( " ##EditStep " , & editStep , 1 , 1 ) ) {
if ( editStep > = e - > song . patLen ) editStep = e - > song . patLen - 1 ;
if ( editStep < 0 ) editStep = 0 ;
}
ImGui : : NextColumn ( ) ;
ImGui : : Checkbox ( " Follow orders " , & followOrders ) ;
ImGui : : Checkbox ( " Follow pattern " , & followPattern ) ;
}
if ( ImGui : : IsWindowFocused ( ImGuiFocusedFlags_ChildWindows ) ) curWindow = GUI_WINDOW_EDIT_CONTROLS ;
ImGui : : End ( ) ;
break ;
2021-12-14 09:45:44 +00:00
}
2021-12-15 22:32:08 +00:00
}
void FurnaceGUI : : drawSongInfo ( ) {
if ( ! songInfoOpen ) return ;
if ( ImGui : : Begin ( " Song Information " , & songInfoOpen ) ) {
2022-02-04 07:51:22 +00:00
if ( ImGui : : BeginTable ( " NameAuthor " , 2 , ImGuiTableFlags_SizingStretchProp ) ) {
ImGui : : TableSetupColumn ( " c0 " , ImGuiTableColumnFlags_WidthFixed , 0.0 ) ;
ImGui : : TableSetupColumn ( " c1 " , ImGuiTableColumnFlags_WidthStretch , 0.0 ) ;
ImGui : : TableNextRow ( ) ;
ImGui : : TableNextColumn ( ) ;
ImGui : : Text ( " Name " ) ;
ImGui : : TableNextColumn ( ) ;
float avail = ImGui : : GetContentRegionAvail ( ) . x ;
ImGui : : SetNextItemWidth ( avail ) ;
if ( ImGui : : InputText ( " ##Name " , & e - > song . name ) ) updateWindowTitle ( ) ;
ImGui : : TableNextRow ( ) ;
ImGui : : TableNextColumn ( ) ;
ImGui : : Text ( " Author " ) ;
ImGui : : TableNextColumn ( ) ;
ImGui : : SetNextItemWidth ( avail ) ;
ImGui : : InputText ( " ##Author " , & e - > song . author ) ;
ImGui : : EndTable ( ) ;
2021-12-15 22:32:08 +00:00
}
2022-02-04 07:51:22 +00:00
if ( ImGui : : BeginTable ( " OtherProps " , 3 , ImGuiTableFlags_SizingStretchProp ) ) {
ImGui : : TableSetupColumn ( " c0 " , ImGuiTableColumnFlags_WidthFixed , 0.0 ) ;
ImGui : : TableSetupColumn ( " c1 " , ImGuiTableColumnFlags_WidthStretch , 0.0 ) ;
ImGui : : TableSetupColumn ( " c2 " , ImGuiTableColumnFlags_WidthStretch , 0.0 ) ;
2021-12-15 22:32:08 +00:00
2022-02-04 07:51:22 +00:00
ImGui : : TableNextRow ( ) ;
ImGui : : TableNextColumn ( ) ;
ImGui : : Text ( " TimeBase " ) ;
ImGui : : TableNextColumn ( ) ;
float avail = ImGui : : GetContentRegionAvail ( ) . x ;
ImGui : : SetNextItemWidth ( avail ) ;
unsigned char realTB = e - > song . timeBase + 1 ;
if ( ImGui : : InputScalar ( " ##TimeBase " , ImGuiDataType_U8 , & realTB , & _ONE , & _THREE ) ) {
if ( realTB < 1 ) realTB = 1 ;
if ( realTB > 16 ) realTB = 16 ;
e - > song . timeBase = realTB - 1 ;
}
ImGui : : TableNextColumn ( ) ;
float hl = e - > song . hilightA ;
if ( hl < = 0.0f ) hl = 4.0f ;
ImGui : : Text ( " %.2f BPM " , 120.0f * ( float ) e - > song . hz / ( hl * ( float ) ( e - > song . speed1 + e - > song . speed2 ) ) ) ;
2021-12-15 22:32:08 +00:00
2022-02-04 07:51:22 +00:00
ImGui : : TableNextRow ( ) ;
ImGui : : TableNextColumn ( ) ;
ImGui : : Text ( " Speed " ) ;
ImGui : : TableNextColumn ( ) ;
ImGui : : SetNextItemWidth ( avail ) ;
if ( ImGui : : InputScalar ( " ##Speed1 " , ImGuiDataType_U8 , & e - > song . speed1 , & _ONE , & _THREE ) ) {
if ( e - > song . speed1 < 1 ) e - > song . speed1 = 1 ;
if ( e - > isPlaying ( ) ) play ( ) ;
}
ImGui : : TableNextColumn ( ) ;
ImGui : : SetNextItemWidth ( avail ) ;
if ( ImGui : : InputScalar ( " ##Speed2 " , ImGuiDataType_U8 , & e - > song . speed2 , & _ONE , & _THREE ) ) {
if ( e - > song . speed2 < 1 ) e - > song . speed2 = 1 ;
if ( e - > isPlaying ( ) ) play ( ) ;
}
2021-12-16 07:21:43 +00:00
2022-02-04 07:51:22 +00:00
ImGui : : TableNextRow ( ) ;
ImGui : : TableNextColumn ( ) ;
ImGui : : Text ( " Highlight " ) ;
ImGui : : TableNextColumn ( ) ;
ImGui : : SetNextItemWidth ( avail ) ;
ImGui : : InputScalar ( " ##Highlight1 " , ImGuiDataType_U8 , & e - > song . hilightA , & _ONE , & _THREE ) ;
ImGui : : TableNextColumn ( ) ;
ImGui : : SetNextItemWidth ( avail ) ;
ImGui : : InputScalar ( " ##Highlight2 " , ImGuiDataType_U8 , & e - > song . hilightB , & _ONE , & _THREE ) ;
2021-12-20 22:03:55 +00:00
2022-02-04 07:51:22 +00:00
ImGui : : TableNextRow ( ) ;
ImGui : : TableNextColumn ( ) ;
ImGui : : Text ( " Pattern Length " ) ;
ImGui : : TableNextColumn ( ) ;
ImGui : : SetNextItemWidth ( avail ) ;
int patLen = e - > song . patLen ;
if ( ImGui : : InputInt ( " ##PatLength " , & patLen , 1 , 3 ) ) {
if ( patLen < 1 ) patLen = 1 ;
if ( patLen > 256 ) patLen = 256 ;
e - > song . patLen = patLen ;
}
2022-01-28 05:55:51 +00:00
2022-02-04 07:51:22 +00:00
ImGui : : TableNextRow ( ) ;
ImGui : : TableNextColumn ( ) ;
ImGui : : Text ( " Song Length " ) ;
ImGui : : TableNextColumn ( ) ;
ImGui : : SetNextItemWidth ( avail ) ;
int ordLen = e - > song . ordersLen ;
if ( ImGui : : InputInt ( " ##OrdLength " , & ordLen , 1 , 3 ) ) {
if ( ordLen < 1 ) ordLen = 1 ;
if ( ordLen > 127 ) ordLen = 127 ;
e - > song . ordersLen = ordLen ;
}
ImGui : : TableNextRow ( ) ;
ImGui : : TableNextColumn ( ) ;
ImGui : : Text ( " Tick Rate " ) ;
ImGui : : TableNextColumn ( ) ;
ImGui : : SetNextItemWidth ( avail ) ;
int setHz = e - > song . hz ;
if ( ImGui : : InputInt ( " ##Rate " , & setHz ) ) {
if ( setHz < 10 ) setHz = 10 ;
if ( setHz > 999 ) setHz = 999 ;
e - > setSongRate ( setHz , setHz < 52 ) ;
}
if ( e - > song . hz = = 50 ) {
ImGui : : TableNextColumn ( ) ;
ImGui : : Text ( " PAL " ) ;
}
if ( e - > song . hz = = 60 ) {
ImGui : : TableNextColumn ( ) ;
ImGui : : Text ( " NTSC " ) ;
}
ImGui : : TableNextRow ( ) ;
ImGui : : TableNextColumn ( ) ;
ImGui : : Text ( " Tuning (A-4) " ) ;
ImGui : : TableNextColumn ( ) ;
float tune = e - > song . tuning ;
ImGui : : SetNextItemWidth ( avail ) ;
if ( ImGui : : InputFloat ( " ##Tuning " , & tune , 1.0f , 3.0f , " %g " ) ) {
if ( tune < 220.0f ) tune = 220.0f ;
if ( tune > 880.0f ) tune = 880.0f ;
e - > song . tuning = tune ;
}
ImGui : : EndTable ( ) ;
2022-01-28 05:55:51 +00:00
}
2021-12-15 22:32:08 +00:00
}
2022-02-04 07:56:35 +00:00
if ( ImGui : : IsWindowFocused ( ImGuiFocusedFlags_ChildWindows ) ) curWindow = GUI_WINDOW_SONG_INFO ;
2021-12-14 09:45:44 +00:00
ImGui : : End ( ) ;
}
2021-12-11 08:11:40 +00:00
2021-12-14 09:45:44 +00:00
void FurnaceGUI : : drawOrders ( ) {
2021-12-30 22:30:24 +00:00
char selID [ 64 ] ;
2021-12-14 09:45:44 +00:00
if ( ! ordersOpen ) return ;
if ( ImGui : : Begin ( " Orders " , & ordersOpen ) ) {
2021-12-21 04:20:30 +00:00
float regionX = ImGui : : GetContentRegionAvail ( ) . x ;
2021-12-22 22:53:52 +00:00
ImVec2 prevSpacing = ImGui : : GetStyle ( ) . ItemSpacing ;
2021-12-21 04:20:30 +00:00
ImGui : : PushStyleVar ( ImGuiStyleVar_ItemSpacing , ImVec2 ( 1.0f * dpiScale , 1.0f * dpiScale ) ) ;
ImGui : : Columns ( 2 , NULL , false ) ;
2021-12-21 05:30:55 +00:00
ImGui : : SetColumnWidth ( - 1 , regionX - 24.0f * dpiScale ) ;
2022-02-05 06:48:35 +00:00
int displayChans = 0 ;
for ( int i = 0 ; i < e - > getTotalChannelCount ( ) ; i + + ) {
if ( e - > song . chanShow [ i ] ) displayChans + + ;
}
if ( ImGui : : BeginTable ( " OrdersTable " , 1 + displayChans , ImGuiTableFlags_SizingStretchSame | ImGuiTableFlags_ScrollX | ImGuiTableFlags_ScrollY ) ) {
2021-12-21 04:20:30 +00:00
ImGui : : PushFont ( patFont ) ;
2021-12-22 22:53:52 +00:00
ImGui : : PushStyleVar ( ImGuiStyleVar_ItemSpacing , prevSpacing ) ;
2022-01-11 08:40:21 +00:00
ImGui : : TableSetupScrollFreeze ( 1 , 1 ) ;
2021-12-21 04:20:30 +00:00
float lineHeight = ( ImGui : : GetTextLineHeight ( ) + 4 * dpiScale ) ;
2022-01-20 07:11:03 +00:00
int curOrder = e - > getOrder ( ) ;
2021-12-21 04:20:30 +00:00
if ( e - > isPlaying ( ) ) {
2021-12-21 22:42:27 +00:00
if ( followOrders ) {
2022-01-20 07:11:03 +00:00
ImGui : : SetScrollY ( ( curOrder + 1 ) * lineHeight - ( ImGui : : GetContentRegionAvail ( ) . y / 2 ) ) ;
2021-12-21 22:42:27 +00:00
}
2021-12-21 04:20:30 +00:00
}
ImGui : : TableNextRow ( 0 , lineHeight ) ;
2021-12-14 09:45:44 +00:00
ImGui : : TableNextColumn ( ) ;
2021-12-16 07:21:43 +00:00
ImGui : : PushStyleColor ( ImGuiCol_Text , uiColors [ GUI_COLOR_PATTERN_ROW_INDEX ] ) ;
2022-01-08 06:57:37 +00:00
for ( int i = 0 ; i < e - > getTotalChannelCount ( ) ; i + + ) {
2022-02-05 06:48:35 +00:00
if ( ! e - > song . chanShow [ i ] ) continue ;
2021-12-14 09:45:44 +00:00
ImGui : : TableNextColumn ( ) ;
ImGui : : Text ( " %s " , e - > getChannelShortName ( i ) ) ;
}
2021-12-16 07:21:43 +00:00
ImGui : : PopStyleColor ( ) ;
2021-12-14 09:45:44 +00:00
for ( int i = 0 ; i < e - > song . ordersLen ; i + + ) {
2021-12-21 04:20:30 +00:00
ImGui : : TableNextRow ( 0 , lineHeight ) ;
if ( oldOrder1 = = i ) ImGui : : TableSetBgColor ( ImGuiTableBgTarget_RowBg0 , 0x40ffffff ) ;
2021-12-12 09:21:09 +00:00
ImGui : : TableNextColumn ( ) ;
2021-12-16 07:21:43 +00:00
ImGui : : PushStyleColor ( ImGuiCol_Text , uiColors [ GUI_COLOR_PATTERN_ROW_INDEX ] ) ;
2022-01-27 06:04:26 +00:00
bool highlightLoop = ( i > = loopOrder & & i < = loopEnd ) ;
if ( highlightLoop ) ImGui : : TableSetBgColor ( ImGuiTableBgTarget_CellBg , ImGui : : GetColorU32 ( uiColors [ GUI_COLOR_SONG_LOOP ] ) ) ;
2022-01-19 23:04:07 +00:00
if ( settings . orderRowsBase = = 1 ) {
2022-01-31 07:38:17 +00:00
snprintf ( selID , 64 , " %.2X##O_S%.2x " , i , i ) ;
2022-01-19 23:04:07 +00:00
} else {
snprintf ( selID , 64 , " %d##O_S%.2x " , i , i ) ;
}
2021-12-14 09:45:44 +00:00
if ( ImGui : : Selectable ( selID ) ) {
e - > setOrder ( i ) ;
2022-01-20 07:11:03 +00:00
curNibble = false ;
orderCursor = - 1 ;
2021-12-12 09:21:09 +00:00
}
2021-12-16 07:21:43 +00:00
ImGui : : PopStyleColor ( ) ;
2022-01-08 06:57:37 +00:00
for ( int j = 0 ; j < e - > getTotalChannelCount ( ) ; j + + ) {
2022-02-05 06:48:35 +00:00
if ( ! e - > song . chanShow [ j ] ) continue ;
2021-12-12 09:21:09 +00:00
ImGui : : TableNextColumn ( ) ;
2022-01-31 07:38:17 +00:00
snprintf ( selID , 64 , " %.2X##O_%.2x_%.2x " , e - > song . orders . ord [ j ] [ i ] , j , i ) ;
2022-01-20 07:11:03 +00:00
if ( ImGui : : Selectable ( selID , ( orderEditMode ! = 0 & & curOrder = = i & & orderCursor = = j ) ) ) {
if ( curOrder = = i ) {
if ( orderEditMode = = 0 ) {
prepareUndo ( GUI_ACTION_CHANGE_ORDER ) ;
if ( changeAllOrders ) {
for ( int k = 0 ; k < e - > getTotalChannelCount ( ) ; k + + ) {
if ( e - > song . orders . ord [ k ] [ i ] < 0x7f ) e - > song . orders . ord [ k ] [ i ] + + ;
}
} else {
if ( e - > song . orders . ord [ j ] [ i ] < 0x7f ) e - > song . orders . ord [ j ] [ i ] + + ;
2021-12-22 21:22:47 +00:00
}
2022-01-27 06:04:26 +00:00
e - > walkSong ( loopOrder , loopRow , loopEnd ) ;
2022-01-20 07:11:03 +00:00
makeUndo ( GUI_ACTION_CHANGE_ORDER ) ;
2021-12-22 21:22:47 +00:00
} else {
2022-01-20 07:11:03 +00:00
orderCursor = j ;
curNibble = false ;
2021-12-22 21:22:47 +00:00
}
2021-12-16 07:21:43 +00:00
} else {
e - > setOrder ( i ) ;
2022-01-27 06:04:26 +00:00
e - > walkSong ( loopOrder , loopRow , loopEnd ) ;
2022-01-20 07:11:03 +00:00
if ( orderEditMode ! = 0 ) {
orderCursor = j ;
curNibble = false ;
}
2021-12-16 07:21:43 +00:00
}
2021-12-12 09:21:09 +00:00
}
2021-12-14 09:45:44 +00:00
if ( ImGui : : IsItemClicked ( ImGuiMouseButton_Right ) ) {
2022-01-20 07:11:03 +00:00
if ( curOrder = = i ) {
if ( orderEditMode = = 0 ) {
prepareUndo ( GUI_ACTION_CHANGE_ORDER ) ;
if ( changeAllOrders ) {
for ( int k = 0 ; k < e - > getTotalChannelCount ( ) ; k + + ) {
if ( e - > song . orders . ord [ k ] [ i ] > 0 ) e - > song . orders . ord [ k ] [ i ] - - ;
}
} else {
if ( e - > song . orders . ord [ j ] [ i ] > 0 ) e - > song . orders . ord [ j ] [ i ] - - ;
2021-12-22 21:22:47 +00:00
}
2022-01-27 06:04:26 +00:00
e - > walkSong ( loopOrder , loopRow , loopEnd ) ;
2022-01-20 07:11:03 +00:00
makeUndo ( GUI_ACTION_CHANGE_ORDER ) ;
2021-12-22 21:22:47 +00:00
} else {
2022-01-20 07:11:03 +00:00
orderCursor = j ;
curNibble = false ;
2021-12-22 21:22:47 +00:00
}
2021-12-16 07:21:43 +00:00
} else {
e - > setOrder ( i ) ;
2022-01-27 06:04:26 +00:00
e - > walkSong ( loopOrder , loopRow , loopEnd ) ;
2022-01-20 07:11:03 +00:00
if ( orderEditMode ! = 0 ) {
orderCursor = j ;
curNibble = false ;
}
2021-12-16 07:21:43 +00:00
}
2021-12-12 09:21:09 +00:00
}
}
2021-12-13 22:09:46 +00:00
}
2021-12-22 22:53:52 +00:00
ImGui : : PopStyleVar ( ) ;
2021-12-21 04:20:30 +00:00
ImGui : : PopFont ( ) ;
2021-12-14 09:45:44 +00:00
ImGui : : EndTable ( ) ;
2021-12-12 09:21:09 +00:00
}
2021-12-21 04:20:30 +00:00
ImGui : : NextColumn ( ) ;
2021-12-22 21:22:47 +00:00
if ( ImGui : : Button ( ICON_FA_PLUS ) ) {
// add order row (new)
2021-12-26 23:05:18 +00:00
prepareUndo ( GUI_ACTION_CHANGE_ORDER ) ;
2021-12-22 22:39:16 +00:00
e - > addOrder ( false , false ) ;
2021-12-26 23:05:18 +00:00
makeUndo ( GUI_ACTION_CHANGE_ORDER ) ;
2021-12-22 21:22:47 +00:00
}
if ( ImGui : : Button ( ICON_FA_MINUS ) ) {
// remove this order row
2021-12-26 23:05:18 +00:00
prepareUndo ( GUI_ACTION_CHANGE_ORDER ) ;
2021-12-22 22:39:16 +00:00
e - > deleteOrder ( ) ;
2021-12-26 23:05:18 +00:00
makeUndo ( GUI_ACTION_CHANGE_ORDER ) ;
2021-12-22 21:22:47 +00:00
}
if ( ImGui : : Button ( ICON_FA_FILES_O ) ) {
// duplicate order row
2021-12-26 23:05:18 +00:00
prepareUndo ( GUI_ACTION_CHANGE_ORDER ) ;
2021-12-22 22:39:16 +00:00
e - > addOrder ( true , false ) ;
2021-12-26 23:05:18 +00:00
makeUndo ( GUI_ACTION_CHANGE_ORDER ) ;
2021-12-22 21:22:47 +00:00
}
if ( ImGui : : Button ( ICON_FA_ANGLE_UP ) ) {
// move order row up
2021-12-26 23:05:18 +00:00
prepareUndo ( GUI_ACTION_CHANGE_ORDER ) ;
2021-12-22 22:39:16 +00:00
e - > moveOrderUp ( ) ;
2021-12-26 23:05:18 +00:00
makeUndo ( GUI_ACTION_CHANGE_ORDER ) ;
2021-12-22 21:22:47 +00:00
}
if ( ImGui : : Button ( ICON_FA_ANGLE_DOWN ) ) {
// move order row down
2021-12-26 23:05:18 +00:00
prepareUndo ( GUI_ACTION_CHANGE_ORDER ) ;
2021-12-22 22:39:16 +00:00
e - > moveOrderDown ( ) ;
2021-12-26 23:05:18 +00:00
makeUndo ( GUI_ACTION_CHANGE_ORDER ) ;
2021-12-22 21:22:47 +00:00
}
if ( ImGui : : Button ( ICON_FA_ANGLE_DOUBLE_DOWN ) ) {
// duplicate order row at end
2021-12-26 23:05:18 +00:00
prepareUndo ( GUI_ACTION_CHANGE_ORDER ) ;
2021-12-22 22:39:16 +00:00
e - > addOrder ( true , true ) ;
2021-12-26 23:05:18 +00:00
makeUndo ( GUI_ACTION_CHANGE_ORDER ) ;
2021-12-22 21:22:47 +00:00
}
2021-12-22 22:39:16 +00:00
if ( ImGui : : Button ( changeAllOrders ? ICON_FA_LINK " ##ChangeAll " : ICON_FA_CHAIN_BROKEN " ##ChangeAll " ) ) {
2021-12-22 21:22:47 +00:00
// whether to change one or all orders in a row
2021-12-22 22:39:16 +00:00
changeAllOrders = ! changeAllOrders ;
2021-12-22 21:22:47 +00:00
}
2022-01-19 23:19:52 +00:00
const char * orderEditModeLabel = " ?##OrderEditMode " ;
if ( orderEditMode = = 3 ) {
orderEditModeLabel = ICON_FA_ARROWS_V " ##OrderEditMode " ;
} else if ( orderEditMode = = 2 ) {
orderEditModeLabel = ICON_FA_ARROWS_H " ##OrderEditMode " ;
} else if ( orderEditMode = = 1 ) {
orderEditModeLabel = ICON_FA_I_CURSOR " ##OrderEditMode " ;
} else {
orderEditModeLabel = ICON_FA_MOUSE_POINTER " ##OrderEditMode " ;
}
if ( ImGui : : Button ( orderEditModeLabel ) ) {
orderEditMode + + ;
if ( orderEditMode > 3 ) orderEditMode = 0 ;
2022-01-20 07:11:03 +00:00
curNibble = false ;
2022-01-19 23:19:52 +00:00
}
if ( ImGui : : IsItemHovered ( ) ) {
if ( orderEditMode = = 3 ) {
ImGui : : SetTooltip ( " Order edit mode: Select and type (scroll vertically) " ) ;
} else if ( orderEditMode = = 2 ) {
ImGui : : SetTooltip ( " Order edit mode: Select and type (scroll horizontally) " ) ;
} else if ( orderEditMode = = 1 ) {
ImGui : : SetTooltip ( " Order edit mode: Select and type (don't scroll) " ) ;
} else {
ImGui : : SetTooltip ( " Order edit mode: Click to change " ) ;
}
}
2021-12-21 04:20:30 +00:00
ImGui : : PopStyleVar ( ) ;
2021-12-14 09:45:44 +00:00
}
2022-01-20 07:11:03 +00:00
if ( ImGui : : IsWindowFocused ( ImGuiFocusedFlags_ChildWindows ) ) curWindow = GUI_WINDOW_ORDERS ;
2021-12-21 04:20:30 +00:00
oldOrder1 = e - > getOrder ( ) ;
2021-12-14 09:45:44 +00:00
ImGui : : End ( ) ;
}
2021-12-12 09:21:09 +00:00
2021-12-14 09:45:44 +00:00
void FurnaceGUI : : drawInsList ( ) {
if ( ! insListOpen ) return ;
if ( ImGui : : Begin ( " Instruments " , & insListOpen ) ) {
2021-12-21 05:30:55 +00:00
if ( ImGui : : Button ( ICON_FA_PLUS " ##InsAdd " ) ) {
2022-01-10 04:50:26 +00:00
curIns = e - > addInstrument ( cursor . xCoarse ) ;
2021-12-30 23:25:55 +00:00
modified = true ;
2021-12-17 08:33:12 +00:00
}
ImGui : : SameLine ( ) ;
2022-01-19 07:59:44 +00:00
if ( ImGui : : Button ( ICON_FA_FILES_O " ##InsClone " ) ) {
if ( curIns > = 0 & & curIns < ( int ) e - > song . ins . size ( ) ) {
int prevIns = curIns ;
curIns = e - > addInstrument ( cursor . xCoarse ) ;
( * e - > song . ins [ curIns ] ) = ( * e - > song . ins [ prevIns ] ) ;
modified = true ;
}
}
ImGui : : SameLine ( ) ;
2022-01-19 08:15:20 +00:00
if ( ImGui : : Button ( ICON_FA_FOLDER_OPEN " ##InsLoad " ) ) {
openFileDialog ( GUI_FILE_INS_OPEN ) ;
}
ImGui : : SameLine ( ) ;
if ( ImGui : : Button ( ICON_FA_FLOPPY_O " ##InsSave " ) ) {
if ( curIns > = 0 & & curIns < ( int ) e - > song . ins . size ( ) ) openFileDialog ( GUI_FILE_INS_SAVE ) ;
}
ImGui : : SameLine ( ) ;
2021-12-17 08:33:12 +00:00
if ( ImGui : : ArrowButton ( " InsUp " , ImGuiDir_Up ) ) {
2022-01-11 08:52:11 +00:00
if ( e - > moveInsUp ( curIns ) ) curIns - - ;
2021-12-17 08:33:12 +00:00
}
ImGui : : SameLine ( ) ;
if ( ImGui : : ArrowButton ( " InsDown " , ImGuiDir_Down ) ) {
2022-01-11 08:52:11 +00:00
if ( e - > moveInsDown ( curIns ) ) curIns + + ;
2021-12-17 08:33:12 +00:00
}
ImGui : : SameLine ( ) ;
2021-12-21 05:30:55 +00:00
if ( ImGui : : Button ( ICON_FA_TIMES " ##InsDelete " ) ) {
2022-01-19 07:59:44 +00:00
if ( curIns > = 0 & & curIns < ( int ) e - > song . ins . size ( ) ) {
e - > delInstrument ( curIns ) ;
modified = true ;
if ( curIns > = ( int ) e - > song . ins . size ( ) ) {
curIns - - ;
}
2021-12-17 08:33:12 +00:00
}
}
ImGui : : Separator ( ) ;
2022-02-04 05:03:30 +00:00
if ( ImGui : : BeginTable ( " InsListScroll " , 1 , ImGuiTableFlags_ScrollY ) ) {
for ( int i = 0 ; i < ( int ) e - > song . ins . size ( ) ; i + + ) {
DivInstrument * ins = e - > song . ins [ i ] ;
String name ;
switch ( ins - > type ) {
case DIV_INS_FM :
ImGui : : PushStyleColor ( ImGuiCol_Text , uiColors [ GUI_COLOR_INSTR_FM ] ) ;
name = fmt : : sprintf ( ICON_FA_AREA_CHART " %.2X: %s##_INS%d \n " , i , ins - > name , i ) ;
break ;
case DIV_INS_STD :
ImGui : : PushStyleColor ( ImGuiCol_Text , uiColors [ GUI_COLOR_INSTR_STD ] ) ;
name = fmt : : sprintf ( ICON_FA_BAR_CHART " %.2X: %s##_INS%d \n " , i , ins - > name , i ) ;
break ;
case DIV_INS_GB :
ImGui : : PushStyleColor ( ImGuiCol_Text , uiColors [ GUI_COLOR_INSTR_GB ] ) ;
name = fmt : : sprintf ( ICON_FA_GAMEPAD " %.2X: %s##_INS%d \n " , i , ins - > name , i ) ;
break ;
case DIV_INS_C64 :
ImGui : : PushStyleColor ( ImGuiCol_Text , uiColors [ GUI_COLOR_INSTR_C64 ] ) ;
name = fmt : : sprintf ( ICON_FA_KEYBOARD_O " %.2X: %s##_INS%d \n " , i , ins - > name , i ) ;
break ;
case DIV_INS_AMIGA :
ImGui : : PushStyleColor ( ImGuiCol_Text , uiColors [ GUI_COLOR_INSTR_AMIGA ] ) ;
name = fmt : : sprintf ( ICON_FA_VOLUME_UP " %.2X: %s##_INS%d \n " , i , ins - > name , i ) ;
break ;
case DIV_INS_PCE :
ImGui : : PushStyleColor ( ImGuiCol_Text , uiColors [ GUI_COLOR_INSTR_PCE ] ) ;
name = fmt : : sprintf ( ICON_FA_ID_BADGE " %.2X: %s##_INS%d \n " , i , ins - > name , i ) ;
break ;
case DIV_INS_AY :
ImGui : : PushStyleColor ( ImGuiCol_Text , uiColors [ GUI_COLOR_INSTR_AY ] ) ;
name = fmt : : sprintf ( ICON_FA_BAR_CHART " %.2X: %s##_INS%d \n " , i , ins - > name , i ) ;
break ;
case DIV_INS_AY8930 :
ImGui : : PushStyleColor ( ImGuiCol_Text , uiColors [ GUI_COLOR_INSTR_AY8930 ] ) ;
name = fmt : : sprintf ( ICON_FA_BAR_CHART " %.2X: %s##_INS%d \n " , i , ins - > name , i ) ;
break ;
case DIV_INS_TIA :
ImGui : : PushStyleColor ( ImGuiCol_Text , uiColors [ GUI_COLOR_INSTR_TIA ] ) ;
name = fmt : : sprintf ( ICON_FA_BAR_CHART " %.2X: %s##_INS%d \n " , i , ins - > name , i ) ;
break ;
case DIV_INS_SAA1099 :
ImGui : : PushStyleColor ( ImGuiCol_Text , uiColors [ GUI_COLOR_INSTR_SAA1099 ] ) ;
name = fmt : : sprintf ( ICON_FA_BAR_CHART " %.2X: %s##_INS%d \n " , i , ins - > name , i ) ;
break ;
default :
ImGui : : PushStyleColor ( ImGuiCol_Text , uiColors [ GUI_COLOR_INSTR_UNKNOWN ] ) ;
name = fmt : : sprintf ( ICON_FA_QUESTION " %.2X: %s##_INS%d \n " , i , ins - > name , i ) ;
break ;
}
ImGui : : TableNextRow ( ) ;
ImGui : : TableNextColumn ( ) ;
if ( ImGui : : Selectable ( name . c_str ( ) , curIns = = i ) ) {
curIns = i ;
}
ImGui : : PopStyleColor ( ) ;
if ( ImGui : : IsItemHovered ( ) ) {
if ( ImGui : : IsMouseDoubleClicked ( ImGuiMouseButton_Left ) ) {
insEditOpen = true ;
}
2021-12-16 07:21:43 +00:00
}
}
2022-02-04 05:03:30 +00:00
ImGui : : EndTable ( ) ;
2021-12-11 21:44:02 +00:00
}
2021-12-14 09:45:44 +00:00
}
2022-02-04 07:56:35 +00:00
if ( ImGui : : IsWindowFocused ( ImGuiFocusedFlags_ChildWindows ) ) curWindow = GUI_WINDOW_INS_LIST ;
2021-12-14 09:45:44 +00:00
ImGui : : End ( ) ;
}
2021-12-11 22:41:32 +00:00
2022-01-18 05:04:13 +00:00
const char * fourOpAlgs [ 8 ] = {
" 1 > 2 > 3 > 4 " , " (1+2) > 3 > 4 " , " 1+(2>3) > 4 " , " (1>2)+3 > 4 " , " (1>2) + (3>4) " , " 1 > (2+3+4) " , " (1>2) + 3 + 4 " , " 1 + 2 + 3 + 4 "
} ;
2022-01-15 04:26:22 +00:00
const char * insTypes [ 10 ] = {
2022-01-20 19:18:15 +00:00
" Standard " , " FM " , " Game Boy " , " C64 " , " Amiga/Sample " , " PC Engine " , " AY-3-8910/SSG " , " AY8930 " , " TIA " , " SAA1099 "
2022-01-09 22:48:09 +00:00
} ;
2021-12-24 05:48:08 +00:00
const char * ssgEnvTypes [ 8 ] = {
" Down Down Down " , " Down. " , " Down Up Down Up " , " Down UP " , " Up Up Up " , " Up. " , " Up Down Up Down " , " Up DOWN "
} ;
2022-01-27 20:01:05 +00:00
const char * fmParamNames [ 3 ] [ 16 ] = {
2022-01-27 09:51:34 +00:00
{ " Algorithm " , " Feedback " , " LFO > Freq " , " LFO > Amp " , " Attack " , " Decay " , " Decay 2 " , " Release " , " Sustain " , " Level " , " EnvScale " , " Multiplier " , " Detune " , " Detune 2 " , " SSG-EG " , " AM " } ,
2022-02-05 19:57:55 +00:00
{ " ALG " , " FB " , " FMS/PMS " , " AMS " , " AR " , " DR " , " SR " , " RR " , " SL " , " TL " , " KS " , " MULT " , " DT " , " DT2 " , " SSG-EG " , " AM " } ,
{ " ALG " , " FB " , " FMS/PMS " , " AMS " , " AR " , " DR " , " D2R " , " RR " , " SL " , " TL " , " RS " , " MULT " , " DT " , " DT2 " , " SSG-EG " , " AM " }
2022-01-27 09:51:34 +00:00
} ;
enum FMParams {
FM_ALG = 0 ,
FM_FB = 1 ,
FM_FMS = 2 ,
FM_AMS = 3 ,
FM_AR = 4 ,
FM_DR = 5 ,
FM_D2R = 6 ,
FM_RR = 7 ,
FM_SL = 8 ,
FM_TL = 9 ,
FM_RS = 10 ,
FM_MULT = 11 ,
FM_DT = 12 ,
FM_DT2 = 13 ,
FM_SSG = 14 ,
FM_AM = 15
} ;
# define FM_NAME(x) fmParamNames[settings.fmNames][x]
2022-01-21 06:56:30 +00:00
const char * c64ShapeBits [ 5 ] = {
" triangle " , " saw " , " pulse " , " noise " , NULL
} ;
const char * ayShapeBits [ 4 ] = {
" tone " , " noise " , " envelope " , NULL
} ;
2022-01-27 20:31:48 +00:00
const char * ayEnvBits [ 4 ] = {
2022-01-27 20:01:05 +00:00
" hold " , " alternate " , " direction " , " enable "
2022-01-27 20:31:48 +00:00
} ;
2022-01-27 20:01:05 +00:00
2022-01-23 21:34:20 +00:00
const char * ssgEnvBits [ 5 ] = {
" 0 " , " 1 " , " 2 " , " enabled " , NULL
} ;
2022-02-01 08:44:02 +00:00
const char * saaEnvBits [ 9 ] = {
" mirror " , " loop " , " cut " , " direction " , " resolution " , " fixed " , " N/A " , " enabled " , NULL
} ;
2022-02-06 20:44:06 +00:00
const char * filtModeBits [ 5 ] = {
2022-02-06 20:48:27 +00:00
" low " , " band " , " high " , " ch3off " , NULL
2022-02-06 20:44:06 +00:00
} ;
2022-02-06 20:56:10 +00:00
const char * c64SpecialBits [ 3 ] = {
" sync " , " ring " , NULL
} ;
2022-01-23 20:56:03 +00:00
const int orderedOps [ 4 ] = {
0 , 2 , 1 , 3
} ;
2022-02-09 02:30:06 +00:00
String macroHoverNote ( int id , float val ) {
if ( val < - 60 | | val > = 120 ) return " ??? " ;
return fmt : : sprintf ( " %d: %s " , id , noteNames [ ( int ) val + 60 ] ) ;
}
String macroHover ( int id , float val ) {
return fmt : : sprintf ( " %d: %d " , id , val ) ;
}
2022-02-09 02:59:30 +00:00
String macroHoverLoop ( int id , float val ) {
if ( val > 1 ) return " Release " ;
if ( val > 0 ) return " Loop " ;
return " " ;
}
2022-01-18 04:59:52 +00:00
# define P(x) if (x) { \
modified = true ; \
e - > notifyInsChange ( curIns ) ; \
}
# define PARAMETER modified=true; e->notifyInsChange(curIns);
2022-02-09 02:30:06 +00:00
# define NORMAL_MACRO(macro,macroLen,macroLoop,macroRel,macroMin,macroHeight,macroName,displayName,displayHeight,displayLoop,bitfield,bfVal,drawSlider,sliderVal,sliderLow,macroDispMin,bitOff,macroMode,macroColor,mmlStr,macroAMin,macroAMax,hoverFunc) \
2022-02-06 21:11:36 +00:00
ImGui : : TableNextRow ( ) ; \
ImGui : : TableNextColumn ( ) ; \
2022-01-23 22:55:02 +00:00
ImGui : : Text ( " %s " , displayName ) ; \
2022-01-26 08:49:46 +00:00
ImGui : : SameLine ( ) ; \
if ( ImGui : : SmallButton ( displayLoop ? ( ICON_FA_CHEVRON_UP " ##IMacroOpen_ " macroName ) : ( ICON_FA_CHEVRON_DOWN " ##IMacroOpen_ " macroName ) ) ) { \
displayLoop = ! displayLoop ; \
} \
if ( displayLoop ) { \
2022-02-06 21:11:36 +00:00
ImGui : : SetNextItemWidth ( lenAvail ) ; \
2022-01-26 08:49:46 +00:00
if ( ImGui : : InputScalar ( " ##IMacroLen_ " macroName , ImGuiDataType_U8 , & macroLen , & _ONE , & _THREE ) ) { \
if ( macroLen > 127 ) macroLen = 127 ; \
} \
if ( macroMode ! = NULL ) { \
ImGui : : Checkbox ( " Fixed##IMacroMode_ " macroName , macroMode ) ; \
} \
2022-01-23 21:34:20 +00:00
} \
2022-02-06 21:11:36 +00:00
ImGui : : TableNextColumn ( ) ; \
2022-01-23 21:34:20 +00:00
for ( int j = 0 ; j < 256 ; j + + ) { \
if ( j + macroDragScroll > = macroLen ) { \
asFloat [ j ] = 0 ; \
asInt [ j ] = 0 ; \
} else { \
2022-01-23 22:55:02 +00:00
asFloat [ j ] = macro [ j + macroDragScroll ] + macroDispMin ; \
asInt [ j ] = macro [ j + macroDragScroll ] + macroDispMin + bitOff ; \
2022-01-23 21:34:20 +00:00
} \
2022-01-26 08:49:46 +00:00
if ( j + macroDragScroll > = macroLen ) { \
loopIndicator [ j ] = 0 ; \
} else { \
2022-02-09 02:59:30 +00:00
loopIndicator [ j ] = ( macroLoop ! = - 1 & & ( j + macroDragScroll ) > = macroLoop ) | ( ( macroRel ! = - 1 & & ( j + macroDragScroll ) = = macroRel ) < < 1 ) ; \
2022-01-26 08:49:46 +00:00
} \
2022-01-23 21:34:20 +00:00
} \
ImGui : : PushStyleVar ( ImGuiStyleVar_FramePadding , ImVec2 ( 0.0f , 0.0f ) ) ; \
\
if ( bitfield ) { \
2022-01-26 08:49:46 +00:00
PlotBitfield ( " ##IMacro_ " macroName , asInt , totalFit , 0 , bfVal , macroHeight , ImVec2 ( availableWidth , ( displayLoop ) ? ( displayHeight * dpiScale ) : ( 32.0f * dpiScale ) ) ) ; \
2022-01-23 21:34:20 +00:00
} else { \
2022-02-09 02:30:06 +00:00
PlotCustom ( " ##IMacro_ " macroName , asFloat , totalFit , macroDragScroll , NULL , macroDispMin + macroMin , macroHeight + macroDispMin , ImVec2 ( availableWidth , ( displayLoop ) ? ( displayHeight * dpiScale ) : ( 32.0f * dpiScale ) ) , sizeof ( float ) , macroColor , macroLen - macroDragScroll , hoverFunc ) ; \
2022-01-23 21:34:20 +00:00
} \
2022-01-26 08:49:46 +00:00
if ( displayLoop & & ImGui : : IsItemClicked ( ImGuiMouseButton_Left ) ) { \
2022-01-23 21:34:20 +00:00
macroDragStart = ImGui : : GetItemRectMin ( ) ; \
macroDragAreaSize = ImVec2 ( availableWidth , displayHeight * dpiScale ) ; \
macroDragMin = macroMin ; \
macroDragMax = macroHeight ; \
2022-01-23 22:55:02 +00:00
macroDragBitOff = bitOff ; \
2022-01-23 21:34:20 +00:00
macroDragBitMode = bitfield ; \
macroDragInitialValueSet = false ; \
macroDragInitialValue = false ; \
macroDragLen = totalFit ; \
macroDragActive = true ; \
macroDragTarget = macro ; \
macroDragChar = false ; \
processDrags ( ImGui : : GetMousePos ( ) . x , ImGui : : GetMousePos ( ) . y ) ; \
} \
if ( displayLoop ) { \
2022-01-23 22:55:02 +00:00
if ( drawSlider ) { \
ImGui : : SameLine ( ) ; \
ImGui : : VSliderInt ( " ##IArpMacroPos " , ImVec2 ( 20.0f * dpiScale , displayHeight * dpiScale ) , sliderVal , sliderLow , 70 ) ; \
} \
2022-02-09 02:59:30 +00:00
PlotCustom ( " ##IMacroLoop_ " macroName , loopIndicator , totalFit , macroDragScroll , NULL , 0 , 2 , ImVec2 ( availableWidth , 16.0f * dpiScale ) , sizeof ( float ) , macroColor , macroLen - macroDragScroll , & macroHoverLoop ) ; \
2022-01-23 21:34:20 +00:00
if ( ImGui : : IsItemClicked ( ImGuiMouseButton_Left ) ) { \
macroLoopDragStart = ImGui : : GetItemRectMin ( ) ; \
2022-02-09 02:59:30 +00:00
macroLoopDragAreaSize = ImVec2 ( availableWidth , 16.0f * dpiScale ) ; \
2022-01-23 21:34:20 +00:00
macroLoopDragLen = totalFit ; \
2022-02-09 02:59:30 +00:00
if ( ImGui : : IsKeyDown ( ImGuiKey_LeftShift ) | | ImGui : : IsKeyDown ( ImGuiKey_RightShift ) ) { \
macroLoopDragTarget = & macroRel ; \
} else { \
macroLoopDragTarget = & macroLoop ; \
} \
2022-01-23 21:34:20 +00:00
macroLoopDragActive = true ; \
processDrags ( ImGui : : GetMousePos ( ) . x , ImGui : : GetMousePos ( ) . y ) ; \
} \
if ( ImGui : : IsItemClicked ( ImGuiMouseButton_Right ) ) { \
2022-02-09 02:59:30 +00:00
if ( ImGui : : IsKeyDown ( ImGuiKey_LeftShift ) | | ImGui : : IsKeyDown ( ImGuiKey_RightShift ) ) { \
macroRel = - 1 ; \
} else { \
macroLoop = - 1 ; \
} \
2022-01-23 21:34:20 +00:00
} \
2022-01-26 18:13:17 +00:00
ImGui : : SetNextItemWidth ( availableWidth ) ; \
if ( ImGui : : InputText ( " ##IMacroMML_ " macroName , & mmlStr ) ) { \
2022-02-08 08:50:42 +00:00
decodeMMLStr ( mmlStr , macro , macroLen , macroLoop , macroAMin , ( bitfield ) ? ( ( 1 < < macroAMax ) - 1 ) : macroAMax , macroRel ) ; \
2022-01-26 18:13:17 +00:00
} \
if ( ! ImGui : : IsItemActive ( ) ) { \
2022-02-08 08:50:42 +00:00
encodeMMLStr ( mmlStr , macro , macroLen , macroLoop , macroRel ) ; \
2022-01-26 18:13:17 +00:00
} \
2022-01-23 21:34:20 +00:00
} \
ImGui : : PopStyleVar ( ) ;
2022-02-08 08:50:42 +00:00
# define OP_MACRO(macro,macroLen,macroLoop,macroRel,macroHeight,op,macroName,displayName,displayHeight,displayLoop,bitfield,bfVal,mmlStr) \
2022-02-06 21:11:36 +00:00
ImGui : : TableNextRow ( ) ; \
ImGui : : TableNextColumn ( ) ; \
2022-01-27 20:01:05 +00:00
ImGui : : Text ( " %s " , displayName ) ; \
2022-01-26 08:49:46 +00:00
ImGui : : SameLine ( ) ; \
if ( ImGui : : SmallButton ( displayLoop ? ( ICON_FA_CHEVRON_UP " ##IOPMacroOpen_ " macroName ) : ( ICON_FA_CHEVRON_DOWN " ##IOPMacroOpen_ " macroName ) ) ) { \
displayLoop = ! displayLoop ; \
} \
if ( displayLoop ) { \
2022-02-06 21:11:36 +00:00
ImGui : : SetNextItemWidth ( lenAvail ) ; \
2022-01-26 08:49:46 +00:00
if ( ImGui : : InputScalar ( " ##IOPMacroLen_ " # op macroName , ImGuiDataType_U8 , & macroLen , & _ONE , & _THREE ) ) { \
if ( macroLen > 127 ) macroLen = 127 ; \
} \
2022-01-21 07:54:52 +00:00
} \
2022-02-06 21:11:36 +00:00
ImGui : : TableNextColumn ( ) ; \
2022-01-21 07:54:52 +00:00
for ( int j = 0 ; j < 256 ; j + + ) { \
2022-01-21 22:00:28 +00:00
if ( j + macroDragScroll > = macroLen ) { \
2022-01-21 07:54:52 +00:00
asFloat [ j ] = 0 ; \
2022-01-21 22:13:50 +00:00
asInt [ j ] = 0 ; \
2022-01-21 07:54:52 +00:00
} else { \
2022-01-21 22:00:28 +00:00
asFloat [ j ] = macro [ j + macroDragScroll ] ; \
2022-01-21 22:13:50 +00:00
asInt [ j ] = macro [ j + macroDragScroll ] ; \
2022-01-21 07:54:52 +00:00
} \
2022-01-21 22:00:28 +00:00
loopIndicator [ j ] = ( macroLoop ! = - 1 & & ( j + macroDragScroll ) > = macroLoop ) ; \
2022-01-21 07:54:52 +00:00
} \
ImGui : : PushStyleVar ( ImGuiStyleVar_FramePadding , ImVec2 ( 0.0f , 0.0f ) ) ; \
\
2022-01-21 22:13:50 +00:00
if ( bitfield ) { \
2022-01-26 08:49:46 +00:00
PlotBitfield ( " ##IOPMacro_ " # op macroName , asInt , totalFit , 0 , bfVal , macroHeight , ImVec2 ( availableWidth , displayLoop ? ( displayHeight * dpiScale ) : ( 24 * dpiScale ) ) ) ; \
2022-01-21 22:13:50 +00:00
} else { \
2022-01-26 22:22:29 +00:00
PlotCustom ( " ##IOPMacro_ " # op macroName , asFloat , totalFit , macroDragScroll , NULL , 0 , macroHeight , ImVec2 ( availableWidth , displayLoop ? ( displayHeight * dpiScale ) : ( 24 * dpiScale ) ) , sizeof ( float ) , uiColors [ GUI_COLOR_MACRO_OTHER ] , macroLen - macroDragScroll ) ; \
2022-01-21 22:13:50 +00:00
} \
2022-01-26 08:49:46 +00:00
if ( displayLoop & & ImGui : : IsItemClicked ( ImGuiMouseButton_Left ) ) { \
2022-01-21 07:54:52 +00:00
macroDragStart = ImGui : : GetItemRectMin ( ) ; \
2022-01-21 22:00:28 +00:00
macroDragAreaSize = ImVec2 ( availableWidth , displayHeight * dpiScale ) ; \
2022-01-21 07:54:52 +00:00
macroDragMin = 0 ; \
macroDragMax = macroHeight ; \
2022-01-21 22:13:50 +00:00
macroDragBitOff = 0 ; \
macroDragBitMode = bitfield ; \
macroDragInitialValueSet = false ; \
macroDragInitialValue = false ; \
2022-01-21 07:54:52 +00:00
macroDragLen = totalFit ; \
macroDragActive = true ; \
macroDragCTarget = macro ; \
macroDragChar = true ; \
processDrags ( ImGui : : GetMousePos ( ) . x , ImGui : : GetMousePos ( ) . y ) ; \
} \
2022-01-21 22:00:28 +00:00
if ( displayLoop ) { \
ImGui : : PlotHistogram ( " ##IOPMacroLoop_ " # op macroName , loopIndicator , totalFit , 0 , NULL , 0 , 1 , ImVec2 ( availableWidth , 8.0f * dpiScale ) ) ; \
if ( ImGui : : IsItemClicked ( ImGuiMouseButton_Left ) ) { \
macroLoopDragStart = ImGui : : GetItemRectMin ( ) ; \
macroLoopDragAreaSize = ImVec2 ( availableWidth , 8.0f * dpiScale ) ; \
macroLoopDragLen = totalFit ; \
macroLoopDragTarget = & macroLoop ; \
macroLoopDragActive = true ; \
processDrags ( ImGui : : GetMousePos ( ) . x , ImGui : : GetMousePos ( ) . y ) ; \
} \
2022-01-23 20:56:03 +00:00
if ( ImGui : : IsItemClicked ( ImGuiMouseButton_Right ) ) { \
macroLoop = - 1 ; \
} \
2022-01-26 22:22:29 +00:00
ImGui : : SetNextItemWidth ( availableWidth ) ; \
if ( ImGui : : InputText ( " ##IOPMacroMML_ " macroName , & mmlStr ) ) { \
2022-02-08 08:50:42 +00:00
decodeMMLStr ( mmlStr , macro , macroLen , macroLoop , 0 , bitfield ? ( ( 1 < < macroHeight ) - 1 ) : ( macroHeight ) , macroRel ) ; \
2022-01-26 22:22:29 +00:00
} \
if ( ! ImGui : : IsItemActive ( ) ) { \
2022-02-08 08:50:42 +00:00
encodeMMLStr ( mmlStr , macro , macroLen , macroLoop , macroRel ) ; \
2022-01-26 22:22:29 +00:00
} \
2022-01-21 07:54:52 +00:00
} \
2022-01-23 21:34:20 +00:00
ImGui : : PopStyleVar ( ) ;
2022-01-23 22:55:02 +00:00
# define MACRO_BEGIN(reservedSpace) \
2022-02-06 21:11:36 +00:00
if ( ImGui : : BeginTable ( " MacroSpace " , 2 ) ) { \
ImGui : : TableSetupColumn ( " c0 " , ImGuiTableColumnFlags_WidthFixed , 0.0 ) ; \
ImGui : : TableSetupColumn ( " c1 " , ImGuiTableColumnFlags_WidthStretch , 0.0 ) ; \
ImGui : : TableNextRow ( ) ; \
ImGui : : TableNextColumn ( ) ; \
float lenAvail = ImGui : : GetContentRegionAvail ( ) . x ; \
ImGui : : TableNextColumn ( ) ; \
2022-01-23 22:55:02 +00:00
float availableWidth = ImGui : : GetContentRegionAvail ( ) . x - reservedSpace ; \
2022-01-23 21:34:20 +00:00
int totalFit = MIN ( 127 , availableWidth / ( 16 * dpiScale ) ) ; \
if ( macroDragScroll > 127 - totalFit ) { \
macroDragScroll = 127 - totalFit ; \
} \
ImGui : : SetNextItemWidth ( availableWidth ) ; \
if ( ImGui : : SliderInt ( " ##MacroScroll " , & macroDragScroll , 0 , 127 - totalFit , " " ) ) { \
if ( macroDragScroll < 0 ) macroDragScroll = 0 ; \
if ( macroDragScroll > 127 - totalFit ) macroDragScroll = 127 - totalFit ; \
}
# define MACRO_END \
2022-02-06 21:11:36 +00:00
ImGui : : TableNextRow ( ) ; \
ImGui : : TableNextColumn ( ) ; \
ImGui : : TableNextColumn ( ) ; \
2022-01-23 21:34:20 +00:00
ImGui : : SetNextItemWidth ( availableWidth ) ; \
if ( ImGui : : SliderInt ( " ##MacroScroll " , & macroDragScroll , 0 , 127 - totalFit , " " ) ) { \
if ( macroDragScroll < 0 ) macroDragScroll = 0 ; \
if ( macroDragScroll > 127 - totalFit ) macroDragScroll = 127 - totalFit ; \
} \
2022-02-06 21:11:36 +00:00
ImGui : : EndTable ( ) ; \
}
2022-01-21 07:54:52 +00:00
2021-12-14 09:45:44 +00:00
void FurnaceGUI : : drawInsEdit ( ) {
if ( ! insEditOpen ) return ;
2022-01-20 22:42:14 +00:00
ImGui : : SetNextWindowSizeConstraints ( ImVec2 ( 440.0f * dpiScale , 400.0f * dpiScale ) , ImVec2 ( scrW * dpiScale , scrH * dpiScale ) ) ;
2022-01-28 06:26:26 +00:00
if ( ImGui : : Begin ( " Instrument Editor " , & insEditOpen , settings . allowEditDocking ? 0 : ImGuiWindowFlags_NoDocking ) ) {
2021-12-17 08:33:12 +00:00
if ( curIns < 0 | | curIns > = ( int ) e - > song . ins . size ( ) ) {
2021-12-14 09:45:44 +00:00
ImGui : : Text ( " no instrument selected " ) ;
} else {
DivInstrument * ins = e - > song . ins [ curIns ] ;
ImGui : : InputText ( " Name " , & ins - > name ) ;
2022-01-15 04:26:22 +00:00
if ( ins - > type < 0 | | ins - > type > 9 ) ins - > type = DIV_INS_FM ;
2022-01-27 21:59:51 +00:00
int insType = ins - > type ;
if ( ImGui : : Combo ( " Type " , & insType , insTypes , 10 ) ) {
ins - > type = ( DivInstrumentType ) insType ;
2022-01-09 22:48:09 +00:00
}
if ( ImGui : : BeginTabBar ( " insEditTab " ) ) {
2022-01-21 07:54:52 +00:00
if ( ins - > type = = DIV_INS_FM ) {
2022-01-23 21:34:20 +00:00
char label [ 32 ] ;
float asFloat [ 256 ] ;
int asInt [ 256 ] ;
float loopIndicator [ 256 ] ;
2022-01-21 07:54:52 +00:00
if ( ImGui : : BeginTabItem ( " FM " ) ) {
ImGui : : Columns ( 3 , NULL , false ) ;
2022-01-27 20:01:05 +00:00
P ( ImGui : : SliderScalar ( FM_NAME ( FM_FB ) , ImGuiDataType_U8 , & ins - > fm . fb , & _ZERO , & _SEVEN ) ) ;
2022-01-21 07:54:52 +00:00
ImGui : : NextColumn ( ) ;
2022-01-29 09:25:28 +00:00
P ( ImGui : : SliderScalar ( FM_NAME ( FM_ALG ) , ImGuiDataType_U8 , & ins - > fm . alg , & _ZERO , & _SEVEN ) ) ;
ImGui : : NextColumn ( ) ;
2022-01-21 07:54:52 +00:00
ImGui : : Text ( " %s " , fourOpAlgs [ ins - > fm . alg & 7 ] ) ;
ImGui : : NextColumn ( ) ;
2022-01-27 20:01:05 +00:00
P ( ImGui : : SliderScalar ( FM_NAME ( FM_FMS ) , ImGuiDataType_U8 , & ins - > fm . fms , & _ZERO , & _SEVEN ) ) ;
2022-01-21 07:54:52 +00:00
ImGui : : NextColumn ( ) ;
2022-01-27 20:01:05 +00:00
P ( ImGui : : SliderScalar ( FM_NAME ( FM_AMS ) , ImGuiDataType_U8 , & ins - > fm . ams , & _ZERO , & _THREE ) ) ;
2022-02-04 07:51:22 +00:00
ImGui : : NextColumn ( ) ;
2022-02-05 09:21:36 +00:00
ImGui : : Columns ( 1 ) ;
2022-02-04 07:51:22 +00:00
if ( ImGui : : BeginTable ( " FMOperators " , 2 , ImGuiTableFlags_SizingStretchSame ) ) {
2022-01-21 07:54:52 +00:00
for ( int i = 0 ; i < 4 ; i + + ) {
DivInstrumentFM : : Operator & op = ins - > fm . op [ opOrder [ i ] ] ;
if ( ( i + 1 ) & 1 ) ImGui : : TableNextRow ( ) ;
ImGui : : TableNextColumn ( ) ;
ImGui : : PushID ( fmt : : sprintf ( " op%d " , i ) . c_str ( ) ) ;
2022-02-04 07:51:22 +00:00
ImGui : : Dummy ( ImVec2 ( dpiScale , dpiScale ) ) ;
2022-01-21 07:54:52 +00:00
ImGui : : Text ( " Operator %d " , i + 1 ) ;
2022-01-27 20:01:05 +00:00
P ( ImGui : : SliderScalar ( FM_NAME ( FM_AR ) , ImGuiDataType_U8 , & op . ar , & _ZERO , & _THIRTY_ONE ) ) ;
P ( ImGui : : SliderScalar ( FM_NAME ( FM_DR ) , ImGuiDataType_U8 , & op . dr , & _ZERO , & _THIRTY_ONE ) ) ;
P ( ImGui : : SliderScalar ( FM_NAME ( FM_D2R ) , ImGuiDataType_U8 , & op . d2r , & _ZERO , & _THIRTY_ONE ) ) ;
P ( ImGui : : SliderScalar ( FM_NAME ( FM_RR ) , ImGuiDataType_U8 , & op . rr , & _ZERO , & _FIFTEEN ) ) ;
P ( ImGui : : SliderScalar ( FM_NAME ( FM_SL ) , ImGuiDataType_U8 , & op . sl , & _ZERO , & _FIFTEEN ) ) ;
P ( ImGui : : SliderScalar ( FM_NAME ( FM_TL ) , ImGuiDataType_U8 , & op . tl , & _ZERO , & _ONE_HUNDRED_TWENTY_SEVEN ) ) ;
2022-01-21 07:54:52 +00:00
ImGui : : Separator ( ) ;
2022-01-27 20:01:05 +00:00
P ( ImGui : : SliderScalar ( FM_NAME ( FM_RS ) , ImGuiDataType_U8 , & op . rs , & _ZERO , & _THREE ) ) ;
P ( ImGui : : SliderScalar ( FM_NAME ( FM_MULT ) , ImGuiDataType_U8 , & op . mult , & _ZERO , & _FIFTEEN ) ) ;
2022-01-21 07:54:52 +00:00
2022-01-22 04:30:05 +00:00
int detune = ( op . dt & 7 ) - 3 ;
2022-01-27 20:01:05 +00:00
if ( ImGui : : SliderInt ( FM_NAME ( FM_DT ) , & detune , - 3 , 3 ) ) { PARAMETER
2022-01-22 04:30:05 +00:00
op . dt = detune + 3 ;
2022-01-21 07:54:52 +00:00
}
2022-01-27 20:01:05 +00:00
P ( ImGui : : SliderScalar ( FM_NAME ( FM_DT2 ) , ImGuiDataType_U8 , & op . dt2 , & _ZERO , & _THREE ) ) ;
2022-01-21 07:54:52 +00:00
if ( ImGui : : IsItemHovered ( ) ) {
ImGui : : SetTooltip ( " Only for Arcade system " ) ;
}
bool ssgOn = op . ssgEnv & 8 ;
unsigned char ssgEnv = op . ssgEnv & 7 ;
2022-01-27 20:01:05 +00:00
if ( ImGui : : SliderScalar ( FM_NAME ( FM_SSG ) , ImGuiDataType_U8 , & ssgEnv , & _ZERO , & _SEVEN , ssgEnvTypes [ ssgEnv ] ) ) { PARAMETER
2022-01-21 07:54:52 +00:00
op . ssgEnv = ( op . ssgEnv & 8 ) | ( ssgEnv & 7 ) ;
}
ImGui : : SameLine ( ) ;
if ( ImGui : : Checkbox ( " ##SSGOn " , & ssgOn ) ) { PARAMETER
op . ssgEnv = ( op . ssgEnv & 7 ) | ( ssgOn < < 3 ) ;
}
if ( ImGui : : IsItemHovered ( ) ) {
ImGui : : SetTooltip ( " Only for Genesis and Neo Geo systems " ) ;
}
2021-12-12 23:19:43 +00:00
2022-01-21 07:54:52 +00:00
bool amOn = op . am ;
2022-01-27 20:01:05 +00:00
if ( ImGui : : Checkbox ( FM_NAME ( FM_AM ) , & amOn ) ) { PARAMETER
2022-01-21 07:54:52 +00:00
op . am = amOn ;
}
ImGui : : PopID ( ) ;
2022-01-18 04:59:52 +00:00
}
2022-01-21 07:54:52 +00:00
ImGui : : EndTable ( ) ;
}
ImGui : : EndTabItem ( ) ;
}
if ( ImGui : : BeginTabItem ( " Macros (FM) " ) ) {
2022-01-23 22:55:02 +00:00
MACRO_BEGIN ( 0 ) ;
2022-02-09 02:30:06 +00:00
NORMAL_MACRO ( ins - > std . algMacro , ins - > std . algMacroLen , ins - > std . algMacroLoop , ins - > std . algMacroRel , 0 , 7 , " alg " , FM_NAME ( FM_ALG ) , 96 , ins - > std . algMacroOpen , false , NULL , false , NULL , 0 , 0 , 0 , NULL , uiColors [ GUI_COLOR_MACRO_OTHER ] , mmlString [ 0 ] , 0 , 7 , NULL ) ;
NORMAL_MACRO ( ins - > std . fbMacro , ins - > std . fbMacroLen , ins - > std . fbMacroLoop , ins - > std . fbMacroRel , 0 , 7 , " fb " , FM_NAME ( FM_FB ) , 96 , ins - > std . fbMacroOpen , false , NULL , false , NULL , 0 , 0 , 0 , NULL , uiColors [ GUI_COLOR_MACRO_OTHER ] , mmlString [ 1 ] , 0 , 7 , NULL ) ;
NORMAL_MACRO ( ins - > std . fmsMacro , ins - > std . fmsMacroLen , ins - > std . fmsMacroLoop , ins - > std . fmsMacroRel , 0 , 7 , " fms " , FM_NAME ( FM_FMS ) , 96 , ins - > std . fmsMacroOpen , false , NULL , false , NULL , 0 , 0 , 0 , NULL , uiColors [ GUI_COLOR_MACRO_OTHER ] , mmlString [ 2 ] , 0 , 7 , NULL ) ;
NORMAL_MACRO ( ins - > std . amsMacro , ins - > std . amsMacroLen , ins - > std . amsMacroLoop , ins - > std . amsMacroRel , 0 , 3 , " ams " , FM_NAME ( FM_AMS ) , 48 , ins - > std . amsMacroOpen , false , NULL , false , NULL , 0 , 0 , 0 , NULL , uiColors [ GUI_COLOR_MACRO_OTHER ] , mmlString [ 3 ] , 0 , 3 , NULL ) ;
2022-01-29 09:37:53 +00:00
2022-02-09 02:30:06 +00:00
NORMAL_MACRO ( ins - > std . ex1Macro , ins - > std . ex1MacroLen , ins - > std . ex1MacroLoop , ins - > std . ex1MacroRel , 0 , 127 , " ex1 " , " AM Depth " , 128 , ins - > std . ex1MacroOpen , false , NULL , false , NULL , 0 , 0 , 0 , NULL , uiColors [ GUI_COLOR_MACRO_OTHER ] , mmlString [ 4 ] , 0 , 127 , NULL ) ;
NORMAL_MACRO ( ins - > std . ex2Macro , ins - > std . ex2MacroLen , ins - > std . ex2MacroLoop , ins - > std . ex2MacroRel , 0 , 127 , " ex2 " , " PM Depth " , 128 , ins - > std . ex2MacroOpen , false , NULL , false , NULL , 0 , 0 , 0 , NULL , uiColors [ GUI_COLOR_MACRO_OTHER ] , mmlString [ 5 ] , 0 , 127 , NULL ) ;
NORMAL_MACRO ( ins - > std . ex3Macro , ins - > std . ex3MacroLen , ins - > std . ex3MacroLoop , ins - > std . ex3MacroRel , 0 , 255 , " ex3 " , " LFO Speed " , 128 , ins - > std . ex3MacroOpen , false , NULL , false , NULL , 0 , 0 , 0 , NULL , uiColors [ GUI_COLOR_MACRO_OTHER ] , mmlString [ 6 ] , 0 , 255 , NULL ) ;
NORMAL_MACRO ( ins - > std . waveMacro , ins - > std . waveMacroLen , ins - > std . waveMacroLoop , ins - > std . waveMacroRel , 0 , 3 , " wave " , " LFO Shape " , 48 , ins - > std . waveMacroOpen , false , NULL , false , NULL , 0 , 0 , 0 , NULL , uiColors [ GUI_COLOR_MACRO_WAVE ] , mmlString [ 7 ] , 0 , 3 , NULL ) ;
2022-01-23 21:34:20 +00:00
MACRO_END ;
2022-01-21 07:54:52 +00:00
ImGui : : EndTabItem ( ) ;
}
for ( int i = 0 ; i < 4 ; i + + ) {
snprintf ( label , 31 , " Macros (OP%d) " , i + 1 ) ;
if ( ImGui : : BeginTabItem ( label ) ) {
ImGui : : PushID ( i ) ;
2022-01-23 22:55:02 +00:00
MACRO_BEGIN ( 0 ) ;
2022-01-23 20:56:03 +00:00
int ordi = orderedOps [ i ] ;
2022-02-08 08:50:42 +00:00
OP_MACRO ( ins - > std . opMacros [ ordi ] . tlMacro , ins - > std . opMacros [ ordi ] . tlMacroLen , ins - > std . opMacros [ ordi ] . tlMacroLoop , ins - > std . opMacros [ ordi ] . tlMacroRel , 127 , ordi , " tl " , FM_NAME ( FM_TL ) , 128 , ins - > std . opMacros [ ordi ] . tlMacroOpen , false , NULL , mmlString [ 0 ] ) ;
OP_MACRO ( ins - > std . opMacros [ ordi ] . arMacro , ins - > std . opMacros [ ordi ] . arMacroLen , ins - > std . opMacros [ ordi ] . arMacroLoop , ins - > std . opMacros [ ordi ] . arMacroRel , 31 , ordi , " ar " , FM_NAME ( FM_AR ) , 64 , ins - > std . opMacros [ ordi ] . arMacroOpen , false , NULL , mmlString [ 1 ] ) ;
OP_MACRO ( ins - > std . opMacros [ ordi ] . drMacro , ins - > std . opMacros [ ordi ] . drMacroLen , ins - > std . opMacros [ ordi ] . drMacroLoop , ins - > std . opMacros [ ordi ] . drMacroRel , 31 , ordi , " dr " , FM_NAME ( FM_DR ) , 64 , ins - > std . opMacros [ ordi ] . drMacroOpen , false , NULL , mmlString [ 2 ] ) ;
OP_MACRO ( ins - > std . opMacros [ ordi ] . d2rMacro , ins - > std . opMacros [ ordi ] . d2rMacroLen , ins - > std . opMacros [ ordi ] . d2rMacroLoop , ins - > std . opMacros [ ordi ] . d2rMacroRel , 31 , ordi , " d2r " , FM_NAME ( FM_D2R ) , 64 , ins - > std . opMacros [ ordi ] . d2rMacroOpen , false , NULL , mmlString [ 3 ] ) ;
OP_MACRO ( ins - > std . opMacros [ ordi ] . rrMacro , ins - > std . opMacros [ ordi ] . rrMacroLen , ins - > std . opMacros [ ordi ] . rrMacroLoop , ins - > std . opMacros [ ordi ] . rrMacroRel , 15 , ordi , " rr " , FM_NAME ( FM_RR ) , 64 , ins - > std . opMacros [ ordi ] . rrMacroOpen , false , NULL , mmlString [ 4 ] ) ;
OP_MACRO ( ins - > std . opMacros [ ordi ] . slMacro , ins - > std . opMacros [ ordi ] . slMacroLen , ins - > std . opMacros [ ordi ] . slMacroLoop , ins - > std . opMacros [ ordi ] . slMacroRel , 15 , ordi , " sl " , FM_NAME ( FM_SL ) , 64 , ins - > std . opMacros [ ordi ] . slMacroOpen , false , NULL , mmlString [ 5 ] ) ;
OP_MACRO ( ins - > std . opMacros [ ordi ] . rsMacro , ins - > std . opMacros [ ordi ] . rsMacroLen , ins - > std . opMacros [ ordi ] . rsMacroLoop , ins - > std . opMacros [ ordi ] . rsMacroRel , 3 , ordi , " rs " , FM_NAME ( FM_RS ) , 32 , ins - > std . opMacros [ ordi ] . rsMacroOpen , false , NULL , mmlString [ 6 ] ) ;
OP_MACRO ( ins - > std . opMacros [ ordi ] . multMacro , ins - > std . opMacros [ ordi ] . multMacroLen , ins - > std . opMacros [ ordi ] . multMacroLoop , ins - > std . opMacros [ ordi ] . multMacroRel , 15 , ordi , " mult " , FM_NAME ( FM_MULT ) , 64 , ins - > std . opMacros [ ordi ] . multMacroOpen , false , NULL , mmlString [ 7 ] ) ;
OP_MACRO ( ins - > std . opMacros [ ordi ] . dtMacro , ins - > std . opMacros [ ordi ] . dtMacroLen , ins - > std . opMacros [ ordi ] . dtMacroLoop , ins - > std . opMacros [ ordi ] . dtMacroRel , 7 , ordi , " dt " , FM_NAME ( FM_DT ) , 64 , ins - > std . opMacros [ ordi ] . dtMacroOpen , false , NULL , mmlString [ 8 ] ) ;
OP_MACRO ( ins - > std . opMacros [ ordi ] . dt2Macro , ins - > std . opMacros [ ordi ] . dt2MacroLen , ins - > std . opMacros [ ordi ] . dt2MacroLoop , ins - > std . opMacros [ ordi ] . dt2MacroRel , 3 , ordi , " dt2 " , FM_NAME ( FM_DT2 ) , 32 , ins - > std . opMacros [ ordi ] . dt2MacroOpen , false , NULL , mmlString [ 9 ] ) ;
OP_MACRO ( ins - > std . opMacros [ ordi ] . amMacro , ins - > std . opMacros [ ordi ] . amMacroLen , ins - > std . opMacros [ ordi ] . amMacroLoop , ins - > std . opMacros [ ordi ] . amMacroRel , 1 , ordi , " am " , FM_NAME ( FM_AM ) , 32 , ins - > std . opMacros [ ordi ] . amMacroOpen , true , NULL , mmlString [ 10 ] ) ;
OP_MACRO ( ins - > std . opMacros [ ordi ] . ssgMacro , ins - > std . opMacros [ ordi ] . ssgMacroLen , ins - > std . opMacros [ ordi ] . ssgMacroLoop , ins - > std . opMacros [ ordi ] . ssgMacroRel , 4 , ordi , " ssg " , FM_NAME ( FM_SSG ) , 64 , ins - > std . opMacros [ ordi ] . ssgMacroOpen , true , ssgEnvBits , mmlString [ 11 ] ) ;
2022-01-23 21:34:20 +00:00
MACRO_END ;
2022-01-09 22:48:09 +00:00
ImGui : : PopID ( ) ;
2022-01-21 07:54:52 +00:00
ImGui : : EndTabItem ( ) ;
2022-01-09 22:48:09 +00:00
}
2021-12-24 05:14:02 +00:00
}
2021-12-14 09:45:44 +00:00
}
2022-01-10 03:09:45 +00:00
if ( ins - > type = = DIV_INS_GB ) if ( ImGui : : BeginTabItem ( " Game Boy " ) ) {
2022-01-18 04:59:52 +00:00
P ( ImGui : : SliderScalar ( " Volume " , ImGuiDataType_U8 , & ins - > gb . envVol , & _ZERO , & _FIFTEEN ) ) ;
P ( ImGui : : SliderScalar ( " Envelope Length " , ImGuiDataType_U8 , & ins - > gb . envLen , & _ZERO , & _SEVEN ) ) ;
P ( ImGui : : SliderScalar ( " Sound Length " , ImGuiDataType_U8 , & ins - > gb . soundLen , & _ZERO , & _SIXTY_FOUR , ins - > gb . soundLen > 63 ? " Infinity " : " %d " ) ) ;
2022-02-05 03:02:19 +00:00
ImGui : : Text ( " Envelope Direction: " ) ;
2022-01-10 03:09:45 +00:00
bool goesUp = ins - > gb . envDir ;
2022-02-05 03:02:19 +00:00
ImGui : : SameLine ( ) ;
if ( ImGui : : RadioButton ( " Up " , goesUp ) ) { PARAMETER
goesUp = true ;
ins - > gb . envDir = goesUp ;
}
ImGui : : SameLine ( ) ;
if ( ImGui : : RadioButton ( " Down " , ! goesUp ) ) { PARAMETER
goesUp = false ;
2022-01-10 03:09:45 +00:00
ins - > gb . envDir = goesUp ;
}
ImGui : : EndTabItem ( ) ;
}
if ( ins - > type = = DIV_INS_C64 ) if ( ImGui : : BeginTabItem ( " C64 " ) ) {
ImGui : : Text ( " Waveform " ) ;
ImGui : : SameLine ( ) ;
ImGui : : PushStyleColor ( ImGuiCol_Button , ImVec4 ( 0.2f , ( ins - > c64 . triOn ) ? 0.6f : 0.2f , 0.2f , 1.0f ) ) ;
2022-01-18 04:59:52 +00:00
if ( ImGui : : Button ( " tri " ) ) { PARAMETER
2022-01-10 03:09:45 +00:00
ins - > c64 . triOn = ! ins - > c64 . triOn ;
}
ImGui : : PopStyleColor ( ) ;
ImGui : : SameLine ( ) ;
ImGui : : PushStyleColor ( ImGuiCol_Button , ImVec4 ( 0.2f , ( ins - > c64 . sawOn ) ? 0.6f : 0.2f , 0.2f , 1.0f ) ) ;
2022-01-18 04:59:52 +00:00
if ( ImGui : : Button ( " saw " ) ) { PARAMETER
2022-01-10 03:09:45 +00:00
ins - > c64 . sawOn = ! ins - > c64 . sawOn ;
}
ImGui : : PopStyleColor ( ) ;
ImGui : : SameLine ( ) ;
ImGui : : PushStyleColor ( ImGuiCol_Button , ImVec4 ( 0.2f , ( ins - > c64 . pulseOn ) ? 0.6f : 0.2f , 0.2f , 1.0f ) ) ;
2022-01-18 04:59:52 +00:00
if ( ImGui : : Button ( " pulse " ) ) { PARAMETER
2022-01-10 03:09:45 +00:00
ins - > c64 . pulseOn = ! ins - > c64 . pulseOn ;
}
ImGui : : PopStyleColor ( ) ;
ImGui : : SameLine ( ) ;
ImGui : : PushStyleColor ( ImGuiCol_Button , ImVec4 ( 0.2f , ( ins - > c64 . noiseOn ) ? 0.6f : 0.2f , 0.2f , 1.0f ) ) ;
2022-01-18 04:59:52 +00:00
if ( ImGui : : Button ( " noise " ) ) { PARAMETER
2022-01-10 03:09:45 +00:00
ins - > c64 . noiseOn = ! ins - > c64 . noiseOn ;
}
ImGui : : PopStyleColor ( ) ;
2022-01-18 04:59:52 +00:00
P ( ImGui : : SliderScalar ( " Attack " , ImGuiDataType_U8 , & ins - > c64 . a , & _ZERO , & _FIFTEEN ) ) ;
P ( ImGui : : SliderScalar ( " Decay " , ImGuiDataType_U8 , & ins - > c64 . d , & _ZERO , & _FIFTEEN ) ) ;
P ( ImGui : : SliderScalar ( " Sustain " , ImGuiDataType_U8 , & ins - > c64 . s , & _ZERO , & _FIFTEEN ) ) ;
P ( ImGui : : SliderScalar ( " Release " , ImGuiDataType_U8 , & ins - > c64 . r , & _ZERO , & _FIFTEEN ) ) ;
P ( ImGui : : SliderScalar ( " Duty " , ImGuiDataType_U16 , & ins - > c64 . duty , & _ZERO , & _FOUR_THOUSAND_NINETY_FIVE ) ) ;
2022-01-10 03:09:45 +00:00
bool ringMod = ins - > c64 . ringMod ;
2022-01-18 04:59:52 +00:00
if ( ImGui : : Checkbox ( " Ring Modulation " , & ringMod ) ) { PARAMETER
ins - > c64 . ringMod = ringMod ;
}
2022-01-10 03:09:45 +00:00
bool oscSync = ins - > c64 . oscSync ;
2022-01-18 04:59:52 +00:00
if ( ImGui : : Checkbox ( " Oscillator Sync " , & oscSync ) ) { PARAMETER
ins - > c64 . oscSync = oscSync ;
}
2022-01-10 03:09:45 +00:00
2022-01-18 04:59:52 +00:00
P ( ImGui : : Checkbox ( " Enable filter " , & ins - > c64 . toFilter ) ) ;
P ( ImGui : : Checkbox ( " Initialize filter " , & ins - > c64 . initFilter ) ) ;
2022-01-10 03:09:45 +00:00
2022-01-18 04:59:52 +00:00
P ( ImGui : : SliderScalar ( " Cutoff " , ImGuiDataType_U16 , & ins - > c64 . cut , & _ZERO , & _TWO_THOUSAND_FORTY_SEVEN ) ) ;
P ( ImGui : : SliderScalar ( " Resonance " , ImGuiDataType_U8 , & ins - > c64 . res , & _ZERO , & _FIFTEEN ) ) ;
2022-01-10 03:09:45 +00:00
ImGui : : Text ( " Filter Mode " ) ;
ImGui : : SameLine ( ) ;
ImGui : : PushStyleColor ( ImGuiCol_Button , ImVec4 ( 0.2f , ( ins - > c64 . lp ) ? 0.6f : 0.2f , 0.2f , 1.0f ) ) ;
2022-01-18 04:59:52 +00:00
if ( ImGui : : Button ( " low " ) ) { PARAMETER
2022-01-10 03:09:45 +00:00
ins - > c64 . lp = ! ins - > c64 . lp ;
}
ImGui : : PopStyleColor ( ) ;
ImGui : : SameLine ( ) ;
ImGui : : PushStyleColor ( ImGuiCol_Button , ImVec4 ( 0.2f , ( ins - > c64 . bp ) ? 0.6f : 0.2f , 0.2f , 1.0f ) ) ;
2022-01-18 04:59:52 +00:00
if ( ImGui : : Button ( " band " ) ) { PARAMETER
2022-01-10 03:09:45 +00:00
ins - > c64 . bp = ! ins - > c64 . bp ;
}
ImGui : : PopStyleColor ( ) ;
ImGui : : SameLine ( ) ;
ImGui : : PushStyleColor ( ImGuiCol_Button , ImVec4 ( 0.2f , ( ins - > c64 . hp ) ? 0.6f : 0.2f , 0.2f , 1.0f ) ) ;
2022-01-18 04:59:52 +00:00
if ( ImGui : : Button ( " high " ) ) { PARAMETER
2022-01-10 03:09:45 +00:00
ins - > c64 . hp = ! ins - > c64 . hp ;
}
ImGui : : PopStyleColor ( ) ;
ImGui : : SameLine ( ) ;
ImGui : : PushStyleColor ( ImGuiCol_Button , ImVec4 ( 0.2f , ( ins - > c64 . ch3off ) ? 0.6f : 0.2f , 0.2f , 1.0f ) ) ;
2022-01-18 04:59:52 +00:00
if ( ImGui : : Button ( " ch3off " ) ) { PARAMETER
2022-01-10 03:09:45 +00:00
ins - > c64 . ch3off = ! ins - > c64 . ch3off ;
}
ImGui : : PopStyleColor ( ) ;
2022-01-18 04:59:52 +00:00
P ( ImGui : : Checkbox ( " Volume Macro is Cutoff Macro " , & ins - > c64 . volIsCutoff ) ) ;
P ( ImGui : : Checkbox ( " Absolute Cutoff Macro " , & ins - > c64 . filterIsAbs ) ) ;
P ( ImGui : : Checkbox ( " Absolute Duty Macro " , & ins - > c64 . dutyIsAbs ) ) ;
2022-01-10 03:09:45 +00:00
ImGui : : EndTabItem ( ) ;
}
2022-01-20 19:18:15 +00:00
if ( ins - > type = = DIV_INS_AMIGA ) if ( ImGui : : BeginTabItem ( " Amiga/Sample " ) ) {
2022-01-15 22:28:33 +00:00
String sName ;
if ( ins - > amiga . initSample < 0 | | ins - > amiga . initSample > = e - > song . sampleLen ) {
sName = " none selected " ;
} else {
sName = e - > song . sample [ ins - > amiga . initSample ] - > name ;
}
if ( ImGui : : BeginCombo ( " Initial Sample " , sName . c_str ( ) ) ) {
String id ;
for ( int i = 0 ; i < e - > song . sampleLen ; i + + ) {
id = fmt : : sprintf ( " %d: %s " , i , e - > song . sample [ i ] - > name ) ;
2022-01-18 04:59:52 +00:00
if ( ImGui : : Selectable ( id . c_str ( ) , ins - > amiga . initSample = = i ) ) { PARAMETER
2022-01-15 22:28:33 +00:00
ins - > amiga . initSample = i ;
}
}
ImGui : : EndCombo ( ) ;
}
2022-01-10 03:09:45 +00:00
ImGui : : EndTabItem ( ) ;
}
2022-01-23 20:56:03 +00:00
if ( ImGui : : BeginTabItem ( " Macros " ) ) {
2022-01-21 06:56:30 +00:00
float asFloat [ 256 ] ;
int asInt [ 256 ] ;
float loopIndicator [ 256 ] ;
2022-01-23 22:55:02 +00:00
const char * volumeLabel = " Volume " ;
2022-01-09 22:48:09 +00:00
2022-01-14 05:02:10 +00:00
int volMax = ( ins - > type = = DIV_INS_PCE | | ins - > type = = DIV_INS_AY8930 ) ? 31 : 15 ;
2022-01-10 21:42:51 +00:00
int volMin = 0 ;
2022-01-09 22:48:09 +00:00
if ( ins - > type = = DIV_INS_C64 ) {
2022-01-10 21:42:51 +00:00
if ( ins - > c64 . volIsCutoff ) {
2022-01-23 22:55:02 +00:00
volumeLabel = " Cutoff " ;
2022-01-10 22:04:31 +00:00
if ( ins - > c64 . filterIsAbs ) {
volMax = 2047 ;
} else {
volMin = - 18 ;
volMax = 18 ;
}
2022-01-10 21:42:51 +00:00
}
2022-01-09 22:48:09 +00:00
}
2022-01-15 22:42:17 +00:00
if ( ins - > type = = DIV_INS_AMIGA ) {
volMax = 64 ;
}
2022-01-23 20:56:03 +00:00
if ( ins - > type = = DIV_INS_FM ) {
volMax = 127 ;
}
2022-01-09 22:48:09 +00:00
bool arpMode = ins - > std . arpMacroMode ;
2022-01-26 08:49:46 +00:00
const char * dutyLabel = " Duty/Noise " ;
2022-01-14 05:02:10 +00:00
int dutyMax = ( ins - > type = = DIV_INS_AY | | ins - > type = = DIV_INS_AY8930 ) ? 31 : 3 ;
2022-01-10 21:42:51 +00:00
if ( ins - > type = = DIV_INS_C64 ) {
2022-01-23 22:55:02 +00:00
dutyLabel = " Duty " ;
2022-01-10 21:54:58 +00:00
if ( ins - > c64 . dutyIsAbs ) {
dutyMax = 4095 ;
} else {
dutyMax = 24 ;
}
2022-01-10 21:42:51 +00:00
}
2022-01-27 20:42:31 +00:00
if ( ins - > type = = DIV_INS_FM ) {
dutyMax = 32 ;
}
if ( ins - > type = = DIV_INS_AY | | ins - > type = = DIV_INS_AY8930 | | ins - > type = = DIV_INS_FM ) {
2022-01-23 22:55:02 +00:00
dutyLabel = " Noise Freq " ;
}
2022-01-14 05:02:10 +00:00
if ( ins - > type = = DIV_INS_AY8930 ) {
dutyMax = 255 ;
}
2022-02-07 18:32:18 +00:00
if ( ins - > type = = DIV_INS_TIA | | ins - > type = = DIV_INS_PCE | | ins - > type = = DIV_INS_AMIGA ) {
2022-01-14 20:21:57 +00:00
dutyMax = 0 ;
}
2022-01-23 22:01:19 +00:00
bool dutyIsRel = ( ins - > type = = DIV_INS_C64 & & ! ins - > c64 . dutyIsAbs ) ;
2021-12-14 09:45:44 +00:00
2022-01-21 06:56:30 +00:00
int waveMax = ( ins - > type = = DIV_INS_AY | | ins - > type = = DIV_INS_AY8930 ) ? 3 : 63 ;
bool bitMode = false ;
2022-01-23 22:55:02 +00:00
if ( ins - > type = = DIV_INS_C64 | | ins - > type = = DIV_INS_AY | | ins - > type = = DIV_INS_AY8930 | | ins - > type = = DIV_INS_SAA1099 ) {
bitMode = true ;
}
2022-02-04 19:46:15 +00:00
if ( ins - > type = = DIV_INS_STD ) waveMax = 0 ;
2022-01-14 20:21:57 +00:00
if ( ins - > type = = DIV_INS_TIA ) waveMax = 15 ;
2022-01-21 06:56:30 +00:00
if ( ins - > type = = DIV_INS_C64 ) waveMax = 4 ;
if ( ins - > type = = DIV_INS_SAA1099 ) waveMax = 2 ;
2022-01-23 20:56:03 +00:00
if ( ins - > type = = DIV_INS_FM ) waveMax = 0 ;
2022-01-23 22:01:19 +00:00
2022-01-23 22:55:02 +00:00
const char * * waveNames = ayShapeBits ;
if ( ins - > type = = DIV_INS_C64 ) waveNames = c64ShapeBits ;
2022-01-23 22:01:19 +00:00
int ex1Max = ( ins - > type = = DIV_INS_AY8930 ) ? 8 : 0 ;
2022-01-27 20:31:48 +00:00
int ex2Max = ( ins - > type = = DIV_INS_AY | | ins - > type = = DIV_INS_AY8930 ) ? 4 : 0 ;
2022-01-23 22:01:19 +00:00
2022-02-06 20:56:10 +00:00
if ( ins - > type = = DIV_INS_C64 ) {
ex1Max = 4 ;
ex2Max = 15 ;
}
2022-02-01 08:44:02 +00:00
if ( ins - > type = = DIV_INS_SAA1099 ) ex1Max = 8 ;
2022-01-23 22:01:19 +00:00
if ( settings . macroView = = 0 ) { // modern view
2022-01-23 22:55:02 +00:00
MACRO_BEGIN ( 28 * dpiScale ) ;
2022-02-09 02:30:06 +00:00
NORMAL_MACRO ( ins - > std . volMacro , ins - > std . volMacroLen , ins - > std . volMacroLoop , ins - > std . volMacroRel , volMin , volMax , " vol " , volumeLabel , 160 , ins - > std . volMacroOpen , false , NULL , false , NULL , 0 , 0 , 0 , NULL , uiColors [ GUI_COLOR_MACRO_VOLUME ] , mmlString [ 0 ] , volMin , volMax , NULL ) ;
NORMAL_MACRO ( ins - > std . arpMacro , ins - > std . arpMacroLen , ins - > std . arpMacroLoop , ins - > std . arpMacroRel , arpMacroScroll , arpMacroScroll + 24 , " arp " , " Arpeggio " , 160 , ins - > std . arpMacroOpen , false , NULL , true , & arpMacroScroll , ( arpMode ? 0 : - 80 ) , 0 , 0 , & ins - > std . arpMacroMode , uiColors [ GUI_COLOR_MACRO_PITCH ] , mmlString [ 1 ] , - 92 , 94 , ( ins - > std . arpMacroMode ? ( & macroHoverNote ) : NULL ) ) ;
2022-01-23 22:55:02 +00:00
if ( dutyMax > 0 ) {
2022-02-09 02:30:06 +00:00
NORMAL_MACRO ( ins - > std . dutyMacro , ins - > std . dutyMacroLen , ins - > std . dutyMacroLoop , ins - > std . dutyMacroRel , 0 , dutyMax , " duty " , dutyLabel , 160 , ins - > std . dutyMacroOpen , false , NULL , false , NULL , 0 , 0 , 0 , NULL , uiColors [ GUI_COLOR_MACRO_OTHER ] , mmlString [ 2 ] , 0 , dutyMax , NULL ) ;
2022-01-23 22:55:02 +00:00
}
if ( waveMax > 0 ) {
2022-02-09 02:30:06 +00:00
NORMAL_MACRO ( ins - > std . waveMacro , ins - > std . waveMacroLen , ins - > std . waveMacroLoop , ins - > std . waveMacroRel , 0 , waveMax , " wave " , " Waveform " , bitMode ? 64 : 160 , ins - > std . waveMacroOpen , bitMode , waveNames , false , NULL , 0 , 0 , ( ( ins - > type = = DIV_INS_AY | | ins - > type = = DIV_INS_AY8930 ) ? 1 : 0 ) , NULL , uiColors [ GUI_COLOR_MACRO_WAVE ] , mmlString [ 3 ] , 0 , waveMax , NULL ) ;
2022-01-23 22:55:02 +00:00
}
if ( ex1Max > 0 ) {
2022-02-06 20:44:06 +00:00
if ( ins - > type = = DIV_INS_C64 ) {
2022-02-09 02:30:06 +00:00
NORMAL_MACRO ( ins - > std . ex1Macro , ins - > std . ex1MacroLen , ins - > std . ex1MacroLoop , ins - > std . ex1MacroRel , 0 , ex1Max , " ex1 " , " Filter Mode " , 64 , ins - > std . ex1MacroOpen , true , filtModeBits , false , NULL , 0 , 0 , 0 , NULL , uiColors [ GUI_COLOR_MACRO_OTHER ] , mmlString [ 4 ] , 0 , ex1Max , NULL ) ;
2022-02-06 20:44:06 +00:00
} else if ( ins - > type = = DIV_INS_SAA1099 ) {
2022-02-09 02:30:06 +00:00
NORMAL_MACRO ( ins - > std . ex1Macro , ins - > std . ex1MacroLen , ins - > std . ex1MacroLoop , ins - > std . ex1MacroRel , 0 , ex1Max , " ex1 " , " Envelope " , 160 , ins - > std . ex1MacroOpen , true , saaEnvBits , false , NULL , 0 , 0 , 0 , NULL , uiColors [ GUI_COLOR_MACRO_OTHER ] , mmlString [ 4 ] , 0 , ex1Max , NULL ) ;
2022-02-01 08:44:02 +00:00
} else {
2022-02-09 02:30:06 +00:00
NORMAL_MACRO ( ins - > std . ex1Macro , ins - > std . ex1MacroLen , ins - > std . ex1MacroLoop , ins - > std . ex1MacroRel , 0 , ex1Max , " ex1 " , " Duty " , 160 , ins - > std . ex1MacroOpen , false , NULL , false , NULL , 0 , 0 , 0 , NULL , uiColors [ GUI_COLOR_MACRO_OTHER ] , mmlString [ 4 ] , 0 , ex1Max , NULL ) ;
2022-02-01 08:44:02 +00:00
}
2022-01-23 22:55:02 +00:00
}
2022-01-27 20:31:48 +00:00
if ( ex2Max > 0 ) {
2022-02-06 20:56:10 +00:00
if ( ins - > type = = DIV_INS_C64 ) {
2022-02-09 02:30:06 +00:00
NORMAL_MACRO ( ins - > std . ex2Macro , ins - > std . ex2MacroLen , ins - > std . ex2MacroLoop , ins - > std . ex2MacroRel , 0 , ex2Max , " ex2 " , " Resonance " , 64 , ins - > std . ex2MacroOpen , false , NULL , false , NULL , 0 , 0 , 0 , NULL , uiColors [ GUI_COLOR_MACRO_OTHER ] , mmlString [ 5 ] , 0 , ex2Max , NULL ) ;
2022-02-06 20:56:10 +00:00
} else {
2022-02-09 02:30:06 +00:00
NORMAL_MACRO ( ins - > std . ex2Macro , ins - > std . ex2MacroLen , ins - > std . ex2MacroLoop , ins - > std . ex2MacroRel , 0 , ex2Max , " ex2 " , " Envelope " , 64 , ins - > std . ex2MacroOpen , true , ayEnvBits , false , NULL , 0 , 0 , 0 , NULL , uiColors [ GUI_COLOR_MACRO_OTHER ] , mmlString [ 5 ] , 0 , ex2Max , NULL ) ;
2022-02-06 20:56:10 +00:00
}
}
if ( ins - > type = = DIV_INS_C64 ) {
2022-02-09 02:30:06 +00:00
NORMAL_MACRO ( ins - > std . ex3Macro , ins - > std . ex3MacroLen , ins - > std . ex3MacroLoop , ins - > std . ex3MacroRel , 0 , 2 , " ex3 " , " Special " , 32 , ins - > std . ex3MacroOpen , true , c64SpecialBits , false , NULL , 0 , 0 , 0 , NULL , uiColors [ GUI_COLOR_MACRO_OTHER ] , mmlString [ 6 ] , 0 , 2 , NULL ) ;
2022-01-27 20:31:48 +00:00
}
if ( ins - > type = = DIV_INS_AY | | ins - > type = = DIV_INS_AY8930 ) {
2022-02-09 02:30:06 +00:00
NORMAL_MACRO ( ins - > std . ex3Macro , ins - > std . ex3MacroLen , ins - > std . ex3MacroLoop , ins - > std . ex3MacroRel , 0 , 15 , " ex3 " , " AutoEnv Num " , 96 , ins - > std . ex3MacroOpen , false , NULL , false , NULL , 0 , 0 , 0 , NULL , uiColors [ GUI_COLOR_MACRO_OTHER ] , mmlString [ 6 ] , 0 , 15 , NULL ) ;
NORMAL_MACRO ( ins - > std . algMacro , ins - > std . algMacroLen , ins - > std . algMacroLoop , ins - > std . algMacroRel , 0 , 15 , " alg " , " AutoEnv Den " , 96 , ins - > std . algMacroOpen , false , NULL , false , NULL , 0 , 0 , 0 , NULL , uiColors [ GUI_COLOR_MACRO_OTHER ] , mmlString [ 7 ] , 0 , 15 , NULL ) ;
2022-01-27 20:31:48 +00:00
}
2022-01-31 22:45:02 +00:00
if ( ins - > type = = DIV_INS_AY8930 ) {
// oh my i am running out of macros
2022-02-09 02:30:06 +00:00
NORMAL_MACRO ( ins - > std . fbMacro , ins - > std . fbMacroLen , ins - > std . fbMacroLoop , ins - > std . fbMacroRel , 0 , 8 , " fb " , " Noise AND Mask " , 96 , ins - > std . fbMacroOpen , true , NULL , false , NULL , 0 , 0 , 0 , NULL , uiColors [ GUI_COLOR_MACRO_OTHER ] , mmlString [ 8 ] , 0 , 8 , NULL ) ;
NORMAL_MACRO ( ins - > std . fmsMacro , ins - > std . fmsMacroLen , ins - > std . fmsMacroLoop , ins - > std . fmsMacroRel , 0 , 8 , " fms " , " Noise OR Mask " , 96 , ins - > std . fmsMacroOpen , true , NULL , false , NULL , 0 , 0 , 0 , NULL , uiColors [ GUI_COLOR_MACRO_OTHER ] , mmlString [ 9 ] , 0 , 8 , NULL ) ;
2022-01-31 22:45:02 +00:00
}
2022-01-23 22:01:19 +00:00
2022-01-23 22:55:02 +00:00
MACRO_END ;
2022-01-23 22:01:19 +00:00
} else { // classic view
// volume macro
2022-01-09 22:48:09 +00:00
ImGui : : Separator ( ) ;
2022-01-23 22:01:19 +00:00
if ( ins - > type = = DIV_INS_C64 & & ins - > c64 . volIsCutoff ) {
if ( ins - > c64 . filterIsAbs ) {
2022-01-23 22:02:09 +00:00
ImGui : : Text ( " Cutoff Macro " ) ;
2022-01-21 06:56:30 +00:00
} else {
2022-01-23 22:01:19 +00:00
ImGui : : Text ( " Relative Cutoff Macro " ) ;
2022-01-21 06:56:30 +00:00
}
} else {
2022-01-23 22:01:19 +00:00
ImGui : : Text ( " Volume Macro " ) ;
2022-01-21 06:56:30 +00:00
}
2022-01-23 22:01:19 +00:00
for ( int i = 0 ; i < ins - > std . volMacroLen ; i + + ) {
if ( ins - > type = = DIV_INS_C64 & & ins - > c64 . volIsCutoff & & ! ins - > c64 . filterIsAbs ) {
asFloat [ i ] = ins - > std . volMacro [ i ] - 18 ;
} else {
asFloat [ i ] = ins - > std . volMacro [ i ] ;
}
loopIndicator [ i ] = ( ins - > std . volMacroLoop ! = - 1 & & i > = ins - > std . volMacroLoop ) ;
}
ImGui : : PushStyleVar ( ImGuiStyleVar_FramePadding , ImVec2 ( 0.0f , 0.0f ) ) ;
macroDragScroll = 0 ;
ImGui : : PlotHistogram ( " ##IVolMacro " , asFloat , ins - > std . volMacroLen , 0 , NULL , volMin , volMax , ImVec2 ( 400.0f * dpiScale , 200.0f * dpiScale ) ) ;
2022-01-09 22:48:09 +00:00
if ( ImGui : : IsItemClicked ( ImGuiMouseButton_Left ) ) {
macroDragStart = ImGui : : GetItemRectMin ( ) ;
2022-01-23 22:01:19 +00:00
macroDragAreaSize = ImVec2 ( 400.0f * dpiScale , 200.0f * dpiScale ) ;
macroDragMin = volMin ;
macroDragMax = volMax ;
macroDragLen = ins - > std . volMacroLen ;
2022-01-09 22:48:09 +00:00
macroDragActive = true ;
2022-01-23 22:01:19 +00:00
macroDragTarget = ins - > std . volMacro ;
2022-01-21 07:54:52 +00:00
macroDragChar = false ;
2022-01-09 22:48:09 +00:00
processDrags ( ImGui : : GetMousePos ( ) . x , ImGui : : GetMousePos ( ) . y ) ;
}
2022-01-23 22:01:19 +00:00
ImGui : : PlotHistogram ( " ##IVolMacroLoop " , loopIndicator , ins - > std . volMacroLen , 0 , NULL , 0 , 1 , ImVec2 ( 400.0f * dpiScale , 16.0f * dpiScale ) ) ;
2022-01-09 22:48:09 +00:00
if ( ImGui : : IsItemClicked ( ImGuiMouseButton_Left ) ) {
macroLoopDragStart = ImGui : : GetItemRectMin ( ) ;
macroLoopDragAreaSize = ImVec2 ( 400.0f * dpiScale , 16.0f * dpiScale ) ;
2022-01-23 22:01:19 +00:00
macroLoopDragLen = ins - > std . volMacroLen ;
macroLoopDragTarget = & ins - > std . volMacroLoop ;
2022-01-09 22:48:09 +00:00
macroLoopDragActive = true ;
processDrags ( ImGui : : GetMousePos ( ) . x , ImGui : : GetMousePos ( ) . y ) ;
}
2022-01-23 20:56:03 +00:00
if ( ImGui : : IsItemClicked ( ImGuiMouseButton_Right ) ) {
2022-01-23 22:01:19 +00:00
ins - > std . volMacroLoop = - 1 ;
2022-01-23 20:56:03 +00:00
}
2022-01-09 22:48:09 +00:00
ImGui : : PopStyleVar ( ) ;
2022-01-23 22:01:19 +00:00
if ( ImGui : : InputScalar ( " Length##IVolMacroL " , ImGuiDataType_U8 , & ins - > std . volMacroLen , & _ONE , & _THREE ) ) {
if ( ins - > std . volMacroLen > 127 ) ins - > std . volMacroLen = 127 ;
2022-01-09 22:48:09 +00:00
}
2022-01-14 05:02:10 +00:00
2022-01-23 22:01:19 +00:00
// arp macro
2022-01-14 05:02:10 +00:00
ImGui : : Separator ( ) ;
2022-01-23 22:01:19 +00:00
ImGui : : Text ( " Arpeggio Macro " ) ;
for ( int i = 0 ; i < ins - > std . arpMacroLen ; i + + ) {
2022-01-26 20:53:52 +00:00
asFloat [ i ] = ins - > std . arpMacro [ i ] ;
2022-01-23 22:01:19 +00:00
loopIndicator [ i ] = ( ins - > std . arpMacroLoop ! = - 1 & & i > = ins - > std . arpMacroLoop ) ;
2022-01-14 05:02:10 +00:00
}
ImGui : : PushStyleVar ( ImGuiStyleVar_FramePadding , ImVec2 ( 0.0f , 0.0f ) ) ;
2022-01-23 22:01:19 +00:00
ImGui : : PlotHistogram ( " ##IArpMacro " , asFloat , ins - > std . arpMacroLen , 0 , NULL , arpMode ? arpMacroScroll : ( arpMacroScroll - 12 ) , arpMacroScroll + ( arpMode ? 24 : 12 ) , ImVec2 ( 400.0f * dpiScale , 200.0f * dpiScale ) ) ;
2022-01-14 05:02:10 +00:00
if ( ImGui : : IsItemClicked ( ImGuiMouseButton_Left ) ) {
macroDragStart = ImGui : : GetItemRectMin ( ) ;
macroDragAreaSize = ImVec2 ( 400.0f * dpiScale , 200.0f * dpiScale ) ;
2022-01-23 22:01:19 +00:00
macroDragMin = arpMacroScroll ;
macroDragMax = arpMacroScroll + 24 ;
macroDragLen = ins - > std . arpMacroLen ;
2022-01-14 05:02:10 +00:00
macroDragActive = true ;
2022-01-23 22:01:19 +00:00
macroDragTarget = ins - > std . arpMacro ;
2022-01-21 07:54:52 +00:00
macroDragChar = false ;
2022-01-14 05:02:10 +00:00
processDrags ( ImGui : : GetMousePos ( ) . x , ImGui : : GetMousePos ( ) . y ) ;
}
2022-01-23 22:01:19 +00:00
ImGui : : SameLine ( ) ;
ImGui : : VSliderInt ( " ##IArpMacroPos " , ImVec2 ( 20.0f * dpiScale , 200.0f * dpiScale ) , & arpMacroScroll , arpMode ? 0 : - 80 , 70 ) ;
ImGui : : PlotHistogram ( " ##IArpMacroLoop " , loopIndicator , ins - > std . arpMacroLen , 0 , NULL , 0 , 1 , ImVec2 ( 400.0f * dpiScale , 16.0f * dpiScale ) ) ;
2022-01-14 05:02:10 +00:00
if ( ImGui : : IsItemClicked ( ImGuiMouseButton_Left ) ) {
macroLoopDragStart = ImGui : : GetItemRectMin ( ) ;
macroLoopDragAreaSize = ImVec2 ( 400.0f * dpiScale , 16.0f * dpiScale ) ;
2022-01-23 22:01:19 +00:00
macroLoopDragLen = ins - > std . arpMacroLen ;
macroLoopDragTarget = & ins - > std . arpMacroLoop ;
2022-01-14 05:02:10 +00:00
macroLoopDragActive = true ;
processDrags ( ImGui : : GetMousePos ( ) . x , ImGui : : GetMousePos ( ) . y ) ;
}
2022-01-23 20:56:03 +00:00
if ( ImGui : : IsItemClicked ( ImGuiMouseButton_Right ) ) {
2022-01-23 22:01:19 +00:00
ins - > std . arpMacroLoop = - 1 ;
2022-01-23 20:56:03 +00:00
}
2022-01-14 05:02:10 +00:00
ImGui : : PopStyleVar ( ) ;
2022-01-23 22:01:19 +00:00
if ( ImGui : : InputScalar ( " Length##IArpMacroL " , ImGuiDataType_U8 , & ins - > std . arpMacroLen , & _ONE , & _THREE ) ) {
if ( ins - > std . arpMacroLen > 127 ) ins - > std . arpMacroLen = 127 ;
}
2022-01-23 22:02:24 +00:00
if ( ImGui : : Checkbox ( " Fixed " , & arpMode ) ) {
2022-01-23 22:01:19 +00:00
ins - > std . arpMacroMode = arpMode ;
if ( arpMode ) {
if ( arpMacroScroll < 0 ) arpMacroScroll = 0 ;
}
}
// duty macro
if ( dutyMax > 0 ) {
ImGui : : Separator ( ) ;
if ( ins - > type = = DIV_INS_C64 ) {
if ( ins - > c64 . dutyIsAbs ) {
2022-01-23 22:02:09 +00:00
ImGui : : Text ( " Duty Macro " ) ;
2022-01-23 22:01:19 +00:00
} else {
ImGui : : Text ( " Relative Duty Macro " ) ;
}
} else {
if ( ins - > type = = DIV_INS_AY | | ins - > type = = DIV_INS_AY8930 | | ins - > type = = DIV_INS_SAA1099 ) {
ImGui : : Text ( " Noise Frequency Macro " ) ;
} else {
ImGui : : Text ( " Duty/Noise Mode Macro " ) ;
}
}
for ( int i = 0 ; i < ins - > std . dutyMacroLen ; i + + ) {
asFloat [ i ] = ins - > std . dutyMacro [ i ] - ( dutyIsRel ? 12 : 0 ) ;
loopIndicator [ i ] = ( ins - > std . dutyMacroLoop ! = - 1 & & i > = ins - > std . dutyMacroLoop ) ;
}
ImGui : : PushStyleVar ( ImGuiStyleVar_FramePadding , ImVec2 ( 0.0f , 0.0f ) ) ;
ImGui : : PlotHistogram ( " ##IDutyMacro " , asFloat , ins - > std . dutyMacroLen , 0 , NULL , dutyIsRel ? - 12 : 0 , dutyMax - ( dutyIsRel ? 12 : 0 ) , ImVec2 ( 400.0f * dpiScale , 200.0f * dpiScale ) ) ;
if ( ImGui : : IsItemClicked ( ImGuiMouseButton_Left ) ) {
macroDragStart = ImGui : : GetItemRectMin ( ) ;
macroDragAreaSize = ImVec2 ( 400.0f * dpiScale , 200.0f * dpiScale ) ;
macroDragMin = 0 ;
macroDragMax = dutyMax ;
macroDragLen = ins - > std . dutyMacroLen ;
macroDragActive = true ;
macroDragTarget = ins - > std . dutyMacro ;
macroDragChar = false ;
processDrags ( ImGui : : GetMousePos ( ) . x , ImGui : : GetMousePos ( ) . y ) ;
}
ImGui : : PlotHistogram ( " ##IDutyMacroLoop " , loopIndicator , ins - > std . dutyMacroLen , 0 , NULL , 0 , 1 , ImVec2 ( 400.0f * dpiScale , 16.0f * dpiScale ) ) ;
if ( ImGui : : IsItemClicked ( ImGuiMouseButton_Left ) ) {
macroLoopDragStart = ImGui : : GetItemRectMin ( ) ;
macroLoopDragAreaSize = ImVec2 ( 400.0f * dpiScale , 16.0f * dpiScale ) ;
macroLoopDragLen = ins - > std . dutyMacroLen ;
macroLoopDragTarget = & ins - > std . dutyMacroLoop ;
macroLoopDragActive = true ;
processDrags ( ImGui : : GetMousePos ( ) . x , ImGui : : GetMousePos ( ) . y ) ;
}
if ( ImGui : : IsItemClicked ( ImGuiMouseButton_Right ) ) {
ins - > std . dutyMacroLoop = - 1 ;
}
ImGui : : PopStyleVar ( ) ;
if ( ImGui : : InputScalar ( " Length##IDutyMacroL " , ImGuiDataType_U8 , & ins - > std . dutyMacroLen , & _ONE , & _THREE ) ) {
if ( ins - > std . dutyMacroLen > 127 ) ins - > std . dutyMacroLen = 127 ;
}
2022-01-14 05:02:10 +00:00
}
2022-01-23 22:01:19 +00:00
// wave macro
if ( waveMax > 0 ) {
ImGui : : Separator ( ) ;
ImGui : : Text ( " Waveform Macro " ) ;
for ( int i = 0 ; i < ins - > std . waveMacroLen ; i + + ) {
asFloat [ i ] = ins - > std . waveMacro [ i ] ;
if ( ins - > type = = DIV_INS_AY | | ins - > type = = DIV_INS_AY8930 ) {
asInt [ i ] = ins - > std . waveMacro [ i ] + 1 ;
} else {
asInt [ i ] = ins - > std . waveMacro [ i ] ;
}
loopIndicator [ i ] = ( ins - > std . waveMacroLoop ! = - 1 & & i > = ins - > std . waveMacroLoop ) ;
}
ImGui : : PushStyleVar ( ImGuiStyleVar_FramePadding , ImVec2 ( 0.0f , 0.0f ) ) ;
ImVec2 areaSize = ImVec2 ( 400.0f * dpiScale , 200.0f * dpiScale ) ;
if ( ins - > type = = DIV_INS_C64 | | ins - > type = = DIV_INS_AY | | ins - > type = = DIV_INS_AY8930 | | ins - > type = = DIV_INS_SAA1099 ) {
areaSize = ImVec2 ( 400.0f * dpiScale , waveMax * 32.0f * dpiScale ) ;
PlotBitfield ( " ##IWaveMacro " , asInt , ins - > std . waveMacroLen , 0 , ( ins - > type = = DIV_INS_C64 ) ? c64ShapeBits : ayShapeBits , waveMax , areaSize ) ;
bitMode = true ;
} else {
ImGui : : PlotHistogram ( " ##IWaveMacro " , asFloat , ins - > std . waveMacroLen , 0 , NULL , 0 , waveMax , areaSize ) ;
}
if ( ImGui : : IsItemClicked ( ImGuiMouseButton_Left ) ) {
macroDragStart = ImGui : : GetItemRectMin ( ) ;
macroDragAreaSize = areaSize ;
macroDragMin = 0 ;
macroDragMax = waveMax ;
macroDragBitOff = ( ins - > type = = DIV_INS_AY | | ins - > type = = DIV_INS_AY8930 ) ? 1 : 0 ;
macroDragBitMode = bitMode ;
macroDragInitialValueSet = false ;
macroDragInitialValue = false ;
macroDragLen = ins - > std . waveMacroLen ;
macroDragActive = true ;
macroDragTarget = ins - > std . waveMacro ;
macroDragChar = false ;
processDrags ( ImGui : : GetMousePos ( ) . x , ImGui : : GetMousePos ( ) . y ) ;
}
ImGui : : PlotHistogram ( " ##IWaveMacroLoop " , loopIndicator , ins - > std . waveMacroLen , 0 , NULL , 0 , 1 , ImVec2 ( 400.0f * dpiScale , 16.0f * dpiScale ) ) ;
if ( ImGui : : IsItemClicked ( ImGuiMouseButton_Left ) ) {
macroLoopDragStart = ImGui : : GetItemRectMin ( ) ;
macroLoopDragAreaSize = ImVec2 ( 400.0f * dpiScale , 16.0f * dpiScale ) ;
macroLoopDragLen = ins - > std . waveMacroLen ;
macroLoopDragTarget = & ins - > std . waveMacroLoop ;
macroLoopDragActive = true ;
processDrags ( ImGui : : GetMousePos ( ) . x , ImGui : : GetMousePos ( ) . y ) ;
}
if ( ImGui : : IsItemClicked ( ImGuiMouseButton_Right ) ) {
ins - > std . waveMacroLoop = - 1 ;
}
ImGui : : PopStyleVar ( ) ;
if ( ImGui : : InputScalar ( " Length##IWaveMacroL " , ImGuiDataType_U8 , & ins - > std . waveMacroLen , & _ONE , & _THREE ) ) {
if ( ins - > std . waveMacroLen > 127 ) ins - > std . waveMacroLen = 127 ;
}
}
// extra 1 macro
if ( ex1Max > 0 ) {
ImGui : : Separator ( ) ;
if ( ins - > type = = DIV_INS_AY8930 ) {
ImGui : : Text ( " Duty Macro " ) ;
} else {
ImGui : : Text ( " Extra 1 Macro " ) ;
}
for ( int i = 0 ; i < ins - > std . ex1MacroLen ; i + + ) {
asFloat [ i ] = ins - > std . ex1Macro [ i ] ;
loopIndicator [ i ] = ( ins - > std . ex1MacroLoop ! = - 1 & & i > = ins - > std . ex1MacroLoop ) ;
}
ImGui : : PushStyleVar ( ImGuiStyleVar_FramePadding , ImVec2 ( 0.0f , 0.0f ) ) ;
ImGui : : PlotHistogram ( " ##IEx1Macro " , asFloat , ins - > std . ex1MacroLen , 0 , NULL , 0 , ex1Max , ImVec2 ( 400.0f * dpiScale , 200.0f * dpiScale ) ) ;
if ( ImGui : : IsItemClicked ( ImGuiMouseButton_Left ) ) {
macroDragStart = ImGui : : GetItemRectMin ( ) ;
macroDragAreaSize = ImVec2 ( 400.0f * dpiScale , 200.0f * dpiScale ) ;
macroDragMin = 0 ;
macroDragMax = ex1Max ;
macroDragLen = ins - > std . ex1MacroLen ;
macroDragActive = true ;
macroDragTarget = ins - > std . ex1Macro ;
macroDragChar = false ;
processDrags ( ImGui : : GetMousePos ( ) . x , ImGui : : GetMousePos ( ) . y ) ;
}
ImGui : : PlotHistogram ( " ##IEx1MacroLoop " , loopIndicator , ins - > std . ex1MacroLen , 0 , NULL , 0 , 1 , ImVec2 ( 400.0f * dpiScale , 16.0f * dpiScale ) ) ;
if ( ImGui : : IsItemClicked ( ImGuiMouseButton_Left ) ) {
macroLoopDragStart = ImGui : : GetItemRectMin ( ) ;
macroLoopDragAreaSize = ImVec2 ( 400.0f * dpiScale , 16.0f * dpiScale ) ;
macroLoopDragLen = ins - > std . ex1MacroLen ;
macroLoopDragTarget = & ins - > std . ex1MacroLoop ;
macroLoopDragActive = true ;
processDrags ( ImGui : : GetMousePos ( ) . x , ImGui : : GetMousePos ( ) . y ) ;
}
if ( ImGui : : IsItemClicked ( ImGuiMouseButton_Right ) ) {
ins - > std . ex1MacroLoop = - 1 ;
}
ImGui : : PopStyleVar ( ) ;
if ( ImGui : : InputScalar ( " Length##IEx1MacroL " , ImGuiDataType_U8 , & ins - > std . ex1MacroLen , & _ONE , & _THREE ) ) {
if ( ins - > std . ex1MacroLen > 127 ) ins - > std . ex1MacroLen = 127 ;
}
}
}
2022-01-09 22:48:09 +00:00
ImGui : : EndTabItem ( ) ;
}
ImGui : : EndTabBar ( ) ;
}
2021-12-11 22:41:32 +00:00
}
2021-12-14 09:45:44 +00:00
}
2022-02-04 07:56:35 +00:00
if ( ImGui : : IsWindowFocused ( ImGuiFocusedFlags_ChildWindows ) ) curWindow = GUI_WINDOW_INS_EDIT ;
2021-12-14 09:45:44 +00:00
ImGui : : End ( ) ;
}
2022-01-18 04:59:52 +00:00
# undef P
# undef PARAMETER
2021-12-16 08:09:18 +00:00
void FurnaceGUI : : drawWaveList ( ) {
if ( ! waveListOpen ) return ;
float wavePreview [ 256 ] ;
if ( ImGui : : Begin ( " Wavetables " , & waveListOpen ) ) {
2021-12-21 05:30:55 +00:00
if ( ImGui : : Button ( ICON_FA_PLUS " ##WaveAdd " ) ) {
2021-12-17 08:33:12 +00:00
curWave = e - > addWave ( ) ;
2021-12-30 23:25:55 +00:00
modified = true ;
2021-12-17 08:33:12 +00:00
}
ImGui : : SameLine ( ) ;
2022-01-19 07:59:44 +00:00
if ( ImGui : : Button ( ICON_FA_FILES_O " ##WaveClone " ) ) {
if ( curWave > = 0 & & curWave < ( int ) e - > song . wave . size ( ) ) {
int prevWave = curWave ;
curWave = e - > addWave ( ) ;
( * e - > song . wave [ curWave ] ) = ( * e - > song . wave [ prevWave ] ) ;
modified = true ;
}
}
ImGui : : SameLine ( ) ;
2022-01-19 08:15:20 +00:00
if ( ImGui : : Button ( ICON_FA_FOLDER_OPEN " ##WaveLoad " ) ) {
openFileDialog ( GUI_FILE_WAVE_OPEN ) ;
}
ImGui : : SameLine ( ) ;
if ( ImGui : : Button ( ICON_FA_FLOPPY_O " ##WaveSave " ) ) {
if ( curWave > = 0 & & curWave < ( int ) e - > song . wave . size ( ) ) openFileDialog ( GUI_FILE_WAVE_SAVE ) ;
}
ImGui : : SameLine ( ) ;
2021-12-17 08:33:12 +00:00
if ( ImGui : : ArrowButton ( " WaveUp " , ImGuiDir_Up ) ) {
2022-01-11 08:52:11 +00:00
if ( e - > moveWaveUp ( curWave ) ) curWave - - ;
2021-12-17 08:33:12 +00:00
}
ImGui : : SameLine ( ) ;
if ( ImGui : : ArrowButton ( " WaveDown " , ImGuiDir_Down ) ) {
2022-01-11 08:52:11 +00:00
if ( e - > moveWaveDown ( curWave ) ) curWave + + ;
2021-12-17 08:33:12 +00:00
}
ImGui : : SameLine ( ) ;
2021-12-21 05:30:55 +00:00
if ( ImGui : : Button ( ICON_FA_TIMES " ##WaveDelete " ) ) {
2022-01-19 07:59:44 +00:00
if ( curWave > = 0 & & curWave < ( int ) e - > song . wave . size ( ) ) {
e - > delWave ( curWave ) ;
modified = true ;
if ( curWave > = ( int ) e - > song . wave . size ( ) ) {
curWave - - ;
}
2021-12-17 08:33:12 +00:00
}
}
ImGui : : Separator ( ) ;
2022-02-04 05:11:16 +00:00
if ( ImGui : : BeginTable ( " WaveListScroll " , 1 , ImGuiTableFlags_ScrollY ) ) {
for ( int i = 0 ; i < ( int ) e - > song . wave . size ( ) ; i + + ) {
DivWavetable * wave = e - > song . wave [ i ] ;
for ( int i = 0 ; i < wave - > len ; i + + ) {
wavePreview [ i ] = wave - > data [ i ] ;
}
if ( wave - > len > 0 ) wavePreview [ wave - > len ] = wave - > data [ wave - > len - 1 ] ;
ImGui : : TableNextRow ( ) ;
ImGui : : TableNextColumn ( ) ;
if ( ImGui : : Selectable ( fmt : : sprintf ( " %d##_WAVE%d \n " , i , i ) . c_str ( ) , curWave = = i ) ) {
curWave = i ;
2021-12-16 08:09:18 +00:00
}
2022-02-04 05:11:16 +00:00
if ( ImGui : : IsItemHovered ( ) ) {
if ( ImGui : : IsMouseDoubleClicked ( ImGuiMouseButton_Left ) ) {
waveEditOpen = true ;
}
}
ImGui : : SameLine ( ) ;
PlotNoLerp ( fmt : : sprintf ( " ##_WAVEP%d " , i ) . c_str ( ) , wavePreview , wave - > len + 1 , 0 , NULL , 0 , wave - > max ) ;
2021-12-16 08:09:18 +00:00
}
2022-02-04 05:11:16 +00:00
ImGui : : EndTable ( ) ;
2021-12-16 08:09:18 +00:00
}
}
2022-02-04 07:56:35 +00:00
if ( ImGui : : IsWindowFocused ( ImGuiFocusedFlags_ChildWindows ) ) curWindow = GUI_WINDOW_WAVE_LIST ;
2021-12-16 08:09:18 +00:00
ImGui : : End ( ) ;
}
void FurnaceGUI : : drawWaveEdit ( ) {
if ( ! waveEditOpen ) return ;
2021-12-18 22:54:26 +00:00
float wavePreview [ 256 ] ;
2022-01-21 07:06:49 +00:00
ImGui : : SetNextWindowSizeConstraints ( ImVec2 ( 450.0f * dpiScale , 300.0f * dpiScale ) , ImVec2 ( scrW * dpiScale , scrH * dpiScale ) ) ;
2022-01-28 06:26:26 +00:00
if ( ImGui : : Begin ( " Wavetable Editor " , & waveEditOpen , settings . allowEditDocking ? 0 : ImGuiWindowFlags_NoDocking ) ) {
2021-12-18 22:54:26 +00:00
if ( curWave < 0 | | curWave > = ( int ) e - > song . wave . size ( ) ) {
ImGui : : Text ( " no wavetable selected " ) ;
} else {
DivWavetable * wave = e - > song . wave [ curWave ] ;
2022-01-11 08:16:32 +00:00
ImGui : : Text ( " Width " ) ;
if ( ImGui : : IsItemHovered ( ) ) {
ImGui : : SetTooltip ( " use a width of 32 on Game Boy and PC Engine. \n any other widths will be scaled during playback. " ) ;
}
ImGui : : SameLine ( ) ;
ImGui : : SetNextItemWidth ( 128.0f * dpiScale ) ;
if ( ImGui : : InputInt ( " ##_WTW " , & wave - > len , 1 , 2 ) ) {
if ( wave - > len > 256 ) wave - > len = 256 ;
if ( wave - > len < 1 ) wave - > len = 1 ;
2022-01-18 05:25:10 +00:00
e - > notifyWaveChange ( curWave ) ;
2022-01-20 05:07:53 +00:00
if ( wavePreviewOn ) e - > previewWave ( curWave , wavePreviewNote ) ;
2022-01-18 05:25:10 +00:00
modified = true ;
2022-01-11 08:16:32 +00:00
}
ImGui : : SameLine ( ) ;
ImGui : : Text ( " Height " ) ;
if ( ImGui : : IsItemHovered ( ) ) {
ImGui : : SetTooltip ( " use a height of: \n - 15 for Game Boy \n - 31 for PC Engine \n any other heights will be scaled during playback. " ) ;
}
ImGui : : SameLine ( ) ;
ImGui : : SetNextItemWidth ( 128.0f * dpiScale ) ;
if ( ImGui : : InputInt ( " ##_WTH " , & wave - > max , 1 , 2 ) ) {
if ( wave - > max > 255 ) wave - > max = 255 ;
if ( wave - > max < 1 ) wave - > max = 1 ;
2022-01-18 05:25:10 +00:00
e - > notifyWaveChange ( curWave ) ;
modified = true ;
2022-01-11 08:16:32 +00:00
}
2021-12-18 22:54:26 +00:00
for ( int i = 0 ; i < wave - > len ; i + + ) {
wavePreview [ i ] = wave - > data [ i ] ;
}
if ( wave - > len > 0 ) wavePreview [ wave - > len ] = wave - > data [ wave - > len - 1 ] ;
2022-01-26 21:29:49 +00:00
if ( ImGui : : InputText ( " ##MMLWave " , & mmlStringW ) ) {
decodeMMLStrW ( mmlStringW , wave - > data , wave - > len , wave - > max ) ;
}
if ( ! ImGui : : IsItemActive ( ) ) {
2022-02-08 08:50:42 +00:00
encodeMMLStr ( mmlStringW , wave - > data , wave - > len , - 1 , - 1 ) ;
2022-01-26 21:29:49 +00:00
}
2021-12-18 22:54:26 +00:00
ImGui : : PushStyleVar ( ImGuiStyleVar_FramePadding , ImVec2 ( 0.0f , 0.0f ) ) ;
ImVec2 contentRegion = ImGui : : GetContentRegionAvail ( ) ;
2022-01-09 22:48:09 +00:00
PlotNoLerp ( " ##Waveform " , wavePreview , wave - > len + 1 , 0 , NULL , 0 , wave - > max , contentRegion ) ;
2021-12-18 22:54:26 +00:00
if ( ImGui : : IsItemClicked ( ImGuiMouseButton_Left ) ) {
waveDragStart = ImGui : : GetItemRectMin ( ) ;
waveDragAreaSize = contentRegion ;
waveDragMin = 0 ;
2022-01-09 22:48:09 +00:00
waveDragMax = wave - > max ;
2021-12-18 22:54:26 +00:00
waveDragLen = wave - > len ;
waveDragActive = true ;
waveDragTarget = wave - > data ;
2021-12-24 03:58:43 +00:00
processDrags ( ImGui : : GetMousePos ( ) . x , ImGui : : GetMousePos ( ) . y ) ;
2022-01-18 05:25:10 +00:00
e - > notifyWaveChange ( curWave ) ;
modified = true ;
2021-12-18 22:54:26 +00:00
}
ImGui : : PopStyleVar ( ) ;
}
2021-12-16 08:09:18 +00:00
}
2022-02-04 07:56:35 +00:00
if ( ImGui : : IsWindowFocused ( ImGuiFocusedFlags_ChildWindows ) ) curWindow = GUI_WINDOW_WAVE_EDIT ;
2021-12-16 08:09:18 +00:00
ImGui : : End ( ) ;
}
2021-12-24 03:58:43 +00:00
const char * sampleNote [ 12 ] = {
" C " , " C# " , " D " , " D# " , " E " , " F " , " F# " , " G " , " G# " , " A " , " A# " , " B "
} ;
2021-12-16 08:09:18 +00:00
void FurnaceGUI : : drawSampleList ( ) {
if ( ! sampleListOpen ) return ;
if ( ImGui : : Begin ( " Samples " , & sampleListOpen ) ) {
2021-12-21 05:30:55 +00:00
if ( ImGui : : Button ( ICON_FA_PLUS " ##SampleAdd " ) ) {
2021-12-17 08:33:12 +00:00
curSample = e - > addSample ( ) ;
2021-12-30 23:25:55 +00:00
modified = true ;
2021-12-17 08:33:12 +00:00
}
ImGui : : SameLine ( ) ;
2021-12-21 05:30:55 +00:00
if ( ImGui : : Button ( ICON_FA_FOLDER_OPEN " ##SampleLoad " ) ) {
2021-12-17 08:33:12 +00:00
openFileDialog ( GUI_FILE_SAMPLE_OPEN ) ;
}
ImGui : : SameLine ( ) ;
2021-12-21 05:30:55 +00:00
if ( ImGui : : Button ( ICON_FA_FLOPPY_O " ##SampleSave " ) ) {
2021-12-18 06:03:59 +00:00
if ( curSample > = 0 & & curSample < ( int ) e - > song . sample . size ( ) ) openFileDialog ( GUI_FILE_SAMPLE_SAVE ) ;
2021-12-17 08:33:12 +00:00
}
ImGui : : SameLine ( ) ;
if ( ImGui : : ArrowButton ( " SampleUp " , ImGuiDir_Up ) ) {
2022-01-11 08:52:11 +00:00
if ( e - > moveSampleUp ( curSample ) ) curSample - - ;
2021-12-17 08:33:12 +00:00
}
ImGui : : SameLine ( ) ;
if ( ImGui : : ArrowButton ( " SampleDown " , ImGuiDir_Down ) ) {
2022-01-11 08:52:11 +00:00
if ( e - > moveSampleDown ( curSample ) ) curSample + + ;
2021-12-17 08:33:12 +00:00
}
ImGui : : SameLine ( ) ;
2021-12-21 05:30:55 +00:00
if ( ImGui : : Button ( ICON_FA_TIMES " ##SampleDelete " ) ) {
2021-12-17 08:33:12 +00:00
e - > delSample ( curSample ) ;
2021-12-30 23:25:55 +00:00
modified = true ;
2021-12-17 08:33:12 +00:00
if ( curSample > = ( int ) e - > song . sample . size ( ) ) {
curSample - - ;
}
}
2021-12-29 04:10:30 +00:00
ImGui : : SameLine ( ) ;
if ( ImGui : : Button ( ICON_FA_VOLUME_UP " ##PreviewSampleL " ) ) {
e - > previewSample ( curSample ) ;
}
2022-02-03 21:52:27 +00:00
ImGui : : SameLine ( ) ;
if ( ImGui : : Button ( ICON_FA_VOLUME_OFF " ##StopSampleL " ) ) {
e - > stopSamplePreview ( ) ;
}
2021-12-17 08:33:12 +00:00
ImGui : : Separator ( ) ;
2022-02-04 05:11:16 +00:00
if ( ImGui : : BeginTable ( " SampleListScroll " , 1 , ImGuiTableFlags_ScrollY ) ) {
for ( int i = 0 ; i < ( int ) e - > song . sample . size ( ) ; i + + ) {
DivSample * sample = e - > song . sample [ i ] ;
ImGui : : TableNextRow ( ) ;
ImGui : : TableNextColumn ( ) ;
if ( ( i % 12 ) = = 0 ) {
if ( i > 0 ) ImGui : : Unindent ( ) ;
ImGui : : Text ( " Bank %d " , i / 12 ) ;
ImGui : : Indent ( ) ;
}
if ( ImGui : : Selectable ( fmt : : sprintf ( " %s: %s##_SAM%d " , sampleNote [ i % 12 ] , sample - > name , i ) . c_str ( ) , curSample = = i ) ) {
curSample = i ;
}
if ( ImGui : : IsItemHovered ( ) ) {
if ( ImGui : : IsMouseDoubleClicked ( ImGuiMouseButton_Left ) ) {
sampleEditOpen = true ;
}
2021-12-16 08:09:18 +00:00
}
}
2022-02-04 05:11:16 +00:00
ImGui : : EndTable ( ) ;
2021-12-16 08:09:18 +00:00
}
2021-12-24 03:58:43 +00:00
ImGui : : Unindent ( ) ;
2021-12-16 08:09:18 +00:00
}
2022-02-04 07:56:35 +00:00
if ( ImGui : : IsWindowFocused ( ImGuiFocusedFlags_ChildWindows ) ) curWindow = GUI_WINDOW_SAMPLE_LIST ;
2021-12-16 08:09:18 +00:00
ImGui : : End ( ) ;
}
void FurnaceGUI : : drawSampleEdit ( ) {
if ( ! sampleEditOpen ) return ;
2022-01-28 06:26:26 +00:00
if ( ImGui : : Begin ( " Sample Editor " , & sampleEditOpen , settings . allowEditDocking ? 0 : ImGuiWindowFlags_NoDocking ) ) {
2021-12-17 08:33:12 +00:00
if ( curSample < 0 | | curSample > = ( int ) e - > song . sample . size ( ) ) {
ImGui : : Text ( " no sample selected " ) ;
} else {
DivSample * sample = e - > song . sample [ curSample ] ;
ImGui : : InputText ( " Name " , & sample - > name ) ;
2022-01-16 02:57:56 +00:00
ImGui : : Text ( " Length: %d " , sample - > length ) ;
2022-01-27 21:52:06 +00:00
if ( ImGui : : InputInt ( " Rate (Hz) " , & sample - > rate , 10 , 200 ) ) {
if ( sample - > rate < 100 ) sample - > rate = 100 ;
2021-12-23 23:04:44 +00:00
if ( sample - > rate > 32000 ) sample - > rate = 32000 ;
2021-12-17 08:33:12 +00:00
}
2022-01-27 21:52:06 +00:00
if ( ImGui : : InputInt ( " Pitch of C-4 (Hz) " , & sample - > centerRate , 10 , 200 ) ) {
if ( sample - > centerRate < 100 ) sample - > centerRate = 100 ;
if ( sample - > centerRate > 32000 ) sample - > centerRate = 32000 ;
}
2021-12-23 23:04:44 +00:00
ImGui : : Text ( " effective rate: %dHz " , e - > getEffectiveSampleRate ( sample - > rate ) ) ;
2022-01-15 23:03:37 +00:00
bool doLoop = ( sample - > loopStart > = 0 ) ;
if ( ImGui : : Checkbox ( " Loop " , & doLoop ) ) {
if ( doLoop ) {
sample - > loopStart = 0 ;
} else {
sample - > loopStart = - 1 ;
}
}
2022-01-16 02:57:56 +00:00
if ( doLoop ) {
ImGui : : SameLine ( ) ;
2022-02-02 09:33:53 +00:00
if ( ImGui : : InputInt ( " ##LoopPosition " , & sample - > loopStart , 1 , 10 ) ) {
2022-01-16 02:57:56 +00:00
if ( sample - > loopStart < 0 | | sample - > loopStart > = sample - > length ) {
sample - > loopStart = 0 ;
}
2022-01-15 23:03:37 +00:00
}
}
2021-12-17 08:33:12 +00:00
if ( ImGui : : SliderScalar ( " Volume " , ImGuiDataType_S8 , & sample - > vol , & _ZERO , & _ONE_HUNDRED , fmt : : sprintf ( " %d%%%% " , sample - > vol * 2 ) . c_str ( ) ) ) {
if ( sample - > vol < 0 ) sample - > vol = 0 ;
if ( sample - > vol > 100 ) sample - > vol = 100 ;
}
if ( ImGui : : SliderScalar ( " Pitch " , ImGuiDataType_S8 , & sample - > pitch , & _ZERO , & _TEN , pitchLabel [ sample - > pitch ] ) ) {
if ( sample - > pitch < 0 ) sample - > pitch = 0 ;
if ( sample - > pitch > 10 ) sample - > pitch = 10 ;
}
if ( ImGui : : Button ( " Apply " ) ) {
e - > renderSamplesP ( ) ;
}
2021-12-21 18:06:14 +00:00
ImGui : : SameLine ( ) ;
2021-12-29 04:10:30 +00:00
if ( ImGui : : Button ( ICON_FA_VOLUME_UP " ##PreviewSample " ) ) {
2021-12-21 18:06:14 +00:00
e - > previewSample ( curSample ) ;
}
2022-02-03 21:52:27 +00:00
ImGui : : SameLine ( ) ;
if ( ImGui : : Button ( ICON_FA_VOLUME_OFF " ##StopSample " ) ) {
e - > stopSamplePreview ( ) ;
}
2022-01-16 02:57:56 +00:00
ImGui : : Separator ( ) ;
bool considerations = false ;
ImGui : : Text ( " notes: " ) ;
if ( sample - > loopStart > = 0 ) {
considerations = true ;
ImGui : : Text ( " - sample won't loop on Neo Geo ADPCM " ) ;
if ( sample - > loopStart & 1 ) {
ImGui : : Text ( " - sample loop start will be aligned to the nearest even sample on Amiga " ) ;
}
}
if ( sample - > length & 1 ) {
considerations = true ;
ImGui : : Text ( " - sample length will be aligned to the nearest even sample on Amiga " ) ;
}
if ( sample - > length > 65535 ) {
considerations = true ;
ImGui : : Text ( " - maximum sample length on Sega PCM is 65536 samples " ) ;
}
if ( sample - > length > 2097151 ) {
considerations = true ;
ImGui : : Text ( " - maximum sample length on Neo Geo ADPCM is 2097152 samples " ) ;
}
if ( ! considerations ) {
ImGui : : Text ( " - none " ) ;
}
2021-12-17 08:33:12 +00:00
}
2021-12-16 08:09:18 +00:00
}
2022-02-04 07:56:35 +00:00
if ( ImGui : : IsWindowFocused ( ImGuiFocusedFlags_ChildWindows ) ) curWindow = GUI_WINDOW_SAMPLE_EDIT ;
2021-12-16 08:09:18 +00:00
ImGui : : End ( ) ;
}
2022-01-13 06:03:57 +00:00
void FurnaceGUI : : drawMixer ( ) {
if ( ! mixerOpen ) return ;
2022-01-27 22:24:47 +00:00
ImGui : : SetNextWindowSizeConstraints ( ImVec2 ( 400.0f * dpiScale , 200.0f * dpiScale ) , ImVec2 ( scrW * dpiScale , scrH * dpiScale ) ) ;
2022-01-28 06:26:26 +00:00
if ( ImGui : : Begin ( " Mixer " , & mixerOpen , settings . allowEditDocking ? 0 : ImGuiWindowFlags_NoDocking ) ) {
2022-01-13 06:03:57 +00:00
char id [ 32 ] ;
for ( int i = 0 ; i < e - > song . systemLen ; i + + ) {
snprintf ( id , 31 , " MixS%d " , i ) ;
bool doInvert = e - > song . systemVol [ i ] & 128 ;
signed char vol = e - > song . systemVol [ i ] & 127 ;
ImGui : : PushID ( id ) ;
2022-01-28 08:17:35 +00:00
ImGui : : Text ( " %d. %s " , i + 1 , getSystemName ( e - > song . system [ i ] ) ) ;
2022-01-27 22:24:47 +00:00
if ( ImGui : : SliderScalar ( " Volume " , ImGuiDataType_S8 , & vol , & _ZERO , & _ONE_HUNDRED_TWENTY_SEVEN ) ) {
2022-01-13 06:03:57 +00:00
e - > song . systemVol [ i ] = ( e - > song . systemVol [ i ] & 128 ) | vol ;
}
2022-01-27 22:24:47 +00:00
ImGui : : SliderScalar ( " Panning " , ImGuiDataType_S8 , & e - > song . systemPan [ i ] , & _MINUS_ONE_HUNDRED_TWENTY_SEVEN , & _ONE_HUNDRED_TWENTY_SEVEN ) ;
2022-01-13 06:03:57 +00:00
if ( ImGui : : Checkbox ( " Invert " , & doInvert ) ) {
e - > song . systemVol [ i ] ^ = 128 ;
}
ImGui : : PopID ( ) ;
}
}
ImGui : : End ( ) ;
}
2022-01-27 22:49:00 +00:00
void FurnaceGUI : : drawOsc ( ) {
if ( ! oscOpen ) return ;
ImGui : : SetNextWindowSizeConstraints ( ImVec2 ( 64.0f * dpiScale , 32.0f * dpiScale ) , ImVec2 ( scrW * dpiScale , scrH * dpiScale ) ) ;
2022-01-28 05:55:51 +00:00
ImGui : : PushStyleVar ( ImGuiStyleVar_WindowPadding , ImVec2 ( 0 , 0 ) ) ;
ImGui : : PushStyleVar ( ImGuiStyleVar_FramePadding , ImVec2 ( 0 , 0 ) ) ;
ImGui : : PushStyleVar ( ImGuiStyleVar_ItemSpacing , ImVec2 ( 0 , 0 ) ) ;
ImGui : : PushStyleVar ( ImGuiStyleVar_ItemInnerSpacing , ImVec2 ( 0 , 0 ) ) ;
2022-01-27 22:49:00 +00:00
if ( ImGui : : Begin ( " Oscilloscope " , & oscOpen ) ) {
float values [ 512 ] ;
for ( int i = 0 ; i < 512 ; i + + ) {
int pos = i * e - > oscSize / 512 ;
values [ i ] = ( e - > oscBuf [ 0 ] [ pos ] + e - > oscBuf [ 1 ] [ pos ] ) * 0.5f ;
}
2022-01-28 05:55:51 +00:00
//ImGui::SetCursorPos(ImVec2(0,0));
2022-01-28 08:08:55 +00:00
ImGui : : BeginDisabled ( ) ;
2022-01-27 22:49:00 +00:00
ImGui : : PlotLines ( " ##SingleOsc " , values , 512 , 0 , NULL , - 1.0f , 1.0f , ImGui : : GetContentRegionAvail ( ) ) ;
2022-01-28 08:08:55 +00:00
ImGui : : EndDisabled ( ) ;
2022-01-27 22:49:00 +00:00
}
2022-01-28 05:55:51 +00:00
ImGui : : PopStyleVar ( 4 ) ;
2022-01-27 22:49:00 +00:00
ImGui : : End ( ) ;
}
2022-01-29 23:56:08 +00:00
void FurnaceGUI : : drawVolMeter ( ) {
if ( ! volMeterOpen ) return ;
if ( - - isClipping < 0 ) isClipping = 0 ;
ImGui : : SetNextWindowSizeConstraints ( ImVec2 ( 6.0f * dpiScale , 6.0f * dpiScale ) , ImVec2 ( scrW * dpiScale , scrH * dpiScale ) ) ;
ImGui : : PushStyleVar ( ImGuiStyleVar_WindowPadding , ImVec2 ( 0 , 0 ) ) ;
ImGui : : PushStyleVar ( ImGuiStyleVar_FramePadding , ImVec2 ( 0 , 0 ) ) ;
ImGui : : PushStyleVar ( ImGuiStyleVar_ItemSpacing , ImVec2 ( 0 , 0 ) ) ;
ImGui : : PushStyleVar ( ImGuiStyleVar_ItemInnerSpacing , ImVec2 ( 0 , 0 ) ) ;
if ( ImGui : : Begin ( " Volume Meter " , & volMeterOpen ) ) {
ImDrawList * dl = ImGui : : GetWindowDrawList ( ) ;
bool aspectRatio = ( ImGui : : GetWindowSize ( ) . x / ImGui : : GetWindowSize ( ) . y ) > 1.0 ;
ImVec2 minArea = ImVec2 (
ImGui : : GetWindowPos ( ) . x + ImGui : : GetCursorPos ( ) . x ,
ImGui : : GetWindowPos ( ) . y + ImGui : : GetCursorPos ( ) . y
) ;
ImVec2 maxArea = ImVec2 (
ImGui : : GetWindowPos ( ) . x + ImGui : : GetCursorPos ( ) . x + ImGui : : GetContentRegionAvail ( ) . x ,
ImGui : : GetWindowPos ( ) . y + ImGui : : GetCursorPos ( ) . y + ImGui : : GetContentRegionAvail ( ) . y
) ;
ImRect rect = ImRect ( minArea , maxArea ) ;
ImGuiStyle & style = ImGui : : GetStyle ( ) ;
ImGui : : ItemSize ( ImVec2 ( 4.0f , 4.0f ) , style . FramePadding . y ) ;
ImU32 lowColor = ImGui : : GetColorU32 ( uiColors [ GUI_COLOR_VOLMETER_LOW ] ) ;
if ( ImGui : : ItemAdd ( rect , ImGui : : GetID ( " volMeter " ) ) ) {
ImGui : : RenderFrame ( rect . Min , rect . Max , ImGui : : GetColorU32 ( ImGuiCol_FrameBg ) , true , style . FrameRounding ) ;
for ( int i = 0 ; i < 2 ; i + + ) {
peak [ i ] * = 0.95 ;
if ( peak [ i ] < 0.0001 ) peak [ i ] = 0.0 ;
for ( int j = 0 ; j < e - > oscSize ; j + + ) {
if ( fabs ( e - > oscBuf [ i ] [ j ] ) > peak [ i ] ) {
peak [ i ] = fabs ( e - > oscBuf [ i ] [ j ] ) ;
}
}
float logPeak = ( 20 * log10 ( peak [ i ] ) / 36.0 ) ;
if ( logPeak = = NAN ) logPeak = 0.0 ;
if ( logPeak < - 1.0 ) logPeak = - 1.0 ;
if ( logPeak > 0.0 ) {
isClipping = 8 ;
logPeak = 0.0 ;
}
logPeak + = 1.0 ;
ImU32 highColor = ImGui : : GetColorU32 (
ImLerp ( uiColors [ GUI_COLOR_VOLMETER_LOW ] , uiColors [ GUI_COLOR_VOLMETER_HIGH ] , logPeak )
) ;
ImRect s ;
if ( aspectRatio ) {
s = ImRect (
ImLerp ( rect . Min , rect . Max , ImVec2 ( 0 , float ( i ) * 0.5 ) ) ,
ImLerp ( rect . Min , rect . Max , ImVec2 ( logPeak , float ( i + 1 ) * 0.5 ) )
) ;
if ( i = = 0 ) s . Max . y - = dpiScale ;
if ( isClipping ) {
dl - > AddRectFilled ( s . Min , s . Max , ImGui : : GetColorU32 ( uiColors [ GUI_COLOR_VOLMETER_PEAK ] ) ) ;
} else {
dl - > AddRectFilledMultiColor ( s . Min , s . Max , lowColor , highColor , highColor , lowColor ) ;
}
} else {
s = ImRect (
ImLerp ( rect . Min , rect . Max , ImVec2 ( float ( i ) * 0.5 , 1.0 - logPeak ) ) ,
ImLerp ( rect . Min , rect . Max , ImVec2 ( float ( i + 1 ) * 0.5 , 1.0 ) )
) ;
if ( i = = 0 ) s . Max . x - = dpiScale ;
if ( isClipping ) {
dl - > AddRectFilled ( s . Min , s . Max , ImGui : : GetColorU32 ( uiColors [ GUI_COLOR_VOLMETER_PEAK ] ) ) ;
} else {
dl - > AddRectFilledMultiColor ( s . Min , s . Max , highColor , highColor , lowColor , lowColor ) ;
}
}
}
if ( ImGui : : IsItemHovered ( ) ) {
if ( aspectRatio ) {
ImGui : : SetTooltip ( " %.1fdB " , 36 * ( ( ImGui : : GetMousePos ( ) . x - ImGui : : GetItemRectMin ( ) . x ) / ( rect . Max . x - rect . Min . x ) - 1.0 ) ) ;
} else {
ImGui : : SetTooltip ( " %.1fdB " , - ( 36 + 36 * ( ( ImGui : : GetMousePos ( ) . y - ImGui : : GetItemRectMin ( ) . y ) / ( rect . Max . y - rect . Min . y ) - 1.0 ) ) ) ;
}
}
}
}
ImGui : : PopStyleVar ( 4 ) ;
ImGui : : End ( ) ;
}
2021-12-14 09:45:44 +00:00
void FurnaceGUI : : drawPattern ( ) {
if ( ! patternOpen ) return ;
2021-12-23 16:29:11 +00:00
if ( e - > isPlaying ( ) & & followPattern ) cursor . y = oldRow ;
2021-12-14 22:45:37 +00:00
SelectionPoint sel1 = selStart ;
SelectionPoint sel2 = selEnd ;
if ( sel2 . y < sel1 . y ) {
sel2 . y ^ = sel1 . y ;
sel1 . y ^ = sel2 . y ;
sel2 . y ^ = sel1 . y ;
}
if ( sel2 . xCoarse < sel1 . xCoarse ) {
sel2 . xCoarse ^ = sel1 . xCoarse ;
sel1 . xCoarse ^ = sel2 . xCoarse ;
sel2 . xCoarse ^ = sel1 . xCoarse ;
sel2 . xFine ^ = sel1 . xFine ;
sel1 . xFine ^ = sel2 . xFine ;
sel2 . xFine ^ = sel1 . xFine ;
} else if ( sel2 . xCoarse = = sel1 . xCoarse & & sel2 . xFine < sel1 . xFine ) {
sel2 . xFine ^ = sel1 . xFine ;
sel1 . xFine ^ = sel2 . xFine ;
sel2 . xFine ^ = sel1 . xFine ;
}
2021-12-21 00:46:49 +00:00
ImGui : : PushStyleVar ( ImGuiStyleVar_WindowPadding , ImVec2 ( 0.0f , 0.0f ) ) ;
2021-12-14 09:45:44 +00:00
if ( ImGui : : Begin ( " Pattern " , & patternOpen ) ) {
2021-12-24 03:14:59 +00:00
//ImGui::SetWindowSize(ImVec2(scrW*dpiScale,scrH*dpiScale));
patWindowPos = ImGui : : GetWindowPos ( ) ;
patWindowSize = ImGui : : GetWindowSize ( ) ;
2021-12-14 09:45:44 +00:00
char id [ 32 ] ;
ImGui : : PushFont ( patFont ) ;
2021-12-21 04:20:30 +00:00
unsigned char ord = e - > isPlaying ( ) ? oldOrder : e - > getOrder ( ) ;
oldOrder = e - > getOrder ( ) ;
2022-01-08 06:57:37 +00:00
int chans = e - > getTotalChannelCount ( ) ;
2022-02-05 06:48:35 +00:00
int displayChans = 0 ;
for ( int i = 0 ; i < chans ; i + + ) {
if ( e - > song . chanShow [ i ] ) displayChans + + ;
}
2021-12-14 09:45:44 +00:00
ImGui : : PushStyleVar ( ImGuiStyleVar_CellPadding , ImVec2 ( 0.0f , 0.0f ) ) ;
2021-12-23 16:29:11 +00:00
ImGui : : PushStyleColor ( ImGuiCol_Header , uiColors [ GUI_COLOR_PATTERN_SELECTION ] ) ;
ImGui : : PushStyleColor ( ImGuiCol_HeaderHovered , uiColors [ GUI_COLOR_PATTERN_SELECTION_HOVER ] ) ;
ImGui : : PushStyleColor ( ImGuiCol_HeaderActive , uiColors [ GUI_COLOR_PATTERN_SELECTION_ACTIVE ] ) ;
2022-02-05 06:48:35 +00:00
if ( ImGui : : BeginTable ( " PatternView " , displayChans + 2 , ImGuiTableFlags_BordersInnerV | ImGuiTableFlags_ScrollX | ImGuiTableFlags_ScrollY | ImGuiTableFlags_NoPadInnerX ) ) {
2021-12-14 09:45:44 +00:00
ImGui : : TableSetupColumn ( " pos " , ImGuiTableColumnFlags_WidthFixed ) ;
2022-02-05 10:40:47 +00:00
char chanID [ 2048 ] ;
2021-12-21 00:46:49 +00:00
float lineHeight = ( ImGui : : GetTextLineHeight ( ) + 2 * dpiScale ) ;
2021-12-14 09:45:44 +00:00
int curRow = e - > getRow ( ) ;
2021-12-23 16:29:11 +00:00
if ( e - > isPlaying ( ) & & followPattern ) updateScroll ( curRow ) ;
2021-12-14 09:45:44 +00:00
if ( nextScroll > - 0.5f ) {
2021-12-23 16:29:11 +00:00
ImGui : : SetScrollY ( nextScroll ) ;
2021-12-14 09:45:44 +00:00
nextScroll = - 1.0f ;
2021-12-24 03:14:59 +00:00
nextAddScroll = 0.0f ;
}
if ( nextAddScroll ! = 0.0f ) {
ImGui : : SetScrollY ( ImGui : : GetScrollY ( ) + nextAddScroll ) ;
nextScroll = - 1.0f ;
nextAddScroll = 0.0f ;
2021-12-14 09:45:44 +00:00
}
ImGui : : TableSetupScrollFreeze ( 1 , 1 ) ;
for ( int i = 0 ; i < chans ; i + + ) {
2022-02-05 06:48:35 +00:00
if ( ! e - > song . chanShow [ i ] ) continue ;
2021-12-14 09:45:44 +00:00
ImGui : : TableSetupColumn ( fmt : : sprintf ( " c%d " , i ) . c_str ( ) , ImGuiTableColumnFlags_WidthFixed ) ;
}
ImGui : : TableNextRow ( ) ;
ImGui : : TableNextColumn ( ) ;
2021-12-21 04:20:30 +00:00
if ( ImGui : : Selectable ( extraChannelButtons ? " --##ExtraChannelButtons " : " ++##ExtraChannelButtons " , false , ImGuiSelectableFlags_NoPadWithHalfSpacing , ImVec2 ( 0.0f , lineHeight + 1.0f * dpiScale ) ) ) {
2021-12-21 00:46:49 +00:00
extraChannelButtons = ! extraChannelButtons ;
}
2021-12-14 09:45:44 +00:00
for ( int i = 0 ; i < chans ; i + + ) {
2022-02-05 06:48:35 +00:00
if ( ! e - > song . chanShow [ i ] ) continue ;
2021-12-14 09:45:44 +00:00
ImGui : : TableNextColumn ( ) ;
2022-02-05 08:10:19 +00:00
bool displayTooltip = false ;
2022-02-05 07:41:29 +00:00
if ( e - > song . chanCollapse [ i ] ) {
2022-02-05 08:10:19 +00:00
const char * chName = e - > getChannelShortName ( i ) ;
if ( strlen ( chName ) > 3 ) {
2022-02-05 10:40:47 +00:00
snprintf ( chanID , 2048 , " ...##_CH%d " , i ) ;
2022-02-05 08:10:19 +00:00
} else {
2022-02-05 10:40:47 +00:00
snprintf ( chanID , 2048 , " %s##_CH%d " , chName , i ) ;
2022-02-05 08:10:19 +00:00
}
displayTooltip = true ;
2022-02-05 07:41:29 +00:00
} else {
2022-02-05 08:10:19 +00:00
const char * chName = e - > getChannelName ( i ) ;
size_t chNameLimit = 6 + 4 * e - > song . pat [ i ] . effectRows ;
if ( strlen ( chName ) > chNameLimit ) {
String shortChName = chName ;
shortChName . resize ( chNameLimit - 3 ) ;
shortChName + = " ... " ;
2022-02-05 10:40:47 +00:00
snprintf ( chanID , 2048 , " %s##_CH%d " , shortChName . c_str ( ) , i ) ;
2022-02-05 08:10:19 +00:00
displayTooltip = true ;
} else {
2022-02-05 10:40:47 +00:00
snprintf ( chanID , 2048 , " %s##_CH%d " , chName , i ) ;
2022-02-05 08:10:19 +00:00
}
2022-02-05 07:41:29 +00:00
}
2021-12-23 22:09:33 +00:00
bool muted = e - > isChannelMuted ( i ) ;
ImVec4 chanHead = muted ? uiColors [ GUI_COLOR_CHANNEL_MUTED ] : uiColors [ GUI_COLOR_CHANNEL_FM + e - > getChannelType ( i ) ] ;
ImVec4 chanHeadActive = chanHead ;
ImVec4 chanHeadHover = chanHead ;
chanHead . x * = 0.25 ; chanHead . y * = 0.25 ; chanHead . z * = 0.25 ;
chanHeadActive . x * = 0.8 ; chanHeadActive . y * = 0.8 ; chanHeadActive . z * = 0.8 ;
chanHeadHover . x * = 0.4 ; chanHeadHover . y * = 0.4 ; chanHeadHover . z * = 0.4 ;
ImGui : : PushStyleColor ( ImGuiCol_Header , chanHead ) ;
ImGui : : PushStyleColor ( ImGuiCol_HeaderActive , chanHeadActive ) ;
ImGui : : PushStyleColor ( ImGuiCol_HeaderHovered , chanHeadHover ) ;
2022-02-05 07:41:29 +00:00
// help me why is the color leakingggggggg
ImGui : : TableSetBgColor ( ImGuiTableBgTarget_CellBg , ImGui : : GetColorU32 ( chanHead ) ) ;
2021-12-23 22:09:33 +00:00
if ( muted ) ImGui : : PushStyleColor ( ImGuiCol_Text , uiColors [ GUI_COLOR_CHANNEL_MUTED ] ) ;
2022-02-01 08:01:07 +00:00
ImGui : : Selectable ( chanID , true , ImGuiSelectableFlags_NoPadWithHalfSpacing , ImVec2 ( 0.0f , lineHeight + 1.0f * dpiScale ) ) ;
2022-02-05 08:10:19 +00:00
if ( displayTooltip & & ImGui : : IsItemHovered ( ) ) {
ImGui : : SetTooltip ( " %s " , e - > getChannelName ( i ) ) ;
}
2022-01-20 07:28:55 +00:00
if ( ImGui : : IsItemClicked ( ImGuiMouseButton_Left ) ) {
if ( settings . soloAction ! = 1 & & soloTimeout > 0 & & soloChan = = i ) {
e - > toggleSolo ( i ) ;
soloTimeout = 0 ;
} else {
e - > toggleMute ( i ) ;
soloTimeout = 20 ;
soloChan = i ;
}
2021-12-18 08:25:42 +00:00
}
2021-12-23 22:09:33 +00:00
if ( muted ) ImGui : : PopStyleColor ( ) ;
ImGui : : PopStyleColor ( 3 ) ;
2022-01-20 07:28:55 +00:00
if ( settings . soloAction ! = 2 ) if ( ImGui : : IsItemClicked ( ImGuiMouseButton_Right ) ) {
2021-12-18 08:25:42 +00:00
e - > toggleSolo ( i ) ;
}
2021-12-21 00:46:49 +00:00
if ( extraChannelButtons ) {
2022-02-05 10:40:47 +00:00
snprintf ( chanID , 2048 , " %c##_HCH%d " , e - > song . chanCollapse [ i ] ? ' + ' : ' - ' , i ) ;
2021-12-21 00:46:49 +00:00
ImGui : : SetCursorPosX ( ImGui : : GetCursorPosX ( ) + 4.0f * dpiScale ) ;
if ( ImGui : : SmallButton ( chanID ) ) {
2022-02-05 07:41:29 +00:00
e - > song . chanCollapse [ i ] = ! e - > song . chanCollapse [ i ] ;
2021-12-21 00:46:49 +00:00
}
2022-02-05 07:41:29 +00:00
if ( ! e - > song . chanCollapse [ i ] ) {
ImGui : : SameLine ( ) ;
2022-02-05 10:40:47 +00:00
snprintf ( chanID , 2048 , " <##_LCH%d " , i ) ;
2022-02-05 07:41:29 +00:00
ImGui : : BeginDisabled ( e - > song . pat [ i ] . effectRows < = 1 ) ;
if ( ImGui : : SmallButton ( chanID ) ) {
e - > song . pat [ i ] . effectRows - - ;
if ( e - > song . pat [ i ] . effectRows < 1 ) e - > song . pat [ i ] . effectRows = 1 ;
}
ImGui : : EndDisabled ( ) ;
ImGui : : SameLine ( ) ;
ImGui : : BeginDisabled ( e - > song . pat [ i ] . effectRows > = 8 ) ;
2022-02-05 10:40:47 +00:00
snprintf ( chanID , 2048 , " >##_RCH%d " , i ) ;
2022-02-05 07:41:29 +00:00
if ( ImGui : : SmallButton ( chanID ) ) {
e - > song . pat [ i ] . effectRows + + ;
if ( e - > song . pat [ i ] . effectRows > 8 ) e - > song . pat [ i ] . effectRows = 8 ;
}
ImGui : : EndDisabled ( ) ;
2021-12-21 00:46:49 +00:00
}
2021-12-21 04:20:30 +00:00
ImGui : : Spacing ( ) ;
2021-12-21 00:46:49 +00:00
}
}
ImGui : : TableNextColumn ( ) ;
if ( e - > hasExtValue ( ) ) {
ImGui : : TextColored ( uiColors [ GUI_COLOR_EE_VALUE ] , " %.2X " , e - > getExtValue ( ) ) ;
2021-12-14 09:45:44 +00:00
}
float oneCharSize = ImGui : : CalcTextSize ( " A " ) . x ;
ImVec2 threeChars = ImVec2 ( oneCharSize * 3.0f , lineHeight ) ;
ImVec2 twoChars = ImVec2 ( oneCharSize * 2.0f , lineHeight ) ;
2021-12-14 17:40:26 +00:00
//ImVec2 oneChar=ImVec2(oneCharSize,lineHeight);
2021-12-14 09:45:44 +00:00
int dummyRows = ( ImGui : : GetWindowSize ( ) . y / lineHeight ) / 2 ;
for ( int i = 0 ; i < dummyRows - 1 ; i + + ) {
ImGui : : TableNextRow ( 0 , lineHeight ) ;
ImGui : : TableNextColumn ( ) ;
}
for ( int i = 0 ; i < e - > song . patLen ; i + + ) {
2021-12-14 22:45:37 +00:00
bool selectedRow = ( i > = sel1 . y & & i < = sel2 . y ) ;
2021-12-14 09:45:44 +00:00
ImGui : : TableNextRow ( 0 , lineHeight ) ;
if ( ( lineHeight * ( i + dummyRows + 1 ) ) - ImGui : : GetScrollY ( ) < 0 ) {
continue ;
2021-12-13 22:09:46 +00:00
}
2021-12-14 09:45:44 +00:00
if ( ( lineHeight * ( i + dummyRows ) ) - ImGui : : GetScrollY ( ) > ImGui : : GetWindowSize ( ) . y ) {
continue ;
2021-12-13 07:03:36 +00:00
}
ImGui : : TableNextColumn ( ) ;
2022-01-29 19:12:38 +00:00
bool isPlaying = e - > isPlaying ( ) ;
if ( settings . overflowHighlight ) {
if ( edit & & cursor . y = = i ) {
ImGui : : TableSetBgColor ( ImGuiTableBgTarget_RowBg0 , ImGui : : GetColorU32 ( uiColors [ GUI_COLOR_EDITING ] ) ) ;
} else if ( isPlaying & & oldRow = = i ) {
ImGui : : TableSetBgColor ( ImGuiTableBgTarget_RowBg0 , 0x40ffffff ) ;
} else if ( e - > song . hilightB > 0 & & ! ( i % e - > song . hilightB ) ) {
ImGui : : TableSetBgColor ( ImGuiTableBgTarget_RowBg0 , ImGui : : GetColorU32 ( uiColors [ GUI_COLOR_PATTERN_HI_2 ] ) ) ;
} else if ( e - > song . hilightA > 0 & & ! ( i % e - > song . hilightA ) ) {
ImGui : : TableSetBgColor ( ImGuiTableBgTarget_RowBg0 , ImGui : : GetColorU32 ( uiColors [ GUI_COLOR_PATTERN_HI_1 ] ) ) ;
}
2021-12-13 07:03:36 +00:00
}
2022-01-19 23:04:07 +00:00
if ( settings . patRowsBase = = 1 ) {
ImGui : : TextColored ( uiColors [ GUI_COLOR_PATTERN_ROW_INDEX ] , " %.2x " , i ) ;
} else {
ImGui : : TextColored ( uiColors [ GUI_COLOR_PATTERN_ROW_INDEX ] , " %3d " , i ) ;
}
2021-12-14 09:45:44 +00:00
for ( int j = 0 ; j < chans ; j + + ) {
2022-02-05 06:48:35 +00:00
if ( ! e - > song . chanShow [ j ] ) continue ;
2021-12-14 09:45:44 +00:00
int chanVolMax = e - > getMaxVolumeChan ( j ) ;
DivPattern * pat = e - > song . pat [ j ] . getPattern ( e - > song . orders . ord [ j ] [ ord ] , true ) ;
2021-12-13 22:09:46 +00:00
ImGui : : TableNextColumn ( ) ;
2021-12-13 07:03:36 +00:00
2022-01-29 19:12:38 +00:00
if ( ! settings . overflowHighlight ) {
if ( edit & & cursor . y = = i ) {
ImGui : : TableSetBgColor ( ImGuiTableBgTarget_CellBg , ImGui : : GetColorU32 ( uiColors [ GUI_COLOR_EDITING ] ) ) ;
} else if ( isPlaying & & oldRow = = i ) {
ImGui : : TableSetBgColor ( ImGuiTableBgTarget_CellBg , 0x40ffffff ) ;
} else if ( e - > song . hilightB > 0 & & ! ( i % e - > song . hilightB ) ) {
ImGui : : TableSetBgColor ( ImGuiTableBgTarget_CellBg , ImGui : : GetColorU32 ( uiColors [ GUI_COLOR_PATTERN_HI_2 ] ) ) ;
} else if ( e - > song . hilightA > 0 & & ! ( i % e - > song . hilightA ) ) {
ImGui : : TableSetBgColor ( ImGuiTableBgTarget_CellBg , ImGui : : GetColorU32 ( uiColors [ GUI_COLOR_PATTERN_HI_1 ] ) ) ;
}
}
2021-12-14 22:45:37 +00:00
int sel1XSum = sel1 . xCoarse * 32 + sel1 . xFine ;
int sel2XSum = sel2 . xCoarse * 32 + sel2 . xFine ;
int j32 = j * 32 ;
bool selectedNote = selectedRow & & ( j32 > = sel1XSum & & j32 < = sel2XSum ) ;
bool selectedIns = selectedRow & & ( j32 + 1 > = sel1XSum & & j32 + 1 < = sel2XSum ) ;
bool selectedVol = selectedRow & & ( j32 + 2 > = sel1XSum & & j32 + 2 < = sel2XSum ) ;
2021-12-23 16:29:11 +00:00
bool cursorNote = ( cursor . y = = i & & cursor . xCoarse = = j & & cursor . xFine = = 0 ) ;
bool cursorIns = ( cursor . y = = i & & cursor . xCoarse = = j & & cursor . xFine = = 1 ) ;
bool cursorVol = ( cursor . y = = i & & cursor . xCoarse = = j & & cursor . xFine = = 2 ) ;
2021-12-14 22:45:37 +00:00
2021-12-14 09:45:44 +00:00
sprintf ( id , " %s##PN_%d_%d " , noteName ( pat - > data [ i ] [ 0 ] , pat - > data [ i ] [ 1 ] ) , i , j ) ;
if ( pat - > data [ i ] [ 0 ] = = 0 & & pat - > data [ i ] [ 1 ] = = 0 ) {
ImGui : : PushStyleColor ( ImGuiCol_Text , uiColors [ GUI_COLOR_PATTERN_INACTIVE ] ) ;
} else {
ImGui : : PushStyleColor ( ImGuiCol_Text , uiColors [ GUI_COLOR_PATTERN_ACTIVE ] ) ;
}
2021-12-23 16:29:11 +00:00
if ( cursorNote ) {
ImGui : : PushStyleColor ( ImGuiCol_Header , uiColors [ GUI_COLOR_PATTERN_CURSOR ] ) ;
ImGui : : PushStyleColor ( ImGuiCol_HeaderActive , uiColors [ GUI_COLOR_PATTERN_CURSOR_ACTIVE ] ) ;
ImGui : : PushStyleColor ( ImGuiCol_HeaderHovered , uiColors [ GUI_COLOR_PATTERN_CURSOR_HOVER ] ) ;
ImGui : : Selectable ( id , true , ImGuiSelectableFlags_NoPadWithHalfSpacing , threeChars ) ;
ImGui : : PopStyleColor ( 3 ) ;
} else {
ImGui : : Selectable ( id , selectedNote , ImGuiSelectableFlags_NoPadWithHalfSpacing , threeChars ) ;
}
2021-12-14 22:45:37 +00:00
if ( ImGui : : IsItemClicked ( ) ) {
startSelection ( j , 0 , i ) ;
}
if ( ImGui : : IsItemHovered ( ImGuiHoveredFlags_AllowWhenBlockedByActiveItem ) ) {
2021-12-15 22:32:08 +00:00
//ImGui::SetTooltip("N: %d O: %d",pat->data[i][0],pat->data[i][1]);
2021-12-14 22:45:37 +00:00
updateSelection ( j , 0 , i ) ;
}
2021-12-14 09:45:44 +00:00
ImGui : : PopStyleColor ( ) ;
2022-02-05 07:41:29 +00:00
if ( ! e - > song . chanCollapse [ j ] ) {
if ( pat - > data [ i ] [ 2 ] = = - 1 ) {
2021-12-13 22:09:46 +00:00
ImGui : : PushStyleColor ( ImGuiCol_Text , uiColors [ GUI_COLOR_PATTERN_INACTIVE ] ) ;
2022-02-05 07:41:29 +00:00
sprintf ( id , " ..##PI_%d_%d " , i , j ) ;
2021-12-13 07:03:36 +00:00
} else {
2022-02-05 07:41:29 +00:00
ImGui : : PushStyleColor ( ImGuiCol_Text , uiColors [ GUI_COLOR_PATTERN_INS ] ) ;
sprintf ( id , " %.2X##PI_%d_%d " , pat - > data [ i ] [ 2 ] , i , j ) ;
2021-12-13 07:03:36 +00:00
}
ImGui : : SameLine ( 0.0f , 0.0f ) ;
2022-02-05 07:41:29 +00:00
if ( cursorIns ) {
ImGui : : PushStyleColor ( ImGuiCol_Header , uiColors [ GUI_COLOR_PATTERN_CURSOR ] ) ;
2021-12-23 16:29:11 +00:00
ImGui : : PushStyleColor ( ImGuiCol_HeaderActive , uiColors [ GUI_COLOR_PATTERN_CURSOR_ACTIVE ] ) ;
ImGui : : PushStyleColor ( ImGuiCol_HeaderHovered , uiColors [ GUI_COLOR_PATTERN_CURSOR_HOVER ] ) ;
ImGui : : Selectable ( id , true , ImGuiSelectableFlags_NoPadWithHalfSpacing , twoChars ) ;
ImGui : : PopStyleColor ( 3 ) ;
} else {
2022-02-05 07:41:29 +00:00
ImGui : : Selectable ( id , selectedIns , ImGuiSelectableFlags_NoPadWithHalfSpacing , twoChars ) ;
2021-12-23 16:29:11 +00:00
}
2021-12-14 22:45:37 +00:00
if ( ImGui : : IsItemClicked ( ) ) {
2022-02-05 07:41:29 +00:00
startSelection ( j , 1 , i ) ;
2021-12-14 22:45:37 +00:00
}
if ( ImGui : : IsItemHovered ( ImGuiHoveredFlags_AllowWhenBlockedByActiveItem ) ) {
2022-02-05 07:41:29 +00:00
updateSelection ( j , 1 , i ) ;
2021-12-14 22:45:37 +00:00
}
2022-02-05 07:41:29 +00:00
ImGui : : PopStyleColor ( ) ;
if ( pat - > data [ i ] [ 3 ] = = - 1 ) {
sprintf ( id , " ..##PV_%d_%d " , i , j ) ;
ImGui : : PushStyleColor ( ImGuiCol_Text , uiColors [ GUI_COLOR_PATTERN_INACTIVE ] ) ;
2021-12-13 07:03:36 +00:00
} else {
2022-02-05 07:41:29 +00:00
int volColor = ( pat - > data [ i ] [ 3 ] * 127 ) / chanVolMax ;
if ( volColor > 127 ) volColor = 127 ;
if ( volColor < 0 ) volColor = 0 ;
sprintf ( id , " %.2X##PV_%d_%d " , pat - > data [ i ] [ 3 ] , i , j ) ;
ImGui : : PushStyleColor ( ImGuiCol_Text , volColors [ volColor ] ) ;
2021-12-13 07:03:36 +00:00
}
ImGui : : SameLine ( 0.0f , 0.0f ) ;
2022-02-05 07:41:29 +00:00
if ( cursorVol ) {
ImGui : : PushStyleColor ( ImGuiCol_Header , uiColors [ GUI_COLOR_PATTERN_CURSOR ] ) ;
2021-12-23 16:29:11 +00:00
ImGui : : PushStyleColor ( ImGuiCol_HeaderActive , uiColors [ GUI_COLOR_PATTERN_CURSOR_ACTIVE ] ) ;
ImGui : : PushStyleColor ( ImGuiCol_HeaderHovered , uiColors [ GUI_COLOR_PATTERN_CURSOR_HOVER ] ) ;
ImGui : : Selectable ( id , true , ImGuiSelectableFlags_NoPadWithHalfSpacing , twoChars ) ;
ImGui : : PopStyleColor ( 3 ) ;
} else {
2022-02-05 07:41:29 +00:00
ImGui : : Selectable ( id , selectedVol , ImGuiSelectableFlags_NoPadWithHalfSpacing , twoChars ) ;
2021-12-23 16:29:11 +00:00
}
2021-12-14 22:45:37 +00:00
if ( ImGui : : IsItemClicked ( ) ) {
2022-02-05 07:41:29 +00:00
startSelection ( j , 2 , i ) ;
2021-12-14 22:45:37 +00:00
}
if ( ImGui : : IsItemHovered ( ImGuiHoveredFlags_AllowWhenBlockedByActiveItem ) ) {
2022-02-05 07:41:29 +00:00
updateSelection ( j , 2 , i ) ;
2021-12-14 22:45:37 +00:00
}
2021-12-13 22:09:46 +00:00
ImGui : : PopStyleColor ( ) ;
2022-02-05 07:41:29 +00:00
for ( int k = 0 ; k < e - > song . pat [ j ] . effectRows ; k + + ) {
int index = 4 + ( k < < 1 ) ;
bool selectedEffect = selectedRow & & ( j32 + index - 1 > = sel1XSum & & j32 + index - 1 < = sel2XSum ) ;
bool selectedEffectVal = selectedRow & & ( j32 + index > = sel1XSum & & j32 + index < = sel2XSum ) ;
bool cursorEffect = ( cursor . y = = i & & cursor . xCoarse = = j & & cursor . xFine = = index - 1 ) ;
bool cursorEffectVal = ( cursor . y = = i & & cursor . xCoarse = = j & & cursor . xFine = = index ) ;
if ( pat - > data [ i ] [ index ] = = - 1 ) {
sprintf ( id , " ..##PE%d_%d_%d " , k , i , j ) ;
ImGui : : PushStyleColor ( ImGuiCol_Text , uiColors [ GUI_COLOR_PATTERN_INACTIVE ] ) ;
} else {
sprintf ( id , " %.2X##PE%d_%d_%d " , pat - > data [ i ] [ index ] , k , i , j ) ;
if ( pat - > data [ i ] [ index ] < 0x10 ) {
ImGui : : PushStyleColor ( ImGuiCol_Text , uiColors [ fxColors [ pat - > data [ i ] [ index ] ] ] ) ;
} else if ( pat - > data [ i ] [ index ] < 0x20 ) {
ImGui : : PushStyleColor ( ImGuiCol_Text , uiColors [ GUI_COLOR_PATTERN_EFFECT_SYS_PRIMARY ] ) ;
} else if ( pat - > data [ i ] [ index ] < 0x30 ) {
ImGui : : PushStyleColor ( ImGuiCol_Text , uiColors [ GUI_COLOR_PATTERN_EFFECT_SYS_SECONDARY ] ) ;
} else if ( pat - > data [ i ] [ index ] < 0x48 ) {
ImGui : : PushStyleColor ( ImGuiCol_Text , uiColors [ GUI_COLOR_PATTERN_EFFECT_SYS_PRIMARY ] ) ;
} else if ( pat - > data [ i ] [ index ] < 0xc0 ) {
ImGui : : PushStyleColor ( ImGuiCol_Text , uiColors [ GUI_COLOR_PATTERN_EFFECT_INVALID ] ) ;
} else if ( pat - > data [ i ] [ index ] < 0xd0 ) {
ImGui : : PushStyleColor ( ImGuiCol_Text , uiColors [ GUI_COLOR_PATTERN_EFFECT_SPEED ] ) ;
} else if ( pat - > data [ i ] [ index ] < 0xe0 ) {
ImGui : : PushStyleColor ( ImGuiCol_Text , uiColors [ GUI_COLOR_PATTERN_EFFECT_INVALID ] ) ;
} else if ( pat - > data [ i ] [ index ] < 0xf0 ) {
ImGui : : PushStyleColor ( ImGuiCol_Text , uiColors [ extFxColors [ pat - > data [ i ] [ index ] - 0xe0 ] ] ) ;
} else {
ImGui : : PushStyleColor ( ImGuiCol_Text , uiColors [ GUI_COLOR_PATTERN_EFFECT_INVALID ] ) ;
}
}
ImGui : : SameLine ( 0.0f , 0.0f ) ;
if ( cursorEffect ) {
ImGui : : PushStyleColor ( ImGuiCol_Header , uiColors [ GUI_COLOR_PATTERN_CURSOR ] ) ;
ImGui : : PushStyleColor ( ImGuiCol_HeaderActive , uiColors [ GUI_COLOR_PATTERN_CURSOR_ACTIVE ] ) ;
ImGui : : PushStyleColor ( ImGuiCol_HeaderHovered , uiColors [ GUI_COLOR_PATTERN_CURSOR_HOVER ] ) ;
ImGui : : Selectable ( id , true , ImGuiSelectableFlags_NoPadWithHalfSpacing , twoChars ) ;
ImGui : : PopStyleColor ( 3 ) ;
} else {
ImGui : : Selectable ( id , selectedEffect , ImGuiSelectableFlags_NoPadWithHalfSpacing , twoChars ) ;
}
if ( ImGui : : IsItemClicked ( ) ) {
startSelection ( j , index - 1 , i ) ;
}
if ( ImGui : : IsItemHovered ( ImGuiHoveredFlags_AllowWhenBlockedByActiveItem ) ) {
updateSelection ( j , index - 1 , i ) ;
}
if ( pat - > data [ i ] [ index + 1 ] = = - 1 ) {
sprintf ( id , " ..##PF%d_%d_%d " , k , i , j ) ;
} else {
sprintf ( id , " %.2X##PF%d_%d_%d " , pat - > data [ i ] [ index + 1 ] , k , i , j ) ;
}
ImGui : : SameLine ( 0.0f , 0.0f ) ;
if ( cursorEffectVal ) {
ImGui : : PushStyleColor ( ImGuiCol_Header , uiColors [ GUI_COLOR_PATTERN_CURSOR ] ) ;
ImGui : : PushStyleColor ( ImGuiCol_HeaderActive , uiColors [ GUI_COLOR_PATTERN_CURSOR_ACTIVE ] ) ;
ImGui : : PushStyleColor ( ImGuiCol_HeaderHovered , uiColors [ GUI_COLOR_PATTERN_CURSOR_HOVER ] ) ;
ImGui : : Selectable ( id , true , ImGuiSelectableFlags_NoPadWithHalfSpacing , twoChars ) ;
ImGui : : PopStyleColor ( 3 ) ;
} else {
ImGui : : Selectable ( id , selectedEffectVal , ImGuiSelectableFlags_NoPadWithHalfSpacing , twoChars ) ;
}
if ( ImGui : : IsItemClicked ( ) ) {
startSelection ( j , index , i ) ;
}
if ( ImGui : : IsItemHovered ( ImGuiHoveredFlags_AllowWhenBlockedByActiveItem ) ) {
updateSelection ( j , index , i ) ;
}
ImGui : : PopStyleColor ( ) ;
}
2021-12-14 09:45:44 +00:00
}
}
}
for ( int i = 0 ; i < = dummyRows ; i + + ) {
ImGui : : TableNextRow ( 0 , lineHeight ) ;
ImGui : : TableNextColumn ( ) ;
}
oldRow = curRow ;
ImGui : : EndTable ( ) ;
}
2021-12-23 16:29:11 +00:00
ImGui : : PopStyleColor ( 3 ) ;
2021-12-14 09:45:44 +00:00
ImGui : : PopStyleVar ( ) ;
ImGui : : PopFont ( ) ;
}
2021-12-21 00:46:49 +00:00
ImGui : : PopStyleVar ( ) ;
2021-12-15 05:37:27 +00:00
if ( ImGui : : IsWindowFocused ( ImGuiFocusedFlags_ChildWindows ) ) curWindow = GUI_WINDOW_PATTERN ;
2021-12-14 09:45:44 +00:00
ImGui : : End ( ) ;
}
2021-12-13 07:03:36 +00:00
2022-01-18 23:32:42 +00:00
const char * aboutLine [ 56 ] = {
2021-12-19 04:03:50 +00:00
" tildearrow " ,
" is proud to present " ,
" " ,
( " Furnace " DIV_VERSION ) ,
" " ,
" the free software chiptune tracker, " ,
2022-01-16 03:38:51 +00:00
" compatible with DefleMask modules. " ,
2021-12-19 04:03:50 +00:00
" " ,
" zero disassembly. " ,
" zero reverse-engineering. " ,
" only time and dedication. " ,
" " ,
" powered by: " ,
" Dear ImGui by Omar Cornut " ,
" SDL2 by Sam Lantinga " ,
" zlib by Jean-loup Gailly " ,
" and Mark Adler " ,
" libsndfile by Erik de Castro Lopo " ,
" Nuked-OPM & Nuked-OPN2 by Nuke.YKT " ,
" ymfm by Aaron Giles " ,
" MAME SN76496 by Nicola Salmoria " ,
2022-01-13 07:52:19 +00:00
" MAME AY-3-8910 by Couriersud " ,
2022-01-18 23:32:42 +00:00
" with AY8930 fixes by Eulous " ,
2022-01-16 06:47:19 +00:00
" MAME SAA1099 by Juergen Buchmueller and Manuel Abadia " ,
2021-12-19 04:03:50 +00:00
" SameBoy by Lior Halphon " ,
" Mednafen PCE " ,
" puNES by FHorse " ,
" reSID by Dag Lem " ,
2022-01-14 08:37:36 +00:00
" Stella by Stella Team " ,
2021-12-19 04:03:50 +00:00
" " ,
" greetings to: " ,
" Delek " ,
" fd " ,
" ILLUMIDARO " ,
" all members of Deflers of Noice! " ,
" " ,
2022-01-16 03:38:51 +00:00
" copyright © 2021-2022 tildearrow. " ,
2021-12-19 04:03:50 +00:00
" licensed under GPLv2! see " ,
" LICENSE.txt for more information. " ,
" " ,
" help Furnace grow: " ,
" https://github.com/tildearrow/furnace " ,
" " ,
" contact tildearrow at: " ,
" https://tildearrow.org/?p=contact " ,
" " ,
" disclaimer: " ,
" despite the fact this program works " ,
" with the .dmf file format, it is NOT " ,
" affiliated with Delek or DefleMask in " ,
" any way, nor it is a replacement for " ,
" the original program. " ,
" " ,
" it also comes with ABSOLUTELY NO WARRANTY. " ,
" " ,
" thanks to all contributors! "
} ;
void FurnaceGUI : : drawAbout ( ) {
// do stuff
if ( ImGui : : Begin ( " About Furnace " , NULL , ImGuiWindowFlags_Modal | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoDocking | ImGuiWindowFlags_NoTitleBar ) ) {
ImGui : : SetWindowPos ( ImVec2 ( 0 , 0 ) ) ;
ImGui : : SetWindowSize ( ImVec2 ( scrW * dpiScale , scrH * dpiScale ) ) ;
ImGui : : PushFont ( bigFont ) ;
ImDrawList * dl = ImGui : : GetWindowDrawList ( ) ;
float r = 0 ;
float g = 0 ;
float b = 0 ;
2022-02-01 07:52:36 +00:00
float peakMix = settings . partyTime ? ( ( peak [ 0 ] + peak [ 1 ] ) * 0.5 ) : 0.3 ;
ImGui : : ColorConvertHSVtoRGB ( aboutHue , 1.0 , 0.25 + MIN ( 0.75f , peakMix * 0.75f ) , r , g , b ) ;
aboutHue + = 0.001 + peakMix * 0.004 ;
2021-12-19 04:03:50 +00:00
dl - > AddRectFilled ( ImVec2 ( 0 , 0 ) , ImVec2 ( scrW * dpiScale , scrH * dpiScale ) , 0xff000000 ) ;
bool skip = false ;
bool skip2 = false ;
2021-12-19 22:01:34 +00:00
for ( int i = ( - 80 - sin ( double ( aboutSin ) * 2 * M_PI / 120.0 ) * 80.0 ) * 2 ; i < scrW ; i + = 160 ) {
2021-12-19 04:03:50 +00:00
skip2 = ! skip2 ;
skip = skip2 ;
2021-12-19 22:01:34 +00:00
for ( int j = ( - 80 - cos ( double ( aboutSin ) * 2 * M_PI / 150.0 ) * 80.0 ) * 2 ; j < scrH ; j + = 160 ) {
2021-12-19 04:03:50 +00:00
skip = ! skip ;
if ( skip ) continue ;
dl - > AddRectFilled ( ImVec2 ( i * dpiScale , j * dpiScale ) , ImVec2 ( ( i + 160 ) * dpiScale , ( j + 160 ) * dpiScale ) , ImGui : : GetColorU32 ( ImVec4 ( r * 0.25 , g * 0.25 , b * 0.25 , 1.0 ) ) ) ;
}
}
skip = false ;
skip2 = false ;
2021-12-19 22:01:34 +00:00
for ( int i = ( - 80 - cos ( double ( aboutSin ) * 2 * M_PI / 120.0 ) * 80.0 ) * 2 ; i < scrW ; i + = 160 ) {
2021-12-19 04:03:50 +00:00
skip2 = ! skip2 ;
skip = skip2 ;
2021-12-19 22:01:34 +00:00
for ( int j = ( - 80 - sin ( double ( aboutSin ) * 2 * M_PI / 150.0 ) * 80.0 ) * 2 ; j < scrH ; j + = 160 ) {
2021-12-19 04:03:50 +00:00
skip = ! skip ;
if ( skip ) continue ;
dl - > AddRectFilled ( ImVec2 ( i * dpiScale , j * dpiScale ) , ImVec2 ( ( i + 160 ) * dpiScale , ( j + 160 ) * dpiScale ) , ImGui : : GetColorU32 ( ImVec4 ( r * 0.5 , g * 0.5 , b * 0.5 , 1.0 ) ) ) ;
}
}
skip = false ;
skip2 = false ;
2021-12-19 22:01:34 +00:00
for ( int i = ( - ( 160 - ( aboutSin * 2 ) % 160 ) ) * 2 ; i < scrW ; i + = 160 ) {
2021-12-19 04:03:50 +00:00
skip2 = ! skip2 ;
skip = skip2 ;
2021-12-19 22:01:34 +00:00
for ( int j = ( - 240 - cos ( double ( aboutSin * M_PI / 300.0 ) ) * 240.0 ) * 2 ; j < scrH ; j + = 160 ) {
2021-12-19 04:03:50 +00:00
skip = ! skip ;
if ( skip ) continue ;
dl - > AddRectFilled ( ImVec2 ( i * dpiScale , j * dpiScale ) , ImVec2 ( ( i + 160 ) * dpiScale , ( j + 160 ) * dpiScale ) , ImGui : : GetColorU32 ( ImVec4 ( r * 0.75 , g * 0.75 , b * 0.75 , 1.0 ) ) ) ;
}
}
2022-01-18 23:32:42 +00:00
for ( int i = 0 ; i < 56 ; i + + ) {
2021-12-19 04:03:50 +00:00
double posX = ( scrW * dpiScale / 2.0 ) + ( sin ( double ( i ) * 0.5 + double ( aboutScroll ) / 90.0 ) * 120 * dpiScale ) - ( ImGui : : CalcTextSize ( aboutLine [ i ] ) . x * 0.5 ) ;
double posY = ( scrH - aboutScroll + 42 * i ) * dpiScale ;
if ( posY < - 80 * dpiScale | | posY > scrH * dpiScale ) continue ;
dl - > AddText ( bigFont , bigFont - > FontSize ,
ImVec2 ( posX + dpiScale , posY + dpiScale ) ,
0xff000000 , aboutLine [ i ] ) ;
dl - > AddText ( bigFont , bigFont - > FontSize ,
ImVec2 ( posX + dpiScale , posY - dpiScale ) ,
0xff000000 , aboutLine [ i ] ) ;
dl - > AddText ( bigFont , bigFont - > FontSize ,
ImVec2 ( posX - dpiScale , posY + dpiScale ) ,
0xff000000 , aboutLine [ i ] ) ;
dl - > AddText ( bigFont , bigFont - > FontSize ,
ImVec2 ( posX - dpiScale , posY - dpiScale ) ,
0xff000000 , aboutLine [ i ] ) ;
dl - > AddText ( bigFont , bigFont - > FontSize ,
ImVec2 ( posX , posY ) ,
0xffffffff , aboutLine [ i ] ) ;
}
ImGui : : PopFont ( ) ;
2022-02-01 07:52:36 +00:00
aboutScroll + = 2 + ( peakMix > 0.78 ) * 3 ;
aboutSin + = 1 + ( peakMix > 0.75 ) * 2 ;
if ( aboutSin > = 2400 ) aboutSin - = 2400 ;
2022-01-18 23:32:42 +00:00
if ( aboutScroll > ( 42 * 56 + scrH ) ) aboutScroll = - 20 ;
2021-12-19 04:03:50 +00:00
}
ImGui : : End ( ) ;
}
2021-12-29 05:50:00 +00:00
const char * mainFonts [ ] = {
" IBM Plex Sans " ,
" Liberation Sans " ,
2022-01-19 21:58:01 +00:00
" Exo " ,
" Proggy Clean " ,
" GNU Unifont " ,
2021-12-29 05:50:00 +00:00
" <Use system font> " ,
" <Custom...> "
} ;
const char * patFonts [ ] = {
" IBM Plex Mono " ,
" Mononoki " ,
" PT Mono " ,
2022-01-19 21:58:01 +00:00
" Proggy Clean " ,
" GNU Unifont " ,
2021-12-29 05:50:00 +00:00
" <Use system font> " ,
" <Custom...> "
} ;
const char * audioBackends [ ] = {
2022-01-16 22:25:43 +00:00
" JACK " ,
" SDL "
2021-12-29 05:50:00 +00:00
} ;
2022-01-16 22:38:52 +00:00
const char * audioQualities [ ] = {
" High " ,
" Low "
} ;
2021-12-29 05:50:00 +00:00
const char * arcadeCores [ ] = {
" ymfm " ,
" Nuked-OPM "
} ;
2022-02-03 04:08:45 +00:00
const char * ym2612Cores [ ] = {
" Nuked-OPN2 " ,
" ymfm "
} ;
2022-01-16 22:25:43 +00:00
# define SAMPLE_RATE_SELECTABLE(x) \
if ( ImGui : : Selectable ( # x , settings . audioRate = = x ) ) { \
settings . audioRate = x ; \
}
# define BUFFER_SIZE_SELECTABLE(x) \
if ( ImGui : : Selectable ( # x , settings . audioBufSize = = x ) ) { \
settings . audioBufSize = x ; \
}
2022-01-22 06:50:52 +00:00
# define UI_COLOR_CONFIG(what,label) \
ImGui : : ColorEdit4 ( label " ##CC_ " # what , ( float * ) & uiColors [ what ] ) ;
2021-12-20 03:51:02 +00:00
void FurnaceGUI : : drawSettings ( ) {
if ( ! settingsOpen ) return ;
if ( ImGui : : Begin ( " Settings " , NULL , ImGuiWindowFlags_NoDocking ) ) {
if ( ImGui : : BeginTabBar ( " settingsTab " ) ) {
if ( ImGui : : BeginTabItem ( " General " ) ) {
2022-01-20 07:28:55 +00:00
ImGui : : Text ( " Toggle channel solo on: " ) ;
if ( ImGui : : RadioButton ( " Right-click or double-click##soloA " , settings . soloAction = = 0 ) ) {
settings . soloAction = 0 ;
}
if ( ImGui : : RadioButton ( " Right-click##soloR " , settings . soloAction = = 1 ) ) {
settings . soloAction = 1 ;
}
if ( ImGui : : RadioButton ( " Double-click##soloD " , settings . soloAction = = 2 ) ) {
settings . soloAction = 2 ;
}
2022-01-20 07:53:59 +00:00
bool pullDeleteBehaviorB = settings . pullDeleteBehavior ;
if ( ImGui : : Checkbox ( " Move cursor up on backspace-delete " , & pullDeleteBehaviorB ) ) {
settings . pullDeleteBehavior = pullDeleteBehaviorB ;
}
2022-01-20 18:15:37 +00:00
2022-02-04 05:03:30 +00:00
bool stepOnDeleteB = settings . stepOnDelete ;
if ( ImGui : : Checkbox ( " Move cursor by edit step on delete " , & stepOnDeleteB ) ) {
settings . stepOnDelete = stepOnDeleteB ;
}
2022-01-28 06:26:26 +00:00
bool allowEditDockingB = settings . allowEditDocking ;
if ( ImGui : : Checkbox ( " Allow docking editors " , & allowEditDockingB ) ) {
settings . allowEditDocking = allowEditDockingB ;
}
2022-02-07 22:24:26 +00:00
bool restartOnFlagChangeB = settings . restartOnFlagChange ;
if ( ImGui : : Checkbox ( " Restart song when changing system properties " , & restartOnFlagChangeB ) ) {
settings . restartOnFlagChange = restartOnFlagChangeB ;
}
2022-01-20 18:15:37 +00:00
ImGui : : Text ( " Wrap pattern cursor horizontally: " ) ;
if ( ImGui : : RadioButton ( " No##wrapH0 " , settings . wrapHorizontal = = 0 ) ) {
settings . wrapHorizontal = 0 ;
}
if ( ImGui : : RadioButton ( " Yes##wrapH1 " , settings . wrapHorizontal = = 1 ) ) {
settings . wrapHorizontal = 1 ;
}
if ( ImGui : : RadioButton ( " Yes, and move to next/prev row##wrapH2 " , settings . wrapHorizontal = = 2 ) ) {
settings . wrapHorizontal = 2 ;
}
ImGui : : Text ( " Wrap pattern cursor vertically: " ) ;
if ( ImGui : : RadioButton ( " No##wrapV0 " , settings . wrapVertical = = 0 ) ) {
settings . wrapVertical = 0 ;
}
if ( ImGui : : RadioButton ( " Yes##wrapV1 " , settings . wrapVertical = = 1 ) ) {
settings . wrapVertical = 1 ;
}
if ( ImGui : : RadioButton ( " Yes, and move to next/prev pattern##wrapV2 " , settings . wrapVertical = = 2 ) ) {
settings . wrapVertical = 2 ;
}
2022-02-04 05:03:30 +00:00
ImGui : : Text ( " Cursor movement keys behavior: " ) ;
if ( ImGui : : RadioButton ( " Move by one##cmk0 " , settings . scrollStep = = 0 ) ) {
settings . scrollStep = 0 ;
}
if ( ImGui : : RadioButton ( " Move by Edit Step##cmk1 " , settings . scrollStep = = 1 ) ) {
settings . scrollStep = 1 ;
}
2021-12-20 03:51:02 +00:00
ImGui : : EndTabItem ( ) ;
}
2021-12-29 05:50:00 +00:00
if ( ImGui : : BeginTabItem ( " Audio " ) ) {
ImGui : : Text ( " Backend " ) ;
ImGui : : SameLine ( ) ;
2022-01-16 22:25:43 +00:00
ImGui : : Combo ( " ##Backend " , & settings . audioEngine , audioBackends , 2 ) ;
2021-12-29 05:50:00 +00:00
ImGui : : Text ( " Sample rate " ) ;
2022-01-16 22:25:43 +00:00
ImGui : : SameLine ( ) ;
String sr = fmt : : sprintf ( " %d " , settings . audioRate ) ;
if ( ImGui : : BeginCombo ( " ##SampleRate " , sr . c_str ( ) ) ) {
SAMPLE_RATE_SELECTABLE ( 8000 ) ;
SAMPLE_RATE_SELECTABLE ( 16000 ) ;
SAMPLE_RATE_SELECTABLE ( 22050 ) ;
SAMPLE_RATE_SELECTABLE ( 32000 ) ;
SAMPLE_RATE_SELECTABLE ( 44100 ) ;
SAMPLE_RATE_SELECTABLE ( 48000 ) ;
SAMPLE_RATE_SELECTABLE ( 88200 ) ;
SAMPLE_RATE_SELECTABLE ( 96000 ) ;
SAMPLE_RATE_SELECTABLE ( 192000 ) ;
ImGui : : EndCombo ( ) ;
}
2021-12-29 05:50:00 +00:00
ImGui : : Text ( " Buffer size " ) ;
2022-01-16 22:25:43 +00:00
ImGui : : SameLine ( ) ;
String bs = fmt : : sprintf ( " %d (latency: ~%.1fms) " , settings . audioBufSize , 2000.0 * ( double ) settings . audioBufSize / ( double ) settings . audioRate ) ;
if ( ImGui : : BeginCombo ( " ##BufferSize " , bs . c_str ( ) ) ) {
BUFFER_SIZE_SELECTABLE ( 64 ) ;
BUFFER_SIZE_SELECTABLE ( 128 ) ;
BUFFER_SIZE_SELECTABLE ( 256 ) ;
BUFFER_SIZE_SELECTABLE ( 512 ) ;
BUFFER_SIZE_SELECTABLE ( 1024 ) ;
BUFFER_SIZE_SELECTABLE ( 2048 ) ;
ImGui : : EndCombo ( ) ;
}
2022-01-16 22:38:52 +00:00
ImGui : : Text ( " Quality " ) ;
ImGui : : SameLine ( ) ;
ImGui : : Combo ( " ##Quality " , & settings . audioQuality , audioQualities , 2 ) ;
2021-12-29 05:50:00 +00:00
2022-02-04 22:04:36 +00:00
bool forceMonoB = settings . forceMono ;
if ( ImGui : : Checkbox ( " Force mono audio " , & forceMonoB ) ) {
settings . forceMono = forceMonoB ;
}
2022-02-06 02:26:24 +00:00
TAAudioDesc & audioWant = e - > getAudioDescWant ( ) ;
TAAudioDesc & audioGot = e - > getAudioDescGot ( ) ;
ImGui : : Text ( " want: %d samples @ %.0fHz \n " , audioWant . bufsize , audioWant . rate ) ;
ImGui : : Text ( " got: %d samples @ %.0fHz \n " , audioGot . bufsize , audioGot . rate ) ;
2021-12-29 05:50:00 +00:00
ImGui : : EndTabItem ( ) ;
}
if ( ImGui : : BeginTabItem ( " Emulation " ) ) {
ImGui : : Text ( " Arcade core " ) ;
ImGui : : SameLine ( ) ;
2022-01-16 22:25:43 +00:00
ImGui : : Combo ( " ##ArcadeCore " , & settings . arcadeCore , arcadeCores , 2 ) ;
2021-12-29 05:50:00 +00:00
2022-02-03 04:08:45 +00:00
ImGui : : Text ( " Genesis core " ) ;
ImGui : : SameLine ( ) ;
ImGui : : Combo ( " ##YM2612Core " , & settings . ym2612Core , ym2612Cores , 2 ) ;
2021-12-29 05:50:00 +00:00
ImGui : : EndTabItem ( ) ;
}
2021-12-20 03:51:02 +00:00
if ( ImGui : : BeginTabItem ( " Appearance " ) ) {
ImGui : : Text ( " Main font " ) ;
2021-12-29 05:50:00 +00:00
ImGui : : SameLine ( ) ;
2022-01-22 08:37:57 +00:00
ImGui : : Combo ( " ##MainFont " , & settings . mainFont , mainFonts , 6 ) ;
2022-01-16 22:25:43 +00:00
if ( ImGui : : InputInt ( " Size##MainFontSize " , & settings . mainFontSize ) ) {
if ( settings . mainFontSize < 3 ) settings . mainFontSize = 3 ;
if ( settings . mainFontSize > 96 ) settings . mainFontSize = 96 ;
2021-12-20 03:51:02 +00:00
}
ImGui : : Text ( " Pattern font " ) ;
2021-12-29 05:50:00 +00:00
ImGui : : SameLine ( ) ;
2022-01-22 08:37:57 +00:00
ImGui : : Combo ( " ##PatFont " , & settings . patFont , patFonts , 6 ) ;
2022-01-16 22:25:43 +00:00
if ( ImGui : : InputInt ( " Size##PatFontSize " , & settings . patFontSize ) ) {
if ( settings . patFontSize < 3 ) settings . patFontSize = 3 ;
if ( settings . patFontSize > 96 ) settings . patFontSize = 96 ;
2021-12-20 03:51:02 +00:00
}
2022-01-19 23:04:07 +00:00
ImGui : : Separator ( ) ;
2022-01-20 07:28:55 +00:00
ImGui : : Text ( " Orders row number format: " ) ;
2022-01-19 23:04:07 +00:00
if ( ImGui : : RadioButton ( " Decimal##orbD " , settings . orderRowsBase = = 0 ) ) {
settings . orderRowsBase = 0 ;
}
if ( ImGui : : RadioButton ( " Hexadecimal##orbH " , settings . orderRowsBase = = 1 ) ) {
settings . orderRowsBase = 1 ;
}
2022-01-20 07:28:55 +00:00
ImGui : : Text ( " Pattern row number format: " ) ;
2022-01-19 23:04:07 +00:00
if ( ImGui : : RadioButton ( " Decimal##prbD " , settings . patRowsBase = = 0 ) ) {
settings . patRowsBase = 0 ;
}
if ( ImGui : : RadioButton ( " Hexadecimal##prbH " , settings . patRowsBase = = 1 ) ) {
settings . patRowsBase = 1 ;
}
2022-01-27 20:01:05 +00:00
ImGui : : Text ( " FM parameter names: " ) ;
if ( ImGui : : RadioButton ( " Friendly##fmn0 " , settings . fmNames = = 0 ) ) {
settings . fmNames = 0 ;
}
if ( ImGui : : RadioButton ( " Technical##fmn1 " , settings . fmNames = = 1 ) ) {
settings . fmNames = 1 ;
}
if ( ImGui : : RadioButton ( " Technical (alternate)##fmn2 " , settings . fmNames = = 2 ) ) {
settings . fmNames = 2 ;
}
2022-01-23 21:46:32 +00:00
ImGui : : Separator ( ) ;
2022-02-05 04:21:00 +00:00
ImGui : : Text ( " Play/edit controls layout: " ) ;
if ( ImGui : : RadioButton ( " Classic##ecl0 " , settings . controlLayout = = 0 ) ) {
settings . controlLayout = 0 ;
}
if ( ImGui : : RadioButton ( " Compact##ecl1 " , settings . controlLayout = = 1 ) ) {
settings . controlLayout = 1 ;
}
if ( ImGui : : RadioButton ( " Compact (vertical)##ecl2 " , settings . controlLayout = = 2 ) ) {
settings . controlLayout = 2 ;
}
if ( ImGui : : RadioButton ( " Split##ecl3 " , settings . controlLayout = = 3 ) ) {
settings . controlLayout = 3 ;
}
2022-01-23 21:46:32 +00:00
bool macroViewB = settings . macroView ;
2022-01-23 22:01:19 +00:00
if ( ImGui : : Checkbox ( " Classic macro view (standard macros only) " , & macroViewB ) ) {
2022-01-23 21:46:32 +00:00
settings . macroView = macroViewB ;
}
2022-01-28 08:17:35 +00:00
bool chipNamesB = settings . chipNames ;
if ( ImGui : : Checkbox ( " Use chip names instead of system names " , & chipNamesB ) ) {
settings . chipNames = chipNamesB ;
}
2022-01-29 19:12:38 +00:00
bool overflowHighlightB = settings . overflowHighlight ;
if ( ImGui : : Checkbox ( " Overflow pattern highlights " , & overflowHighlightB ) ) {
settings . overflowHighlight = overflowHighlightB ;
}
2022-02-03 19:40:09 +00:00
bool germanNotationB = settings . germanNotation ;
if ( ImGui : : Checkbox ( " Use German notation " , & germanNotationB ) ) {
settings . germanNotation = germanNotationB ;
}
2022-02-04 05:03:30 +00:00
// sorry. temporarily disabled until ImGui has a way to add separators in tables arbitrarily.
/*bool sysSeparatorsB=settings.sysSeparators;
if ( ImGui : : Checkbox ( " Add separators between systems in Orders " , & sysSeparatorsB ) ) {
settings . sysSeparators = sysSeparatorsB ;
} */
2022-02-03 19:40:09 +00:00
2022-02-01 07:52:36 +00:00
bool partyTimeB = settings . partyTime ;
if ( ImGui : : Checkbox ( " About screen party time " , & partyTimeB ) ) {
settings . partyTime = partyTimeB ;
}
2022-01-23 21:46:32 +00:00
ImGui : : Separator ( ) ;
2022-01-22 06:50:52 +00:00
if ( ImGui : : TreeNode ( " Color scheme " ) ) {
if ( ImGui : : TreeNode ( " General " ) ) {
UI_COLOR_CONFIG ( GUI_COLOR_BACKGROUND , " Background " ) ;
UI_COLOR_CONFIG ( GUI_COLOR_FRAME_BACKGROUND , " Window background " ) ;
2022-01-29 19:20:30 +00:00
UI_COLOR_CONFIG ( GUI_COLOR_MODAL_BACKDROP , " Modal backdrop " ) ;
2022-01-22 06:50:52 +00:00
UI_COLOR_CONFIG ( GUI_COLOR_HEADER , " Header " ) ;
UI_COLOR_CONFIG ( GUI_COLOR_TEXT , " Text " ) ;
UI_COLOR_CONFIG ( GUI_COLOR_ACCENT_PRIMARY , " Primary " ) ;
UI_COLOR_CONFIG ( GUI_COLOR_ACCENT_SECONDARY , " Secondary " ) ;
UI_COLOR_CONFIG ( GUI_COLOR_EDITING , " Editing " ) ;
2022-01-27 06:04:26 +00:00
UI_COLOR_CONFIG ( GUI_COLOR_SONG_LOOP , " Song loop " ) ;
2022-01-22 06:50:52 +00:00
UI_COLOR_CONFIG ( GUI_COLOR_PLAYBACK_STAT , " Playback status " ) ;
ImGui : : TreePop ( ) ;
}
2022-01-29 23:56:08 +00:00
if ( ImGui : : TreeNode ( " Volume Meter " ) ) {
UI_COLOR_CONFIG ( GUI_COLOR_VOLMETER_LOW , " Low " ) ;
UI_COLOR_CONFIG ( GUI_COLOR_VOLMETER_HIGH , " High " ) ;
UI_COLOR_CONFIG ( GUI_COLOR_VOLMETER_PEAK , " Clip " ) ;
ImGui : : TreePop ( ) ;
}
2022-01-22 06:50:52 +00:00
if ( ImGui : : TreeNode ( " Macro Editor " ) ) {
UI_COLOR_CONFIG ( GUI_COLOR_MACRO_VOLUME , " Volume " ) ;
UI_COLOR_CONFIG ( GUI_COLOR_MACRO_PITCH , " Pitch " ) ;
UI_COLOR_CONFIG ( GUI_COLOR_MACRO_WAVE , " Wave " ) ;
UI_COLOR_CONFIG ( GUI_COLOR_MACRO_OTHER , " Other " ) ;
ImGui : : TreePop ( ) ;
}
if ( ImGui : : TreeNode ( " Instrument Types " ) ) {
UI_COLOR_CONFIG ( GUI_COLOR_INSTR_FM , " FM " ) ;
UI_COLOR_CONFIG ( GUI_COLOR_INSTR_STD , " Standard " ) ;
UI_COLOR_CONFIG ( GUI_COLOR_INSTR_GB , " Game Boy " ) ;
UI_COLOR_CONFIG ( GUI_COLOR_INSTR_C64 , " C64 " ) ;
UI_COLOR_CONFIG ( GUI_COLOR_INSTR_AMIGA , " Amiga/Sample " ) ;
UI_COLOR_CONFIG ( GUI_COLOR_INSTR_PCE , " PC Engine " ) ;
UI_COLOR_CONFIG ( GUI_COLOR_INSTR_AY , " AY-3-8910/SSG " ) ;
UI_COLOR_CONFIG ( GUI_COLOR_INSTR_AY8930 , " AY8930 " ) ;
UI_COLOR_CONFIG ( GUI_COLOR_INSTR_TIA , " TIA " ) ;
UI_COLOR_CONFIG ( GUI_COLOR_INSTR_SAA1099 , " SAA1099 " ) ;
UI_COLOR_CONFIG ( GUI_COLOR_INSTR_UNKNOWN , " Other/Unknown " ) ;
ImGui : : TreePop ( ) ;
}
if ( ImGui : : TreeNode ( " Channel " ) ) {
UI_COLOR_CONFIG ( GUI_COLOR_CHANNEL_FM , " FM " ) ;
UI_COLOR_CONFIG ( GUI_COLOR_CHANNEL_PULSE , " Pulse " ) ;
UI_COLOR_CONFIG ( GUI_COLOR_CHANNEL_NOISE , " Noise " ) ;
UI_COLOR_CONFIG ( GUI_COLOR_CHANNEL_PCM , " PCM " ) ;
UI_COLOR_CONFIG ( GUI_COLOR_CHANNEL_WAVE , " Wave " ) ;
UI_COLOR_CONFIG ( GUI_COLOR_CHANNEL_OP , " FM operator " ) ;
UI_COLOR_CONFIG ( GUI_COLOR_CHANNEL_MUTED , " Muted " ) ;
ImGui : : TreePop ( ) ;
}
if ( ImGui : : TreeNode ( " Pattern " ) ) {
UI_COLOR_CONFIG ( GUI_COLOR_PATTERN_CURSOR , " Cursor " ) ;
UI_COLOR_CONFIG ( GUI_COLOR_PATTERN_CURSOR_HOVER , " Cursor (hovered) " ) ;
UI_COLOR_CONFIG ( GUI_COLOR_PATTERN_CURSOR_ACTIVE , " Cursor (clicked) " ) ;
UI_COLOR_CONFIG ( GUI_COLOR_PATTERN_SELECTION , " Selection " ) ;
UI_COLOR_CONFIG ( GUI_COLOR_PATTERN_SELECTION_HOVER , " Selection (hovered) " ) ;
UI_COLOR_CONFIG ( GUI_COLOR_PATTERN_SELECTION_ACTIVE , " Selection (clicked) " ) ;
UI_COLOR_CONFIG ( GUI_COLOR_PATTERN_HI_1 , " Highlight 1 " ) ;
UI_COLOR_CONFIG ( GUI_COLOR_PATTERN_HI_2 , " Highlight 2 " ) ;
UI_COLOR_CONFIG ( GUI_COLOR_PATTERN_ROW_INDEX , " Row number " ) ;
UI_COLOR_CONFIG ( GUI_COLOR_PATTERN_ACTIVE , " Note " ) ;
UI_COLOR_CONFIG ( GUI_COLOR_PATTERN_INACTIVE , " Blank " ) ;
UI_COLOR_CONFIG ( GUI_COLOR_PATTERN_INS , " Instrument " ) ;
UI_COLOR_CONFIG ( GUI_COLOR_PATTERN_VOLUME_MIN , " Volume (0%) " ) ;
UI_COLOR_CONFIG ( GUI_COLOR_PATTERN_VOLUME_HALF , " Volume (50%) " ) ;
UI_COLOR_CONFIG ( GUI_COLOR_PATTERN_VOLUME_MAX , " Volume (100%) " ) ;
UI_COLOR_CONFIG ( GUI_COLOR_PATTERN_EFFECT_INVALID , " Invalid effect " ) ;
UI_COLOR_CONFIG ( GUI_COLOR_PATTERN_EFFECT_PITCH , " Pitch effect " ) ;
UI_COLOR_CONFIG ( GUI_COLOR_PATTERN_EFFECT_VOLUME , " Volume effect " ) ;
UI_COLOR_CONFIG ( GUI_COLOR_PATTERN_EFFECT_PANNING , " Panning effect " ) ;
UI_COLOR_CONFIG ( GUI_COLOR_PATTERN_EFFECT_SONG , " Song effect " ) ;
UI_COLOR_CONFIG ( GUI_COLOR_PATTERN_EFFECT_TIME , " Time effect " ) ;
UI_COLOR_CONFIG ( GUI_COLOR_PATTERN_EFFECT_SPEED , " Speed effect " ) ;
UI_COLOR_CONFIG ( GUI_COLOR_PATTERN_EFFECT_SYS_PRIMARY , " Primary system effect " ) ;
UI_COLOR_CONFIG ( GUI_COLOR_PATTERN_EFFECT_SYS_SECONDARY , " Secondary system effect " ) ;
UI_COLOR_CONFIG ( GUI_COLOR_PATTERN_EFFECT_MISC , " Miscellaneous " ) ;
UI_COLOR_CONFIG ( GUI_COLOR_EE_VALUE , " External command output " ) ;
ImGui : : TreePop ( ) ;
}
ImGui : : TreePop ( ) ;
}
2021-12-20 03:51:02 +00:00
ImGui : : EndTabItem ( ) ;
}
ImGui : : EndTabBar ( ) ;
}
ImGui : : Separator ( ) ;
if ( ImGui : : Button ( " OK##SettingsOK " ) ) {
settingsOpen = false ;
willCommit = true ;
}
ImGui : : SameLine ( ) ;
if ( ImGui : : Button ( " Cancel##SettingsCancel " ) ) {
settingsOpen = false ;
2022-01-20 07:28:55 +00:00
syncSettings ( ) ;
2021-12-20 03:51:02 +00:00
}
}
ImGui : : End ( ) ;
}
2022-01-16 22:25:43 +00:00
void FurnaceGUI : : syncSettings ( ) {
settings . mainFontSize = e - > getConfInt ( " mainFontSize " , 18 ) ;
settings . patFontSize = e - > getConfInt ( " patFontSize " , 18 ) ;
settings . iconSize = e - > getConfInt ( " iconSize " , 16 ) ;
settings . audioEngine = ( e - > getConfString ( " audioEngine " , " SDL " ) = = " SDL " ) ? 1 : 0 ;
2022-01-16 22:38:52 +00:00
settings . audioQuality = e - > getConfInt ( " audioQuality " , 0 ) ;
2022-01-16 22:25:43 +00:00
settings . audioBufSize = e - > getConfInt ( " audioBufSize " , 1024 ) ;
settings . audioRate = e - > getConfInt ( " audioRate " , 44100 ) ;
settings . arcadeCore = e - > getConfInt ( " arcadeCore " , 0 ) ;
2022-02-03 04:08:45 +00:00
settings . ym2612Core = e - > getConfInt ( " ym2612Core " , 0 ) ;
2022-01-16 22:25:43 +00:00
settings . mainFont = e - > getConfInt ( " mainFont " , 0 ) ;
settings . patFont = e - > getConfInt ( " patFont " , 0 ) ;
settings . mainFontPath = e - > getConfString ( " mainFontPath " , " " ) ;
settings . patFontPath = e - > getConfString ( " patFontPath " , " " ) ;
2022-01-19 23:04:07 +00:00
settings . patRowsBase = e - > getConfInt ( " patRowsBase " , 0 ) ;
settings . orderRowsBase = e - > getConfInt ( " orderRowsBase " , 1 ) ;
2022-01-20 07:28:55 +00:00
settings . soloAction = e - > getConfInt ( " soloAction " , 0 ) ;
2022-01-20 07:53:59 +00:00
settings . pullDeleteBehavior = e - > getConfInt ( " pullDeleteBehavior " , 1 ) ;
2022-01-20 18:15:37 +00:00
settings . wrapHorizontal = e - > getConfInt ( " wrapHorizontal " , 0 ) ;
settings . wrapVertical = e - > getConfInt ( " wrapVertical " , 0 ) ;
2022-01-23 21:34:20 +00:00
settings . macroView = e - > getConfInt ( " macroView " , 0 ) ;
2022-01-27 20:01:05 +00:00
settings . fmNames = e - > getConfInt ( " fmNames " , 0 ) ;
2022-01-28 06:26:26 +00:00
settings . allowEditDocking = e - > getConfInt ( " allowEditDocking " , 0 ) ;
2022-01-28 08:17:35 +00:00
settings . chipNames = e - > getConfInt ( " chipNames " , 0 ) ;
2022-01-29 19:12:38 +00:00
settings . overflowHighlight = e - > getConfInt ( " overflowHighlight " , 0 ) ;
2022-01-27 20:01:05 +00:00
if ( settings . fmNames < 0 | | settings . fmNames > 2 ) settings . fmNames = 0 ;
2022-02-01 07:52:36 +00:00
settings . partyTime = e - > getConfInt ( " partyTime " , 0 ) ;
2022-02-03 19:40:09 +00:00
settings . germanNotation = e - > getConfInt ( " germanNotation " , 0 ) ;
2022-02-04 05:03:30 +00:00
settings . stepOnDelete = e - > getConfInt ( " stepOnDelete " , 0 ) ;
settings . scrollStep = e - > getConfInt ( " scrollStep " , 0 ) ;
settings . sysSeparators = e - > getConfInt ( " sysSeparators " , 1 ) ;
2022-02-04 22:04:36 +00:00
settings . forceMono = e - > getConfInt ( " forceMono " , 0 ) ;
2022-02-05 04:21:00 +00:00
settings . controlLayout = e - > getConfInt ( " controlLayout " , 0 ) ;
2022-02-07 22:24:26 +00:00
settings . restartOnFlagChange = e - > getConfInt ( " restartOnFlagChange " , 1 ) ;
2022-01-16 22:25:43 +00:00
}
2022-01-22 06:50:52 +00:00
# define PUT_UI_COLOR(source) e->setConf(#source,(int)ImGui::GetColorU32(uiColors[source]));
2021-12-20 03:51:02 +00:00
void FurnaceGUI : : commitSettings ( ) {
2022-01-16 22:25:43 +00:00
e - > setConf ( " mainFontSize " , settings . mainFontSize ) ;
e - > setConf ( " patFontSize " , settings . patFontSize ) ;
e - > setConf ( " iconSize " , settings . iconSize ) ;
e - > setConf ( " audioEngine " , String ( audioBackends [ settings . audioEngine ] ) ) ;
2022-01-16 22:38:52 +00:00
e - > setConf ( " audioQuality " , settings . audioQuality ) ;
2022-01-16 22:25:43 +00:00
e - > setConf ( " audioBufSize " , settings . audioBufSize ) ;
e - > setConf ( " audioRate " , settings . audioRate ) ;
e - > setConf ( " arcadeCore " , settings . arcadeCore ) ;
2022-02-03 04:08:45 +00:00
e - > setConf ( " ym2612Core " , settings . ym2612Core ) ;
2022-01-16 22:25:43 +00:00
e - > setConf ( " mainFont " , settings . mainFont ) ;
e - > setConf ( " patFont " , settings . patFont ) ;
e - > setConf ( " mainFontPath " , settings . mainFontPath ) ;
e - > setConf ( " patFontPath " , settings . patFontPath ) ;
2022-01-19 23:04:07 +00:00
e - > setConf ( " patRowsBase " , settings . patRowsBase ) ;
e - > setConf ( " orderRowsBase " , settings . orderRowsBase ) ;
2022-01-20 07:28:55 +00:00
e - > setConf ( " soloAction " , settings . soloAction ) ;
2022-01-20 07:53:59 +00:00
e - > setConf ( " pullDeleteBehavior " , settings . pullDeleteBehavior ) ;
2022-01-20 18:15:37 +00:00
e - > setConf ( " wrapHorizontal " , settings . wrapHorizontal ) ;
e - > setConf ( " wrapVertical " , settings . wrapVertical ) ;
2022-01-23 21:34:20 +00:00
e - > setConf ( " macroView " , settings . macroView ) ;
2022-01-27 20:01:05 +00:00
e - > setConf ( " fmNames " , settings . fmNames ) ;
2022-01-28 06:26:26 +00:00
e - > setConf ( " allowEditDocking " , settings . allowEditDocking ) ;
2022-01-28 08:17:35 +00:00
e - > setConf ( " chipNames " , settings . chipNames ) ;
2022-01-29 19:12:38 +00:00
e - > setConf ( " overflowHighlight " , settings . overflowHighlight ) ;
2022-02-01 07:52:36 +00:00
e - > setConf ( " partyTime " , settings . partyTime ) ;
2022-02-03 19:40:09 +00:00
e - > setConf ( " germanNotation " , settings . germanNotation ) ;
2022-02-04 05:03:30 +00:00
e - > setConf ( " stepOnDelete " , settings . stepOnDelete ) ;
e - > setConf ( " scrollStep " , settings . scrollStep ) ;
e - > setConf ( " sysSeparators " , settings . sysSeparators ) ;
2022-02-04 22:04:36 +00:00
e - > setConf ( " forceMono " , settings . forceMono ) ;
2022-02-05 04:21:00 +00:00
e - > setConf ( " controlLayout " , settings . controlLayout ) ;
2022-02-07 22:24:26 +00:00
e - > setConf ( " restartOnFlagChange " , settings . restartOnFlagChange ) ;
2021-12-20 03:51:02 +00:00
2022-01-22 06:50:52 +00:00
PUT_UI_COLOR ( GUI_COLOR_BACKGROUND ) ;
PUT_UI_COLOR ( GUI_COLOR_FRAME_BACKGROUND ) ;
2022-01-29 19:20:30 +00:00
PUT_UI_COLOR ( GUI_COLOR_MODAL_BACKDROP ) ;
2022-01-22 06:50:52 +00:00
PUT_UI_COLOR ( GUI_COLOR_HEADER ) ;
PUT_UI_COLOR ( GUI_COLOR_TEXT ) ;
PUT_UI_COLOR ( GUI_COLOR_ACCENT_PRIMARY ) ;
PUT_UI_COLOR ( GUI_COLOR_ACCENT_SECONDARY ) ;
PUT_UI_COLOR ( GUI_COLOR_EDITING ) ;
2022-01-27 06:04:26 +00:00
PUT_UI_COLOR ( GUI_COLOR_SONG_LOOP ) ;
2022-01-29 23:56:08 +00:00
PUT_UI_COLOR ( GUI_COLOR_VOLMETER_LOW ) ;
PUT_UI_COLOR ( GUI_COLOR_VOLMETER_HIGH ) ;
PUT_UI_COLOR ( GUI_COLOR_VOLMETER_PEAK ) ;
2022-01-22 06:50:52 +00:00
PUT_UI_COLOR ( GUI_COLOR_MACRO_VOLUME ) ;
PUT_UI_COLOR ( GUI_COLOR_MACRO_PITCH ) ;
PUT_UI_COLOR ( GUI_COLOR_MACRO_OTHER ) ;
PUT_UI_COLOR ( GUI_COLOR_MACRO_WAVE ) ;
PUT_UI_COLOR ( GUI_COLOR_INSTR_FM ) ;
PUT_UI_COLOR ( GUI_COLOR_INSTR_STD ) ;
PUT_UI_COLOR ( GUI_COLOR_INSTR_GB ) ;
PUT_UI_COLOR ( GUI_COLOR_INSTR_C64 ) ;
PUT_UI_COLOR ( GUI_COLOR_INSTR_AMIGA ) ;
PUT_UI_COLOR ( GUI_COLOR_INSTR_PCE ) ;
PUT_UI_COLOR ( GUI_COLOR_INSTR_AY ) ;
PUT_UI_COLOR ( GUI_COLOR_INSTR_AY8930 ) ;
PUT_UI_COLOR ( GUI_COLOR_INSTR_TIA ) ;
PUT_UI_COLOR ( GUI_COLOR_INSTR_SAA1099 ) ;
PUT_UI_COLOR ( GUI_COLOR_INSTR_UNKNOWN ) ;
PUT_UI_COLOR ( GUI_COLOR_CHANNEL_FM ) ;
PUT_UI_COLOR ( GUI_COLOR_CHANNEL_PULSE ) ;
PUT_UI_COLOR ( GUI_COLOR_CHANNEL_NOISE ) ;
PUT_UI_COLOR ( GUI_COLOR_CHANNEL_PCM ) ;
PUT_UI_COLOR ( GUI_COLOR_CHANNEL_WAVE ) ;
PUT_UI_COLOR ( GUI_COLOR_CHANNEL_OP ) ;
PUT_UI_COLOR ( GUI_COLOR_CHANNEL_MUTED ) ;
PUT_UI_COLOR ( GUI_COLOR_PATTERN_CURSOR ) ;
PUT_UI_COLOR ( GUI_COLOR_PATTERN_CURSOR_HOVER ) ;
PUT_UI_COLOR ( GUI_COLOR_PATTERN_CURSOR_ACTIVE ) ;
PUT_UI_COLOR ( GUI_COLOR_PATTERN_SELECTION ) ;
PUT_UI_COLOR ( GUI_COLOR_PATTERN_SELECTION_HOVER ) ;
PUT_UI_COLOR ( GUI_COLOR_PATTERN_SELECTION_ACTIVE ) ;
PUT_UI_COLOR ( GUI_COLOR_PATTERN_HI_1 ) ;
PUT_UI_COLOR ( GUI_COLOR_PATTERN_HI_2 ) ;
PUT_UI_COLOR ( GUI_COLOR_PATTERN_ROW_INDEX ) ;
PUT_UI_COLOR ( GUI_COLOR_PATTERN_ACTIVE ) ;
PUT_UI_COLOR ( GUI_COLOR_PATTERN_INACTIVE ) ;
PUT_UI_COLOR ( GUI_COLOR_PATTERN_INS ) ;
PUT_UI_COLOR ( GUI_COLOR_PATTERN_VOLUME_MIN ) ;
PUT_UI_COLOR ( GUI_COLOR_PATTERN_VOLUME_HALF ) ;
PUT_UI_COLOR ( GUI_COLOR_PATTERN_VOLUME_MAX ) ;
PUT_UI_COLOR ( GUI_COLOR_PATTERN_EFFECT_INVALID ) ;
PUT_UI_COLOR ( GUI_COLOR_PATTERN_EFFECT_PITCH ) ;
PUT_UI_COLOR ( GUI_COLOR_PATTERN_EFFECT_VOLUME ) ;
PUT_UI_COLOR ( GUI_COLOR_PATTERN_EFFECT_PANNING ) ;
PUT_UI_COLOR ( GUI_COLOR_PATTERN_EFFECT_SONG ) ;
PUT_UI_COLOR ( GUI_COLOR_PATTERN_EFFECT_TIME ) ;
PUT_UI_COLOR ( GUI_COLOR_PATTERN_EFFECT_SPEED ) ;
PUT_UI_COLOR ( GUI_COLOR_PATTERN_EFFECT_SYS_PRIMARY ) ;
PUT_UI_COLOR ( GUI_COLOR_PATTERN_EFFECT_SYS_SECONDARY ) ;
PUT_UI_COLOR ( GUI_COLOR_PATTERN_EFFECT_MISC ) ;
PUT_UI_COLOR ( GUI_COLOR_EE_VALUE ) ;
PUT_UI_COLOR ( GUI_COLOR_PLAYBACK_STAT ) ;
2021-12-20 03:51:02 +00:00
e - > saveConf ( ) ;
2022-02-06 04:48:56 +00:00
if ( ! e - > switchMaster ( ) ) {
showError ( " could not initialize audio! " ) ;
}
2022-01-17 06:42:26 +00:00
2021-12-20 03:51:02 +00:00
ImGui : : GetIO ( ) . Fonts - > Clear ( ) ;
2021-12-21 05:30:55 +00:00
2022-01-22 06:50:52 +00:00
applyUISettings ( ) ;
2021-12-20 03:51:02 +00:00
ImGui_ImplSDLRenderer_DestroyFontsTexture ( ) ;
ImGui : : GetIO ( ) . Fonts - > Build ( ) ;
}
2022-01-27 05:29:16 +00:00
void FurnaceGUI : : drawDebug ( ) {
static int bpOrder ;
static int bpRow ;
static int bpTick ;
static bool bpOn ;
if ( ! debugOpen ) return ;
if ( ImGui : : Begin ( " Debug " , & debugOpen , ImGuiWindowFlags_NoDocking ) ) {
ImGui : : Text ( " NOTE: use with caution. " ) ;
if ( ImGui : : TreeNode ( " Debug Controls " ) ) {
2022-02-03 23:38:57 +00:00
if ( e - > isHalted ( ) ) {
if ( ImGui : : Button ( " Resume " ) ) e - > resume ( ) ;
} else {
if ( ImGui : : Button ( " Pause " ) ) e - > halt ( ) ;
}
2022-01-27 05:29:16 +00:00
ImGui : : SameLine ( ) ;
2022-02-03 23:38:57 +00:00
if ( ImGui : : Button ( " Frame Advance " ) ) e - > haltWhen ( DIV_HALT_TICK ) ;
2022-01-27 05:29:16 +00:00
ImGui : : SameLine ( ) ;
2022-02-03 23:38:57 +00:00
if ( ImGui : : Button ( " Row Advance " ) ) e - > haltWhen ( DIV_HALT_ROW ) ;
2022-01-27 05:29:16 +00:00
ImGui : : SameLine ( ) ;
2022-02-03 23:38:57 +00:00
if ( ImGui : : Button ( " Pattern Advance " ) ) e - > haltWhen ( DIV_HALT_PATTERN ) ;
2022-01-27 05:29:16 +00:00
2022-02-03 23:38:57 +00:00
if ( ImGui : : Button ( " Panic " ) ) e - > syncReset ( ) ;
2022-01-27 05:29:16 +00:00
ImGui : : SameLine ( ) ;
if ( ImGui : : Button ( " Abort " ) ) {
abort ( ) ;
}
ImGui : : TreePop ( ) ;
}
if ( ImGui : : TreeNode ( " Breakpoint " ) ) {
ImGui : : InputInt ( " Order " , & bpOrder ) ;
ImGui : : InputInt ( " Row " , & bpRow ) ;
ImGui : : InputInt ( " Tick " , & bpTick ) ;
ImGui : : Checkbox ( " Enable " , & bpOn ) ;
ImGui : : TreePop ( ) ;
}
if ( ImGui : : TreeNode ( " Dispatch Status " ) ) {
ImGui : : Text ( " for best results set latency to minimum or use the Frame Advance button. " ) ;
ImGui : : Columns ( e - > getTotalChannelCount ( ) ) ;
for ( int i = 0 ; i < e - > getTotalChannelCount ( ) ; i + + ) {
void * ch = e - > getDispatchChanState ( i ) ;
ImGui : : TextColored ( uiColors [ GUI_COLOR_ACCENT_PRIMARY ] , " Ch. %d: %d, %d " , i , e - > dispatchOfChan [ i ] , e - > dispatchChanOfChan [ i ] ) ;
if ( ch = = NULL ) {
ImGui : : Text ( " NULL " ) ;
} else {
putDispatchChan ( ch , e - > dispatchChanOfChan [ i ] , e - > sysOfChan [ i ] ) ;
}
ImGui : : NextColumn ( ) ;
}
ImGui : : Columns ( ) ;
ImGui : : TreePop ( ) ;
}
if ( ImGui : : TreeNode ( " Playback Status " ) ) {
ImGui : : Text ( " for best results set latency to minimum or use the Frame Advance button. " ) ;
ImGui : : Columns ( e - > getTotalChannelCount ( ) ) ;
for ( int i = 0 ; i < e - > getTotalChannelCount ( ) ; i + + ) {
DivChannelState * ch = e - > getChanState ( i ) ;
ImGui : : TextColored ( uiColors [ GUI_COLOR_ACCENT_PRIMARY ] , " Channel %d: " , i ) ;
if ( ch = = NULL ) {
ImGui : : Text ( " NULL " ) ;
} else {
ImGui : : Text ( " * General: " ) ;
ImGui : : Text ( " - note = %d " , ch - > note ) ;
ImGui : : Text ( " - oldNote = %d " , ch - > oldNote ) ;
ImGui : : Text ( " - pitch = %d " , ch - > pitch ) ;
ImGui : : Text ( " - portaSpeed = %d " , ch - > portaSpeed ) ;
ImGui : : Text ( " - portaNote = %d " , ch - > portaNote ) ;
ImGui : : Text ( " - volume = %.4x " , ch - > volume ) ;
ImGui : : Text ( " - volSpeed = %d " , ch - > volSpeed ) ;
ImGui : : Text ( " - cut = %d " , ch - > cut ) ;
ImGui : : Text ( " - rowDelay = %d " , ch - > rowDelay ) ;
ImGui : : Text ( " - volMax = %.4x " , ch - > volMax ) ;
ImGui : : Text ( " - delayOrder = %d " , ch - > delayOrder ) ;
ImGui : : Text ( " - delayRow = %d " , ch - > delayRow ) ;
ImGui : : Text ( " - retrigSpeed = %d " , ch - > retrigSpeed ) ;
ImGui : : Text ( " - retrigTick = %d " , ch - > retrigTick ) ;
ImGui : : PushStyleColor ( ImGuiCol_Text , ( ch - > vibratoDepth > 0 ) ? uiColors [ GUI_COLOR_MACRO_VOLUME ] : uiColors [ GUI_COLOR_TEXT ] ) ;
ImGui : : Text ( " * Vibrato: " ) ;
ImGui : : Text ( " - depth = %d " , ch - > vibratoDepth ) ;
ImGui : : Text ( " - rate = %d " , ch - > vibratoRate ) ;
ImGui : : Text ( " - pos = %d " , ch - > vibratoPos ) ;
ImGui : : Text ( " - dir = %d " , ch - > vibratoDir ) ;
ImGui : : Text ( " - fine = %d " , ch - > vibratoFine ) ;
ImGui : : PopStyleColor ( ) ;
ImGui : : PushStyleColor ( ImGuiCol_Text , ( ch - > tremoloDepth > 0 ) ? uiColors [ GUI_COLOR_MACRO_VOLUME ] : uiColors [ GUI_COLOR_TEXT ] ) ;
ImGui : : Text ( " * Tremolo: " ) ;
ImGui : : Text ( " - depth = %d " , ch - > tremoloDepth ) ;
ImGui : : Text ( " - rate = %d " , ch - > tremoloRate ) ;
ImGui : : Text ( " - pos = %d " , ch - > tremoloPos ) ;
ImGui : : PopStyleColor ( ) ;
ImGui : : PushStyleColor ( ImGuiCol_Text , ( ch - > arp > 0 ) ? uiColors [ GUI_COLOR_MACRO_VOLUME ] : uiColors [ GUI_COLOR_TEXT ] ) ;
ImGui : : Text ( " * Arpeggio: " ) ;
ImGui : : Text ( " - arp = %.2X " , ch - > arp ) ;
ImGui : : Text ( " - stage = %d " , ch - > arpStage ) ;
ImGui : : Text ( " - ticks = %d " , ch - > arpTicks ) ;
ImGui : : PopStyleColor ( ) ;
ImGui : : Text ( " * Miscellaneous: " ) ;
ImGui : : TextColored ( ch - > doNote ? uiColors [ GUI_COLOR_MACRO_VOLUME ] : uiColors [ GUI_COLOR_HEADER ] , " >> Do Note " ) ;
ImGui : : TextColored ( ch - > legato ? uiColors [ GUI_COLOR_MACRO_VOLUME ] : uiColors [ GUI_COLOR_HEADER ] , " >> Legato " ) ;
ImGui : : TextColored ( ch - > portaStop ? uiColors [ GUI_COLOR_MACRO_VOLUME ] : uiColors [ GUI_COLOR_HEADER ] , " >> PortaStop " ) ;
ImGui : : TextColored ( ch - > keyOn ? uiColors [ GUI_COLOR_MACRO_VOLUME ] : uiColors [ GUI_COLOR_HEADER ] , " >> Key On " ) ;
ImGui : : TextColored ( ch - > keyOff ? uiColors [ GUI_COLOR_MACRO_VOLUME ] : uiColors [ GUI_COLOR_HEADER ] , " >> Key Off " ) ;
ImGui : : TextColored ( ch - > nowYouCanStop ? uiColors [ GUI_COLOR_MACRO_VOLUME ] : uiColors [ GUI_COLOR_HEADER ] , " >> NowYouCanStop " ) ;
ImGui : : TextColored ( ch - > stopOnOff ? uiColors [ GUI_COLOR_MACRO_VOLUME ] : uiColors [ GUI_COLOR_HEADER ] , " >> Stop on Off " ) ;
ImGui : : TextColored ( ch - > arpYield ? uiColors [ GUI_COLOR_MACRO_VOLUME ] : uiColors [ GUI_COLOR_HEADER ] , " >> Arp Yield " ) ;
ImGui : : TextColored ( ch - > delayLocked ? uiColors [ GUI_COLOR_MACRO_VOLUME ] : uiColors [ GUI_COLOR_HEADER ] , " >> DelayLocked " ) ;
ImGui : : TextColored ( ch - > inPorta ? uiColors [ GUI_COLOR_MACRO_VOLUME ] : uiColors [ GUI_COLOR_HEADER ] , " >> InPorta " ) ;
ImGui : : TextColored ( ch - > scheduledSlideReset ? uiColors [ GUI_COLOR_MACRO_VOLUME ] : uiColors [ GUI_COLOR_HEADER ] , " >> SchedSlide " ) ;
}
ImGui : : NextColumn ( ) ;
}
ImGui : : Columns ( ) ;
ImGui : : TreePop ( ) ;
}
2022-02-01 23:08:19 +00:00
if ( ImGui : : TreeNode ( " Playground " ) ) {
if ( pgSys < 0 | | pgSys > = e - > song . systemLen ) pgSys = 0 ;
if ( ImGui : : BeginCombo ( " System " , fmt : : sprintf ( " %d. %s " , pgSys + 1 , e - > getSystemName ( e - > song . system [ pgSys ] ) ) . c_str ( ) ) ) {
for ( int i = 0 ; i < e - > song . systemLen ; i + + ) {
if ( ImGui : : Selectable ( fmt : : sprintf ( " %d. %s " , i + 1 , e - > getSystemName ( e - > song . system [ i ] ) ) . c_str ( ) ) ) {
pgSys = i ;
break ;
}
}
ImGui : : EndCombo ( ) ;
}
ImGui : : Text ( " Program " ) ;
if ( pgProgram . empty ( ) ) {
ImGui : : Text ( " -nothing here- " ) ;
} else {
char id [ 32 ] ;
for ( size_t index = 0 ; index < pgProgram . size ( ) ; index + + ) {
DivRegWrite & i = pgProgram [ index ] ;
2022-02-02 04:59:25 +00:00
snprintf ( id , 31 , " pgw%d " , ( int ) index ) ;
2022-02-01 23:08:19 +00:00
ImGui : : PushID ( id ) ;
ImGui : : SetNextItemWidth ( 100.0f * dpiScale ) ;
ImGui : : InputScalar ( " ##PAddress " , ImGuiDataType_U32 , & i . addr , NULL , NULL , " %.2X " , ImGuiInputTextFlags_CharsHexadecimal ) ;
ImGui : : SameLine ( ) ;
ImGui : : Text ( " = " ) ;
ImGui : : SameLine ( ) ;
ImGui : : SetNextItemWidth ( 100.0f * dpiScale ) ;
ImGui : : InputScalar ( " ##PValue " , ImGuiDataType_U16 , & i . val , NULL , NULL , " %.2X " , ImGuiInputTextFlags_CharsHexadecimal ) ;
ImGui : : SameLine ( ) ;
if ( ImGui : : Button ( ICON_FA_TIMES " ##PRemove " ) ) {
pgProgram . erase ( pgProgram . begin ( ) + index ) ;
index - - ;
}
ImGui : : PopID ( ) ;
}
}
if ( ImGui : : Button ( " Execute " ) ) {
e - > poke ( pgSys , pgProgram ) ;
}
ImGui : : SameLine ( ) ;
if ( ImGui : : Button ( " Clear " ) ) {
pgProgram . clear ( ) ;
}
ImGui : : Text ( " Address " ) ;
ImGui : : SameLine ( ) ;
ImGui : : SetNextItemWidth ( 100.0f * dpiScale ) ;
ImGui : : InputInt ( " ##PAddress " , & pgAddr , 0 , 0 , ImGuiInputTextFlags_CharsHexadecimal ) ;
ImGui : : SameLine ( ) ;
ImGui : : Text ( " Value " ) ;
ImGui : : SameLine ( ) ;
ImGui : : SetNextItemWidth ( 100.0f * dpiScale ) ;
ImGui : : InputInt ( " ##PValue " , & pgVal , 0 , 0 , ImGuiInputTextFlags_CharsHexadecimal ) ;
ImGui : : SameLine ( ) ;
if ( ImGui : : Button ( " Write " ) ) {
e - > poke ( pgSys , pgAddr , pgVal ) ;
}
ImGui : : SameLine ( ) ;
if ( ImGui : : Button ( " Add " ) ) {
pgProgram . push_back ( DivRegWrite ( pgAddr , pgVal ) ) ;
}
2022-02-03 23:38:57 +00:00
if ( ImGui : : TreeNode ( " Register Cheatsheet " ) ) {
const char * * sheet = e - > getRegisterSheet ( pgSys ) ;
if ( sheet = = NULL ) {
ImGui : : Text ( " no cheatsheet available for this system. " ) ;
} else {
if ( ImGui : : BeginTable ( " RegisterSheet " , 2 , ImGuiTableFlags_SizingFixedSame ) ) {
ImGui : : TableNextRow ( ) ;
ImGui : : TableNextColumn ( ) ;
ImGui : : Text ( " Name " ) ;
ImGui : : TableNextColumn ( ) ;
ImGui : : Text ( " Address " ) ;
for ( int i = 0 ; sheet [ i ] ! = NULL ; i + = 2 ) {
ImGui : : TableNextRow ( ) ;
ImGui : : TableNextColumn ( ) ;
ImGui : : Text ( " %s " , sheet [ i ] ) ;
ImGui : : TableNextColumn ( ) ;
ImGui : : Text ( " $%s " , sheet [ i + 1 ] ) ;
}
ImGui : : EndTable ( ) ;
}
}
ImGui : : TreePop ( ) ;
}
2022-02-01 23:08:19 +00:00
ImGui : : TreePop ( ) ;
}
2022-01-27 05:29:16 +00:00
if ( ImGui : : TreeNode ( " Settings " ) ) {
if ( ImGui : : Button ( " Sync " ) ) syncSettings ( ) ;
ImGui : : SameLine ( ) ;
if ( ImGui : : Button ( " Commit " ) ) commitSettings ( ) ;
ImGui : : SameLine ( ) ;
if ( ImGui : : Button ( " Force Load " ) ) e - > loadConf ( ) ;
ImGui : : SameLine ( ) ;
if ( ImGui : : Button ( " Force Save " ) ) e - > saveConf ( ) ;
ImGui : : TreePop ( ) ;
}
ImGui : : Text ( " Song format version %d " , e - > song . version ) ;
ImGui : : Text ( " Furnace version " DIV_VERSION " (%d) " , DIV_ENGINE_VERSION ) ;
}
ImGui : : End ( ) ;
}
2022-02-03 05:34:48 +00:00
void FurnaceGUI : : drawStats ( ) {
if ( ! statsOpen ) return ;
if ( ImGui : : Begin ( " Statistics " , & statsOpen ) ) {
String adpcmUsage = fmt : : sprintf ( " %d/16384KB " , e - > adpcmMemLen / 1024 ) ;
String adpcmBUsage = fmt : : sprintf ( " %d/16384KB " , e - > adpcmBMemLen / 1024 ) ;
ImGui : : Text ( " ADPCM-A " ) ;
ImGui : : SameLine ( ) ;
ImGui : : ProgressBar ( ( ( float ) e - > adpcmMemLen ) / 16777216.0f , ImVec2 ( - FLT_MIN , 0 ) , adpcmUsage . c_str ( ) ) ;
ImGui : : Text ( " ADPCM-B " ) ;
ImGui : : SameLine ( ) ;
ImGui : : ProgressBar ( ( ( float ) e - > adpcmBMemLen ) / 16777216.0f , ImVec2 ( - FLT_MIN , 0 ) , adpcmBUsage . c_str ( ) ) ;
}
ImGui : : End ( ) ;
}
void FurnaceGUI : : drawCompatFlags ( ) {
if ( ! compatFlagsOpen ) return ;
if ( ImGui : : Begin ( " Compatibility Flags " , & compatFlagsOpen ) ) {
ImGui : : TextWrapped ( " these flags are stored in the song when saving in .fur format, and are automatically enabled when saving in .dmf format. " ) ;
ImGui : : Checkbox ( " Limit slide range " , & e - > song . limitSlides ) ;
2022-02-06 06:56:50 +00:00
if ( ImGui : : IsItemHovered ( ) ) {
ImGui : : SetTooltip ( " when enabled, slides are limited to a compatible range. \n may cause problems with slides in negative octaves. " ) ;
}
2022-02-03 05:34:48 +00:00
ImGui : : Checkbox ( " Linear pitch control " , & e - > song . linearPitch ) ;
2022-02-06 06:56:50 +00:00
if ( ImGui : : IsItemHovered ( ) ) {
ImGui : : SetTooltip ( " linear pitch: \n - slides work in frequency/period space \n - E5xx and 04xx effects work in tonality space \n non-linear pitch: \n - slides work in frequency/period space \n - E5xx and 04xx effects work on frequency/period space " ) ;
}
ImGui : : Checkbox ( " Proper noise layout on NES and PC Engine " , & e - > song . properNoiseLayout ) ;
if ( ImGui : : IsItemHovered ( ) ) {
ImGui : : SetTooltip ( " use a proper noise channel note mapping (0-15) instead of a rather unusual compatible one. \n unlocks all noise frequencies on PC Engine. " ) ;
}
ImGui : : Checkbox ( " Game Boy instrument duty is wave volume " , & e - > song . waveDutyIsVol ) ;
if ( ImGui : : IsItemHovered ( ) ) {
ImGui : : SetTooltip ( " if enabled, an instrument with duty macro in the wave channel will be mapped to wavetable volume. " ) ;
}
2022-02-08 21:15:53 +00:00
ImGui : : Checkbox ( " Restart macro on portamento " , & e - > song . resetMacroOnPorta ) ;
if ( ImGui : : IsItemHovered ( ) ) {
ImGui : : SetTooltip ( " when enabled, a portamento effect will reset the channel's macro if used in combination with a note. " ) ;
}
ImGui : : Checkbox ( " Legacy volume slides " , & e - > song . legacyVolumeSlides ) ;
if ( ImGui : : IsItemHovered ( ) ) {
ImGui : : SetTooltip ( " simulate glitchy volume slide behavior by silently overflowing the volume when the slide goes below 0. " ) ;
}
ImGui : : Checkbox ( " Compatible arpeggio " , & e - > song . compatibleArpeggio ) ;
if ( ImGui : : IsItemHovered ( ) ) {
ImGui : : SetTooltip ( " delay arpeggio by one tick on every new note. " ) ;
}
ImGui : : Checkbox ( " Reset slides after note off " , & e - > song . noteOffResetsSlides ) ;
if ( ImGui : : IsItemHovered ( ) ) {
ImGui : : SetTooltip ( " when enabled, note off will reset the channel's slide effect. " ) ;
}
ImGui : : Checkbox ( " Reset portamento after reaching target " , & e - > song . targetResetsSlides ) ;
if ( ImGui : : IsItemHovered ( ) ) {
ImGui : : SetTooltip ( " when enabled, the slide effect is disabled after it reaches its target. " ) ;
}
2022-02-03 05:34:48 +00:00
ImGui : : Text ( " Loop modality: " ) ;
if ( ImGui : : RadioButton ( " Reset channels " , e - > song . loopModality = = 0 ) ) {
e - > song . loopModality = 0 ;
}
2022-02-06 06:56:50 +00:00
if ( ImGui : : IsItemHovered ( ) ) {
ImGui : : SetTooltip ( " select to reset channels on loop. may trigger a voltage click on every loop! " ) ;
}
2022-02-03 05:34:48 +00:00
if ( ImGui : : RadioButton ( " Soft reset channels " , e - > song . loopModality = = 1 ) ) {
e - > song . loopModality = 1 ;
}
2022-02-06 06:56:50 +00:00
if ( ImGui : : IsItemHovered ( ) ) {
ImGui : : SetTooltip ( " select to turn channels off on loop. " ) ;
}
2022-02-03 05:34:48 +00:00
if ( ImGui : : RadioButton ( " Do nothing " , e - > song . loopModality = = 2 ) ) {
e - > song . loopModality = 2 ;
}
2022-02-06 06:56:50 +00:00
if ( ImGui : : IsItemHovered ( ) ) {
ImGui : : SetTooltip ( " select to not reset channels on loop. " ) ;
}
2022-02-03 05:34:48 +00:00
}
ImGui : : End ( ) ;
}
void FurnaceGUI : : drawPiano ( ) {
if ( ! pianoOpen ) return ;
if ( ImGui : : Begin ( " Piano " , & pianoOpen ) ) {
for ( int i = 0 ; i < e - > getTotalChannelCount ( ) ; i + + ) {
DivChannelState * cs = e - > getChanState ( i ) ;
if ( cs - > keyOn ) {
const char * noteName = NULL ;
if ( cs - > note < - 60 | | cs - > note > 120 ) {
noteName = " ??? " ;
} else {
noteName = noteNames [ cs - > note + 60 ] ;
}
ImGui : : Text ( " %d: %s " , i , noteName ) ;
}
}
}
ImGui : : End ( ) ;
}
2022-02-05 06:57:24 +00:00
// NOTE: please don't ask me to enable text wrap.
// Dear ImGui doesn't have that feature. D:
2022-02-03 05:34:48 +00:00
void FurnaceGUI : : drawNotes ( ) {
if ( ! notesOpen ) return ;
if ( ImGui : : Begin ( " Song Comments " , & notesOpen ) ) {
2022-02-05 06:48:35 +00:00
ImGui : : InputTextMultiline ( " ##SongNotes " , & e - > song . notes , ImGui : : GetContentRegionAvail ( ) ) ;
}
ImGui : : End ( ) ;
}
void FurnaceGUI : : drawChannels ( ) {
if ( ! channelsOpen ) return ;
if ( ImGui : : Begin ( " Channels " , & channelsOpen ) ) {
if ( ImGui : : BeginTable ( " ChannelList " , 3 ) ) {
ImGui : : TableSetupColumn ( " c0 " , ImGuiTableColumnFlags_WidthFixed , 0.0 ) ;
ImGui : : TableSetupColumn ( " c1 " , ImGuiTableColumnFlags_WidthStretch , 0.0 ) ;
ImGui : : TableSetupColumn ( " c2 " , ImGuiTableColumnFlags_WidthFixed , 48.0f * dpiScale ) ;
for ( int i = 0 ; i < e - > getTotalChannelCount ( ) ; i + + ) {
ImGui : : PushID ( i ) ;
ImGui : : TableNextRow ( ) ;
ImGui : : TableNextColumn ( ) ;
ImGui : : Checkbox ( " ##Visible " , & e - > song . chanShow [ i ] ) ;
ImGui : : TableNextColumn ( ) ;
ImGui : : SetNextItemWidth ( ImGui : : GetContentRegionAvail ( ) . x ) ;
ImGui : : InputTextWithHint ( " ##ChanName " , e - > getChannelName ( i ) , & e - > song . chanName [ i ] ) ;
ImGui : : TableNextColumn ( ) ;
ImGui : : SetNextItemWidth ( ImGui : : GetContentRegionAvail ( ) . x ) ;
ImGui : : InputTextWithHint ( " ##ChanShortName " , e - > getChannelShortName ( i ) , & e - > song . chanShortName [ i ] ) ;
ImGui : : PopID ( ) ;
}
ImGui : : EndTable ( ) ;
}
2022-02-03 05:34:48 +00:00
}
ImGui : : End ( ) ;
}
2021-12-14 22:45:37 +00:00
void FurnaceGUI : : startSelection ( int xCoarse , int xFine , int y ) {
2021-12-23 16:29:11 +00:00
if ( xCoarse ! = selStart . xCoarse | | xFine ! = selStart . xFine | | y ! = selStart . y ) {
curNibble = false ;
}
cursor . xCoarse = xCoarse ;
cursor . xFine = xFine ;
cursor . y = y ;
2021-12-14 22:45:37 +00:00
selStart . xCoarse = xCoarse ;
selStart . xFine = xFine ;
selStart . y = y ;
selEnd . xCoarse = xCoarse ;
selEnd . xFine = xFine ;
selEnd . y = y ;
selecting = true ;
}
void FurnaceGUI : : updateSelection ( int xCoarse , int xFine , int y ) {
if ( ! selecting ) return ;
selEnd . xCoarse = xCoarse ;
selEnd . xFine = xFine ;
selEnd . y = y ;
}
void FurnaceGUI : : finishSelection ( ) {
// swap points if needed
if ( selEnd . y < selStart . y ) {
selEnd . y ^ = selStart . y ;
selStart . y ^ = selEnd . y ;
selEnd . y ^ = selStart . y ;
}
if ( selEnd . xCoarse < selStart . xCoarse ) {
selEnd . xCoarse ^ = selStart . xCoarse ;
selStart . xCoarse ^ = selEnd . xCoarse ;
selEnd . xCoarse ^ = selStart . xCoarse ;
selEnd . xFine ^ = selStart . xFine ;
selStart . xFine ^ = selEnd . xFine ;
selEnd . xFine ^ = selStart . xFine ;
} else if ( selEnd . xCoarse = = selStart . xCoarse & & selEnd . xFine < selStart . xFine ) {
selEnd . xFine ^ = selStart . xFine ;
selStart . xFine ^ = selEnd . xFine ;
selEnd . xFine ^ = selStart . xFine ;
}
selecting = false ;
2022-02-05 07:24:23 +00:00
// boundary check
int chanCount = e - > getTotalChannelCount ( ) ;
if ( selStart . xCoarse < 0 ) selStart . xCoarse = 0 ;
if ( selStart . xCoarse > = chanCount ) selStart . xCoarse = chanCount - 1 ;
if ( selStart . y < 0 ) selStart . y = 0 ;
if ( selStart . y > = e - > song . patLen ) selStart . y = e - > song . patLen - 1 ;
if ( selEnd . xCoarse < 0 ) selEnd . xCoarse = 0 ;
if ( selEnd . xCoarse > = chanCount ) selEnd . xCoarse = chanCount - 1 ;
if ( selEnd . y < 0 ) selEnd . y = 0 ;
if ( selEnd . y > = e - > song . patLen ) selEnd . y = e - > song . patLen - 1 ;
if ( cursor . xCoarse < 0 ) cursor . xCoarse = 0 ;
if ( cursor . xCoarse > = chanCount ) cursor . xCoarse = chanCount - 1 ;
if ( cursor . y < 0 ) cursor . y = 0 ;
if ( cursor . y > = e - > song . patLen ) cursor . y = e - > song . patLen - 1 ;
2022-02-05 07:51:56 +00:00
if ( e - > song . chanCollapse [ selEnd . xCoarse ] ) {
selStart . xFine = 0 ;
}
if ( e - > song . chanCollapse [ selEnd . xCoarse ] ) {
selEnd . xFine = 2 + e - > song . pat [ cursor . xCoarse ] . effectRows * 2 ;
}
2021-12-14 22:45:37 +00:00
}
2022-02-05 07:24:23 +00:00
# define DETERMINE_FIRST \
int firstChannel = 0 ; \
for ( int i = 0 ; i < e - > getTotalChannelCount ( ) ; i + + ) { \
if ( e - > song . chanShow [ i ] ) { \
firstChannel = i ; \
break ; \
} \
} \
# define DETERMINE_LAST \
int lastChannel = 0 ; \
for ( int i = e - > getTotalChannelCount ( ) - 1 ; i > = 0 ; i - - ) { \
if ( e - > song . chanShow [ i ] ) { \
lastChannel = i + 1 ; \
break ; \
} \
}
# define DETERMINE_FIRST_LAST \
DETERMINE_FIRST \
DETERMINE_LAST
2022-01-22 08:12:02 +00:00
void FurnaceGUI : : moveCursor ( int x , int y , bool select ) {
if ( ! select ) {
finishSelection ( ) ;
}
2022-02-05 07:24:23 +00:00
DETERMINE_FIRST_LAST ;
2021-12-23 16:29:11 +00:00
curNibble = false ;
2021-12-15 05:37:27 +00:00
if ( x ! = 0 ) {
if ( x > 0 ) {
for ( int i = 0 ; i < x ; i + + ) {
2022-02-05 07:51:56 +00:00
if ( + + cursor . xFine > = ( e - > song . chanCollapse [ cursor . xCoarse ] ? 1 : ( 3 + e - > song . pat [ cursor . xCoarse ] . effectRows * 2 ) ) ) {
2021-12-23 16:29:11 +00:00
cursor . xFine = 0 ;
2022-02-05 07:24:23 +00:00
if ( + + cursor . xCoarse > = lastChannel ) {
2022-01-22 08:12:02 +00:00
if ( settings . wrapHorizontal ! = 0 & & ! select ) {
2022-02-05 07:24:23 +00:00
cursor . xCoarse = firstChannel ;
2022-01-20 18:15:37 +00:00
if ( settings . wrapHorizontal = = 2 ) y + + ;
} else {
2022-02-05 07:24:23 +00:00
cursor . xCoarse = lastChannel - 1 ;
2022-02-05 07:51:56 +00:00
cursor . xFine = e - > song . chanCollapse [ cursor . xCoarse ] ? 0 : ( 2 + e - > song . pat [ cursor . xCoarse ] . effectRows * 2 ) ;
2022-01-20 18:15:37 +00:00
}
2022-02-05 07:24:23 +00:00
} else {
while ( ! e - > song . chanShow [ cursor . xCoarse ] ) {
cursor . xCoarse + + ;
if ( cursor . xCoarse > = e - > getTotalChannelCount ( ) ) break ;
}
2021-12-15 05:37:27 +00:00
}
}
}
} else {
for ( int i = 0 ; i < - x ; i + + ) {
2021-12-23 16:29:11 +00:00
if ( - - cursor . xFine < 0 ) {
2022-02-05 07:24:23 +00:00
if ( - - cursor . xCoarse < firstChannel ) {
2022-01-22 08:12:02 +00:00
if ( settings . wrapHorizontal ! = 0 & & ! select ) {
2022-02-05 07:24:23 +00:00
cursor . xCoarse = lastChannel - 1 ;
2022-01-20 18:15:37 +00:00
cursor . xFine = 2 + e - > song . pat [ cursor . xCoarse ] . effectRows * 2 ;
if ( settings . wrapHorizontal = = 2 ) y - - ;
} else {
2022-02-05 07:24:23 +00:00
cursor . xCoarse = firstChannel ;
2022-01-20 18:15:37 +00:00
cursor . xFine = 0 ;
}
2021-12-15 05:37:27 +00:00
} else {
2022-02-05 07:24:23 +00:00
while ( ! e - > song . chanShow [ cursor . xCoarse ] ) {
cursor . xCoarse - - ;
if ( cursor . xCoarse < 0 ) break ;
}
2022-02-05 07:51:56 +00:00
if ( e - > song . chanCollapse [ cursor . xCoarse ] ) {
cursor . xFine = 0 ;
} else {
cursor . xFine = 2 + e - > song . pat [ cursor . xCoarse ] . effectRows * 2 ;
}
2021-12-15 05:37:27 +00:00
}
}
}
}
}
if ( y ! = 0 ) {
2022-01-20 18:15:37 +00:00
if ( y > 0 ) {
for ( int i = 0 ; i < y ; i + + ) {
cursor . y + + ;
if ( cursor . y > = e - > song . patLen ) {
2022-01-22 08:12:02 +00:00
if ( settings . wrapVertical ! = 0 & & ! select ) {
2022-01-20 18:15:37 +00:00
cursor . y = 0 ;
if ( settings . wrapVertical = = 2 ) {
if ( ! e - > isPlaying ( ) & & e - > getOrder ( ) < ( e - > song . ordersLen - 1 ) ) {
e - > setOrder ( e - > getOrder ( ) + 1 ) ;
} else {
cursor . y = e - > song . patLen - 1 ;
}
}
} else {
cursor . y = e - > song . patLen - 1 ;
}
}
}
} else {
for ( int i = 0 ; i < - y ; i + + ) {
cursor . y - - ;
if ( cursor . y < 0 ) {
2022-01-22 08:12:02 +00:00
if ( settings . wrapVertical ! = 0 & & ! select ) {
2022-01-20 18:15:37 +00:00
cursor . y = e - > song . patLen - 1 ;
if ( settings . wrapVertical = = 2 ) {
if ( ! e - > isPlaying ( ) & & e - > getOrder ( ) > 0 ) {
e - > setOrder ( e - > getOrder ( ) - 1 ) ;
} else {
cursor . y = 0 ;
}
}
} else {
cursor . y = 0 ;
}
}
}
}
2021-12-15 05:37:27 +00:00
}
2022-01-22 08:12:02 +00:00
if ( ! select ) {
selStart = cursor ;
}
2021-12-23 16:29:11 +00:00
selEnd = cursor ;
updateScroll ( cursor . y ) ;
2021-12-15 05:37:27 +00:00
}
2022-01-11 23:54:31 +00:00
void FurnaceGUI : : moveCursorTop ( ) {
finishSelection ( ) ;
curNibble = false ;
if ( cursor . y = = 0 ) {
cursor . xCoarse = 0 ;
cursor . xFine = 0 ;
} else {
cursor . y = 0 ;
}
selStart = cursor ;
selEnd = cursor ;
updateScroll ( cursor . y ) ;
}
void FurnaceGUI : : moveCursorBottom ( ) {
finishSelection ( ) ;
curNibble = false ;
if ( cursor . y = = e - > song . patLen - 1 ) {
cursor . xCoarse = e - > getTotalChannelCount ( ) - 1 ;
cursor . xFine = 2 + e - > song . pat [ cursor . xCoarse ] . effectRows * 2 ;
} else {
cursor . y = e - > song . patLen - 1 ;
}
selStart = cursor ;
selEnd = cursor ;
updateScroll ( cursor . y ) ;
}
2021-12-14 22:45:37 +00:00
void FurnaceGUI : : editAdvance ( ) {
2021-12-15 05:37:27 +00:00
finishSelection ( ) ;
2021-12-23 16:29:11 +00:00
cursor . y + = editStep ;
if ( cursor . y > = e - > song . patLen ) cursor . y = e - > song . patLen - 1 ;
selStart = cursor ;
selEnd = cursor ;
updateScroll ( cursor . y ) ;
2021-12-15 05:37:27 +00:00
}
2021-12-26 23:05:18 +00:00
void FurnaceGUI : : prepareUndo ( ActionType action ) {
int order = e - > getOrder ( ) ;
switch ( action ) {
case GUI_ACTION_CHANGE_ORDER :
oldOrders = e - > song . orders ;
oldOrdersLen = e - > song . ordersLen ;
break ;
case GUI_ACTION_PATTERN_EDIT :
case GUI_ACTION_PATTERN_DELETE :
case GUI_ACTION_PATTERN_PULL :
case GUI_ACTION_PATTERN_PUSH :
case GUI_ACTION_PATTERN_CUT :
case GUI_ACTION_PATTERN_PASTE :
2022-01-08 06:57:37 +00:00
for ( int i = 0 ; i < e - > getTotalChannelCount ( ) ; i + + ) {
2021-12-26 23:05:18 +00:00
memcpy ( oldPat [ i ] , e - > song . pat [ i ] . getPattern ( e - > song . orders . ord [ i ] [ order ] , false ) , sizeof ( DivPattern ) ) ;
}
break ;
}
}
void FurnaceGUI : : makeUndo ( ActionType action ) {
bool doPush = false ;
UndoStep s ;
s . type = action ;
s . cursor = cursor ;
s . selStart = selStart ;
s . selEnd = selEnd ;
int order = e - > getOrder ( ) ;
s . order = order ;
s . nibble = curNibble ;
switch ( action ) {
case GUI_ACTION_CHANGE_ORDER :
2022-01-08 22:15:12 +00:00
for ( int i = 0 ; i < DIV_MAX_CHANS ; i + + ) {
2021-12-26 23:05:18 +00:00
for ( int j = 0 ; j < 128 ; j + + ) {
if ( oldOrders . ord [ i ] [ j ] ! = e - > song . orders . ord [ i ] [ j ] ) {
s . ord . push_back ( UndoOrderData ( i , j , oldOrders . ord [ i ] [ j ] , e - > song . orders . ord [ i ] [ j ] ) ) ;
}
}
}
s . oldOrdersLen = oldOrdersLen ;
s . newOrdersLen = e - > song . ordersLen ;
if ( oldOrdersLen ! = e - > song . ordersLen ) {
doPush = true ;
}
if ( ! s . ord . empty ( ) ) {
doPush = true ;
}
break ;
case GUI_ACTION_PATTERN_EDIT :
case GUI_ACTION_PATTERN_DELETE :
case GUI_ACTION_PATTERN_PULL :
case GUI_ACTION_PATTERN_PUSH :
case GUI_ACTION_PATTERN_CUT :
case GUI_ACTION_PATTERN_PASTE :
2022-01-08 06:57:37 +00:00
for ( int i = 0 ; i < e - > getTotalChannelCount ( ) ; i + + ) {
2021-12-26 23:05:18 +00:00
DivPattern * p = e - > song . pat [ i ] . getPattern ( e - > song . orders . ord [ i ] [ order ] , false ) ;
for ( int j = 0 ; j < e - > song . patLen ; j + + ) {
2022-01-19 22:34:20 +00:00
for ( int k = 0 ; k < 32 ; k + + ) {
2021-12-26 23:05:18 +00:00
if ( p - > data [ j ] [ k ] ! = oldPat [ i ] - > data [ j ] [ k ] ) {
2021-12-26 23:21:25 +00:00
s . pat . push_back ( UndoPatternData ( i , e - > song . orders . ord [ i ] [ order ] , j , k , oldPat [ i ] - > data [ j ] [ k ] , p - > data [ j ] [ k ] ) ) ;
2021-12-26 23:05:18 +00:00
}
}
}
}
if ( ! s . pat . empty ( ) ) {
doPush = true ;
}
break ;
}
if ( doPush ) {
2021-12-30 23:25:55 +00:00
modified = true ;
2021-12-26 23:05:18 +00:00
undoHist . push_back ( s ) ;
redoHist . clear ( ) ;
2022-01-16 22:25:43 +00:00
if ( undoHist . size ( ) > settings . maxUndoSteps ) undoHist . pop_front ( ) ;
2021-12-26 23:05:18 +00:00
}
}
2021-12-29 05:50:00 +00:00
void FurnaceGUI : : doSelectAll ( ) {
finishSelection ( ) ;
curNibble = false ;
if ( selStart . xFine = = 0 & & selEnd . xFine = = 2 + e - > song . pat [ selEnd . xCoarse ] . effectRows * 2 ) {
if ( selStart . y = = 0 & & selEnd . y = = e - > song . patLen - 1 ) { // select entire pattern
selStart . xCoarse = 0 ;
selStart . xFine = 0 ;
2022-01-08 06:57:37 +00:00
selEnd . xCoarse = e - > getTotalChannelCount ( ) - 1 ;
2021-12-29 05:50:00 +00:00
selEnd . xFine = 2 + e - > song . pat [ selEnd . xCoarse ] . effectRows * 2 ;
} else { // select entire column
selStart . y = 0 ;
selEnd . y = e - > song . patLen - 1 ;
}
} else {
int selStartX = 0 ;
int selEndX = 0 ;
// find row position
for ( SelectionPoint i ; i . xCoarse ! = selStart . xCoarse | | i . xFine ! = selStart . xFine ; selStartX + + ) {
i . xFine + + ;
if ( i . xFine > = 3 + e - > song . pat [ i . xCoarse ] . effectRows * 2 ) {
i . xFine = 0 ;
i . xCoarse + + ;
}
}
for ( SelectionPoint i ; i . xCoarse ! = selEnd . xCoarse | | i . xFine ! = selEnd . xFine ; selEndX + + ) {
i . xFine + + ;
if ( i . xFine > = 3 + e - > song . pat [ i . xCoarse ] . effectRows * 2 ) {
i . xFine = 0 ;
i . xCoarse + + ;
}
}
float aspect = float ( selEndX - selStartX + 1 ) / float ( selEnd . y - selStart . y + 1 ) ;
if ( aspect < 1.0f & & ! ( selStart . y = = 0 & & selEnd . y = = e - > song . patLen - 1 ) ) { // up-down
selStart . y = 0 ;
selEnd . y = e - > song . patLen - 1 ;
} else { // left-right
selStart . xFine = 0 ;
selEnd . xFine = 2 + e - > song . pat [ selEnd . xCoarse ] . effectRows * 2 ;
}
}
}
2021-12-15 05:37:27 +00:00
void FurnaceGUI : : doDelete ( ) {
finishSelection ( ) ;
2021-12-26 23:05:18 +00:00
prepareUndo ( GUI_ACTION_PATTERN_DELETE ) ;
2021-12-23 16:29:11 +00:00
curNibble = false ;
2021-12-15 05:37:27 +00:00
int iCoarse = selStart . xCoarse ;
int iFine = selStart . xFine ;
int ord = e - > getOrder ( ) ;
for ( ; iCoarse < = selEnd . xCoarse ; iCoarse + + ) {
2022-02-05 07:24:23 +00:00
if ( ! e - > song . chanShow [ iCoarse ] ) continue ;
2021-12-15 05:37:27 +00:00
DivPattern * pat = e - > song . pat [ iCoarse ] . getPattern ( e - > song . orders . ord [ iCoarse ] [ ord ] , true ) ;
for ( ; iFine < 3 + e - > song . pat [ iCoarse ] . effectRows * 2 & & ( iCoarse < selEnd . xCoarse | | iFine < = selEnd . xFine ) ; iFine + + ) {
for ( int j = selStart . y ; j < = selEnd . y ; j + + ) {
if ( iFine = = 0 ) {
pat - > data [ j ] [ iFine ] = 0 ;
2022-01-11 23:50:44 +00:00
if ( selStart . y = = selEnd . y ) pat - > data [ j ] [ 2 ] = - 1 ;
2021-12-15 05:37:27 +00:00
}
pat - > data [ j ] [ iFine + 1 ] = ( iFine < 1 ) ? 0 : - 1 ;
}
}
iFine = 0 ;
}
2021-12-26 23:05:18 +00:00
makeUndo ( GUI_ACTION_PATTERN_DELETE ) ;
2021-12-14 22:45:37 +00:00
}
2021-12-19 07:12:19 +00:00
void FurnaceGUI : : doPullDelete ( ) {
finishSelection ( ) ;
2021-12-26 23:05:18 +00:00
prepareUndo ( GUI_ACTION_PATTERN_PULL ) ;
2021-12-23 16:29:11 +00:00
curNibble = false ;
2021-12-19 07:12:19 +00:00
2022-01-20 07:53:59 +00:00
if ( settings . pullDeleteBehavior ) {
if ( - - selStart . y < 0 ) selStart . y = 0 ;
if ( - - selEnd . y < 0 ) selEnd . y = 0 ;
if ( - - cursor . y < 0 ) cursor . y = 0 ;
updateScroll ( cursor . y ) ;
}
2021-12-19 07:12:19 +00:00
int iCoarse = selStart . xCoarse ;
int iFine = selStart . xFine ;
int ord = e - > getOrder ( ) ;
for ( ; iCoarse < = selEnd . xCoarse ; iCoarse + + ) {
2022-02-05 07:24:23 +00:00
if ( ! e - > song . chanShow [ iCoarse ] ) continue ;
2021-12-19 07:12:19 +00:00
DivPattern * pat = e - > song . pat [ iCoarse ] . getPattern ( e - > song . orders . ord [ iCoarse ] [ ord ] , true ) ;
for ( ; iFine < 3 + e - > song . pat [ iCoarse ] . effectRows * 2 & & ( iCoarse < selEnd . xCoarse | | iFine < = selEnd . xFine ) ; iFine + + ) {
for ( int j = selStart . y ; j < e - > song . patLen ; j + + ) {
if ( j < e - > song . patLen - 1 ) {
if ( iFine = = 0 ) {
pat - > data [ j ] [ iFine ] = pat - > data [ j + 1 ] [ iFine ] ;
}
pat - > data [ j ] [ iFine + 1 ] = pat - > data [ j + 1 ] [ iFine + 1 ] ;
} else {
if ( iFine = = 0 ) {
pat - > data [ j ] [ iFine ] = 0 ;
}
pat - > data [ j ] [ iFine + 1 ] = ( iFine < 1 ) ? 0 : - 1 ;
}
}
}
iFine = 0 ;
}
2021-12-26 23:05:18 +00:00
makeUndo ( GUI_ACTION_PATTERN_PULL ) ;
2021-12-19 07:12:19 +00:00
}
void FurnaceGUI : : doInsert ( ) {
finishSelection ( ) ;
2021-12-26 23:05:18 +00:00
prepareUndo ( GUI_ACTION_PATTERN_PUSH ) ;
2021-12-23 16:29:11 +00:00
curNibble = false ;
2021-12-19 07:12:19 +00:00
int iCoarse = selStart . xCoarse ;
int iFine = selStart . xFine ;
int ord = e - > getOrder ( ) ;
for ( ; iCoarse < = selEnd . xCoarse ; iCoarse + + ) {
2022-02-05 07:24:23 +00:00
if ( ! e - > song . chanShow [ iCoarse ] ) continue ;
2021-12-19 07:12:19 +00:00
DivPattern * pat = e - > song . pat [ iCoarse ] . getPattern ( e - > song . orders . ord [ iCoarse ] [ ord ] , true ) ;
for ( ; iFine < 3 + e - > song . pat [ iCoarse ] . effectRows * 2 & & ( iCoarse < selEnd . xCoarse | | iFine < = selEnd . xFine ) ; iFine + + ) {
for ( int j = e - > song . patLen - 1 ; j > = selStart . y ; j - - ) {
if ( j = = selStart . y ) {
if ( iFine = = 0 ) {
pat - > data [ j ] [ iFine ] = 0 ;
}
pat - > data [ j ] [ iFine + 1 ] = ( iFine < 1 ) ? 0 : - 1 ;
} else {
if ( iFine = = 0 ) {
pat - > data [ j ] [ iFine ] = pat - > data [ j - 1 ] [ iFine ] ;
}
pat - > data [ j ] [ iFine + 1 ] = pat - > data [ j - 1 ] [ iFine + 1 ] ;
}
}
}
iFine = 0 ;
}
2021-12-26 23:05:18 +00:00
makeUndo ( GUI_ACTION_PATTERN_PUSH ) ;
2021-12-19 07:12:19 +00:00
}
2022-01-17 07:06:05 +00:00
void FurnaceGUI : : doTranspose ( int amount ) {
finishSelection ( ) ;
prepareUndo ( GUI_ACTION_PATTERN_DELETE ) ;
curNibble = false ;
int iCoarse = selStart . xCoarse ;
int iFine = selStart . xFine ;
int ord = e - > getOrder ( ) ;
for ( ; iCoarse < = selEnd . xCoarse ; iCoarse + + ) {
2022-02-05 07:24:23 +00:00
if ( ! e - > song . chanShow [ iCoarse ] ) continue ;
2022-01-17 07:06:05 +00:00
DivPattern * pat = e - > song . pat [ iCoarse ] . getPattern ( e - > song . orders . ord [ iCoarse ] [ ord ] , true ) ;
for ( ; iFine < 3 + e - > song . pat [ iCoarse ] . effectRows * 2 & & ( iCoarse < selEnd . xCoarse | | iFine < = selEnd . xFine ) ; iFine + + ) {
for ( int j = selStart . y ; j < = selEnd . y ; j + + ) {
if ( iFine = = 0 ) {
int origNote = pat - > data [ j ] [ 0 ] ;
2022-01-20 21:21:35 +00:00
int origOctave = ( signed char ) pat - > data [ j ] [ 1 ] ;
2022-02-08 08:50:42 +00:00
if ( origNote ! = 0 & & origNote ! = 100 & & origNote ! = 101 & & origNote ! = 102 ) {
2022-01-17 07:06:05 +00:00
origNote + = amount ;
while ( origNote > 12 ) {
origNote - = 12 ;
origOctave + + ;
}
while ( origNote < 1 ) {
origNote + = 12 ;
origOctave - - ;
}
if ( origOctave > 7 ) {
origNote = 12 ;
origOctave = 7 ;
}
2022-01-20 21:21:35 +00:00
if ( origOctave < - 5 ) {
2022-01-17 07:06:05 +00:00
origNote = 1 ;
2022-01-20 21:21:35 +00:00
origOctave = - 5 ;
2022-01-17 07:06:05 +00:00
}
pat - > data [ j ] [ 0 ] = origNote ;
2022-01-20 21:21:35 +00:00
pat - > data [ j ] [ 1 ] = ( unsigned char ) origOctave ;
2022-01-17 07:06:05 +00:00
}
}
}
}
iFine = 0 ;
}
makeUndo ( GUI_ACTION_PATTERN_DELETE ) ;
}
2021-12-19 07:12:19 +00:00
void FurnaceGUI : : doCopy ( bool cut ) {
finishSelection ( ) ;
2021-12-26 23:05:18 +00:00
if ( cut ) {
curNibble = false ;
prepareUndo ( GUI_ACTION_PATTERN_CUT ) ;
}
2021-12-19 07:12:19 +00:00
clipboard = fmt : : sprintf ( " org.tildearrow.furnace - Pattern Data (%d) \n %d " , DIV_ENGINE_VERSION , selStart . xFine ) ;
for ( int j = selStart . y ; j < = selEnd . y ; j + + ) {
int iCoarse = selStart . xCoarse ;
int iFine = selStart . xFine ;
2022-02-02 08:23:33 +00:00
if ( iFine > 3 & & ! ( iFine & 1 ) ) {
iFine - - ;
}
2021-12-19 07:12:19 +00:00
int ord = e - > getOrder ( ) ;
clipboard + = ' \n ' ;
for ( ; iCoarse < = selEnd . xCoarse ; iCoarse + + ) {
2022-02-05 07:24:23 +00:00
if ( ! e - > song . chanShow [ iCoarse ] ) continue ;
2021-12-19 07:12:19 +00:00
DivPattern * pat = e - > song . pat [ iCoarse ] . getPattern ( e - > song . orders . ord [ iCoarse ] [ ord ] , true ) ;
for ( ; iFine < 3 + e - > song . pat [ iCoarse ] . effectRows * 2 & & ( iCoarse < selEnd . xCoarse | | iFine < = selEnd . xFine ) ; iFine + + ) {
if ( iFine = = 0 ) {
2022-02-03 19:40:09 +00:00
clipboard + = noteNameNormal ( pat - > data [ j ] [ 0 ] , pat - > data [ j ] [ 1 ] ) ;
2021-12-19 07:12:19 +00:00
if ( cut ) {
pat - > data [ j ] [ 0 ] = 0 ;
pat - > data [ j ] [ 1 ] = 0 ;
}
} else {
if ( pat - > data [ j ] [ iFine + 1 ] = = - 1 ) {
clipboard + = " .. " ;
} else {
clipboard + = fmt : : sprintf ( " %.2X " , pat - > data [ j ] [ iFine + 1 ] ) ;
}
if ( cut ) {
pat - > data [ j ] [ iFine + 1 ] = - 1 ;
}
}
}
clipboard + = ' | ' ;
iFine = 0 ;
}
}
SDL_SetClipboardText ( clipboard . c_str ( ) ) ;
2021-12-26 23:05:18 +00:00
if ( cut ) {
makeUndo ( GUI_ACTION_PATTERN_CUT ) ;
}
2021-12-19 07:12:19 +00:00
}
void FurnaceGUI : : doPaste ( ) {
finishSelection ( ) ;
2021-12-26 23:05:18 +00:00
prepareUndo ( GUI_ACTION_PATTERN_PASTE ) ;
2021-12-19 07:12:19 +00:00
char * clipText = SDL_GetClipboardText ( ) ;
if ( clipText ! = NULL ) {
if ( clipText [ 0 ] ) {
clipboard = clipText ;
}
SDL_free ( clipText ) ;
}
std : : vector < String > data ;
String tempS ;
for ( char i : clipboard ) {
if ( i = = ' \r ' ) continue ;
if ( i = = ' \n ' ) {
data . push_back ( tempS ) ;
tempS = " " ;
continue ;
}
tempS + = i ;
}
data . push_back ( tempS ) ;
int startOff = - 1 ;
bool invalidData = false ;
if ( data . size ( ) < 2 ) return ;
if ( data [ 0 ] ! = fmt : : sprintf ( " org.tildearrow.furnace - Pattern Data (%d) " , DIV_ENGINE_VERSION ) ) return ;
if ( sscanf ( data [ 1 ] . c_str ( ) , " %d " , & startOff ) ! = 1 ) return ;
if ( startOff < 0 ) return ;
2022-02-05 07:24:23 +00:00
DETERMINE_LAST ;
2021-12-23 16:29:11 +00:00
int j = cursor . y ;
2021-12-19 07:12:19 +00:00
char note [ 4 ] ;
int ord = e - > getOrder ( ) ;
for ( size_t i = 2 ; i < data . size ( ) & & j < e - > song . patLen ; i + + ) {
size_t charPos = 0 ;
2021-12-23 16:29:11 +00:00
int iCoarse = cursor . xCoarse ;
int iFine = ( startOff > 2 & & cursor . xFine > 2 ) ? ( ( ( cursor . xFine - 1 ) & ( ~ 1 ) ) | 1 ) : startOff ;
2021-12-19 07:12:19 +00:00
String & line = data [ i ] ;
2022-02-05 07:24:23 +00:00
while ( charPos < line . size ( ) & & iCoarse < lastChannel ) {
2021-12-19 07:12:19 +00:00
DivPattern * pat = e - > song . pat [ iCoarse ] . getPattern ( e - > song . orders . ord [ iCoarse ] [ ord ] , true ) ;
if ( line [ charPos ] = = ' | ' ) {
iCoarse + + ;
2022-02-05 07:24:23 +00:00
if ( iCoarse < lastChannel ) while ( ! e - > song . chanShow [ iCoarse ] ) {
iCoarse + + ;
if ( iCoarse > = lastChannel ) break ;
}
2021-12-19 07:12:19 +00:00
iFine = 0 ;
charPos + + ;
continue ;
}
if ( iFine = = 0 ) {
if ( charPos > = line . size ( ) ) {
invalidData = true ;
break ;
}
note [ 0 ] = line [ charPos + + ] ;
if ( charPos > = line . size ( ) ) {
invalidData = true ;
break ;
}
note [ 1 ] = line [ charPos + + ] ;
if ( charPos > = line . size ( ) ) {
invalidData = true ;
break ;
}
note [ 2 ] = line [ charPos + + ] ;
note [ 3 ] = 0 ;
if ( ! decodeNote ( note , pat - > data [ j ] [ 0 ] , pat - > data [ j ] [ 1 ] ) ) {
invalidData = true ;
break ;
}
} else {
if ( charPos > = line . size ( ) ) {
invalidData = true ;
break ;
}
note [ 0 ] = line [ charPos + + ] ;
if ( charPos > = line . size ( ) ) {
invalidData = true ;
break ;
}
note [ 1 ] = line [ charPos + + ] ;
note [ 2 ] = 0 ;
if ( strcmp ( note , " .. " ) = = 0 ) {
pat - > data [ j ] [ iFine + 1 ] = - 1 ;
} else {
unsigned int val = 0 ;
if ( sscanf ( note , " %2X " , & val ) ! = 1 ) {
invalidData = true ;
break ;
}
2021-12-23 16:29:11 +00:00
if ( iFine < ( 3 + e - > song . pat [ cursor . xCoarse ] . effectRows * 2 ) ) pat - > data [ j ] [ iFine + 1 ] = val ;
2021-12-19 07:12:19 +00:00
}
}
iFine + + ;
}
if ( invalidData ) {
logW ( " invalid clipboard data! failed at line %d char %d \n " , i , charPos ) ;
logW ( " %s \n " , line . c_str ( ) ) ;
break ;
}
j + + ;
}
2021-12-26 23:05:18 +00:00
makeUndo ( GUI_ACTION_PATTERN_PASTE ) ;
}
void FurnaceGUI : : doUndo ( ) {
if ( undoHist . empty ( ) ) return ;
UndoStep & us = undoHist . back ( ) ;
redoHist . push_back ( us ) ;
2021-12-30 23:25:55 +00:00
modified = true ;
2021-12-26 23:05:18 +00:00
switch ( us . type ) {
case GUI_ACTION_CHANGE_ORDER :
e - > song . ordersLen = us . oldOrdersLen ;
for ( UndoOrderData & i : us . ord ) {
e - > song . orders . ord [ i . chan ] [ i . ord ] = i . oldVal ;
}
break ;
case GUI_ACTION_PATTERN_EDIT :
case GUI_ACTION_PATTERN_DELETE :
case GUI_ACTION_PATTERN_PULL :
case GUI_ACTION_PATTERN_PUSH :
case GUI_ACTION_PATTERN_CUT :
case GUI_ACTION_PATTERN_PASTE :
for ( UndoPatternData & i : us . pat ) {
DivPattern * p = e - > song . pat [ i . chan ] . getPattern ( i . pat , true ) ;
p - > data [ i . row ] [ i . col ] = i . oldVal ;
}
if ( ! e - > isPlaying ( ) ) {
cursor = us . cursor ;
selStart = us . selStart ;
selEnd = us . selEnd ;
curNibble = us . nibble ;
updateScroll ( cursor . y ) ;
e - > setOrder ( us . order ) ;
}
break ;
}
undoHist . pop_back ( ) ;
}
void FurnaceGUI : : doRedo ( ) {
2021-12-26 23:28:06 +00:00
if ( redoHist . empty ( ) ) return ;
UndoStep & us = redoHist . back ( ) ;
undoHist . push_back ( us ) ;
2021-12-30 23:25:55 +00:00
modified = true ;
2021-12-26 23:05:18 +00:00
2021-12-26 23:28:06 +00:00
switch ( us . type ) {
case GUI_ACTION_CHANGE_ORDER :
e - > song . ordersLen = us . newOrdersLen ;
for ( UndoOrderData & i : us . ord ) {
e - > song . orders . ord [ i . chan ] [ i . ord ] = i . newVal ;
}
break ;
case GUI_ACTION_PATTERN_EDIT :
case GUI_ACTION_PATTERN_DELETE :
case GUI_ACTION_PATTERN_PULL :
case GUI_ACTION_PATTERN_PUSH :
case GUI_ACTION_PATTERN_CUT :
case GUI_ACTION_PATTERN_PASTE :
for ( UndoPatternData & i : us . pat ) {
DivPattern * p = e - > song . pat [ i . chan ] . getPattern ( i . pat , true ) ;
p - > data [ i . row ] [ i . col ] = i . newVal ;
}
if ( ! e - > isPlaying ( ) ) {
cursor = us . cursor ;
selStart = us . selStart ;
selEnd = us . selEnd ;
curNibble = us . nibble ;
updateScroll ( cursor . y ) ;
e - > setOrder ( us . order ) ;
}
break ;
}
redoHist . pop_back ( ) ;
2021-12-19 07:12:19 +00:00
}
2022-02-06 05:07:35 +00:00
void FurnaceGUI : : play ( int row ) {
2022-01-27 06:04:26 +00:00
e - > walkSong ( loopOrder , loopRow , loopEnd ) ;
2022-02-06 05:07:35 +00:00
if ( row > 0 ) {
e - > playToRow ( row ) ;
} else {
e - > play ( ) ;
}
2022-01-20 06:32:16 +00:00
curNibble = false ;
2022-01-20 07:11:03 +00:00
orderNibble = false ;
2022-01-20 06:32:16 +00:00
activeNotes . clear ( ) ;
}
void FurnaceGUI : : stop ( ) {
2022-01-27 06:04:26 +00:00
e - > walkSong ( loopOrder , loopRow , loopEnd ) ;
2022-01-20 06:32:16 +00:00
e - > stop ( ) ;
curNibble = false ;
2022-01-20 07:11:03 +00:00
orderNibble = false ;
2022-01-20 06:32:16 +00:00
activeNotes . clear ( ) ;
}
void FurnaceGUI : : previewNote ( int refChan , int note ) {
bool chanBusy [ DIV_MAX_CHANS ] ;
memset ( chanBusy , 0 , DIV_MAX_CHANS * sizeof ( bool ) ) ;
for ( ActiveNote & i : activeNotes ) {
if ( i . chan < 0 | | i . chan > = DIV_MAX_CHANS ) continue ;
chanBusy [ i . chan ] = true ;
}
int chanCount = e - > getTotalChannelCount ( ) ;
int i = refChan ;
do {
if ( ! chanBusy [ i ] ) {
e - > noteOn ( i , curIns , note ) ;
activeNotes . push_back ( ActiveNote ( i , note ) ) ;
//printf("PUSHING: %d NOTE %d\n",i,note);
return ;
}
i + + ;
if ( i > = chanCount ) i = 0 ;
} while ( i ! = refChan ) ;
//printf("FAILED TO FIND CHANNEL!\n");
}
void FurnaceGUI : : stopPreviewNote ( SDL_Scancode scancode ) {
if ( activeNotes . empty ( ) ) return ;
try {
int key = noteKeys . at ( scancode ) ;
int num = 12 * curOctave + key ;
if ( key = = 100 ) return ;
2022-02-08 08:50:42 +00:00
if ( key = = 101 ) return ;
if ( key = = 102 ) return ;
2022-01-20 06:32:16 +00:00
for ( size_t i = 0 ; i < activeNotes . size ( ) ; i + + ) {
if ( activeNotes [ i ] . note = = num ) {
e - > noteOff ( activeNotes [ i ] . chan ) ;
//printf("REMOVING %d\n",activeNotes[i].chan);
activeNotes . erase ( activeNotes . begin ( ) + i ) ;
break ;
}
}
} catch ( std : : out_of_range & e ) {
}
}
2021-12-14 22:45:37 +00:00
void FurnaceGUI : : keyDown ( SDL_Event & ev ) {
2021-12-21 22:42:27 +00:00
// GLOBAL KEYS
2022-01-22 21:34:44 +00:00
if ( ev . key . keysym . mod & CMD_MODIFIER ) {
2022-02-05 04:21:00 +00:00
if ( ! ImGuiFileDialog : : Instance ( ) - > IsOpened ( ) ) switch ( ev . key . keysym . sym ) {
case SDLK_o :
if ( modified ) {
showWarning ( " Unsaved changes! Are you sure? " , GUI_WARN_OPEN ) ;
} else {
openFileDialog ( GUI_FILE_OPEN ) ;
}
break ;
case SDLK_s :
2022-02-05 04:21:42 +00:00
if ( curFileName = = " " | | ev . key . keysym . mod & KMOD_SHIFT ) {
2022-02-05 04:21:00 +00:00
openFileDialog ( GUI_FILE_SAVE ) ;
} else {
if ( save ( curFileName ) > 0 ) {
showError ( fmt : : sprintf ( " Error while saving file! (%s) " , lastError ) ) ;
}
}
break ;
2021-12-27 04:54:56 +00:00
case SDLK_z :
if ( ev . key . keysym . mod & KMOD_SHIFT ) {
doRedo ( ) ;
} else {
doUndo ( ) ;
}
break ;
2022-02-06 05:42:07 +00:00
case SDLK_RETURN :
e - > stepOne ( cursor . y ) ;
break ;
2021-12-27 04:54:56 +00:00
}
} else switch ( ev . key . keysym . sym ) {
2021-12-21 22:42:27 +00:00
case SDLK_F5 :
2022-01-16 06:37:16 +00:00
if ( ! e - > isPlaying ( ) ) {
2022-01-20 06:32:16 +00:00
play ( ) ;
2022-01-16 06:37:16 +00:00
}
2021-12-21 22:42:27 +00:00
break ;
case SDLK_F6 :
2022-01-20 06:32:16 +00:00
play ( ) ;
2021-12-21 22:42:27 +00:00
break ;
case SDLK_F7 :
2022-02-06 05:07:35 +00:00
if ( ! e - > isPlaying ( ) ) {
play ( cursor . y ) ;
}
2021-12-21 22:42:27 +00:00
break ;
case SDLK_F8 :
2022-01-20 06:32:16 +00:00
stop ( ) ;
2021-12-21 22:42:27 +00:00
break ;
2022-01-25 05:08:46 +00:00
case SDLK_KP_DIVIDE :
2022-02-01 08:28:36 +00:00
if ( - - curOctave < - 5 ) {
curOctave = - 5 ;
} else {
for ( size_t i = 0 ; i < activeNotes . size ( ) ; i + + ) {
e - > noteOff ( activeNotes [ i ] . chan ) ;
}
activeNotes . clear ( ) ;
}
2022-01-25 05:08:46 +00:00
break ;
case SDLK_KP_MULTIPLY :
2022-02-01 08:28:36 +00:00
if ( + + curOctave > 6 ) {
curOctave = 6 ;
} else {
for ( size_t i = 0 ; i < activeNotes . size ( ) ; i + + ) {
e - > noteOff ( activeNotes [ i ] . chan ) ;
}
activeNotes . clear ( ) ;
}
2022-01-25 05:08:46 +00:00
break ;
2021-12-23 16:29:11 +00:00
case SDLK_RETURN :
2022-02-06 05:42:07 +00:00
if ( e - > isPlaying ( ) & & ! e - > isStepping ( ) ) {
2022-01-20 06:32:16 +00:00
stop ( ) ;
2021-12-23 16:29:11 +00:00
} else {
2022-02-06 05:07:35 +00:00
if ( ev . key . keysym . mod & KMOD_SHIFT ) {
play ( cursor . y ) ;
} else {
play ( ) ;
}
2021-12-23 16:29:11 +00:00
}
break ;
2021-12-21 22:42:27 +00:00
}
// PER-WINDOW KEYS
2021-12-14 22:45:37 +00:00
switch ( curWindow ) {
2022-01-20 07:11:03 +00:00
case GUI_WINDOW_ORDERS : {
if ( orderEditMode ! = 0 ) {
try {
int num = valueKeys . at ( ev . key . keysym . sym ) ;
if ( orderCursor > = 0 & & orderCursor < e - > getTotalChannelCount ( ) ) {
int curOrder = e - > getOrder ( ) ;
e - > song . orders . ord [ orderCursor ] [ curOrder ] = ( ( e - > song . orders . ord [ orderCursor ] [ curOrder ] < < 4 ) | num ) & 0x7f ;
if ( orderEditMode = = 2 | | orderEditMode = = 3 ) {
curNibble = ! curNibble ;
if ( ! curNibble ) {
if ( orderEditMode = = 2 ) {
orderCursor + + ;
if ( orderCursor > = e - > getTotalChannelCount ( ) ) orderCursor = 0 ;
} else if ( orderEditMode = = 3 ) {
if ( curOrder < e - > song . ordersLen - 1 ) {
e - > setOrder ( curOrder + 1 ) ;
}
}
}
}
2022-01-27 06:04:26 +00:00
e - > walkSong ( loopOrder , loopRow , loopEnd ) ;
2022-01-20 07:11:03 +00:00
}
} catch ( std : : out_of_range & e ) {
}
}
break ;
}
2021-12-14 22:45:37 +00:00
case GUI_WINDOW_PATTERN : {
2022-01-22 21:34:44 +00:00
if ( ev . key . keysym . mod & CMD_MODIFIER ) {
2021-12-19 07:12:19 +00:00
switch ( ev . key . keysym . sym ) {
2022-01-17 07:06:05 +00:00
case SDLK_F1 :
doTranspose ( - 1 ) ;
break ;
case SDLK_F2 :
doTranspose ( 1 ) ;
break ;
case SDLK_F3 :
doTranspose ( - 12 ) ;
break ;
case SDLK_F4 :
doTranspose ( 12 ) ;
break ;
2021-12-29 05:50:00 +00:00
case SDLK_a :
doSelectAll ( ) ;
break ;
2021-12-19 07:12:19 +00:00
case SDLK_x :
doCopy ( true ) ;
break ;
case SDLK_c :
doCopy ( false ) ;
break ;
case SDLK_v :
doPaste ( ) ;
break ;
}
2021-12-23 16:29:11 +00:00
} else if ( ev . key . keysym . mod & KMOD_ALT ) {
// nothing. prevents accidental OFF note.
2021-12-19 07:12:19 +00:00
} else switch ( ev . key . keysym . sym ) {
2021-12-28 23:23:57 +00:00
case SDLK_SPACE :
edit = ! edit ;
break ;
2021-12-15 05:37:27 +00:00
case SDLK_UP :
2022-02-04 05:03:30 +00:00
moveCursor ( 0 , - MAX ( 1 , settings . scrollStep ? editStep : 1 ) , ev . key . keysym . mod & KMOD_SHIFT ) ;
2021-12-15 05:37:27 +00:00
break ;
case SDLK_DOWN :
2022-02-04 05:03:30 +00:00
moveCursor ( 0 , MAX ( 1 , settings . scrollStep ? editStep : 1 ) , ev . key . keysym . mod & KMOD_SHIFT ) ;
2021-12-15 05:37:27 +00:00
break ;
case SDLK_LEFT :
2022-01-22 08:12:02 +00:00
moveCursor ( - 1 , 0 , ev . key . keysym . mod & KMOD_SHIFT ) ;
2021-12-15 05:37:27 +00:00
break ;
case SDLK_RIGHT :
2022-01-22 08:12:02 +00:00
moveCursor ( 1 , 0 , ev . key . keysym . mod & KMOD_SHIFT ) ;
2021-12-15 05:37:27 +00:00
break ;
case SDLK_PAGEUP :
2022-01-22 08:12:02 +00:00
moveCursor ( 0 , - 16 , ev . key . keysym . mod & KMOD_SHIFT ) ;
2021-12-15 05:37:27 +00:00
break ;
case SDLK_PAGEDOWN :
2022-01-22 08:12:02 +00:00
moveCursor ( 0 , 16 , ev . key . keysym . mod & KMOD_SHIFT ) ;
2021-12-15 05:37:27 +00:00
break ;
2022-01-11 23:54:31 +00:00
case SDLK_HOME :
2022-02-07 07:47:32 +00:00
if ( ev . key . keysym . mod & KMOD_SHIFT ) {
moveCursor ( 0 , - 1 , false ) ;
} else {
moveCursorTop ( ) ;
}
2022-01-11 23:54:31 +00:00
break ;
case SDLK_END :
2022-02-07 07:47:32 +00:00
if ( ev . key . keysym . mod & KMOD_SHIFT ) {
moveCursor ( 0 , 1 , false ) ;
} else {
moveCursorBottom ( ) ;
}
2022-01-11 23:54:31 +00:00
break ;
2021-12-15 05:37:27 +00:00
case SDLK_DELETE :
doDelete ( ) ;
2022-02-04 05:03:30 +00:00
if ( settings . stepOnDelete ) {
moveCursor ( 0 , editStep , false ) ;
}
2021-12-15 05:37:27 +00:00
break ;
2021-12-19 07:12:19 +00:00
case SDLK_BACKSPACE :
doPullDelete ( ) ;
break ;
case SDLK_INSERT :
doInsert ( ) ;
break ;
2021-12-15 05:37:27 +00:00
default :
2021-12-28 23:23:57 +00:00
if ( ! ev . key . repeat ) {
if ( cursor . xFine = = 0 ) { // note
try {
2022-01-17 19:53:46 +00:00
int key = noteKeys . at ( ev . key . keysym . scancode ) ;
2021-12-28 23:23:57 +00:00
int num = 12 * curOctave + key ;
if ( edit ) {
DivPattern * pat = e - > song . pat [ cursor . xCoarse ] . getPattern ( e - > song . orders . ord [ cursor . xCoarse ] [ e - > getOrder ( ) ] , true ) ;
prepareUndo ( GUI_ACTION_PATTERN_EDIT ) ;
if ( key = = 100 ) { // note off
pat - > data [ cursor . y ] [ 0 ] = 100 ;
pat - > data [ cursor . y ] [ 1 ] = 0 ;
2022-02-08 08:50:42 +00:00
} else if ( key = = 101 ) { // note off + env release
pat - > data [ cursor . y ] [ 0 ] = 101 ;
pat - > data [ cursor . y ] [ 1 ] = 0 ;
} else if ( key = = 102 ) { // env release only
pat - > data [ cursor . y ] [ 0 ] = 102 ;
pat - > data [ cursor . y ] [ 1 ] = 0 ;
2021-12-28 23:23:57 +00:00
} else {
pat - > data [ cursor . y ] [ 0 ] = num % 12 ;
pat - > data [ cursor . y ] [ 1 ] = num / 12 ;
if ( pat - > data [ cursor . y ] [ 0 ] = = 0 ) {
pat - > data [ cursor . y ] [ 0 ] = 12 ;
pat - > data [ cursor . y ] [ 1 ] - - ;
}
2022-01-20 21:21:35 +00:00
pat - > data [ cursor . y ] [ 1 ] = ( unsigned char ) pat - > data [ cursor . y ] [ 1 ] ;
2021-12-28 23:23:57 +00:00
pat - > data [ cursor . y ] [ 2 ] = curIns ;
2022-01-20 06:32:16 +00:00
previewNote ( cursor . xCoarse , num ) ;
2021-12-28 23:23:57 +00:00
}
makeUndo ( GUI_ACTION_PATTERN_EDIT ) ;
2021-12-15 05:37:27 +00:00
editAdvance ( ) ;
2021-12-28 23:23:57 +00:00
curNibble = false ;
2021-12-15 05:37:27 +00:00
} else {
2022-02-08 08:50:42 +00:00
if ( key ! = 100 & & key ! = 101 & & key ! = 102 ) {
2022-01-20 06:32:16 +00:00
previewNote ( cursor . xCoarse , num ) ;
2021-12-29 04:10:30 +00:00
}
2021-12-15 05:37:27 +00:00
}
2021-12-28 23:23:57 +00:00
} catch ( std : : out_of_range & e ) {
}
} else if ( edit ) { // value
try {
int num = valueKeys . at ( ev . key . keysym . sym ) ;
DivPattern * pat = e - > song . pat [ cursor . xCoarse ] . getPattern ( e - > song . orders . ord [ cursor . xCoarse ] [ e - > getOrder ( ) ] , true ) ;
prepareUndo ( GUI_ACTION_PATTERN_EDIT ) ;
if ( pat - > data [ cursor . y ] [ cursor . xFine + 1 ] = = - 1 ) pat - > data [ cursor . y ] [ cursor . xFine + 1 ] = 0 ;
pat - > data [ cursor . y ] [ cursor . xFine + 1 ] = ( ( pat - > data [ cursor . y ] [ cursor . xFine + 1 ] < < 4 ) | num ) & 0xff ;
if ( cursor . xFine = = 1 ) { // instrument
if ( pat - > data [ cursor . y ] [ cursor . xFine + 1 ] > = ( int ) e - > song . ins . size ( ) ) {
2022-01-11 23:43:19 +00:00
pat - > data [ cursor . y ] [ cursor . xFine + 1 ] & = 0x0f ;
if ( pat - > data [ cursor . y ] [ cursor . xFine + 1 ] > = ( int ) e - > song . ins . size ( ) ) {
pat - > data [ cursor . y ] [ cursor . xFine + 1 ] = ( int ) e - > song . ins . size ( ) - 1 ;
}
2021-12-28 23:23:57 +00:00
}
makeUndo ( GUI_ACTION_PATTERN_EDIT ) ;
if ( e - > song . ins . size ( ) < 16 ) {
curNibble = false ;
editAdvance ( ) ;
} else {
curNibble = ! curNibble ;
if ( ! curNibble ) editAdvance ( ) ;
}
2022-02-02 09:23:36 +00:00
} else if ( cursor . xFine = = 2 ) {
if ( curNibble ) {
if ( pat - > data [ cursor . y ] [ cursor . xFine + 1 ] > e - > getMaxVolumeChan ( cursor . xCoarse ) ) pat - > data [ cursor . y ] [ cursor . xFine + 1 ] = e - > getMaxVolumeChan ( cursor . xCoarse ) ;
} else {
pat - > data [ cursor . y ] [ cursor . xFine + 1 ] & = 15 ;
}
2021-12-28 23:23:57 +00:00
makeUndo ( GUI_ACTION_PATTERN_EDIT ) ;
if ( e - > getMaxVolumeChan ( cursor . xCoarse ) < 16 ) {
curNibble = false ;
editAdvance ( ) ;
} else {
curNibble = ! curNibble ;
if ( ! curNibble ) editAdvance ( ) ;
}
2021-12-15 05:37:27 +00:00
} else {
2021-12-28 23:23:57 +00:00
makeUndo ( GUI_ACTION_PATTERN_EDIT ) ;
2021-12-15 05:37:27 +00:00
curNibble = ! curNibble ;
if ( ! curNibble ) editAdvance ( ) ;
}
2021-12-28 23:23:57 +00:00
} catch ( std : : out_of_range & e ) {
2021-12-15 05:37:27 +00:00
}
}
}
break ;
2021-12-14 22:45:37 +00:00
}
break ;
}
2021-12-31 22:14:30 +00:00
case GUI_WINDOW_INS_EDIT :
case GUI_WINDOW_INS_LIST :
2022-01-30 23:10:41 +00:00
case GUI_WINDOW_EDIT_CONTROLS :
case GUI_WINDOW_SONG_INFO :
2021-12-31 22:14:30 +00:00
if ( ! ev . key . repeat ) {
try {
2022-01-17 19:53:46 +00:00
int key = noteKeys . at ( ev . key . keysym . scancode ) ;
2021-12-31 22:14:30 +00:00
int num = 12 * curOctave + key ;
2022-02-08 08:50:42 +00:00
if ( key ! = 100 & & key ! = 101 & & key ! = 102 ) {
2022-01-20 06:32:16 +00:00
previewNote ( cursor . xCoarse , num ) ;
2021-12-31 22:14:30 +00:00
}
} catch ( std : : out_of_range & e ) {
}
}
break ;
2022-01-20 21:51:31 +00:00
case GUI_WINDOW_SAMPLE_EDIT :
case GUI_WINDOW_SAMPLE_LIST :
if ( ! ev . key . repeat ) {
try {
int key = noteKeys . at ( ev . key . keysym . scancode ) ;
int num = 12 * curOctave + key ;
2022-02-08 08:50:42 +00:00
if ( key ! = 100 & & key ! = 101 & & key ! = 102 ) {
2022-01-20 21:51:31 +00:00
e - > previewSample ( curSample , num ) ;
samplePreviewOn = true ;
samplePreviewKey = ev . key . keysym . scancode ;
samplePreviewNote = num ;
}
} catch ( std : : out_of_range & e ) {
}
}
break ;
2022-01-20 05:07:53 +00:00
case GUI_WINDOW_WAVE_LIST :
case GUI_WINDOW_WAVE_EDIT :
if ( ! ev . key . repeat ) {
try {
int key = noteKeys . at ( ev . key . keysym . scancode ) ;
int num = 12 * curOctave + key ;
2022-02-08 08:50:42 +00:00
if ( key ! = 100 & & key ! = 101 & & key ! = 102 ) {
2022-01-20 05:07:53 +00:00
e - > previewWave ( curWave , num ) ;
wavePreviewOn = true ;
wavePreviewKey = ev . key . keysym . scancode ;
wavePreviewNote = num ;
}
} catch ( std : : out_of_range & e ) {
}
}
break ;
2021-12-14 22:45:37 +00:00
default :
break ;
}
}
void FurnaceGUI : : keyUp ( SDL_Event & ev ) {
2022-01-20 06:32:16 +00:00
stopPreviewNote ( ev . key . keysym . scancode ) ;
2022-01-20 05:07:53 +00:00
if ( wavePreviewOn ) {
if ( ev . key . keysym . scancode = = wavePreviewKey ) {
wavePreviewOn = false ;
e - > stopWavePreview ( ) ;
}
}
2022-01-20 21:51:31 +00:00
if ( samplePreviewOn ) {
if ( ev . key . keysym . scancode = = samplePreviewKey ) {
samplePreviewOn = false ;
e - > stopSamplePreview ( ) ;
}
}
2021-12-14 22:45:37 +00:00
}
2022-01-19 10:44:19 +00:00
bool dirExists ( String what ) {
# ifdef _WIN32
WString ws = utf8To16 ( what . c_str ( ) ) ;
return ( PathIsDirectoryW ( ws . c_str ( ) ) ! = FALSE ) ;
# else
struct stat st ;
if ( stat ( what . c_str ( ) , & st ) < 0 ) return false ;
return ( st . st_mode & S_IFDIR ) ;
# endif
}
2021-12-17 08:33:12 +00:00
void FurnaceGUI : : openFileDialog ( FurnaceGUIFileDialogs type ) {
2022-01-19 10:44:19 +00:00
if ( ! dirExists ( workingDir ) ) workingDir = getHomeDir ( ) ;
2021-12-17 08:33:12 +00:00
switch ( type ) {
case GUI_FILE_OPEN :
2022-01-09 21:36:47 +00:00
ImGuiFileDialog : : Instance ( ) - > OpenModal ( " FileDialog " , " Open File " , " compatible files{.fur,.dmf},.* " , workingDir ) ;
2021-12-17 08:33:12 +00:00
break ;
case GUI_FILE_SAVE :
2022-02-01 07:52:36 +00:00
ImGuiFileDialog : : Instance ( ) - > OpenModal ( " FileDialog " , " Save File " , " Furnace song{.fur},DefleMask module{.dmf} " , workingDir , 1 , nullptr , ImGuiFileDialogFlags_ConfirmOverwrite ) ;
2021-12-17 08:33:12 +00:00
break ;
2022-01-19 08:15:20 +00:00
case GUI_FILE_INS_OPEN :
2022-01-22 05:14:48 +00:00
ImGuiFileDialog : : Instance ( ) - > OpenModal ( " FileDialog " , " Load Instrument " , " compatible files{.fui,.dmp},.* " , workingDir ) ;
2022-01-19 08:15:20 +00:00
break ;
case GUI_FILE_INS_SAVE :
2022-02-01 07:52:36 +00:00
ImGuiFileDialog : : Instance ( ) - > OpenModal ( " FileDialog " , " Save Instrument " , " Furnace instrument{.fui} " , workingDir , 1 , nullptr , ImGuiFileDialogFlags_ConfirmOverwrite ) ;
2022-01-19 08:15:20 +00:00
break ;
case GUI_FILE_WAVE_OPEN :
2022-01-31 18:02:20 +00:00
ImGuiFileDialog : : Instance ( ) - > OpenModal ( " FileDialog " , " Load Wavetable " , " compatible files{.fuw,.dmw},.* " , workingDir ) ;
2022-01-19 08:15:20 +00:00
break ;
case GUI_FILE_WAVE_SAVE :
2022-02-01 07:52:36 +00:00
ImGuiFileDialog : : Instance ( ) - > OpenModal ( " FileDialog " , " Save Wavetable " , " Furnace wavetable{.fuw} " , workingDir , 1 , nullptr , ImGuiFileDialogFlags_ConfirmOverwrite ) ;
2022-01-19 08:15:20 +00:00
break ;
2021-12-17 08:33:12 +00:00
case GUI_FILE_SAMPLE_OPEN :
2021-12-19 21:01:24 +00:00
ImGuiFileDialog : : Instance ( ) - > OpenModal ( " FileDialog " , " Load Sample " , " Wave file{.wav},.* " , workingDir ) ;
2021-12-17 08:33:12 +00:00
break ;
case GUI_FILE_SAMPLE_SAVE :
2022-02-01 07:52:36 +00:00
ImGuiFileDialog : : Instance ( ) - > OpenModal ( " FileDialog " , " Save Sample " , " Wave file{.wav} " , workingDir , 1 , nullptr , ImGuiFileDialogFlags_ConfirmOverwrite ) ;
2021-12-17 08:33:12 +00:00
break ;
2022-01-18 04:34:29 +00:00
case GUI_FILE_EXPORT_AUDIO_ONE :
2022-02-01 07:52:36 +00:00
ImGuiFileDialog : : Instance ( ) - > OpenModal ( " FileDialog " , " Export Audio " , " Wave file{.wav} " , workingDir , 1 , nullptr , ImGuiFileDialogFlags_ConfirmOverwrite ) ;
2022-01-18 04:34:29 +00:00
break ;
case GUI_FILE_EXPORT_AUDIO_PER_SYS :
2022-02-01 07:52:36 +00:00
ImGuiFileDialog : : Instance ( ) - > OpenModal ( " FileDialog " , " Export Audio " , " Wave file{.wav} " , workingDir , 1 , nullptr , ImGuiFileDialogFlags_ConfirmOverwrite ) ;
2022-01-18 04:34:29 +00:00
break ;
case GUI_FILE_EXPORT_AUDIO_PER_CHANNEL :
2022-02-01 07:52:36 +00:00
ImGuiFileDialog : : Instance ( ) - > OpenModal ( " FileDialog " , " Export Audio " , " Wave file{.wav} " , workingDir , 1 , nullptr , ImGuiFileDialogFlags_ConfirmOverwrite ) ;
2022-01-18 04:34:29 +00:00
break ;
2022-01-24 06:10:38 +00:00
case GUI_FILE_EXPORT_VGM :
2022-02-01 07:52:36 +00:00
ImGuiFileDialog : : Instance ( ) - > OpenModal ( " FileDialog " , " Export VGM " , " .vgm " , workingDir , 1 , nullptr , ImGuiFileDialogFlags_ConfirmOverwrite ) ;
2022-01-24 06:10:38 +00:00
break ;
case GUI_FILE_EXPORT_ROM :
2022-01-18 04:34:29 +00:00
showError ( " Coming soon! " ) ;
break ;
2021-12-17 08:33:12 +00:00
}
curFileDialog = type ;
2022-02-01 07:52:36 +00:00
//ImGui::GetIO().ConfigFlags|=ImGuiConfigFlags_NavEnableKeyboard;
2021-12-17 08:33:12 +00:00
}
2021-12-15 19:15:44 +00:00
# define FURNACE_ZLIB_COMPRESS
int FurnaceGUI : : save ( String path ) {
2022-01-09 08:52:41 +00:00
SafeWriter * w ;
if ( path . rfind ( " .dmf " ) = = path . size ( ) - 4 ) {
w = e - > saveDMF ( ) ;
} else {
w = e - > saveFur ( ) ;
}
2022-01-08 07:04:43 +00:00
if ( w = = NULL ) {
lastError = e - > getLastError ( ) ;
return 3 ;
}
2022-01-20 10:04:03 +00:00
FILE * outFile = ps_fopen ( path . c_str ( ) , " wb " ) ;
2022-01-14 05:34:22 +00:00
if ( outFile = = NULL ) {
lastError = strerror ( errno ) ;
w - > finish ( ) ;
return 1 ;
}
2021-12-15 19:15:44 +00:00
# ifdef FURNACE_ZLIB_COMPRESS
unsigned char zbuf [ 131072 ] ;
int ret ;
z_stream zl ;
memset ( & zl , 0 , sizeof ( z_stream ) ) ;
ret = deflateInit ( & zl , Z_DEFAULT_COMPRESSION ) ;
if ( ret ! = Z_OK ) {
logE ( " zlib error! \n " ) ;
2021-12-21 04:20:30 +00:00
lastError = " compression error " ;
2021-12-15 19:15:44 +00:00
fclose ( outFile ) ;
w - > finish ( ) ;
return 2 ;
}
zl . avail_in = w - > size ( ) ;
zl . next_in = w - > getFinalBuf ( ) ;
while ( zl . avail_in > 0 ) {
zl . avail_out = 131072 ;
zl . next_out = zbuf ;
if ( ( ret = deflate ( & zl , Z_NO_FLUSH ) ) = = Z_STREAM_ERROR ) {
logE ( " zlib stream error! \n " ) ;
2021-12-21 04:20:30 +00:00
lastError = " zlib stream error " ;
2021-12-15 19:15:44 +00:00
deflateEnd ( & zl ) ;
fclose ( outFile ) ;
w - > finish ( ) ;
return 2 ;
}
size_t amount = 131072 - zl . avail_out ;
if ( amount > 0 ) {
if ( fwrite ( zbuf , 1 , amount , outFile ) ! = amount ) {
logE ( " did not write entirely: %s! \n " , strerror ( errno ) ) ;
2021-12-21 04:20:30 +00:00
lastError = strerror ( errno ) ;
2021-12-15 19:15:44 +00:00
deflateEnd ( & zl ) ;
fclose ( outFile ) ;
w - > finish ( ) ;
return 1 ;
}
}
}
zl . avail_out = 131072 ;
zl . next_out = zbuf ;
if ( ( ret = deflate ( & zl , Z_FINISH ) ) = = Z_STREAM_ERROR ) {
logE ( " zlib finish stream error! \n " ) ;
2021-12-21 04:20:30 +00:00
lastError = " zlib finish stream error " ;
2021-12-15 19:15:44 +00:00
deflateEnd ( & zl ) ;
fclose ( outFile ) ;
w - > finish ( ) ;
return 2 ;
}
if ( 131072 - zl . avail_out > 0 ) {
if ( fwrite ( zbuf , 1 , 131072 - zl . avail_out , outFile ) ! = ( 131072 - zl . avail_out ) ) {
logE ( " did not write entirely: %s! \n " , strerror ( errno ) ) ;
2021-12-21 04:20:30 +00:00
lastError = strerror ( errno ) ;
2021-12-15 19:15:44 +00:00
deflateEnd ( & zl ) ;
fclose ( outFile ) ;
w - > finish ( ) ;
return 1 ;
}
}
deflateEnd ( & zl ) ;
# else
if ( fwrite ( w - > getFinalBuf ( ) , 1 , w - > size ( ) , outFile ) ! = w - > size ( ) ) {
logE ( " did not write entirely: %s! \n " , strerror ( errno ) ) ;
2021-12-21 04:20:30 +00:00
lastError = strerror ( errno ) ;
2021-12-15 19:15:44 +00:00
fclose ( outFile ) ;
w - > finish ( ) ;
return 1 ;
}
# endif
fclose ( outFile ) ;
w - > finish ( ) ;
2021-12-30 23:25:55 +00:00
curFileName = path ;
modified = false ;
2022-01-29 06:22:32 +00:00
if ( ! e - > getWarnings ( ) . empty ( ) ) {
showWarning ( e - > getWarnings ( ) , GUI_WARN_GENERIC ) ;
}
2021-12-15 19:15:44 +00:00
return 0 ;
}
2021-12-15 05:37:27 +00:00
int FurnaceGUI : : load ( String path ) {
if ( ! path . empty ( ) ) {
logI ( " loading module... \n " ) ;
2022-01-20 10:04:03 +00:00
FILE * f = ps_fopen ( path . c_str ( ) , " rb " ) ;
2021-12-15 05:37:27 +00:00
if ( f = = NULL ) {
perror ( " error " ) ;
2021-12-21 04:20:30 +00:00
lastError = strerror ( errno ) ;
2021-12-15 05:37:27 +00:00
return 1 ;
}
if ( fseek ( f , 0 , SEEK_END ) < 0 ) {
perror ( " size error " ) ;
2021-12-21 04:20:30 +00:00
lastError = fmt : : sprintf ( " on seek: %s " , strerror ( errno ) ) ;
2021-12-15 05:37:27 +00:00
fclose ( f ) ;
return 1 ;
}
ssize_t len = ftell ( f ) ;
2022-01-18 02:08:14 +00:00
if ( len = = ( SIZE_MAX > > 1 ) ) {
2021-12-15 05:37:27 +00:00
perror ( " could not get file length " ) ;
2021-12-21 04:20:30 +00:00
lastError = fmt : : sprintf ( " on pre tell: %s " , strerror ( errno ) ) ;
2021-12-15 05:37:27 +00:00
fclose ( f ) ;
return 1 ;
}
if ( len < 1 ) {
if ( len = = 0 ) {
printf ( " that file is empty! \n " ) ;
2021-12-21 04:20:30 +00:00
lastError = " file is empty " ;
2021-12-15 05:37:27 +00:00
} else {
perror ( " tell error " ) ;
2021-12-21 04:20:30 +00:00
lastError = fmt : : sprintf ( " on tell: %s " , strerror ( errno ) ) ;
2021-12-15 05:37:27 +00:00
}
fclose ( f ) ;
return 1 ;
}
unsigned char * file = new unsigned char [ len ] ;
if ( fseek ( f , 0 , SEEK_SET ) < 0 ) {
perror ( " size error " ) ;
2021-12-21 04:20:30 +00:00
lastError = fmt : : sprintf ( " on get size: %s " , strerror ( errno ) ) ;
2021-12-15 05:37:27 +00:00
fclose ( f ) ;
2021-12-16 07:21:43 +00:00
delete [ ] file ;
2021-12-15 05:37:27 +00:00
return 1 ;
}
if ( fread ( file , 1 , ( size_t ) len , f ) ! = ( size_t ) len ) {
perror ( " read error " ) ;
2021-12-21 04:20:30 +00:00
lastError = fmt : : sprintf ( " on read: %s " , strerror ( errno ) ) ;
2021-12-15 05:37:27 +00:00
fclose ( f ) ;
2021-12-16 07:21:43 +00:00
delete [ ] file ;
2021-12-15 05:37:27 +00:00
return 1 ;
}
fclose ( f ) ;
2021-12-16 07:21:43 +00:00
if ( ! e - > load ( file , ( size_t ) len ) ) {
2021-12-21 04:20:30 +00:00
lastError = e - > getLastError ( ) ;
2021-12-15 05:37:27 +00:00
logE ( " could not open file! \n " ) ;
return 1 ;
}
}
2021-12-30 23:25:55 +00:00
curFileName = path ;
modified = false ;
2022-01-20 07:11:03 +00:00
curNibble = false ;
orderNibble = false ;
orderCursor = - 1 ;
selStart = SelectionPoint ( ) ;
selEnd = SelectionPoint ( ) ;
cursor = SelectionPoint ( ) ;
2021-12-21 04:20:30 +00:00
lastError = " everything OK " ;
2021-12-26 23:05:18 +00:00
undoHist . clear ( ) ;
redoHist . clear ( ) ;
2021-12-15 22:32:08 +00:00
updateWindowTitle ( ) ;
2022-01-29 06:22:32 +00:00
if ( ! e - > getWarnings ( ) . empty ( ) ) {
showWarning ( e - > getWarnings ( ) , GUI_WARN_GENERIC ) ;
}
2021-12-15 05:37:27 +00:00
return 0 ;
}
2022-01-18 04:34:29 +00:00
void FurnaceGUI : : exportAudio ( String path , DivAudioExportModes mode ) {
e - > saveAudio ( path . c_str ( ) , exportLoops + 1 , mode ) ;
displayExporting = true ;
}
2021-12-30 23:52:36 +00:00
void FurnaceGUI : : showWarning ( String what , FurnaceGUIWarnings type ) {
warnString = what ;
warnAction = type ;
warnQuit = true ;
}
2021-12-21 04:20:30 +00:00
void FurnaceGUI : : showError ( String what ) {
errorString = what ;
2022-01-09 21:36:47 +00:00
displayError = true ;
2021-12-21 04:20:30 +00:00
}
2022-01-21 07:54:52 +00:00
# define MACRO_DRAG(t) \
if ( macroDragBitMode ) { \
if ( macroDragLastX ! = x | | macroDragLastY ! = y ) { \
macroDragLastX = x ; \
macroDragLastY = y ; \
if ( macroDragInitialValueSet ) { \
if ( macroDragInitialValue ) { \
t [ x ] = ( ( ( t [ x ] + macroDragBitOff ) & ( ( 1 < < macroDragMax ) - 1 ) ) & ( ~ ( 1 < < y ) ) ) - macroDragBitOff ; \
} else { \
t [ x ] = ( ( ( t [ x ] + macroDragBitOff ) & ( ( 1 < < macroDragMax ) - 1 ) ) | ( 1 < < y ) ) - macroDragBitOff ; \
} \
} else { \
macroDragInitialValue = ( ( ( t [ x ] + macroDragBitOff ) & ( ( 1 < < macroDragMax ) - 1 ) ) & ( 1 < < y ) ) ; \
macroDragInitialValueSet = true ; \
t [ x ] = ( ( ( t [ x ] + macroDragBitOff ) & ( ( 1 < < macroDragMax ) - 1 ) ) ^ ( 1 < < y ) ) - macroDragBitOff ; \
} \
t [ x ] & = ( 1 < < macroDragMax ) - 1 ; \
} \
} else { \
t [ x ] = y ; \
}
2021-12-24 03:58:43 +00:00
void FurnaceGUI : : processDrags ( int dragX , int dragY ) {
if ( macroDragActive ) {
if ( macroDragLen > 0 ) {
2022-01-21 22:00:28 +00:00
int x = ( ( dragX - macroDragStart . x ) * macroDragLen / macroDragAreaSize . x ) ;
2021-12-24 03:58:43 +00:00
if ( x < 0 ) x = 0 ;
if ( x > = macroDragLen ) x = macroDragLen - 1 ;
2022-01-21 22:00:28 +00:00
x + = macroDragScroll ;
2022-01-21 06:56:30 +00:00
int y ;
if ( macroDragBitMode ) {
y = ( int ) ( macroDragMax - ( ( dragY - macroDragStart . y ) * ( double ( macroDragMax - macroDragMin ) / ( double ) macroDragAreaSize . y ) ) ) ;
} else {
y = round ( macroDragMax - ( ( dragY - macroDragStart . y ) * ( double ( macroDragMax - macroDragMin ) / ( double ) macroDragAreaSize . y ) ) ) ;
}
2021-12-24 03:58:43 +00:00
if ( y > macroDragMax ) y = macroDragMax ;
if ( y < macroDragMin ) y = macroDragMin ;
2022-01-21 07:54:52 +00:00
if ( macroDragChar ) {
MACRO_DRAG ( macroDragCTarget ) ;
2022-01-21 06:56:30 +00:00
} else {
2022-01-21 07:54:52 +00:00
MACRO_DRAG ( macroDragTarget ) ;
2022-01-21 06:56:30 +00:00
}
2021-12-24 03:58:43 +00:00
}
}
if ( macroLoopDragActive ) {
if ( macroLoopDragLen > 0 ) {
int x = ( dragX - macroLoopDragStart . x ) * macroLoopDragLen / macroLoopDragAreaSize . x ;
if ( x < 0 ) x = 0 ;
if ( x > = macroLoopDragLen ) x = - 1 ;
2022-01-26 22:22:29 +00:00
x + = macroDragScroll ;
2021-12-24 03:58:43 +00:00
* macroLoopDragTarget = x ;
}
}
if ( waveDragActive ) {
if ( waveDragLen > 0 ) {
int x = ( dragX - waveDragStart . x ) * waveDragLen / waveDragAreaSize . x ;
if ( x < 0 ) x = 0 ;
if ( x > = waveDragLen ) x = waveDragLen - 1 ;
int y = round ( waveDragMax - ( ( dragY - waveDragStart . y ) * ( double ( waveDragMax - waveDragMin ) / ( double ) waveDragAreaSize . y ) ) ) ;
if ( y > waveDragMax ) y = waveDragMax ;
if ( y < waveDragMin ) y = waveDragMin ;
waveDragTarget [ x ] = y ;
2022-01-18 05:25:10 +00:00
e - > notifyWaveChange ( curWave ) ;
modified = true ;
2021-12-24 03:58:43 +00:00
}
}
}
2022-01-08 23:18:23 +00:00
# define sysAddOption(x) \
2022-01-28 08:17:35 +00:00
if ( ImGui : : MenuItem ( getSystemName ( x ) ) ) { \
2022-01-08 23:18:23 +00:00
if ( ! e - > addSystem ( x ) ) { \
2022-01-16 06:17:30 +00:00
showError ( " cannot add system! ( " + e - > getLastError ( ) + " ) " ) ; \
2022-01-08 23:18:23 +00:00
} \
updateWindowTitle ( ) ; \
}
2022-01-09 21:36:47 +00:00
# define sysChangeOption(x,y) \
2022-01-28 08:17:35 +00:00
if ( ImGui : : MenuItem ( getSystemName ( y ) , NULL , e - > song . system [ x ] = = y ) ) { \
2022-01-09 21:36:47 +00:00
e - > changeSystem ( x , y ) ; \
2021-12-18 03:14:41 +00:00
updateWindowTitle ( ) ; \
}
2022-01-19 10:10:06 +00:00
# define checkExtension(x) \
if ( fileName . size ( ) < 4 | | fileName . rfind ( x ) ! = fileName . size ( ) - 4 ) { \
fileName + = x ; \
}
2021-12-14 09:45:44 +00:00
bool FurnaceGUI : : loop ( ) {
while ( ! quit ) {
SDL_Event ev ;
while ( SDL_PollEvent ( & ev ) ) {
ImGui_ImplSDL2_ProcessEvent ( & ev ) ;
switch ( ev . type ) {
2022-02-08 07:04:23 +00:00
case SDL_MOUSEMOTION : {
int motionX = ev . motion . x ;
int motionY = ev . motion . y ;
int motionXrel = ev . motion . xrel ;
int motionYrel = ev . motion . yrel ;
# ifdef __APPLE__
motionX * = dpiScale ;
motionY * = dpiScale ;
motionXrel * = dpiScale ;
motionYrel * = dpiScale ;
# endif
2021-12-23 16:29:11 +00:00
if ( selecting ) {
// detect whether we have to scroll
2022-02-08 07:04:23 +00:00
if ( motionY < patWindowPos . y ) {
2021-12-24 03:14:59 +00:00
addScroll ( - 1 ) ;
}
2022-02-08 07:04:23 +00:00
if ( motionY > patWindowPos . y + patWindowSize . y ) {
2021-12-24 03:14:59 +00:00
addScroll ( 1 ) ;
}
2021-12-23 16:29:11 +00:00
}
2022-01-30 23:10:41 +00:00
if ( macroDragActive | | macroLoopDragActive | | waveDragActive ) {
2022-02-08 07:04:23 +00:00
int distance = fabs ( motionXrel ) ;
2022-01-30 23:10:41 +00:00
if ( distance < 1 ) distance = 1 ;
2022-02-08 07:04:23 +00:00
float start = motionX - motionXrel ;
float end = motionX ;
float startY = motionY - motionYrel ;
float endY = motionY ;
2022-01-30 23:10:41 +00:00
for ( int i = 0 ; i < = distance ; i + + ) {
float fraction = ( float ) i / ( float ) distance ;
float x = start + ( end - start ) * fraction ;
float y = startY + ( endY - startY ) * fraction ;
processDrags ( x , y ) ;
}
}
2021-12-14 09:45:44 +00:00
break ;
2022-02-08 07:04:23 +00:00
}
2021-12-14 09:45:44 +00:00
case SDL_MOUSEBUTTONUP :
2021-12-30 23:25:55 +00:00
if ( macroDragActive | | macroLoopDragActive | | waveDragActive ) modified = true ;
2021-12-14 09:45:44 +00:00
macroDragActive = false ;
2022-01-21 06:56:30 +00:00
macroDragBitMode = false ;
macroDragInitialValue = false ;
macroDragInitialValueSet = false ;
macroDragLastX = - 1 ;
macroDragLastY = - 1 ;
2021-12-14 09:45:44 +00:00
macroLoopDragActive = false ;
2021-12-18 22:54:26 +00:00
waveDragActive = false ;
2021-12-24 03:20:54 +00:00
if ( selecting ) {
2022-01-22 08:12:02 +00:00
cursor = selEnd ;
2021-12-24 03:20:54 +00:00
finishSelection ( ) ;
if ( cursor . xCoarse = = selStart . xCoarse & & cursor . xFine = = selStart . xFine & & cursor . y = = selStart . y & &
cursor . xCoarse = = selEnd . xCoarse & & cursor . xFine = = selEnd . xFine & & cursor . y = = selEnd . y ) {
updateScroll ( cursor . y ) ;
}
}
2021-12-14 09:45:44 +00:00
break ;
2021-12-19 04:03:50 +00:00
case SDL_MOUSEBUTTONDOWN :
aboutOpen = false ;
break ;
2021-12-14 09:45:44 +00:00
case SDL_WINDOWEVENT :
switch ( ev . window . event ) {
case SDL_WINDOWEVENT_RESIZED :
2022-02-08 07:04:23 +00:00
# ifdef __APPLE__
scrW = ev . window . data1 ;
scrH = ev . window . data2 ;
# else
2021-12-14 09:45:44 +00:00
scrW = ev . window . data1 / dpiScale ;
scrH = ev . window . data2 / dpiScale ;
2022-02-08 07:04:23 +00:00
# endif
2021-12-14 09:45:44 +00:00
break ;
}
break ;
2021-12-14 22:45:37 +00:00
case SDL_KEYDOWN :
if ( ! ImGui : : GetIO ( ) . WantCaptureKeyboard ) {
keyDown ( ev ) ;
}
break ;
case SDL_KEYUP :
if ( ! ImGui : : GetIO ( ) . WantCaptureKeyboard ) {
keyUp ( ev ) ;
2022-01-18 02:34:57 +00:00
} else {
2022-01-20 06:32:16 +00:00
stopPreviewNote ( ev . key . keysym . scancode ) ;
2022-01-20 05:07:53 +00:00
if ( wavePreviewOn ) {
if ( ev . key . keysym . scancode = = wavePreviewKey ) {
wavePreviewOn = false ;
e - > stopWavePreview ( ) ;
}
}
2022-01-20 21:51:31 +00:00
if ( samplePreviewOn ) {
if ( ev . key . keysym . scancode = = samplePreviewKey ) {
samplePreviewOn = false ;
e - > stopSamplePreview ( ) ;
}
}
2021-12-14 22:45:37 +00:00
}
break ;
2022-02-01 08:09:53 +00:00
case SDL_DROPFILE :
if ( ev . drop . file ! = NULL ) {
if ( modified ) {
nextFile = ev . drop . file ;
showWarning ( " Unsaved changes! Are you sure? " , GUI_WARN_OPEN_DROP ) ;
} else {
if ( load ( ev . drop . file ) > 0 ) {
showError ( fmt : : sprintf ( " Error while loading file! (%s) " , lastError ) ) ;
}
}
SDL_free ( ev . drop . file ) ;
}
break ;
2021-12-14 09:45:44 +00:00
case SDL_QUIT :
2021-12-30 23:52:36 +00:00
if ( modified ) {
showWarning ( " Unsaved changes! Are you sure you want to quit? " , GUI_WARN_QUIT ) ;
} else {
quit = true ;
return true ;
}
2021-12-14 09:45:44 +00:00
break ;
2021-12-13 07:03:36 +00:00
}
2021-12-12 09:21:09 +00:00
}
2021-12-14 09:45:44 +00:00
ImGui_ImplSDLRenderer_NewFrame ( ) ;
ImGui_ImplSDL2_NewFrame ( sdlWin ) ;
ImGui : : NewFrame ( ) ;
2021-12-14 22:45:37 +00:00
curWindow = GUI_WINDOW_NOTHING ;
2021-12-14 09:45:44 +00:00
ImGui : : BeginMainMenuBar ( ) ;
if ( ImGui : : BeginMenu ( " file " ) ) {
2021-12-24 23:23:01 +00:00
if ( ImGui : : MenuItem ( " new " ) ) {
2021-12-30 23:52:36 +00:00
if ( modified ) {
showWarning ( " Unsaved changes! Are you sure? " , GUI_WARN_NEW ) ;
} else {
e - > createNew ( ) ;
undoHist . clear ( ) ;
redoHist . clear ( ) ;
curFileName = " " ;
modified = false ;
2022-01-20 07:11:03 +00:00
curNibble = false ;
orderNibble = false ;
orderCursor = - 1 ;
selStart = SelectionPoint ( ) ;
selEnd = SelectionPoint ( ) ;
cursor = SelectionPoint ( ) ;
2022-01-09 21:36:47 +00:00
updateWindowTitle ( ) ;
2021-12-30 23:52:36 +00:00
}
2021-12-24 23:23:01 +00:00
}
2021-12-15 05:37:27 +00:00
if ( ImGui : : MenuItem ( " open... " ) ) {
2021-12-30 23:52:36 +00:00
if ( modified ) {
showWarning ( " Unsaved changes! Are you sure? " , GUI_WARN_OPEN ) ;
} else {
openFileDialog ( GUI_FILE_OPEN ) ;
}
2021-12-15 05:37:27 +00:00
}
2021-12-14 09:45:44 +00:00
ImGui : : Separator ( ) ;
2021-12-30 23:25:55 +00:00
if ( ImGui : : MenuItem ( " save " ) ) {
if ( curFileName = = " " ) {
openFileDialog ( GUI_FILE_SAVE ) ;
} else {
if ( save ( curFileName ) > 0 ) {
showError ( fmt : : sprintf ( " Error while saving file! (%s) " , lastError ) ) ;
}
}
}
2021-12-15 19:15:44 +00:00
if ( ImGui : : MenuItem ( " save as... " ) ) {
2021-12-17 08:33:12 +00:00
openFileDialog ( GUI_FILE_SAVE ) ;
2021-12-15 19:15:44 +00:00
}
2021-12-14 09:45:44 +00:00
ImGui : : Separator ( ) ;
2022-01-18 04:34:29 +00:00
if ( ImGui : : BeginMenu ( " export audio... " ) ) {
if ( ImGui : : MenuItem ( " one file " ) ) {
openFileDialog ( GUI_FILE_EXPORT_AUDIO_ONE ) ;
}
if ( ImGui : : MenuItem ( " multiple files (one per system) " ) ) {
openFileDialog ( GUI_FILE_EXPORT_AUDIO_PER_SYS ) ;
}
if ( ImGui : : MenuItem ( " multiple files (one per channel) " ) ) {
openFileDialog ( GUI_FILE_EXPORT_AUDIO_PER_CHANNEL ) ;
}
if ( ImGui : : InputInt ( " Loops " , & exportLoops , 1 , 2 ) ) {
if ( exportLoops < 0 ) exportLoops = 0 ;
}
ImGui : : EndMenu ( ) ;
}
2022-01-26 05:26:15 +00:00
if ( ImGui : : BeginMenu ( " export VGM... " ) ) {
ImGui : : Text ( " settings: " ) ;
ImGui : : Checkbox ( " loop " , & vgmExportLoop ) ;
ImGui : : Text ( " systems to export: " ) ; ;
bool hasOneAtLeast = false ;
for ( int i = 0 ; i < e - > song . systemLen ; i + + ) {
ImGui : : BeginDisabled ( ! e - > isVGMExportable ( e - > song . system [ i ] ) ) ;
2022-01-28 08:17:35 +00:00
ImGui : : Checkbox ( fmt : : sprintf ( " %d. %s##_SYSV%d " , i + 1 , getSystemName ( e - > song . system [ i ] ) , i ) . c_str ( ) , & willExport [ i ] ) ;
2022-01-26 05:26:15 +00:00
ImGui : : EndDisabled ( ) ;
if ( ! e - > isVGMExportable ( e - > song . system [ i ] ) ) {
if ( ImGui : : IsItemHovered ( ImGuiHoveredFlags_AllowWhenDisabled ) ) {
ImGui : : SetTooltip ( " this system is not supported by the VGM format! " ) ;
}
} else {
if ( willExport [ i ] ) hasOneAtLeast = true ;
}
}
ImGui : : Text ( " select the systems you wish to export, " ) ;
ImGui : : Text ( " but only up to 2 of each type. " ) ;
if ( hasOneAtLeast ) {
if ( ImGui : : MenuItem ( " click to export " ) ) {
openFileDialog ( GUI_FILE_EXPORT_VGM ) ;
}
} else {
ImGui : : Text ( " nothing to export " ) ;
}
ImGui : : EndMenu ( ) ;
2022-01-24 02:50:45 +00:00
}
2022-01-18 04:34:29 +00:00
ImGui : : Separator ( ) ;
2022-01-16 06:17:30 +00:00
if ( ImGui : : BeginMenu ( " add system... " ) ) {
2022-01-08 23:18:23 +00:00
sysAddOption ( DIV_SYSTEM_GENESIS ) ;
sysAddOption ( DIV_SYSTEM_GENESIS_EXT ) ;
sysAddOption ( DIV_SYSTEM_SMS ) ;
sysAddOption ( DIV_SYSTEM_GB ) ;
sysAddOption ( DIV_SYSTEM_PCE ) ;
sysAddOption ( DIV_SYSTEM_NES ) ;
sysAddOption ( DIV_SYSTEM_C64_8580 ) ;
sysAddOption ( DIV_SYSTEM_C64_6581 ) ;
sysAddOption ( DIV_SYSTEM_ARCADE ) ;
sysAddOption ( DIV_SYSTEM_YM2610 ) ;
sysAddOption ( DIV_SYSTEM_YM2610_EXT ) ;
2022-01-13 06:03:57 +00:00
sysAddOption ( DIV_SYSTEM_AY8910 ) ;
sysAddOption ( DIV_SYSTEM_AMIGA ) ;
sysAddOption ( DIV_SYSTEM_YM2151 ) ;
sysAddOption ( DIV_SYSTEM_YM2612 ) ;
sysAddOption ( DIV_SYSTEM_TIA ) ;
sysAddOption ( DIV_SYSTEM_SAA1099 ) ;
2022-01-14 05:02:10 +00:00
sysAddOption ( DIV_SYSTEM_AY8930 ) ;
2022-01-08 23:18:23 +00:00
ImGui : : EndMenu ( ) ;
}
2022-01-28 23:12:56 +00:00
if ( ImGui : : BeginMenu ( " configure system... " ) ) {
for ( int i = 0 ; i < e - > song . systemLen ; i + + ) {
if ( ImGui : : TreeNode ( fmt : : sprintf ( " %d. %s##_SYSP%d " , i + 1 , getSystemName ( e - > song . system [ i ] ) , i ) . c_str ( ) ) ) {
unsigned int flags = e - > song . systemFlags [ i ] ;
2022-02-07 22:24:26 +00:00
bool restart = settings . restartOnFlagChange ;
2022-01-28 23:12:56 +00:00
bool sysPal = flags & 1 ;
switch ( e - > song . system [ i ] ) {
case DIV_SYSTEM_GENESIS :
2022-02-02 08:06:30 +00:00
case DIV_SYSTEM_GENESIS_EXT : {
if ( ImGui : : RadioButton ( " NTSC (7.67MHz) " , ( flags & 3 ) = = 0 ) ) {
2022-02-07 22:24:26 +00:00
e - > setSysFlags ( i , ( flags & 0x80000000 ) | 0 , restart ) ;
2022-01-28 23:12:56 +00:00
}
2022-02-02 08:06:30 +00:00
if ( ImGui : : RadioButton ( " PAL (7.61MHz) " , ( flags & 3 ) = = 1 ) ) {
2022-02-07 22:24:26 +00:00
e - > setSysFlags ( i , ( flags & 0x80000000 ) | 1 , restart ) ;
2022-01-28 23:12:56 +00:00
}
2022-02-02 08:06:30 +00:00
if ( ImGui : : RadioButton ( " FM Towns (8MHz) " , ( flags & 3 ) = = 2 ) ) {
2022-02-07 22:24:26 +00:00
e - > setSysFlags ( i , ( flags & 0x80000000 ) | 2 , restart ) ;
2022-02-02 08:06:30 +00:00
}
2022-02-05 02:35:32 +00:00
if ( ImGui : : RadioButton ( " AtGames Genesis (6.13MHz) " , ( flags & 3 ) = = 3 ) ) {
2022-02-07 22:24:26 +00:00
e - > setSysFlags ( i , ( flags & 0x80000000 ) | 3 , restart ) ;
2022-02-05 02:35:24 +00:00
}
2022-02-02 08:06:30 +00:00
bool ladder = flags & 0x80000000 ;
if ( ImGui : : Checkbox ( " Enable DAC distortion " , & ladder ) ) {
2022-02-07 22:24:26 +00:00
e - > setSysFlags ( i , ( flags & ( ~ 0x80000000 ) ) | ( ladder ? 0x80000000 : 0 ) , restart ) ;
2022-01-28 23:12:56 +00:00
}
break ;
2022-02-02 08:06:30 +00:00
}
2022-02-08 04:05:50 +00:00
case DIV_SYSTEM_SMS : {
2022-01-28 23:12:56 +00:00
ImGui : : Text ( " Clock rate: " ) ;
if ( ImGui : : RadioButton ( " NTSC (3.58MHz) " , ( flags & 3 ) = = 0 ) ) {
2022-02-07 22:24:26 +00:00
e - > setSysFlags ( i , ( flags & ( ~ 3 ) ) | 0 , restart ) ;
2022-01-28 23:12:56 +00:00
}
if ( ImGui : : RadioButton ( " PAL (3.55MHz) " , ( flags & 3 ) = = 1 ) ) {
2022-02-07 22:24:26 +00:00
e - > setSysFlags ( i , ( flags & ( ~ 3 ) ) | 1 , restart ) ;
2022-01-28 23:12:56 +00:00
}
if ( ImGui : : RadioButton ( " BBC Micro (4MHz) " , ( flags & 3 ) = = 2 ) ) {
2022-02-07 22:24:26 +00:00
e - > setSysFlags ( i , ( flags & ( ~ 3 ) ) | 2 , restart ) ;
2022-01-28 23:12:56 +00:00
}
ImGui : : Text ( " Chip type: " ) ;
2022-02-08 04:05:50 +00:00
if ( ImGui : : RadioButton ( " Sega VDP/Master System " , ( ( flags > > 2 ) & 3 ) = = 0 ) ) {
e - > setSysFlags ( i , ( flags & ( ~ 12 ) ) | 0 , restart ) ;
2022-01-28 23:12:56 +00:00
}
2022-02-08 04:05:50 +00:00
if ( ImGui : : RadioButton ( " TI SN76489 " , ( ( flags > > 2 ) & 3 ) = = 1 ) ) {
e - > setSysFlags ( i , ( flags & ( ~ 12 ) ) | 4 , restart ) ;
2022-01-28 23:12:56 +00:00
}
2022-02-08 04:05:50 +00:00
if ( ImGui : : RadioButton ( " TI SN76489 with Atari-like short noise " , ( ( flags > > 2 ) & 3 ) = = 2 ) ) {
e - > setSysFlags ( i , ( flags & ( ~ 12 ) ) | 8 , restart ) ;
2022-01-28 23:12:56 +00:00
}
2022-01-29 05:20:27 +00:00
/*if (ImGui::RadioButton("Game Gear",(flags>>2)==3)) {
2022-01-28 23:12:56 +00:00
e - > setSysFlags ( i , ( flags & 3 ) | 12 ) ;
2022-01-29 05:20:27 +00:00
} */
2022-02-08 04:05:50 +00:00
bool noPhaseReset = flags & 16 ;
if ( ImGui : : Checkbox ( " Disable noise period change phase reset " , & noPhaseReset ) ) {
e - > setSysFlags ( i , ( flags & ( ~ 16 ) ) | ( noPhaseReset < < 4 ) , restart ) ;
}
2022-01-28 23:12:56 +00:00
break ;
2022-02-08 04:05:50 +00:00
}
2022-01-28 23:12:56 +00:00
case DIV_SYSTEM_ARCADE :
case DIV_SYSTEM_YM2151 :
if ( ImGui : : RadioButton ( " NTSC (3.58MHz) " , flags = = 0 ) ) {
2022-02-07 22:24:26 +00:00
e - > setSysFlags ( i , 0 , restart ) ;
2022-01-28 23:12:56 +00:00
}
if ( ImGui : : RadioButton ( " PAL (3.55MHz) " , flags = = 1 ) ) {
2022-02-07 22:24:26 +00:00
e - > setSysFlags ( i , 1 , restart ) ;
2022-01-28 23:12:56 +00:00
}
if ( ImGui : : RadioButton ( " X68000 (4MHz) " , flags = = 2 ) ) {
2022-02-07 22:24:26 +00:00
e - > setSysFlags ( i , 2 , restart ) ;
2022-01-28 23:12:56 +00:00
}
break ;
case DIV_SYSTEM_NES :
if ( ImGui : : RadioButton ( " NTSC (1.79MHz) " , flags = = 0 ) ) {
2022-02-07 22:24:26 +00:00
e - > setSysFlags ( i , 0 , restart ) ;
2022-01-28 23:12:56 +00:00
}
if ( ImGui : : RadioButton ( " PAL (1.67MHz) " , flags = = 1 ) ) {
2022-02-07 22:24:26 +00:00
e - > setSysFlags ( i , 1 , restart ) ;
2022-01-28 23:12:56 +00:00
}
if ( ImGui : : RadioButton ( " Dendy (1.77MHz) " , flags = = 2 ) ) {
2022-02-07 22:24:26 +00:00
e - > setSysFlags ( i , 2 , restart ) ;
2022-01-28 23:12:56 +00:00
}
break ;
case DIV_SYSTEM_AY8910 :
case DIV_SYSTEM_AY8930 : {
ImGui : : Text ( " Clock rate: " ) ;
if ( ImGui : : RadioButton ( " 1.79MHz (ZX Spectrum/MSX NTSC) " , ( flags & 15 ) = = 0 ) ) {
2022-02-07 22:24:26 +00:00
e - > setSysFlags ( i , ( flags & ( ~ 15 ) ) | 0 , restart ) ;
2022-01-28 23:12:56 +00:00
}
if ( ImGui : : RadioButton ( " 1.77MHz (ZX Spectrum/MSX PAL) " , ( flags & 15 ) = = 1 ) ) {
2022-02-07 22:24:26 +00:00
e - > setSysFlags ( i , ( flags & ( ~ 15 ) ) | 1 , restart ) ;
2022-01-28 23:12:56 +00:00
}
if ( ImGui : : RadioButton ( " 1.75MHz (ZX Spectrum) " , ( flags & 15 ) = = 2 ) ) {
2022-02-07 22:24:26 +00:00
e - > setSysFlags ( i , ( flags & ( ~ 15 ) ) | 2 , restart ) ;
2022-01-28 23:12:56 +00:00
}
if ( ImGui : : RadioButton ( " 2MHz (Atari ST) " , ( flags & 15 ) = = 3 ) ) {
2022-02-07 22:24:26 +00:00
e - > setSysFlags ( i , ( flags & ( ~ 15 ) ) | 3 , restart ) ;
2022-01-28 23:12:56 +00:00
}
if ( ImGui : : RadioButton ( " 1.5MHz (Vectrex) " , ( flags & 15 ) = = 4 ) ) {
2022-02-07 22:24:26 +00:00
e - > setSysFlags ( i , ( flags & ( ~ 15 ) ) | 4 , restart ) ;
2022-01-28 23:12:56 +00:00
}
if ( ImGui : : RadioButton ( " 1MHz (Amstrad CPC) " , ( flags & 15 ) = = 5 ) ) {
2022-02-07 22:24:26 +00:00
e - > setSysFlags ( i , ( flags & ( ~ 15 ) ) | 5 , restart ) ;
2022-01-28 23:12:56 +00:00
}
if ( ImGui : : RadioButton ( " 0.89MHz (Sunsoft 5B) " , ( flags & 15 ) = = 6 ) ) {
2022-02-07 22:24:26 +00:00
e - > setSysFlags ( i , ( flags & ( ~ 15 ) ) | 6 , restart ) ;
2022-01-28 23:12:56 +00:00
}
if ( ImGui : : RadioButton ( " 1.67MHz (?) " , ( flags & 15 ) = = 7 ) ) {
2022-02-07 22:24:26 +00:00
e - > setSysFlags ( i , ( flags & ( ~ 15 ) ) | 7 , restart ) ;
2022-01-28 23:12:56 +00:00
}
if ( ImGui : : RadioButton ( " 0.83MHz (Sunsoft 5B on PAL) " , ( flags & 15 ) = = 8 ) ) {
2022-02-07 22:24:26 +00:00
e - > setSysFlags ( i , ( flags & ( ~ 15 ) ) | 8 , restart ) ;
2022-01-28 23:12:56 +00:00
}
if ( e - > song . system [ i ] = = DIV_SYSTEM_AY8910 ) {
ImGui : : Text ( " Chip type: " ) ;
if ( ImGui : : RadioButton ( " AY-3-8910 " , ( flags & 0x30 ) = = 0 ) ) {
2022-02-07 22:24:26 +00:00
e - > setSysFlags ( i , ( flags & ( ~ 0x30 ) ) | 0 , restart ) ;
2022-01-28 23:12:56 +00:00
}
if ( ImGui : : RadioButton ( " YM2149(F) " , ( flags & 0x30 ) = = 16 ) ) {
2022-02-07 22:24:26 +00:00
e - > setSysFlags ( i , ( flags & ( ~ 0x30 ) ) | 16 , restart ) ;
2022-01-28 23:12:56 +00:00
}
if ( ImGui : : RadioButton ( " Sunsoft 5B " , ( flags & 0x30 ) = = 32 ) ) {
2022-02-07 22:24:26 +00:00
e - > setSysFlags ( i , ( flags & ( ~ 0x30 ) ) | 32 , restart ) ;
2022-01-28 23:12:56 +00:00
}
}
bool stereo = flags & 0x40 ;
2022-01-29 05:20:27 +00:00
ImGui : : BeginDisabled ( ( flags & 0x30 ) = = 32 ) ;
2022-01-28 23:12:56 +00:00
if ( ImGui : : Checkbox ( " Stereo##_AY_STEREO " , & stereo ) ) {
2022-02-07 22:24:26 +00:00
e - > setSysFlags ( i , ( flags & ( ~ 0x40 ) ) | ( stereo ? 0x40 : 0 ) , restart ) ;
2022-01-28 23:12:56 +00:00
}
2022-01-29 05:20:27 +00:00
ImGui : : EndDisabled ( ) ;
2022-01-28 23:12:56 +00:00
break ;
}
case DIV_SYSTEM_SAA1099 :
if ( ImGui : : RadioButton ( " SAM Coupé (8MHz) " , flags = = 0 ) ) {
2022-02-07 22:24:26 +00:00
e - > setSysFlags ( i , 0 , restart ) ;
2022-01-28 23:12:56 +00:00
}
if ( ImGui : : RadioButton ( " NTSC (7.15MHz) " , flags = = 1 ) ) {
2022-02-07 22:24:26 +00:00
e - > setSysFlags ( i , 1 , restart ) ;
2022-01-28 23:12:56 +00:00
}
if ( ImGui : : RadioButton ( " PAL (7.09MHz) " , flags = = 2 ) ) {
2022-02-07 22:24:26 +00:00
e - > setSysFlags ( i , 2 , restart ) ;
2022-01-28 23:12:56 +00:00
}
break ;
2022-02-04 22:59:55 +00:00
case DIV_SYSTEM_AMIGA : {
ImGui : : Text ( " Stereo separation: " ) ;
int stereoSep = ( flags > > 8 ) & 127 ;
if ( ImGui : : SliderInt ( " ##StereoSep " , & stereoSep , 0 , 127 ) ) {
if ( stereoSep < 0 ) stereoSep = 0 ;
if ( stereoSep > 127 ) stereoSep = 127 ;
2022-02-07 22:24:26 +00:00
e - > setSysFlags ( i , ( flags & 1 ) | ( ( stereoSep & 127 ) < < 8 ) , restart ) ;
2022-02-04 22:59:55 +00:00
}
2022-01-29 05:20:27 +00:00
/* TODO LATER: I want 0.5 out already
2022-01-28 23:12:56 +00:00
if ( ImGui : : RadioButton ( " Amiga 500 (OCS) " , ( flags & 2 ) = = 0 ) ) {
e - > setSysFlags ( i , flags & 1 ) ;
}
if ( ImGui : : RadioButton ( " Amiga 1200 (AGA) " , ( flags & 2 ) = = 2 ) ) {
e - > setSysFlags ( i , ( flags & 1 ) | 2 ) ;
2022-01-29 05:20:27 +00:00
} */
2022-01-28 23:12:56 +00:00
sysPal = flags & 1 ;
if ( ImGui : : Checkbox ( " PAL " , & sysPal ) ) {
2022-02-07 22:24:26 +00:00
e - > setSysFlags ( i , ( flags & 2 ) | sysPal , restart ) ;
2022-01-28 23:12:56 +00:00
}
break ;
2022-02-04 22:59:55 +00:00
}
2022-01-28 23:12:56 +00:00
case DIV_SYSTEM_GB :
case DIV_SYSTEM_YM2610 :
case DIV_SYSTEM_YM2610_EXT :
case DIV_SYSTEM_YMU759 :
ImGui : : Text ( " nothing to configure " ) ;
break ;
default :
if ( ImGui : : Checkbox ( " PAL " , & sysPal ) ) {
2022-02-07 22:24:26 +00:00
e - > setSysFlags ( i , sysPal , restart ) ;
2022-01-28 23:12:56 +00:00
}
break ;
}
ImGui : : TreePop ( ) ;
}
}
ImGui : : EndMenu ( ) ;
}
2022-01-16 06:17:30 +00:00
if ( ImGui : : BeginMenu ( " change system... " ) ) {
2022-01-09 21:36:47 +00:00
for ( int i = 0 ; i < e - > song . systemLen ; i + + ) {
2022-01-28 08:17:35 +00:00
if ( ImGui : : BeginMenu ( fmt : : sprintf ( " %d. %s##_SYSC%d " , i + 1 , getSystemName ( e - > song . system [ i ] ) , i ) . c_str ( ) ) ) {
2022-01-09 21:36:47 +00:00
sysChangeOption ( i , DIV_SYSTEM_GENESIS ) ;
sysChangeOption ( i , DIV_SYSTEM_GENESIS_EXT ) ;
sysChangeOption ( i , DIV_SYSTEM_SMS ) ;
sysChangeOption ( i , DIV_SYSTEM_GB ) ;
sysChangeOption ( i , DIV_SYSTEM_PCE ) ;
sysChangeOption ( i , DIV_SYSTEM_NES ) ;
sysChangeOption ( i , DIV_SYSTEM_C64_8580 ) ;
sysChangeOption ( i , DIV_SYSTEM_C64_6581 ) ;
sysChangeOption ( i , DIV_SYSTEM_ARCADE ) ;
sysChangeOption ( i , DIV_SYSTEM_YM2610 ) ;
sysChangeOption ( i , DIV_SYSTEM_YM2610_EXT ) ;
2022-01-13 06:03:57 +00:00
sysChangeOption ( i , DIV_SYSTEM_AY8910 ) ;
sysChangeOption ( i , DIV_SYSTEM_AMIGA ) ;
sysChangeOption ( i , DIV_SYSTEM_YM2151 ) ;
sysChangeOption ( i , DIV_SYSTEM_YM2612 ) ;
sysChangeOption ( i , DIV_SYSTEM_TIA ) ;
sysChangeOption ( i , DIV_SYSTEM_SAA1099 ) ;
2022-01-14 05:02:10 +00:00
sysChangeOption ( i , DIV_SYSTEM_AY8930 ) ;
2022-01-09 21:36:47 +00:00
ImGui : : EndMenu ( ) ;
}
}
ImGui : : EndMenu ( ) ;
}
2022-01-16 06:17:30 +00:00
if ( ImGui : : BeginMenu ( " remove system... " ) ) {
2022-01-09 21:36:47 +00:00
for ( int i = 0 ; i < e - > song . systemLen ; i + + ) {
2022-01-28 08:17:35 +00:00
if ( ImGui : : MenuItem ( fmt : : sprintf ( " %d. %s##_SYSR%d " , i + 1 , getSystemName ( e - > song . system [ i ] ) , i ) . c_str ( ) ) ) {
2022-01-09 21:36:47 +00:00
if ( ! e - > removeSystem ( i ) ) {
2022-01-16 06:17:30 +00:00
showError ( " cannot remove system! ( " + e - > getLastError ( ) + " ) " ) ;
2022-01-09 21:36:47 +00:00
}
}
}
2021-12-18 03:14:41 +00:00
ImGui : : EndMenu ( ) ;
}
2021-12-16 07:21:43 +00:00
ImGui : : Separator ( ) ;
2021-12-14 09:45:44 +00:00
if ( ImGui : : MenuItem ( " exit " ) ) {
2021-12-30 23:52:36 +00:00
if ( modified ) {
showWarning ( " Unsaved changes! Are you sure you want to quit? " , GUI_WARN_QUIT ) ;
} else {
quit = true ;
}
2021-12-14 09:45:44 +00:00
}
ImGui : : EndMenu ( ) ;
}
2021-12-16 07:21:43 +00:00
if ( ImGui : : BeginMenu ( " edit " ) ) {
2022-01-22 21:34:44 +00:00
if ( ImGui : : MenuItem ( " undo " , CMD_MODIFIER_NAME " Z " ) ) doUndo ( ) ;
if ( ImGui : : MenuItem ( " redo " , SHIFT_MODIFIER_NAME CMD_MODIFIER_NAME " Z " ) ) doRedo ( ) ;
2021-12-16 07:21:43 +00:00
ImGui : : Separator ( ) ;
2022-01-22 21:34:44 +00:00
if ( ImGui : : MenuItem ( " cut " , CMD_MODIFIER_NAME " X " ) ) doCopy ( true ) ;
if ( ImGui : : MenuItem ( " copy " , CMD_MODIFIER_NAME " C " ) ) doCopy ( false ) ;
if ( ImGui : : MenuItem ( " paste " , CMD_MODIFIER_NAME " V " ) ) doPaste ( ) ;
2021-12-29 05:50:00 +00:00
if ( ImGui : : MenuItem ( " delete " , " Delete " ) ) doDelete ( ) ;
2022-01-22 21:34:44 +00:00
if ( ImGui : : MenuItem ( " select all " , CMD_MODIFIER_NAME " A " ) ) doSelectAll ( ) ;
2021-12-16 07:21:43 +00:00
ImGui : : Separator ( ) ;
2022-01-22 21:34:44 +00:00
if ( ImGui : : MenuItem ( " note up " , CMD_MODIFIER_NAME " F1 " ) ) doTranspose ( 1 ) ;
if ( ImGui : : MenuItem ( " note down " , CMD_MODIFIER_NAME " F2 " ) ) doTranspose ( - 1 ) ;
if ( ImGui : : MenuItem ( " octave up " , CMD_MODIFIER_NAME " F3 " ) ) doTranspose ( 12 ) ;
if ( ImGui : : MenuItem ( " octave down " , CMD_MODIFIER_NAME " F4 " ) ) doTranspose ( - 12 ) ;
2021-12-16 07:21:43 +00:00
ImGui : : Separator ( ) ;
ImGui : : MenuItem ( " clear... " ) ;
ImGui : : EndMenu ( ) ;
}
2021-12-20 03:51:02 +00:00
if ( ImGui : : BeginMenu ( " settings " ) ) {
2022-01-16 22:25:43 +00:00
if ( ImGui : : MenuItem ( " settings... " ) ) {
syncSettings ( ) ;
settingsOpen = true ;
}
2021-12-20 03:51:02 +00:00
ImGui : : EndMenu ( ) ;
}
2021-12-14 09:45:44 +00:00
if ( ImGui : : BeginMenu ( " window " ) ) {
2022-02-05 08:10:19 +00:00
if ( ImGui : : MenuItem ( " song information " , NULL , songInfoOpen ) ) songInfoOpen = ! songInfoOpen ;
if ( ImGui : : MenuItem ( " instruments " , NULL , insListOpen ) ) insListOpen = ! insListOpen ;
if ( ImGui : : MenuItem ( " wavetables " , NULL , waveListOpen ) ) waveListOpen = ! waveListOpen ;
if ( ImGui : : MenuItem ( " samples " , NULL , sampleListOpen ) ) sampleListOpen = ! sampleListOpen ;
if ( ImGui : : MenuItem ( " orders " , NULL , ordersOpen ) ) ordersOpen = ! ordersOpen ;
if ( ImGui : : MenuItem ( " pattern " , NULL , patternOpen ) ) patternOpen = ! patternOpen ;
if ( ImGui : : MenuItem ( " mixer " , NULL , mixerOpen ) ) mixerOpen = ! mixerOpen ;
if ( ImGui : : MenuItem ( " channels " , NULL , channelsOpen ) ) channelsOpen = ! channelsOpen ;
if ( ImGui : : MenuItem ( " compatibility flags " , NULL , compatFlagsOpen ) ) compatFlagsOpen = ! compatFlagsOpen ;
if ( ImGui : : MenuItem ( " song comments " , NULL , notesOpen ) ) notesOpen = ! notesOpen ;
ImGui : : Separator ( ) ;
if ( ImGui : : MenuItem ( " instrument editor " , NULL , insEditOpen ) ) insEditOpen = ! insEditOpen ;
if ( ImGui : : MenuItem ( " wavetable editor " , NULL , waveEditOpen ) ) waveEditOpen = ! waveEditOpen ;
if ( ImGui : : MenuItem ( " sample editor " , NULL , sampleEditOpen ) ) sampleEditOpen = ! sampleEditOpen ;
ImGui : : Separator ( ) ;
if ( ImGui : : MenuItem ( " play/edit controls " , NULL , editControlsOpen ) ) editControlsOpen = ! editControlsOpen ;
if ( ImGui : : MenuItem ( " piano/input pad " , NULL , pianoOpen ) ) pianoOpen = ! pianoOpen ;
if ( ImGui : : MenuItem ( " oscilloscope " , NULL , oscOpen ) ) oscOpen = ! oscOpen ;
if ( ImGui : : MenuItem ( " volume meter " , NULL , volMeterOpen ) ) volMeterOpen = ! volMeterOpen ;
if ( ImGui : : MenuItem ( " statistics " , NULL , statsOpen ) ) statsOpen = ! statsOpen ;
2021-12-14 09:45:44 +00:00
ImGui : : EndMenu ( ) ;
}
2021-12-16 07:21:43 +00:00
if ( ImGui : : BeginMenu ( " help " ) ) {
2022-01-27 05:29:16 +00:00
if ( ImGui : : MenuItem ( " debug menu " ) ) debugOpen = ! debugOpen ;
2022-01-31 22:56:49 +00:00
if ( ImGui : : MenuItem ( " panic " ) ) e - > syncReset ( ) ;
2021-12-19 04:03:50 +00:00
if ( ImGui : : MenuItem ( " about... " ) ) {
aboutOpen = true ;
aboutScroll = 0 ;
}
2021-12-16 07:21:43 +00:00
ImGui : : EndMenu ( ) ;
}
2021-12-30 23:25:55 +00:00
ImGui : : PushStyleColor ( ImGuiCol_Text , uiColors [ GUI_COLOR_PLAYBACK_STAT ] ) ;
2021-12-21 07:30:09 +00:00
if ( e - > isPlaying ( ) ) {
int totalTicks = e - > getTotalTicks ( ) ;
2022-01-12 07:45:26 +00:00
int totalSeconds = e - > getTotalSeconds ( ) ;
ImGui : : Text ( " | Speed %d:%d @ %dHz | Order %d/%d | Row %d/%d | %d:%.2d:%.2d.%.2d " , e - > getSpeed1 ( ) , e - > getSpeed2 ( ) , e - > getCurHz ( ) , e - > getOrder ( ) , e - > song . ordersLen , e - > getRow ( ) , e - > song . patLen , totalSeconds / 3600 , ( totalSeconds / 60 ) % 60 , totalSeconds % 60 , totalTicks / 10000 ) ;
2021-12-30 23:25:55 +00:00
} else {
if ( curFileName ! = " " ) ImGui : : Text ( " | %s " , curFileName . c_str ( ) ) ;
}
ImGui : : PopStyleColor ( ) ;
if ( modified ) {
ImGui : : Text ( " | modified " ) ;
2021-12-21 07:30:09 +00:00
}
2021-12-14 09:45:44 +00:00
ImGui : : EndMainMenuBar ( ) ;
ImGui : : DockSpaceOverViewport ( ) ;
2021-12-15 22:32:08 +00:00
drawEditControls ( ) ;
2021-12-14 09:45:44 +00:00
drawSongInfo ( ) ;
drawOrders ( ) ;
drawInsList ( ) ;
drawInsEdit ( ) ;
2021-12-16 08:09:18 +00:00
drawWaveList ( ) ;
drawWaveEdit ( ) ;
drawSampleList ( ) ;
drawSampleEdit ( ) ;
2022-01-13 06:03:57 +00:00
drawMixer ( ) ;
2022-01-27 22:49:00 +00:00
drawOsc ( ) ;
2022-01-29 23:56:08 +00:00
drawVolMeter ( ) ;
2021-12-14 09:45:44 +00:00
drawPattern ( ) ;
2021-12-20 03:51:02 +00:00
drawSettings ( ) ;
2022-01-27 05:29:16 +00:00
drawDebug ( ) ;
2022-02-03 05:34:48 +00:00
drawStats ( ) ;
drawCompatFlags ( ) ;
drawPiano ( ) ;
drawNotes ( ) ;
2022-02-05 06:48:35 +00:00
drawChannels ( ) ;
2021-12-12 09:21:09 +00:00
2022-01-20 05:31:36 +00:00
if ( ImGuiFileDialog : : Instance ( ) - > Display ( " FileDialog " , ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoMove , ImVec2 ( 600.0f * dpiScale , 400.0f * dpiScale ) , ImVec2 ( scrW * dpiScale , scrH * dpiScale ) ) ) {
2022-02-01 07:52:36 +00:00
//ImGui::GetIO().ConfigFlags&=~ImGuiConfigFlags_NavEnableKeyboard;
2021-12-15 05:37:27 +00:00
if ( ImGuiFileDialog : : Instance ( ) - > IsOk ( ) ) {
fileName = ImGuiFileDialog : : Instance ( ) - > GetFilePathName ( ) ;
if ( fileName ! = " " ) {
2021-12-17 08:33:12 +00:00
if ( curFileDialog = = GUI_FILE_SAVE ) {
2022-01-09 08:52:41 +00:00
if ( ImGuiFileDialog : : Instance ( ) - > GetCurrentFilter ( ) = = " Furnace song " ) {
2022-01-19 10:10:06 +00:00
checkExtension ( " .fur " ) ;
2022-01-09 08:52:41 +00:00
} else {
2022-01-19 10:10:06 +00:00
checkExtension ( " .dmf " ) ;
2021-12-15 05:37:27 +00:00
}
}
2022-01-19 10:10:06 +00:00
if ( curFileDialog = = GUI_FILE_SAMPLE_SAVE | |
curFileDialog = = GUI_FILE_EXPORT_AUDIO_ONE | |
curFileDialog = = GUI_FILE_EXPORT_AUDIO_PER_SYS | |
curFileDialog = = GUI_FILE_EXPORT_AUDIO_PER_CHANNEL ) {
checkExtension ( " .wav " ) ;
2021-12-17 08:33:12 +00:00
}
2022-01-21 23:17:05 +00:00
if ( curFileDialog = = GUI_FILE_INS_SAVE ) {
checkExtension ( " .fui " ) ;
}
if ( curFileDialog = = GUI_FILE_WAVE_SAVE ) {
checkExtension ( " .fuw " ) ;
}
2022-01-24 06:10:38 +00:00
if ( curFileDialog = = GUI_FILE_EXPORT_VGM ) {
checkExtension ( " .vgm " ) ;
}
2021-12-15 05:37:27 +00:00
String copyOfName = fileName ;
2021-12-17 08:33:12 +00:00
switch ( curFileDialog ) {
case GUI_FILE_OPEN :
2021-12-21 04:20:30 +00:00
if ( load ( copyOfName ) > 0 ) {
showError ( fmt : : sprintf ( " Error while loading file! (%s) " , lastError ) ) ;
}
2021-12-17 08:33:12 +00:00
break ;
case GUI_FILE_SAVE :
printf ( " saving: %s \n " , copyOfName . c_str ( ) ) ;
2021-12-21 04:20:30 +00:00
if ( save ( copyOfName ) > 0 ) {
showError ( fmt : : sprintf ( " Error while saving file! (%s) " , lastError ) ) ;
}
2021-12-17 08:33:12 +00:00
break ;
2022-01-19 08:28:29 +00:00
case GUI_FILE_INS_SAVE :
if ( curIns > = 0 & & curIns < ( int ) e - > song . ins . size ( ) ) {
e - > song . ins [ curIns ] - > save ( copyOfName . c_str ( ) ) ;
}
break ;
2022-01-19 10:10:06 +00:00
case GUI_FILE_WAVE_SAVE :
if ( curWave > = 0 & & curWave < ( int ) e - > song . wave . size ( ) ) {
e - > song . wave [ curWave ] - > save ( copyOfName . c_str ( ) ) ;
}
break ;
2021-12-17 08:33:12 +00:00
case GUI_FILE_SAMPLE_OPEN :
e - > addSampleFromFile ( copyOfName . c_str ( ) ) ;
2021-12-30 23:25:55 +00:00
modified = true ;
2021-12-17 08:33:12 +00:00
break ;
case GUI_FILE_SAMPLE_SAVE :
2021-12-18 06:03:59 +00:00
if ( curSample > = 0 & & curSample < ( int ) e - > song . sample . size ( ) ) {
e - > song . sample [ curSample ] - > save ( copyOfName . c_str ( ) ) ;
}
2021-12-17 08:33:12 +00:00
break ;
2022-01-18 04:34:29 +00:00
case GUI_FILE_EXPORT_AUDIO_ONE :
exportAudio ( copyOfName , DIV_EXPORT_MODE_ONE ) ;
break ;
case GUI_FILE_EXPORT_AUDIO_PER_SYS :
exportAudio ( copyOfName , DIV_EXPORT_MODE_MANY_SYS ) ;
break ;
case GUI_FILE_EXPORT_AUDIO_PER_CHANNEL :
exportAudio ( copyOfName , DIV_EXPORT_MODE_MANY_CHAN ) ;
break ;
2022-01-19 08:15:20 +00:00
case GUI_FILE_INS_OPEN :
2022-01-29 09:25:28 +00:00
if ( e - > addInstrumentFromFile ( copyOfName . c_str ( ) ) ) {
if ( ! e - > getWarnings ( ) . empty ( ) ) {
showWarning ( e - > getWarnings ( ) , GUI_WARN_GENERIC ) ;
}
} else {
showError ( " cannot load instrument! ( " + e - > getLastError ( ) + " ) " ) ;
2022-01-29 06:22:32 +00:00
}
2022-01-21 22:59:48 +00:00
break ;
2022-01-19 08:15:20 +00:00
case GUI_FILE_WAVE_OPEN :
2022-01-21 22:59:48 +00:00
e - > addWaveFromFile ( copyOfName . c_str ( ) ) ;
modified = true ;
break ;
2022-01-24 06:10:38 +00:00
case GUI_FILE_EXPORT_VGM : {
2022-01-27 07:46:40 +00:00
SafeWriter * w = e - > saveVGM ( willExport , vgmExportLoop ) ;
2022-01-24 06:10:38 +00:00
if ( w ! = NULL ) {
FILE * f = fopen ( copyOfName . c_str ( ) , " wb " ) ;
if ( f ! = NULL ) {
fwrite ( w - > getFinalBuf ( ) , 1 , w - > size ( ) , f ) ;
fclose ( f ) ;
} else {
showError ( " could not open file! " ) ;
}
w - > finish ( ) ;
delete w ;
2022-01-30 22:18:10 +00:00
if ( ! e - > getWarnings ( ) . empty ( ) ) {
showWarning ( e - > getWarnings ( ) , GUI_WARN_GENERIC ) ;
}
2022-01-24 06:10:38 +00:00
} else {
showError ( " could not write VGM. dang it. " ) ;
}
break ;
}
2022-01-18 04:34:29 +00:00
case GUI_FILE_EXPORT_ROM :
showError ( " Coming soon! " ) ;
break ;
2021-12-15 05:37:27 +00:00
}
2021-12-17 08:33:12 +00:00
curFileDialog = GUI_FILE_OPEN ;
2021-12-15 05:37:27 +00:00
}
}
workingDir = ImGuiFileDialog : : Instance ( ) - > GetCurrentPath ( ) ;
# ifdef _WIN32
workingDir + = ' \\ ' ;
# else
workingDir + = ' / ' ;
# endif
ImGuiFileDialog : : Instance ( ) - > Close ( ) ;
}
2021-12-30 23:52:36 +00:00
if ( warnQuit ) {
warnQuit = false ;
ImGui : : OpenPopup ( " Warning " ) ;
}
2022-01-09 21:36:47 +00:00
if ( displayError ) {
displayError = false ;
ImGui : : OpenPopup ( " Error " ) ;
}
2022-01-18 04:34:29 +00:00
if ( displayExporting ) {
displayExporting = false ;
ImGui : : OpenPopup ( " Rendering... " ) ;
}
2021-12-19 04:03:50 +00:00
if ( aboutOpen ) drawAbout ( ) ;
2022-01-18 04:34:29 +00:00
if ( ImGui : : BeginPopupModal ( " Rendering... " , NULL , ImGuiWindowFlags_AlwaysAutoResize ) ) {
ImGui : : Text ( " Please wait... \n " ) ;
if ( ImGui : : Button ( " Abort " ) ) {
if ( e - > haltAudioFile ( ) ) {
ImGui : : CloseCurrentPopup ( ) ;
}
}
if ( ! e - > isExporting ( ) ) {
ImGui : : CloseCurrentPopup ( ) ;
}
ImGui : : EndPopup ( ) ;
}
2021-12-21 04:20:30 +00:00
if ( ImGui : : BeginPopupModal ( " Error " , NULL , ImGuiWindowFlags_AlwaysAutoResize ) ) {
ImGui : : Text ( " %s " , errorString . c_str ( ) ) ;
if ( ImGui : : Button ( " OK " ) ) {
ImGui : : CloseCurrentPopup ( ) ;
}
ImGui : : EndPopup ( ) ;
}
2021-12-30 23:52:36 +00:00
if ( ImGui : : BeginPopupModal ( " Warning " , NULL , ImGuiWindowFlags_AlwaysAutoResize ) ) {
ImGui : : Text ( " %s " , warnString . c_str ( ) ) ;
2022-01-29 06:22:32 +00:00
if ( ImGui : : Button ( warnAction = = GUI_WARN_GENERIC ? " OK " : " Yes " ) ) {
2021-12-30 23:52:36 +00:00
ImGui : : CloseCurrentPopup ( ) ;
switch ( warnAction ) {
case GUI_WARN_QUIT :
quit = true ;
break ;
case GUI_WARN_NEW :
e - > createNew ( ) ;
undoHist . clear ( ) ;
redoHist . clear ( ) ;
curFileName = " " ;
modified = false ;
2022-01-20 07:11:03 +00:00
curNibble = false ;
orderNibble = false ;
orderCursor = - 1 ;
selStart = SelectionPoint ( ) ;
selEnd = SelectionPoint ( ) ;
cursor = SelectionPoint ( ) ;
2022-01-09 21:36:47 +00:00
updateWindowTitle ( ) ;
2021-12-30 23:52:36 +00:00
break ;
case GUI_WARN_OPEN :
openFileDialog ( GUI_FILE_OPEN ) ;
break ;
2022-02-01 08:09:53 +00:00
case GUI_WARN_OPEN_DROP :
if ( load ( nextFile ) > 0 ) {
showError ( fmt : : sprintf ( " Error while loading file! (%s) " , lastError ) ) ;
}
nextFile = " " ;
break ;
2022-01-29 06:22:32 +00:00
case GUI_WARN_GENERIC :
break ;
2021-12-30 23:52:36 +00:00
}
}
2022-01-29 06:23:21 +00:00
if ( warnAction ! = GUI_WARN_GENERIC ) {
2022-01-29 06:22:32 +00:00
ImGui : : SameLine ( ) ;
if ( ImGui : : Button ( " No " ) ) {
ImGui : : CloseCurrentPopup ( ) ;
}
2021-12-30 23:52:36 +00:00
}
ImGui : : EndPopup ( ) ;
}
2021-12-13 22:09:46 +00:00
SDL_SetRenderDrawColor ( sdlRend , uiColors [ GUI_COLOR_BACKGROUND ] . x * 255 ,
uiColors [ GUI_COLOR_BACKGROUND ] . y * 255 ,
uiColors [ GUI_COLOR_BACKGROUND ] . z * 255 ,
uiColors [ GUI_COLOR_BACKGROUND ] . w * 255 ) ;
2021-12-11 08:11:40 +00:00
SDL_RenderClear ( sdlRend ) ;
ImGui : : Render ( ) ;
ImGui_ImplSDLRenderer_RenderDrawData ( ImGui : : GetDrawData ( ) ) ;
SDL_RenderPresent ( sdlRend ) ;
2021-12-20 03:51:02 +00:00
2022-01-20 07:28:55 +00:00
if ( - - soloTimeout < 0 ) soloTimeout = 0 ;
2021-12-20 03:51:02 +00:00
if ( willCommit ) {
commitSettings ( ) ;
willCommit = false ;
}
2021-12-11 08:11:40 +00:00
}
return false ;
}
2021-12-18 03:18:53 +00:00
# define IGFD_FileStyleByExtension IGFD_FileStyleByExtention
2021-12-31 03:34:42 +00:00
String getHomeDir ( ) {
String ret ;
2021-12-15 05:37:27 +00:00
char tempDir [ 4096 ] ;
2021-12-31 03:34:42 +00:00
2021-12-15 05:37:27 +00:00
# ifdef _WIN32
2021-12-31 03:34:42 +00:00
char * up = getenv ( " USERPROFILE " ) ;
if ( up ! = NULL ) {
ret = up ;
ret + = ' \\ ' ;
}
2021-12-15 05:37:27 +00:00
# else
2021-12-31 03:34:42 +00:00
char * home = getenv ( " HOME " ) ;
if ( home ! = NULL ) {
ret = home ;
ret + = ' / ' ;
} else {
int uid = getuid ( ) ;
struct passwd * entry = getpwuid ( uid ) ;
if ( entry ! = NULL ) {
if ( entry - > pw_dir ! = NULL ) {
ret = entry - > pw_dir ;
ret + = ' / ' ;
}
}
}
2021-12-15 05:37:27 +00:00
# endif
2021-12-31 03:34:42 +00:00
if ( ret = = " " ) { // fallback
# ifdef _WIN32
GetCurrentDirectory ( 4095 , tempDir ) ;
ret = tempDir ;
ret + = ' \\ ' ;
# else
2022-01-17 22:12:24 +00:00
char * unused = getcwd ( tempDir , 4095 ) ;
char * unused1 = unused ; // dang it compiler
unused = unused1 ;
2021-12-31 03:34:42 +00:00
ret = tempDir ;
ret + = ' / ' ;
# endif
}
return ret ;
}
2022-01-22 06:50:52 +00:00
# define GET_UI_COLOR(target,def) \
uiColors [ target ] = ImGui : : ColorConvertU32ToFloat4 ( e - > getConfInt ( # target , ImGui : : GetColorU32 ( def ) ) ) ;
2022-01-22 08:37:57 +00:00
# ifdef _WIN32
# define SYSTEM_FONT_PATH_1 "C:\\Windows\\Fonts\\segoeui.ttf"
# define SYSTEM_FONT_PATH_2 "C:\\Windows\\Fonts\\tahoma.ttf"
// TODO!
# define SYSTEM_FONT_PATH_3 "C:\\Windows\\Fonts\\tahoma.ttf"
// TODO!
2022-01-30 23:22:59 +00:00
# define SYSTEM_PAT_FONT_PATH_1 "C:\\Windows\\Fonts\\consola.ttf"
# define SYSTEM_PAT_FONT_PATH_2 "C:\\Windows\\Fonts\\cour.ttf"
// GOOD LUCK WITH THIS ONE - UNTESTED
# define SYSTEM_PAT_FONT_PATH_3 "C:\\Windows\\Fonts\\vgasys.fon"
2022-01-22 08:37:57 +00:00
# elif defined(__APPLE__)
2022-01-27 21:11:40 +00:00
# define SYSTEM_FONT_PATH_1 " / System / Library / Fonts / SFNS.ttf"
2022-01-27 21:11:05 +00:00
# define SYSTEM_FONT_PATH_2 " / System / Library / Fonts / Helvetica.ttc"
# define SYSTEM_FONT_PATH_3 " / System / Library / Fonts / Helvetica.dfont"
2022-01-27 21:13:45 +00:00
# define SYSTEM_PAT_FONT_PATH_1 " / System / Library / Fonts / SFNSMono.ttf"
# define SYSTEM_PAT_FONT_PATH_2 " / System / Library / Fonts / Courier New.ttf"
2022-01-22 08:37:57 +00:00
# define SYSTEM_PAT_FONT_PATH_3 " / System / Library / Fonts / Courier New.ttf"
# else
# define SYSTEM_FONT_PATH_1 " / usr / share / fonts / truetype / dejavu / DejaVuSans.ttf"
# define SYSTEM_FONT_PATH_2 " / usr / share / fonts / TTF / DejaVuSans.ttf"
# define SYSTEM_FONT_PATH_3 " / usr / share / fonts / ubuntu / Ubuntu-R.ttf"
# define SYSTEM_PAT_FONT_PATH_1 " / usr / share / fonts / truetype / dejavu / DejaVuSansMono.ttf"
# define SYSTEM_PAT_FONT_PATH_2 " / usr / share / fonts / TTF / DejaVuSansMono.ttf"
# define SYSTEM_PAT_FONT_PATH_3 " / usr / share / fonts / ubuntu / UbuntuMono-R.ttf"
# endif
2022-01-22 06:50:52 +00:00
void FurnaceGUI : : applyUISettings ( ) {
ImGuiStyle sty ;
ImGui : : StyleColorsDark ( & sty ) ;
GET_UI_COLOR ( GUI_COLOR_BACKGROUND , ImVec4 ( 0.1f , 0.1f , 0.1f , 1.0f ) ) ;
GET_UI_COLOR ( GUI_COLOR_FRAME_BACKGROUND , ImVec4 ( 0.0f , 0.0f , 0.0f , 0.85f ) ) ;
2022-01-29 19:20:30 +00:00
GET_UI_COLOR ( GUI_COLOR_MODAL_BACKDROP , ImVec4 ( 0.0f , 0.0f , 0.0f , 0.55f ) ) ;
2022-01-22 06:50:52 +00:00
GET_UI_COLOR ( GUI_COLOR_HEADER , ImVec4 ( 0.2f , 0.2f , 0.2f , 1.0f ) ) ;
GET_UI_COLOR ( GUI_COLOR_TEXT , ImVec4 ( 1.0f , 1.0f , 1.0f , 1.0f ) ) ;
GET_UI_COLOR ( GUI_COLOR_ACCENT_PRIMARY , ImVec4 ( 0.06f , 0.53f , 0.98f , 1.0f ) ) ;
GET_UI_COLOR ( GUI_COLOR_ACCENT_SECONDARY , ImVec4 ( 0.26f , 0.59f , 0.98f , 1.0f ) ) ;
GET_UI_COLOR ( GUI_COLOR_EDITING , ImVec4 ( 0.2f , 0.1f , 0.1f , 1.0f ) ) ;
2022-01-27 06:04:26 +00:00
GET_UI_COLOR ( GUI_COLOR_SONG_LOOP , ImVec4 ( 0.3f , 0.5f , 0.8f , 0.4f ) ) ;
2022-01-29 23:56:08 +00:00
GET_UI_COLOR ( GUI_COLOR_VOLMETER_LOW , ImVec4 ( 0.2f , 0.6f , 0.2f , 1.0f ) ) ;
GET_UI_COLOR ( GUI_COLOR_VOLMETER_HIGH , ImVec4 ( 1.0f , 0.9f , 0.2f , 1.0f ) ) ;
GET_UI_COLOR ( GUI_COLOR_VOLMETER_PEAK , ImVec4 ( 1.0f , 0.1f , 0.1f , 1.0f ) ) ;
2022-01-22 06:50:52 +00:00
GET_UI_COLOR ( GUI_COLOR_MACRO_VOLUME , ImVec4 ( 0.2f , 1.0f , 0.0f , 1.0f ) ) ;
GET_UI_COLOR ( GUI_COLOR_MACRO_PITCH , ImVec4 ( 1.0f , 0.8f , 0.0f , 1.0f ) ) ;
GET_UI_COLOR ( GUI_COLOR_MACRO_OTHER , ImVec4 ( 0.0f , 0.9f , 1.0f , 1.0f ) ) ;
GET_UI_COLOR ( GUI_COLOR_MACRO_WAVE , ImVec4 ( 1.0f , 0.4f , 0.0f , 1.0f ) ) ;
GET_UI_COLOR ( GUI_COLOR_INSTR_FM , ImVec4 ( 0.6f , 0.9f , 1.0f , 1.0f ) ) ;
GET_UI_COLOR ( GUI_COLOR_INSTR_STD , ImVec4 ( 0.6f , 1.0f , 0.5f , 1.0f ) ) ;
GET_UI_COLOR ( GUI_COLOR_INSTR_GB , ImVec4 ( 1.0f , 1.0f , 0.5f , 1.0f ) ) ;
GET_UI_COLOR ( GUI_COLOR_INSTR_C64 , ImVec4 ( 0.85f , 0.8f , 1.0f , 1.0f ) ) ;
GET_UI_COLOR ( GUI_COLOR_INSTR_AMIGA , ImVec4 ( 1.0f , 0.5f , 0.5f , 1.0f ) ) ;
GET_UI_COLOR ( GUI_COLOR_INSTR_PCE , ImVec4 ( 1.0f , 0.8f , 0.5f , 1.0f ) ) ;
GET_UI_COLOR ( GUI_COLOR_INSTR_AY , ImVec4 ( 1.0f , 0.5f , 1.0f , 1.0f ) ) ;
GET_UI_COLOR ( GUI_COLOR_INSTR_AY8930 , ImVec4 ( 0.7f , 0.5f , 1.0f , 1.0f ) ) ;
GET_UI_COLOR ( GUI_COLOR_INSTR_TIA , ImVec4 ( 1.0f , 0.6f , 0.4f , 1.0f ) ) ;
GET_UI_COLOR ( GUI_COLOR_INSTR_SAA1099 , ImVec4 ( 0.3f , 0.3f , 1.0f , 1.0f ) ) ;
GET_UI_COLOR ( GUI_COLOR_INSTR_UNKNOWN , ImVec4 ( 0.3f , 0.3f , 0.3f , 1.0f ) ) ;
GET_UI_COLOR ( GUI_COLOR_CHANNEL_FM , ImVec4 ( 0.2f , 0.8f , 1.0f , 1.0f ) ) ;
GET_UI_COLOR ( GUI_COLOR_CHANNEL_PULSE , ImVec4 ( 0.4f , 1.0f , 0.2f , 1.0f ) ) ;
GET_UI_COLOR ( GUI_COLOR_CHANNEL_NOISE , ImVec4 ( 0.8f , 0.8f , 0.8f , 1.0f ) ) ;
GET_UI_COLOR ( GUI_COLOR_CHANNEL_PCM , ImVec4 ( 1.0f , 0.9f , 0.2f , 1.0f ) ) ;
GET_UI_COLOR ( GUI_COLOR_CHANNEL_WAVE , ImVec4 ( 1.0f , 0.5f , 0.2f , 1.0f ) ) ;
GET_UI_COLOR ( GUI_COLOR_CHANNEL_OP , ImVec4 ( 0.2f , 0.4f , 1.0f , 1.0f ) ) ;
GET_UI_COLOR ( GUI_COLOR_CHANNEL_MUTED , ImVec4 ( 0.5f , 0.5f , 0.5f , 1.0f ) ) ;
GET_UI_COLOR ( GUI_COLOR_PATTERN_CURSOR , ImVec4 ( 0.1f , 0.3f , 0.5f , 1.0f ) ) ;
GET_UI_COLOR ( GUI_COLOR_PATTERN_CURSOR_HOVER , ImVec4 ( 0.2f , 0.4f , 0.6f , 1.0f ) ) ;
GET_UI_COLOR ( GUI_COLOR_PATTERN_CURSOR_ACTIVE , ImVec4 ( 0.2f , 0.5f , 0.7f , 1.0f ) ) ;
GET_UI_COLOR ( GUI_COLOR_PATTERN_SELECTION , ImVec4 ( 0.15f , 0.15f , 0.2f , 1.0f ) ) ;
GET_UI_COLOR ( GUI_COLOR_PATTERN_SELECTION_HOVER , ImVec4 ( 0.2f , 0.2f , 0.3f , 1.0f ) ) ;
GET_UI_COLOR ( GUI_COLOR_PATTERN_SELECTION_ACTIVE , ImVec4 ( 0.4f , 0.4f , 0.5f , 1.0f ) ) ;
GET_UI_COLOR ( GUI_COLOR_PATTERN_HI_1 , ImVec4 ( 0.6f , 0.6f , 0.6f , 0.2f ) ) ;
GET_UI_COLOR ( GUI_COLOR_PATTERN_HI_2 , ImVec4 ( 0.5f , 0.8f , 1.0f , 0.2f ) ) ;
GET_UI_COLOR ( GUI_COLOR_PATTERN_ROW_INDEX , ImVec4 ( 0.5f , 0.8f , 1.0f , 1.0f ) ) ;
GET_UI_COLOR ( GUI_COLOR_PATTERN_ACTIVE , ImVec4 ( 1.0f , 1.0f , 1.0f , 1.0f ) ) ;
GET_UI_COLOR ( GUI_COLOR_PATTERN_INACTIVE , ImVec4 ( 0.5f , 0.5f , 0.5f , 1.0f ) ) ;
GET_UI_COLOR ( GUI_COLOR_PATTERN_INS , ImVec4 ( 0.4f , 0.7f , 1.0f , 1.0f ) ) ;
GET_UI_COLOR ( GUI_COLOR_PATTERN_VOLUME_MIN , ImVec4 ( 0.0f , 0.5f , 0.0f , 1.0f ) ) ;
GET_UI_COLOR ( GUI_COLOR_PATTERN_VOLUME_HALF , ImVec4 ( 0.0f , 0.75f , 0.0f , 1.0f ) ) ;
GET_UI_COLOR ( GUI_COLOR_PATTERN_VOLUME_MAX , ImVec4 ( 0.0f , 1.0f , 0.0f , 1.0f ) ) ;
GET_UI_COLOR ( GUI_COLOR_PATTERN_EFFECT_INVALID , ImVec4 ( 1.0f , 0.0f , 0.0f , 1.0f ) ) ;
GET_UI_COLOR ( GUI_COLOR_PATTERN_EFFECT_PITCH , ImVec4 ( 1.0f , 1.0f , 0.0f , 1.0f ) ) ;
GET_UI_COLOR ( GUI_COLOR_PATTERN_EFFECT_VOLUME , ImVec4 ( 0.0f , 1.0f , 0.0f , 1.0f ) ) ;
GET_UI_COLOR ( GUI_COLOR_PATTERN_EFFECT_PANNING , ImVec4 ( 0.0f , 1.0f , 1.0f , 1.0f ) ) ;
GET_UI_COLOR ( GUI_COLOR_PATTERN_EFFECT_SONG , ImVec4 ( 1.0f , 0.0f , 0.0f , 1.0f ) ) ;
GET_UI_COLOR ( GUI_COLOR_PATTERN_EFFECT_TIME , ImVec4 ( 0.5f , 0.0f , 1.0f , 1.0f ) ) ;
GET_UI_COLOR ( GUI_COLOR_PATTERN_EFFECT_SPEED , ImVec4 ( 1.0f , 0.0f , 1.0f , 1.0f ) ) ;
GET_UI_COLOR ( GUI_COLOR_PATTERN_EFFECT_SYS_PRIMARY , ImVec4 ( 0.5f , 1.0f , 0.0f , 1.0f ) ) ;
GET_UI_COLOR ( GUI_COLOR_PATTERN_EFFECT_SYS_SECONDARY , ImVec4 ( 0.0f , 1.0f , 0.5f , 1.0f ) ) ;
GET_UI_COLOR ( GUI_COLOR_PATTERN_EFFECT_MISC , ImVec4 ( 0.3f , 0.3f , 1.0f , 1.0f ) ) ;
GET_UI_COLOR ( GUI_COLOR_EE_VALUE , ImVec4 ( 0.0f , 1.0f , 1.0f , 1.0f ) ) ;
GET_UI_COLOR ( GUI_COLOR_PLAYBACK_STAT , ImVec4 ( 0.6f , 0.6f , 0.6f , 1.0f ) ) ;
for ( int i = 0 ; i < 64 ; i + + ) {
ImVec4 col1 = uiColors [ GUI_COLOR_PATTERN_VOLUME_MIN ] ;
ImVec4 col2 = uiColors [ GUI_COLOR_PATTERN_VOLUME_HALF ] ;
ImVec4 col3 = uiColors [ GUI_COLOR_PATTERN_VOLUME_MAX ] ;
volColors [ i ] = ImVec4 ( col1 . x + ( ( col2 . x - col1 . x ) * float ( i ) / 64.0f ) ,
col1 . y + ( ( col2 . y - col1 . y ) * float ( i ) / 64.0f ) ,
col1 . z + ( ( col2 . z - col1 . z ) * float ( i ) / 64.0f ) ,
1.0f ) ;
volColors [ i + 64 ] = ImVec4 ( col2 . x + ( ( col3 . x - col2 . x ) * float ( i ) / 64.0f ) ,
col2 . y + ( ( col3 . y - col2 . y ) * float ( i ) / 64.0f ) ,
col2 . z + ( ( col3 . z - col2 . z ) * float ( i ) / 64.0f ) ,
1.0f ) ;
}
2022-01-22 07:32:17 +00:00
float hue , sat , val ;
ImVec4 primaryActive = uiColors [ GUI_COLOR_ACCENT_PRIMARY ] ;
ImVec4 primaryHover , primary ;
primaryHover . w = primaryActive . w ;
primary . w = primaryActive . w ;
ImGui : : ColorConvertRGBtoHSV ( primaryActive . x , primaryActive . y , primaryActive . z , hue , sat , val ) ;
ImGui : : ColorConvertHSVtoRGB ( hue , sat * 0.9 , val * 0.5 , primaryHover . x , primaryHover . y , primaryHover . z ) ;
ImGui : : ColorConvertHSVtoRGB ( hue , sat * 0.8 , val * 0.35 , primary . x , primary . y , primary . z ) ;
ImVec4 secondaryActive = uiColors [ GUI_COLOR_ACCENT_SECONDARY ] ;
ImVec4 secondaryHover , secondary , secondarySemiActive ;
secondarySemiActive . w = secondaryActive . w ;
secondaryHover . w = secondaryActive . w ;
secondary . w = secondaryActive . w ;
ImGui : : ColorConvertRGBtoHSV ( secondaryActive . x , secondaryActive . y , secondaryActive . z , hue , sat , val ) ;
ImGui : : ColorConvertHSVtoRGB ( hue , sat * 0.9 , val * 0.75 , secondarySemiActive . x , secondarySemiActive . y , secondarySemiActive . z ) ;
ImGui : : ColorConvertHSVtoRGB ( hue , sat * 0.9 , val * 0.5 , secondaryHover . x , secondaryHover . y , secondaryHover . z ) ;
2022-01-22 07:34:36 +00:00
ImGui : : ColorConvertHSVtoRGB ( hue , sat * 0.9 , val * 0.25 , secondary . x , secondary . y , secondary . z ) ;
2022-01-22 07:32:17 +00:00
2022-01-22 06:50:52 +00:00
sty . Colors [ ImGuiCol_WindowBg ] = uiColors [ GUI_COLOR_FRAME_BACKGROUND ] ;
2022-01-29 19:20:30 +00:00
sty . Colors [ ImGuiCol_ModalWindowDimBg ] = uiColors [ GUI_COLOR_MODAL_BACKDROP ] ;
2022-01-22 07:32:17 +00:00
sty . Colors [ ImGuiCol_Text ] = uiColors [ GUI_COLOR_TEXT ] ;
sty . Colors [ ImGuiCol_Button ] = primary ;
sty . Colors [ ImGuiCol_ButtonHovered ] = primaryHover ;
sty . Colors [ ImGuiCol_ButtonActive ] = primaryActive ;
sty . Colors [ ImGuiCol_Tab ] = primary ;
sty . Colors [ ImGuiCol_TabHovered ] = secondaryHover ;
sty . Colors [ ImGuiCol_TabActive ] = secondarySemiActive ;
sty . Colors [ ImGuiCol_TabUnfocused ] = primary ;
sty . Colors [ ImGuiCol_TabUnfocusedActive ] = primaryHover ;
sty . Colors [ ImGuiCol_Header ] = secondary ;
sty . Colors [ ImGuiCol_HeaderHovered ] = secondaryHover ;
sty . Colors [ ImGuiCol_HeaderActive ] = secondaryActive ;
sty . Colors [ ImGuiCol_ResizeGrip ] = secondary ;
sty . Colors [ ImGuiCol_ResizeGripHovered ] = secondaryHover ;
sty . Colors [ ImGuiCol_ResizeGripActive ] = secondaryActive ;
sty . Colors [ ImGuiCol_FrameBg ] = secondary ;
sty . Colors [ ImGuiCol_FrameBgHovered ] = secondaryHover ;
sty . Colors [ ImGuiCol_FrameBgActive ] = secondaryActive ;
sty . Colors [ ImGuiCol_SliderGrab ] = primaryActive ;
sty . Colors [ ImGuiCol_SliderGrabActive ] = primaryActive ;
sty . Colors [ ImGuiCol_TitleBgActive ] = primary ;
sty . Colors [ ImGuiCol_CheckMark ] = primaryActive ;
sty . Colors [ ImGuiCol_TextSelectedBg ] = secondaryHover ;
sty . Colors [ ImGuiCol_PlotHistogram ] = uiColors [ GUI_COLOR_MACRO_OTHER ] ;
sty . Colors [ ImGuiCol_PlotHistogramHovered ] = uiColors [ GUI_COLOR_MACRO_OTHER ] ;
2022-01-22 06:50:52 +00:00
sty . ScaleAllSizes ( dpiScale ) ;
ImGui : : GetStyle ( ) = sty ;
// set to 800 for now due to problems with unifont
static const ImWchar loadEverything [ ] = { 0x20 , 0x800 , 0 } ;
2022-01-22 08:37:57 +00:00
if ( settings . mainFont < 0 | | settings . mainFont > 5 ) settings . mainFont = 0 ;
if ( settings . patFont < 0 | | settings . patFont > 5 ) settings . patFont = 0 ;
if ( settings . mainFont = = 5 ) { // system font
if ( ( mainFont = ImGui : : GetIO ( ) . Fonts - > AddFontFromFileTTF ( SYSTEM_FONT_PATH_1 , e - > getConfInt ( " mainFontSize " , 18 ) * dpiScale , NULL , loadEverything ) ) = = NULL ) {
if ( ( mainFont = ImGui : : GetIO ( ) . Fonts - > AddFontFromFileTTF ( SYSTEM_FONT_PATH_2 , e - > getConfInt ( " mainFontSize " , 18 ) * dpiScale , NULL , loadEverything ) ) = = NULL ) {
if ( ( mainFont = ImGui : : GetIO ( ) . Fonts - > AddFontFromFileTTF ( SYSTEM_FONT_PATH_3 , e - > getConfInt ( " mainFontSize " , 18 ) * dpiScale , NULL , loadEverything ) ) = = NULL ) {
logW ( " could not load UI font! reverting to default font \n " ) ;
settings . mainFont = 0 ;
if ( ( mainFont = ImGui : : GetIO ( ) . Fonts - > AddFontFromMemoryCompressedTTF ( builtinFont [ settings . mainFont ] , builtinFontLen [ settings . mainFont ] , e - > getConfInt ( " mainFontSize " , 18 ) * dpiScale , NULL , loadEverything ) ) = = NULL ) {
logE ( " could not load UI font! falling back to Proggy Clean. \n " ) ;
mainFont = ImGui : : GetIO ( ) . Fonts - > AddFontDefault ( ) ;
}
}
}
}
} else {
if ( ( mainFont = ImGui : : GetIO ( ) . Fonts - > AddFontFromMemoryCompressedTTF ( builtinFont [ settings . mainFont ] , builtinFontLen [ settings . mainFont ] , e - > getConfInt ( " mainFontSize " , 18 ) * dpiScale , NULL , loadEverything ) ) = = NULL ) {
logE ( " could not load UI font! falling back to Proggy Clean. \n " ) ;
mainFont = ImGui : : GetIO ( ) . Fonts - > AddFontDefault ( ) ;
}
2022-01-22 06:50:52 +00:00
}
ImFontConfig fc ;
fc . MergeMode = true ;
fc . GlyphMinAdvanceX = e - > getConfInt ( " iconSize " , 16 ) * dpiScale ;
static const ImWchar fontRange [ ] = { ICON_MIN_FA , ICON_MAX_FA , 0 } ;
if ( ( iconFont = ImGui : : GetIO ( ) . Fonts - > AddFontFromMemoryCompressedTTF ( iconFont_compressed_data , iconFont_compressed_size , e - > getConfInt ( " iconSize " , 16 ) * dpiScale , & fc , fontRange ) ) = = NULL ) {
logE ( " could not load icon font! \n " ) ;
}
2022-01-22 08:37:57 +00:00
if ( settings . mainFontSize = = settings . patFontSize & & settings . patFont ! = 5 & & builtinFontM [ settings . patFont ] = = builtinFont [ settings . mainFont ] ) {
2022-01-22 06:50:52 +00:00
patFont = mainFont ;
} else {
2022-01-22 08:37:57 +00:00
if ( settings . patFont = = 5 ) { // system font
if ( ( patFont = ImGui : : GetIO ( ) . Fonts - > AddFontFromFileTTF ( SYSTEM_PAT_FONT_PATH_1 , e - > getConfInt ( " patFontSize " , 18 ) * dpiScale , NULL , loadEverything ) ) = = NULL ) {
if ( ( patFont = ImGui : : GetIO ( ) . Fonts - > AddFontFromFileTTF ( SYSTEM_PAT_FONT_PATH_2 , e - > getConfInt ( " patFontSize " , 18 ) * dpiScale , NULL , loadEverything ) ) = = NULL ) {
if ( ( patFont = ImGui : : GetIO ( ) . Fonts - > AddFontFromFileTTF ( SYSTEM_PAT_FONT_PATH_3 , e - > getConfInt ( " patFontSize " , 18 ) * dpiScale , NULL , loadEverything ) ) = = NULL ) {
logW ( " could not load UI font! reverting to default font \n " ) ;
settings . patFont = 0 ;
if ( ( patFont = ImGui : : GetIO ( ) . Fonts - > AddFontFromMemoryCompressedTTF ( builtinFontM [ settings . patFont ] , builtinFontMLen [ settings . patFont ] , e - > getConfInt ( " patFontSize " , 18 ) * dpiScale , NULL , loadEverything ) ) = = NULL ) {
logE ( " could not load UI font! falling back to Proggy Clean. \n " ) ;
patFont = ImGui : : GetIO ( ) . Fonts - > AddFontDefault ( ) ;
}
}
}
}
} else {
if ( ( patFont = ImGui : : GetIO ( ) . Fonts - > AddFontFromMemoryCompressedTTF ( builtinFontM [ settings . patFont ] , builtinFontMLen [ settings . patFont ] , e - > getConfInt ( " patFontSize " , 18 ) * dpiScale , NULL , loadEverything ) ) = = NULL ) {
logE ( " could not load pattern font! \n " ) ;
patFont = ImGui : : GetIO ( ) . Fonts - > AddFontDefault ( ) ;
}
}
2022-01-22 06:50:52 +00:00
}
if ( ( bigFont = ImGui : : GetIO ( ) . Fonts - > AddFontFromMemoryCompressedTTF ( font_plexSans_compressed_data , font_plexSans_compressed_size , 40 * dpiScale ) ) = = NULL ) {
logE ( " could not load big UI font! \n " ) ;
}
}
2021-12-31 03:34:42 +00:00
bool FurnaceGUI : : init ( ) {
2022-02-08 07:04:23 +00:00
# ifndef __APPLE__
2021-12-31 03:34:42 +00:00
float dpiScaleF ;
2022-02-08 07:04:23 +00:00
# endif
2021-12-31 03:34:42 +00:00
workingDir = e - > getConfString ( " lastDir " , getHomeDir ( ) ) ;
2022-01-29 06:54:30 +00:00
editControlsOpen = e - > getConfBool ( " editControlsOpen " , true ) ;
ordersOpen = e - > getConfBool ( " ordersOpen " , true ) ;
insListOpen = e - > getConfBool ( " insListOpen " , true ) ;
songInfoOpen = e - > getConfBool ( " songInfoOpen " , true ) ;
patternOpen = e - > getConfBool ( " patternOpen " , true ) ;
insEditOpen = e - > getConfBool ( " insEditOpen " , false ) ;
waveListOpen = e - > getConfBool ( " waveListOpen " , true ) ;
waveEditOpen = e - > getConfBool ( " waveEditOpen " , false ) ;
sampleListOpen = e - > getConfBool ( " sampleListOpen " , true ) ;
sampleEditOpen = e - > getConfBool ( " sampleEditOpen " , false ) ;
settingsOpen = e - > getConfBool ( " settingsOpen " , false ) ;
mixerOpen = e - > getConfBool ( " mixerOpen " , false ) ;
oscOpen = e - > getConfBool ( " oscOpen " , true ) ;
2022-01-29 23:56:08 +00:00
volMeterOpen = e - > getConfBool ( " volMeterOpen " , true ) ;
2022-02-03 05:34:48 +00:00
statsOpen = e - > getConfBool ( " statsOpen " , false ) ;
compatFlagsOpen = e - > getConfBool ( " compatFlagsOpen " , false ) ;
pianoOpen = e - > getConfBool ( " pianoOpen " , false ) ;
notesOpen = e - > getConfBool ( " notesOpen " , false ) ;
2022-02-05 06:48:35 +00:00
channelsOpen = e - > getConfBool ( " channelsOpen " , false ) ;
2022-01-29 06:54:30 +00:00
2022-01-16 22:25:43 +00:00
syncSettings ( ) ;
2021-12-31 03:34:42 +00:00
2022-01-20 06:46:03 +00:00
# if !(defined(__APPLE__) || defined(_WIN32))
2022-01-07 08:29:56 +00:00
unsigned char * furIcon = getFurnaceIcon ( ) ;
SDL_Surface * icon = SDL_CreateRGBSurfaceFrom ( furIcon , 256 , 256 , 32 , 256 * 4 , 0xff , 0xff00 , 0xff0000 , 0xff000000 ) ;
# endif
2022-01-29 22:27:51 +00:00
scrW = e - > getConfInt ( " lastWindowWidth " , 1280 ) ;
scrH = e - > getConfInt ( " lastWindowHeight " , 800 ) ;
2022-02-08 07:04:23 +00:00
# ifndef __APPLE__
2022-01-29 22:23:45 +00:00
SDL_Rect displaySize ;
2022-02-08 07:04:23 +00:00
# endif
2022-01-29 22:23:45 +00:00
2022-02-08 21:15:53 +00:00
SDL_SetHint ( " SDL_HINT_VIDEO_ALLOW_SCREENSAVER " , " 1 " ) ;
SDL_Init ( SDL_INIT_VIDEO ) ;
2021-12-11 08:11:40 +00:00
sdlWin = SDL_CreateWindow ( " Furnace " , SDL_WINDOWPOS_CENTERED , SDL_WINDOWPOS_CENTERED , scrW * dpiScale , scrH * dpiScale , SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI ) ;
if ( sdlWin = = NULL ) {
logE ( " could not open window! \n " ) ;
return false ;
}
2022-01-07 08:29:56 +00:00
2022-02-08 07:04:23 +00:00
# ifndef __APPLE__
2021-12-12 09:21:09 +00:00
SDL_GetDisplayDPI ( SDL_GetWindowDisplayIndex ( sdlWin ) , & dpiScaleF , NULL , NULL ) ;
dpiScale = round ( dpiScaleF / 96.0f ) ;
if ( dpiScale < 1 ) dpiScale = 1 ;
2021-12-12 23:19:43 +00:00
if ( dpiScale ! = 1 ) SDL_SetWindowSize ( sdlWin , scrW * dpiScale , scrH * dpiScale ) ;
2021-12-11 08:11:40 +00:00
2022-01-29 22:23:45 +00:00
if ( SDL_GetDisplayUsableBounds ( SDL_GetWindowDisplayIndex ( sdlWin ) , & displaySize ) = = 0 ) {
if ( scrW > displaySize . w / dpiScale ) scrW = ( displaySize . w / dpiScale ) - 32 ;
if ( scrH > displaySize . h / dpiScale ) scrH = ( displaySize . h / dpiScale ) - 32 ;
SDL_SetWindowSize ( sdlWin , scrW * dpiScale , scrH * dpiScale ) ;
}
2022-02-08 07:04:23 +00:00
# endif
2022-01-29 22:23:45 +00:00
2022-01-20 06:46:03 +00:00
# if !(defined(__APPLE__) || defined(_WIN32))
2022-01-07 08:29:56 +00:00
if ( icon ! = NULL ) {
SDL_SetWindowIcon ( sdlWin , icon ) ;
SDL_FreeSurface ( icon ) ;
free ( furIcon ) ;
} else {
logW ( " could not create icon! \n " ) ;
}
# endif
2021-12-11 08:11:40 +00:00
sdlRend = SDL_CreateRenderer ( sdlWin , - 1 , SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC | SDL_RENDERER_TARGETTEXTURE ) ;
if ( sdlRend = = NULL ) {
logE ( " could not init renderer! %s \n " , SDL_GetError ( ) ) ;
return false ;
}
2022-02-08 07:04:23 +00:00
# ifdef __APPLE__
dpiScale = getMacDPIScale ( ) ;
# endif
2021-12-11 08:11:40 +00:00
IMGUI_CHECKVERSION ( ) ;
ImGui : : CreateContext ( ) ;
2022-02-08 03:09:20 +00:00
ImGui_ImplSDL2_InitForSDLRenderer ( sdlWin , sdlRend ) ;
2021-12-11 08:11:40 +00:00
ImGui_ImplSDLRenderer_Init ( sdlRend ) ;
2022-01-22 06:50:52 +00:00
applyUISettings ( ) ;
2021-12-11 08:11:40 +00:00
2021-12-19 21:01:24 +00:00
strncpy ( finalLayoutPath , ( e - > getConfigPath ( ) + String ( LAYOUT_INI ) ) . c_str ( ) , 4095 ) ;
prepareLayout ( ) ;
2021-12-19 08:16:24 +00:00
2021-12-14 01:55:40 +00:00
ImGui : : GetIO ( ) . ConfigFlags | = ImGuiConfigFlags_DockingEnable ;
2021-12-19 21:01:24 +00:00
ImGui : : GetIO ( ) . IniFilename = finalLayoutPath ;
2021-12-14 01:55:40 +00:00
2021-12-21 05:30:55 +00:00
ImGuiFileDialog : : Instance ( ) - > SetFileStyle ( IGFD_FileStyleByTypeDir , " " , ImVec4 ( 0.0f , 1.0f , 1.0f , 1.0f ) , ICON_FA_FOLDER_O ) ;
ImGuiFileDialog : : Instance ( ) - > SetFileStyle ( IGFD_FileStyleByTypeFile , " " , ImVec4 ( 0.7f , 0.7f , 0.7f , 1.0f ) , ICON_FA_FILE_O ) ;
2022-01-09 08:52:41 +00:00
ImGuiFileDialog : : Instance ( ) - > SetFileStyle ( IGFD_FileStyleByExtension , " .fur " , ImVec4 ( 0.5f , 1.0f , 0.5f , 1.0f ) , ICON_FA_FILE ) ;
2022-01-20 05:39:28 +00:00
ImGuiFileDialog : : Instance ( ) - > SetFileStyle ( IGFD_FileStyleByExtension , " .fui " , ImVec4 ( 1.0f , 0.5f , 0.5f , 1.0f ) , ICON_FA_FILE ) ;
ImGuiFileDialog : : Instance ( ) - > SetFileStyle ( IGFD_FileStyleByExtension , " .fuw " , ImVec4 ( 1.0f , 0.75f , 0.5f , 1.0f ) , ICON_FA_FILE ) ;
2021-12-21 05:30:55 +00:00
ImGuiFileDialog : : Instance ( ) - > SetFileStyle ( IGFD_FileStyleByExtension , " .dmf " , ImVec4 ( 0.5f , 1.0f , 0.5f , 1.0f ) , ICON_FA_FILE ) ;
2022-01-20 05:39:28 +00:00
ImGuiFileDialog : : Instance ( ) - > SetFileStyle ( IGFD_FileStyleByExtension , " .dmp " , ImVec4 ( 1.0f , 0.5f , 0.5f , 1.0f ) , ICON_FA_FILE ) ;
ImGuiFileDialog : : Instance ( ) - > SetFileStyle ( IGFD_FileStyleByExtension , " .dmw " , ImVec4 ( 1.0f , 0.75f , 0.5f , 1.0f ) , ICON_FA_FILE ) ;
2021-12-21 05:30:55 +00:00
ImGuiFileDialog : : Instance ( ) - > SetFileStyle ( IGFD_FileStyleByExtension , " .wav " , ImVec4 ( 1.0f , 1.0f , 0.5f , 1.0f ) , ICON_FA_FILE_AUDIO_O ) ;
2022-01-24 06:10:38 +00:00
ImGuiFileDialog : : Instance ( ) - > SetFileStyle ( IGFD_FileStyleByExtension , " .vgm " , ImVec4 ( 1.0f , 1.0f , 0.5f , 1.0f ) , ICON_FA_FILE_AUDIO_O ) ;
2021-12-18 03:18:53 +00:00
2021-12-15 22:32:08 +00:00
updateWindowTitle ( ) ;
2021-12-26 23:05:18 +00:00
2022-01-08 06:57:37 +00:00
for ( int i = 0 ; i < DIV_MAX_CHANS ; i + + ) {
2021-12-26 23:05:18 +00:00
oldPat [ i ] = new DivPattern ;
}
2022-02-08 07:11:21 +00:00
# ifdef __APPLE__
SDL_RaiseWindow ( sdlWin ) ;
# endif
2021-12-11 08:11:40 +00:00
return true ;
2021-12-19 21:01:24 +00:00
}
bool FurnaceGUI : : finish ( ) {
ImGui : : SaveIniSettingsToDisk ( finalLayoutPath ) ;
ImGui_ImplSDLRenderer_Shutdown ( ) ;
ImGui_ImplSDL2_Shutdown ( ) ;
ImGui : : DestroyContext ( ) ;
SDL_DestroyRenderer ( sdlRend ) ;
SDL_DestroyWindow ( sdlWin ) ;
2021-12-26 23:05:18 +00:00
2021-12-31 03:34:42 +00:00
e - > setConf ( " lastDir " , workingDir ) ;
2022-01-29 06:54:30 +00:00
// commit last open windows
e - > setConf ( " editControlsOpen " , editControlsOpen ) ;
e - > setConf ( " ordersOpen " , ordersOpen ) ;
e - > setConf ( " insListOpen " , insListOpen ) ;
e - > setConf ( " songInfoOpen " , songInfoOpen ) ;
e - > setConf ( " patternOpen " , patternOpen ) ;
e - > setConf ( " insEditOpen " , insEditOpen ) ;
e - > setConf ( " waveListOpen " , waveListOpen ) ;
e - > setConf ( " waveEditOpen " , waveEditOpen ) ;
e - > setConf ( " sampleListOpen " , sampleListOpen ) ;
e - > setConf ( " sampleEditOpen " , sampleEditOpen ) ;
e - > setConf ( " settingsOpen " , settingsOpen ) ;
e - > setConf ( " mixerOpen " , mixerOpen ) ;
e - > setConf ( " oscOpen " , oscOpen ) ;
2022-01-29 23:56:08 +00:00
e - > setConf ( " volMeterOpen " , volMeterOpen ) ;
2022-02-03 05:34:48 +00:00
e - > setConf ( " statsOpen " , statsOpen ) ;
e - > setConf ( " compatFlagsOpen " , compatFlagsOpen ) ;
e - > setConf ( " pianoOpen " , pianoOpen ) ;
e - > setConf ( " notesOpen " , notesOpen ) ;
2022-02-05 06:48:35 +00:00
e - > setConf ( " channelsOpen " , channelsOpen ) ;
2022-01-29 06:54:30 +00:00
2022-01-29 22:27:51 +00:00
// commit last window size
e - > setConf ( " lastWindowWidth " , scrW ) ;
e - > setConf ( " lastWindowHeight " , scrH ) ;
2022-01-08 06:57:37 +00:00
for ( int i = 0 ; i < DIV_MAX_CHANS ; i + + ) {
2021-12-26 23:05:18 +00:00
delete oldPat [ i ] ;
}
2021-12-19 21:01:24 +00:00
return true ;
2021-12-11 08:11:40 +00:00
}
2021-12-11 07:10:09 +00:00
FurnaceGUI : : FurnaceGUI ( ) :
2021-12-11 08:11:40 +00:00
e ( NULL ) ,
quit ( false ) ,
2021-12-30 23:52:36 +00:00
warnQuit ( false ) ,
2021-12-20 03:51:02 +00:00
willCommit ( false ) ,
2021-12-28 23:23:57 +00:00
edit ( false ) ,
2021-12-30 23:25:55 +00:00
modified ( false ) ,
2022-01-09 21:36:47 +00:00
displayError ( false ) ,
2022-01-18 04:34:29 +00:00
displayExporting ( false ) ,
2022-01-26 05:26:15 +00:00
vgmExportLoop ( true ) ,
2021-12-17 08:33:12 +00:00
curFileDialog ( GUI_FILE_OPEN ) ,
2021-12-30 23:52:36 +00:00
warnAction ( GUI_WARN_OPEN ) ,
2021-12-11 08:11:40 +00:00
scrW ( 1280 ) ,
scrH ( 800 ) ,
2021-12-11 21:44:02 +00:00
dpiScale ( 1 ) ,
2021-12-19 04:03:50 +00:00
aboutScroll ( 0 ) ,
aboutSin ( 0 ) ,
aboutHue ( 0.0f ) ,
2021-12-11 21:44:02 +00:00
curIns ( 0 ) ,
2021-12-16 08:09:18 +00:00
curWave ( 0 ) ,
curSample ( 0 ) ,
2021-12-12 09:21:09 +00:00
curOctave ( 3 ) ,
2021-12-13 22:09:46 +00:00
oldRow ( 0 ) ,
2021-12-21 04:20:30 +00:00
oldOrder ( 0 ) ,
oldOrder1 ( 0 ) ,
2021-12-14 22:45:37 +00:00
editStep ( 1 ) ,
2022-01-18 04:34:29 +00:00
exportLoops ( 0 ) ,
2022-01-20 07:28:55 +00:00
soloChan ( - 1 ) ,
soloTimeout ( 0 ) ,
2022-01-19 23:19:52 +00:00
orderEditMode ( 0 ) ,
2022-01-20 07:11:03 +00:00
orderCursor ( - 1 ) ,
2022-01-27 05:29:16 +00:00
loopOrder ( - 1 ) ,
loopRow ( - 1 ) ,
loopEnd ( - 1 ) ,
2022-01-29 23:56:08 +00:00
isClipping ( 0 ) ,
2021-12-15 22:32:08 +00:00
editControlsOpen ( true ) ,
2021-12-14 09:45:44 +00:00
ordersOpen ( true ) ,
insListOpen ( true ) ,
songInfoOpen ( true ) ,
patternOpen ( true ) ,
insEditOpen ( false ) ,
2021-12-16 08:09:18 +00:00
waveListOpen ( true ) ,
waveEditOpen ( false ) ,
sampleListOpen ( true ) ,
sampleEditOpen ( false ) ,
2021-12-19 04:03:50 +00:00
aboutOpen ( false ) ,
2021-12-20 03:51:02 +00:00
settingsOpen ( false ) ,
2022-01-13 06:03:57 +00:00
mixerOpen ( false ) ,
2022-01-27 05:29:16 +00:00
debugOpen ( false ) ,
2022-01-27 22:49:00 +00:00
oscOpen ( true ) ,
2022-01-29 23:56:08 +00:00
volMeterOpen ( true ) ,
2022-02-03 05:34:48 +00:00
statsOpen ( false ) ,
compatFlagsOpen ( false ) ,
pianoOpen ( false ) ,
notesOpen ( false ) ,
2022-02-05 06:48:35 +00:00
channelsOpen ( false ) ,
2021-12-14 22:45:37 +00:00
selecting ( false ) ,
curNibble ( false ) ,
2022-01-20 07:11:03 +00:00
orderNibble ( false ) ,
2021-12-21 00:46:49 +00:00
extraChannelButtons ( false ) ,
2021-12-21 22:42:27 +00:00
followOrders ( true ) ,
followPattern ( true ) ,
2021-12-22 21:22:47 +00:00
changeAllOrders ( false ) ,
2021-12-14 22:45:37 +00:00
curWindow ( GUI_WINDOW_NOTHING ) ,
2022-01-20 05:07:53 +00:00
wavePreviewOn ( false ) ,
wavePreviewKey ( ( SDL_Scancode ) 0 ) ,
wavePreviewNote ( 0 ) ,
2022-01-20 21:51:31 +00:00
samplePreviewOn ( false ) ,
samplePreviewKey ( ( SDL_Scancode ) 0 ) ,
samplePreviewNote ( 0 ) ,
2021-12-12 23:19:43 +00:00
arpMacroScroll ( 0 ) ,
2021-12-12 09:21:09 +00:00
macroDragStart ( 0 , 0 ) ,
macroDragAreaSize ( 0 , 0 ) ,
2022-01-21 07:54:52 +00:00
macroDragCTarget ( NULL ) ,
2021-12-12 09:21:09 +00:00
macroDragTarget ( NULL ) ,
macroDragLen ( 0 ) ,
macroDragMin ( 0 ) ,
macroDragMax ( 0 ) ,
2022-01-21 06:56:30 +00:00
macroDragLastX ( - 1 ) ,
macroDragLastY ( - 1 ) ,
macroDragBitOff ( 0 ) ,
2022-01-21 22:00:28 +00:00
macroDragScroll ( 0 ) ,
2022-01-21 06:56:30 +00:00
macroDragBitMode ( false ) ,
macroDragInitialValueSet ( false ) ,
macroDragInitialValue ( false ) ,
2022-01-21 07:54:52 +00:00
macroDragChar ( false ) ,
2021-12-13 22:09:46 +00:00
macroDragActive ( false ) ,
2021-12-24 03:14:59 +00:00
nextScroll ( - 1.0f ) ,
2021-12-26 23:05:18 +00:00
nextAddScroll ( 0.0f ) ,
oldOrdersLen ( 0 ) {
2021-12-14 22:45:37 +00:00
// octave 1
2022-01-17 19:53:46 +00:00
noteKeys [ SDL_SCANCODE_Z ] = 0 ;
noteKeys [ SDL_SCANCODE_S ] = 1 ;
noteKeys [ SDL_SCANCODE_X ] = 2 ;
noteKeys [ SDL_SCANCODE_D ] = 3 ;
noteKeys [ SDL_SCANCODE_C ] = 4 ;
noteKeys [ SDL_SCANCODE_V ] = 5 ;
noteKeys [ SDL_SCANCODE_G ] = 6 ;
noteKeys [ SDL_SCANCODE_B ] = 7 ;
noteKeys [ SDL_SCANCODE_H ] = 8 ;
noteKeys [ SDL_SCANCODE_N ] = 9 ;
noteKeys [ SDL_SCANCODE_J ] = 10 ;
noteKeys [ SDL_SCANCODE_M ] = 11 ;
2021-12-14 22:45:37 +00:00
// octave 2
2022-01-17 19:53:46 +00:00
noteKeys [ SDL_SCANCODE_Q ] = 12 ;
noteKeys [ SDL_SCANCODE_2 ] = 13 ;
noteKeys [ SDL_SCANCODE_W ] = 14 ;
noteKeys [ SDL_SCANCODE_3 ] = 15 ;
noteKeys [ SDL_SCANCODE_E ] = 16 ;
noteKeys [ SDL_SCANCODE_R ] = 17 ;
noteKeys [ SDL_SCANCODE_5 ] = 18 ;
noteKeys [ SDL_SCANCODE_T ] = 19 ;
noteKeys [ SDL_SCANCODE_6 ] = 20 ;
noteKeys [ SDL_SCANCODE_Y ] = 21 ;
noteKeys [ SDL_SCANCODE_7 ] = 22 ;
noteKeys [ SDL_SCANCODE_U ] = 23 ;
2021-12-14 22:45:37 +00:00
// octave 3
2022-01-17 19:53:46 +00:00
noteKeys [ SDL_SCANCODE_I ] = 24 ;
noteKeys [ SDL_SCANCODE_9 ] = 25 ;
noteKeys [ SDL_SCANCODE_O ] = 26 ;
noteKeys [ SDL_SCANCODE_0 ] = 27 ;
noteKeys [ SDL_SCANCODE_P ] = 28 ;
noteKeys [ SDL_SCANCODE_LEFTBRACKET ] = 29 ;
noteKeys [ SDL_SCANCODE_RIGHTBRACKET ] = 31 ;
2021-12-14 22:45:37 +00:00
2021-12-22 22:45:58 +00:00
// note off
2022-01-17 19:53:46 +00:00
noteKeys [ SDL_SCANCODE_TAB ] = 100 ;
2022-02-01 23:09:54 +00:00
noteKeys [ SDL_SCANCODE_1 ] = 100 ;
2021-12-22 22:45:58 +00:00
2022-02-08 08:50:42 +00:00
// note off + env release
noteKeys [ SDL_SCANCODE_EQUALS ] = 101 ;
// env release
noteKeys [ SDL_SCANCODE_GRAVE ] = 102 ;
2021-12-14 22:45:37 +00:00
// value keys
valueKeys [ SDLK_0 ] = 0 ;
valueKeys [ SDLK_1 ] = 1 ;
valueKeys [ SDLK_2 ] = 2 ;
valueKeys [ SDLK_3 ] = 3 ;
valueKeys [ SDLK_4 ] = 4 ;
valueKeys [ SDLK_5 ] = 5 ;
valueKeys [ SDLK_6 ] = 6 ;
valueKeys [ SDLK_7 ] = 7 ;
valueKeys [ SDLK_8 ] = 8 ;
valueKeys [ SDLK_9 ] = 9 ;
valueKeys [ SDLK_a ] = 10 ;
valueKeys [ SDLK_b ] = 11 ;
valueKeys [ SDLK_c ] = 12 ;
valueKeys [ SDLK_d ] = 13 ;
valueKeys [ SDLK_e ] = 14 ;
valueKeys [ SDLK_f ] = 15 ;
2022-01-26 05:26:15 +00:00
memset ( willExport , 1 , 32 * sizeof ( bool ) ) ;
2022-01-29 23:56:08 +00:00
peak [ 0 ] = 0 ;
peak [ 1 ] = 0 ;
2021-12-11 21:44:02 +00:00
}