2022-10-20 06:49:33 +00:00
# define _USE_MATH_DEFINES
// OK, sorry for inserting the define here but I'm so tired of this extension
2022-02-15 03:12:20 +00:00
/**
* Furnace Tracker - multi - system chiptune tracker
2023-01-20 00:18:40 +00:00
* Copyright ( C ) 2021 - 2023 tildearrow and contributors
2022-02-15 03:12:20 +00:00
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation ; either version 2 of the License , or
* ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License along
* with this program ; if not , write to the Free Software Foundation , Inc . ,
* 51 Franklin Street , Fifth Floor , Boston , MA 02110 - 1301 USA .
*/
2022-09-08 06:49:36 +00:00
// I hate you clangd extension!
// how about you DON'T insert random headers before this freaking important
// define!!!!!!
2022-10-20 06:49:33 +00:00
2021-12-11 07:10:09 +00:00
# include "gui.h"
2022-02-18 03:59:11 +00:00
# include "util.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"
2022-04-02 20:07:47 +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-11 22:41:32 +00:00
# include "misc/cpp/imgui_stdlib.h"
2022-03-14 05:26:27 +00:00
# include "plot_nolerp.h"
2022-02-17 18:08:17 +00:00
# include "guiConst.h"
# include "intConst.h"
2022-10-20 06:49:33 +00:00
# include "scaling.h"
2023-02-23 10:56:48 +00:00
# include "introTune.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
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"
2023-04-06 09:22:43 +00:00
# define BACKUPS_DIR "\\backups"
2021-12-15 05:37:27 +00:00
# else
2023-04-06 09:22:43 +00:00
# include <sys/types.h>
# include <dirent.h>
2021-12-15 05:37:27 +00:00
# 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"
2023-04-06 09:22:43 +00:00
# define BACKUPS_DIR " / backups"
2021-12-15 05:37:27 +00:00
# endif
2022-05-11 21:09:23 +00:00
# ifdef IS_MOBILE
2022-05-09 03:52:21 +00:00
# define MOBILE_UI_DEFAULT true
# else
# define MOBILE_UI_DEFAULT false
# endif
2022-03-21 22:34:43 +00:00
# include "actionUtil.h"
2022-03-02 05:38:32 +00:00
bool Particle : : update ( float frameTime ) {
pos . x + = speed . x * frameTime ;
pos . y + = speed . y * frameTime ;
speed . x * = 1.0 - ( ( 1.0 - friction ) * frameTime ) ;
speed . y * = 1.0 - ( ( 1.0 - friction ) * frameTime ) ;
speed . y + = gravity * frameTime ;
life - = lifeSpeed * frameTime ;
2022-02-15 23:52:12 +00:00
return ( life > 0 ) ;
}
2023-08-10 07:42:42 +00:00
void FurnaceGUI : : centerNextWindow ( const char * name , float w , float h ) {
if ( ImGui : : IsPopupOpen ( name ) ) {
if ( settings . centerPopup ) {
ImGui : : SetNextWindowPos ( ImVec2 ( w * 0.5 , h * 0.5 ) , ImGuiCond_Always , ImVec2 ( 0.5 , 0.5 ) ) ;
}
}
2023-07-12 13:16:39 +00:00
}
2021-12-11 07:10:09 +00:00
void FurnaceGUI : : bindEngine ( DivEngine * eng ) {
e = eng ;
2022-05-21 23:36:15 +00:00
wavePreview . setEngine ( e ) ;
2021-12-11 07:10:09 +00:00
}
2021-12-13 07:03:36 +00:00
const char * FurnaceGUI : : noteName ( short note , short octave ) {
if ( note = = 100 ) {
2022-08-13 23:00:29 +00:00
return noteOffLabel ;
2022-02-08 08:50:42 +00:00
} else if ( note = = 101 ) { // note off and envelope release
2022-08-13 23:00:29 +00:00
return noteRelLabel ;
2022-02-08 08:50:42 +00:00
} else if ( note = = 102 ) { // envelope release only
2022-08-13 23:00:29 +00:00
return macroRelLabel ;
2021-12-13 07:03:36 +00:00
} else if ( octave = = 0 & & note = = 0 ) {
2022-08-13 23:00:29 +00:00
return emptyLabel ;
2022-02-20 04:11:20 +00:00
} else if ( note = = 0 & & octave ! = 0 ) {
return " BUG " ;
2021-12-13 07:03:36 +00:00
}
2022-01-18 21:55:32 +00:00
int seek = ( note + ( signed char ) octave * 12 ) + 60 ;
if ( seek < 0 | | seek > = 180 ) {
return " ??? " ;
}
2023-07-24 19:51:41 +00:00
if ( settings . flatNotes ) {
2023-07-22 16:44:02 +00:00
if ( settings . germanNotation ) return noteNamesGF [ seek ] ;
return noteNamesF [ seek ] ;
}
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-02-13 01:58:39 +00:00
if ( strcmp ( what , " === " ) = = 0 ) {
note = 101 ;
octave = 0 ;
return true ;
}
if ( strcmp ( what , " REL " ) = = 0 ) {
note = 102 ;
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-18 18:11:41 +00:00
String FurnaceGUI : : encodeKeyMap ( std : : map < int , int > & map ) {
String ret ;
for ( std : : map < int , int > : : value_type & i : map ) {
2022-02-21 23:01:41 +00:00
ret + = fmt : : sprintf ( " %d:%d; " , i . first , i . second ) ;
2022-02-18 18:11:41 +00:00
}
return ret ;
}
void FurnaceGUI : : decodeKeyMap ( std : : map < int , int > & map , String source ) {
map . clear ( ) ;
bool inValue = false ;
bool negateKey = false ;
bool negateValue = false ;
int key = 0 ;
int val = 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 ' :
if ( inValue ) {
val * = 10 ;
val + = i - ' 0 ' ;
} else {
key * = 10 ;
key + = i - ' 0 ' ;
}
break ;
case ' - ' :
if ( inValue ) {
negateValue = true ;
} else {
negateKey = true ;
}
break ;
case ' : ' :
inValue = true ;
break ;
case ' ; ' :
if ( inValue ) {
map [ negateKey ? - key : key ] = negateValue ? - val : val ;
}
key = 0 ;
val = 0 ;
inValue = false ;
negateKey = false ;
negateValue = false ;
break ;
}
}
}
2022-08-22 20:59:45 +00:00
void FurnaceGUI : : encodeMMLStr ( String & target , int * macro , int macroLen , int macroLoop , int macroRel , bool hex , bool bit30 ) {
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-08-23 00:09:08 +00:00
if ( bit30 & & ( ( macro [ i ] & 0xc0000000 ) = = 0x40000000 | | ( macro [ i ] & 0xc0000000 ) = = 0x80000000 ) ) target + = " @ " ;
int macroVal = macro [ i ] ;
if ( macro [ i ] < 0 ) {
if ( ! ( macroVal & 0x40000000 ) ) macroVal | = 0x40000000 ;
} else {
if ( macroVal & 0x40000000 ) macroVal & = ~ 0x40000000 ;
}
2022-03-30 05:28:49 +00:00
if ( hex ) {
if ( i = = macroLen - 1 ) {
2022-08-22 20:59:45 +00:00
snprintf ( buf , 31 , " %.2X " , macroVal ) ;
2022-03-30 05:28:49 +00:00
} else {
2022-08-22 20:59:45 +00:00
snprintf ( buf , 31 , " %.2X " , macroVal ) ;
2022-03-30 05:28:49 +00:00
}
2022-01-26 18:13:17 +00:00
} else {
2022-03-30 05:28:49 +00:00
if ( i = = macroLen - 1 ) {
2022-08-22 20:59:45 +00:00
snprintf ( buf , 31 , " %d " , macroVal ) ;
2022-03-30 05:28:49 +00:00
} else {
2022-08-22 20:59:45 +00:00
snprintf ( buf , 31 , " %d " , macroVal ) ;
2022-03-30 05:28:49 +00:00
}
2022-01-26 18:13:17 +00:00
}
target + = buf ;
}
}
2022-09-11 03:35:21 +00:00
void FurnaceGUI : : decodeMMLStrW ( String & source , int * macro , int & macroLen , int macroMin , int macroMax , bool hex ) {
2022-01-26 21:29:49 +00:00
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 ;
2022-03-30 05:28:49 +00:00
buf * = hex ? 16 : 10 ;
2022-01-26 21:29:49 +00:00
buf + = i - ' 0 ' ;
break ;
2022-03-30 05:28:49 +00:00
case ' A ' : case ' B ' : case ' C ' : case ' D ' : case ' E ' : case ' F ' :
if ( hex ) {
hasVal = true ;
buf * = 16 ;
buf + = 10 + i - ' A ' ;
}
break ;
case ' a ' : case ' b ' : case ' c ' : case ' d ' : case ' e ' : case ' f ' :
if ( hex ) {
hasVal = true ;
buf * = 16 ;
buf + = 10 + i - ' a ' ;
}
break ;
2022-01-26 21:29:49 +00:00
case ' - ' :
if ( ! hasVal ) {
hasVal = true ;
negaBuf = true ;
}
break ;
case ' ' :
if ( hasVal ) {
hasVal = false ;
macro [ macroLen ] = negaBuf ? - buf : buf ;
2022-09-11 03:35:21 +00:00
negaBuf = false ;
if ( macro [ macroLen ] < macroMin ) macro [ macroLen ] = macroMin ;
2022-01-26 21:29:49 +00:00
if ( macro [ macroLen ] > macroMax ) macro [ macroLen ] = macroMax ;
macroLen + + ;
buf = 0 ;
}
break ;
}
if ( macroLen > = 256 ) break ;
}
if ( hasVal & & macroLen < 256 ) {
hasVal = false ;
macro [ macroLen ] = negaBuf ? - buf : buf ;
2022-09-11 03:35:21 +00:00
negaBuf = false ;
if ( macro [ macroLen ] < macroMin ) macro [ macroLen ] = macroMin ;
2022-01-26 21:29:49 +00:00
if ( macro [ macroLen ] > macroMax ) macro [ macroLen ] = macroMax ;
macroLen + + ;
buf = 0 ;
}
}
2022-08-22 20:59:45 +00:00
void FurnaceGUI : : decodeMMLStr ( String & source , int * macro , unsigned char & macroLen , unsigned char & macroLoop , int macroMin , int macroMax , unsigned char & macroRel , bool bit30 ) {
2022-01-26 18:13:17 +00:00
int buf = 0 ;
bool negaBuf = false ;
2022-08-22 20:59:45 +00:00
bool setBit30 = false ;
2022-01-26 18:13:17 +00:00
bool hasVal = false ;
macroLen = 0 ;
2022-08-22 07:13:33 +00:00
macroLoop = 255 ;
macroRel = 255 ;
2022-01-26 18:13:17 +00:00
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 ;
2022-08-22 20:59:45 +00:00
case ' @ ' :
if ( bit30 ) {
setBit30 = true ;
}
break ;
2022-01-26 18:13:17 +00:00
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 ;
2022-08-23 00:09:08 +00:00
if ( setBit30 ) macro [ macroLen ] ^ = 0x40000000 ;
2022-08-22 20:59:45 +00:00
setBit30 = false ;
2022-01-26 18:13:17 +00:00
macroLen + + ;
buf = 0 ;
}
break ;
case ' | ' :
2022-05-13 23:03:35 +00:00
if ( hasVal ) {
hasVal = false ;
macro [ macroLen ] = negaBuf ? - buf : buf ;
negaBuf = false ;
if ( macro [ macroLen ] < macroMin ) macro [ macroLen ] = macroMin ;
if ( macro [ macroLen ] > macroMax ) macro [ macroLen ] = macroMax ;
2022-08-23 00:09:08 +00:00
if ( setBit30 ) macro [ macroLen ] ^ = 0x40000000 ;
2022-08-22 20:59:45 +00:00
setBit30 = false ;
2022-05-13 23:03:35 +00:00
macroLen + + ;
buf = 0 ;
}
2022-08-22 07:13:33 +00:00
if ( macroLoop = = 255 ) {
2022-01-26 18:13:17 +00:00
macroLoop = macroLen ;
}
break ;
2022-02-08 08:50:42 +00:00
case ' / ' :
2022-05-13 23:03:35 +00:00
if ( hasVal ) {
hasVal = false ;
macro [ macroLen ] = negaBuf ? - buf : buf ;
negaBuf = false ;
if ( macro [ macroLen ] < macroMin ) macro [ macroLen ] = macroMin ;
if ( macro [ macroLen ] > macroMax ) macro [ macroLen ] = macroMax ;
2022-08-23 00:09:08 +00:00
if ( setBit30 ) macro [ macroLen ] ^ = 0x40000000 ;
2022-08-22 20:59:45 +00:00
setBit30 = false ;
2022-05-13 23:03:35 +00:00
macroLen + + ;
buf = 0 ;
}
2022-08-22 07:13:33 +00:00
if ( macroRel = = 255 ) {
2022-02-08 08:50:42 +00:00
macroRel = macroLen ;
}
break ;
2022-01-26 18:13:17 +00:00
}
2022-08-22 07:13:33 +00:00
if ( macroLen > = 255 ) break ;
2022-01-26 18:13:17 +00:00
}
2022-08-22 07:13:33 +00:00
if ( hasVal & & macroLen < 255 ) {
2022-01-26 18:13:17 +00:00
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 ;
2022-08-23 00:09:08 +00:00
if ( setBit30 ) macro [ macroLen ] ^ = 0x40000000 ;
2022-08-22 20:59:45 +00:00
setBit30 = false ;
2022-01-26 18:13:17 +00:00
macroLen + + ;
buf = 0 ;
}
}
2022-04-02 05:11:44 +00:00
# define CW_ADDITION(T) \
if ( p_min ! = NULL & & p_max ! = NULL ) { \
if ( * ( ( T * ) p_min ) > * ( ( T * ) p_max ) ) { \
if ( wheelY < 0 ) { \
if ( ( * ( ( T * ) p_data ) - wheelY ) > * ( ( T * ) p_min ) ) { \
* ( ( T * ) p_data ) = * ( ( T * ) p_min ) ; \
} else { \
* ( ( T * ) p_data ) - = wheelY ; \
} \
} else { \
if ( ( * ( ( T * ) p_data ) - wheelY ) < * ( ( T * ) p_max ) ) { \
* ( ( T * ) p_data ) = * ( ( T * ) p_max ) ; \
} else { \
* ( ( T * ) p_data ) - = wheelY ; \
} \
} \
} else { \
if ( wheelY > 0 ) { \
if ( ( * ( ( T * ) p_data ) + wheelY ) > * ( ( T * ) p_max ) ) { \
* ( ( T * ) p_data ) = * ( ( T * ) p_max ) ; \
} else { \
* ( ( T * ) p_data ) + = wheelY ; \
} \
} else { \
if ( ( * ( ( T * ) p_data ) + wheelY ) < * ( ( T * ) p_min ) ) { \
* ( ( T * ) p_data ) = * ( ( T * ) p_min ) ; \
} else { \
* ( ( T * ) p_data ) + = wheelY ; \
} \
} \
} \
}
bool FurnaceGUI : : CWSliderScalar ( const char * label , ImGuiDataType data_type , void * p_data , const void * p_min , const void * p_max , const char * format , ImGuiSliderFlags flags ) {
2023-08-31 06:52:11 +00:00
flags ^ = ImGuiSliderFlags_AlwaysClamp ;
2022-04-02 05:11:44 +00:00
if ( ImGui : : SliderScalar ( label , data_type , p_data , p_min , p_max , format , flags ) ) {
return true ;
}
if ( ImGui : : IsItemHovered ( ) & & ctrlWheeling ) {
switch ( data_type ) {
case ImGuiDataType_U8 :
CW_ADDITION ( unsigned char ) ;
break ;
case ImGuiDataType_S8 :
CW_ADDITION ( signed char ) ;
break ;
case ImGuiDataType_U16 :
CW_ADDITION ( unsigned short ) ;
break ;
case ImGuiDataType_S16 :
CW_ADDITION ( short ) ;
break ;
case ImGuiDataType_U32 :
CW_ADDITION ( unsigned int ) ;
break ;
case ImGuiDataType_S32 :
CW_ADDITION ( int ) ;
break ;
case ImGuiDataType_Float :
CW_ADDITION ( float ) ;
break ;
case ImGuiDataType_Double :
CW_ADDITION ( double ) ;
break ;
}
return true ;
}
return false ;
}
bool FurnaceGUI : : CWVSliderScalar ( const char * label , const ImVec2 & size , ImGuiDataType data_type , void * p_data , const void * p_min , const void * p_max , const char * format , ImGuiSliderFlags flags ) {
2023-08-31 06:52:11 +00:00
flags ^ = ImGuiSliderFlags_AlwaysClamp ;
2022-04-02 05:11:44 +00:00
if ( ImGui : : VSliderScalar ( label , size , data_type , p_data , p_min , p_max , format , flags ) ) {
return true ;
}
if ( ImGui : : IsItemHovered ( ) & & ctrlWheeling ) {
switch ( data_type ) {
case ImGuiDataType_U8 :
CW_ADDITION ( unsigned char ) ;
break ;
case ImGuiDataType_S8 :
CW_ADDITION ( signed char ) ;
break ;
case ImGuiDataType_U16 :
CW_ADDITION ( unsigned short ) ;
break ;
case ImGuiDataType_S16 :
CW_ADDITION ( short ) ;
break ;
case ImGuiDataType_U32 :
CW_ADDITION ( unsigned int ) ;
break ;
case ImGuiDataType_S32 :
CW_ADDITION ( int ) ;
break ;
case ImGuiDataType_Float :
CW_ADDITION ( float ) ;
break ;
case ImGuiDataType_Double :
CW_ADDITION ( double ) ;
break ;
}
return true ;
}
return false ;
}
bool FurnaceGUI : : CWSliderInt ( const char * label , int * v , int v_min , int v_max , const char * format , ImGuiSliderFlags flags ) {
return CWSliderScalar ( label , ImGuiDataType_S32 , v , & v_min , & v_max , format , flags ) ;
}
bool FurnaceGUI : : CWSliderFloat ( const char * label , float * v , float v_min , float v_max , const char * format , ImGuiSliderFlags flags ) {
return CWSliderScalar ( label , ImGuiDataType_Float , v , & v_min , & v_max , format , flags ) ;
}
bool FurnaceGUI : : CWVSliderInt ( const char * label , const ImVec2 & size , int * v , int v_min , int v_max , const char * format , ImGuiSliderFlags flags ) {
return CWVSliderScalar ( label , size , ImGuiDataType_S32 , v , & v_min , & v_max , format , flags ) ;
}
2022-10-09 22:59:44 +00:00
bool FurnaceGUI : : InvCheckbox ( const char * label , bool * value ) {
bool t = ! ( * value ) ;
if ( ImGui : : Checkbox ( label , & t ) ) {
2022-10-10 07:17:24 +00:00
* value = ! t ;
2022-10-09 22:59:44 +00:00
return true ;
}
return false ;
}
2023-06-30 21:31:34 +00:00
void FurnaceGUI : : sameLineMaybe ( float width ) {
if ( width < 0.0f ) width = ImGui : : GetFrameHeight ( ) ;
ImGui : : SameLine ( ) ;
if ( ImGui : : GetContentRegionAvail ( ) . x < width ) ImGui : : NewLine ( ) ;
}
2022-01-28 08:17:35 +00:00
const char * FurnaceGUI : : getSystemName ( DivSystem which ) {
2022-04-27 05:56:15 +00:00
/*
2022-01-28 08:17:35 +00:00
if ( settings . chipNames ) {
return e - > getSystemChips ( which ) ;
}
2022-04-27 05:56:15 +00:00
*/
2022-01-28 08:17:35 +00:00
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 ;
2022-04-13 23:16:55 +00:00
haveHitBounds = false ;
2021-12-13 22:09:46 +00:00
}
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-04-13 23:16:55 +00:00
haveHitBounds = false ;
2021-12-24 03:14:59 +00:00
}
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 ;
2023-04-06 21:24:44 +00:00
backupLock . lock ( ) ;
2022-02-02 06:14:21 +00:00
if ( GetFullPathNameW ( ws . c_str ( ) , 4095 , ret , NULL ) = = 0 ) {
curFileName = name ;
} else {
curFileName = utf16To8 ( ret ) ;
}
2023-04-06 21:24:44 +00:00
backupLock . unlock ( ) ;
2022-02-02 06:14:21 +00:00
# else
char ret [ 4096 ] ;
2023-04-06 21:24:44 +00:00
backupLock . lock ( ) ;
2022-02-02 06:14:21 +00:00
if ( realpath ( name . c_str ( ) , ret ) = = NULL ) {
curFileName = name ;
} else {
curFileName = ret ;
}
2023-04-06 21:24:44 +00:00
backupLock . unlock ( ) ;
2022-02-02 06:14:21 +00:00
# endif
2022-04-04 18:25:38 +00:00
updateWindowTitle ( ) ;
2022-09-10 23:53:27 +00:00
pushRecentFile ( curFileName ) ;
2023-02-19 05:08:37 +00:00
if ( settings . alwaysPlayIntro = = 2 ) shortIntro = true ;
2022-02-02 06:14:21 +00:00
}
2021-12-15 22:32:08 +00:00
void FurnaceGUI : : updateWindowTitle ( ) {
2022-04-04 18:25:38 +00:00
String title ;
switch ( settings . titleBarInfo ) {
case 0 :
2023-04-02 07:31:37 +00:00
title = " Furnace " ;
2022-04-04 18:25:38 +00:00
break ;
case 1 :
if ( e - > song . name . empty ( ) ) {
2023-04-02 07:31:37 +00:00
title = " Furnace " ;
2022-04-04 18:25:38 +00:00
} else {
2023-04-02 07:31:37 +00:00
title = fmt : : sprintf ( " %s - Furnace " , e - > song . name ) ;
2022-04-04 18:25:38 +00:00
}
break ;
case 2 :
if ( curFileName . empty ( ) ) {
2023-04-02 07:31:37 +00:00
title = " Furnace " ;
2022-04-04 18:25:38 +00:00
} else {
String shortName ;
size_t pos = curFileName . rfind ( DIR_SEPARATOR ) ;
if ( pos = = String : : npos ) {
shortName = curFileName ;
} else {
shortName = curFileName . substr ( pos + 1 ) ;
}
2023-04-02 07:31:37 +00:00
title = fmt : : sprintf ( " %s - Furnace " , shortName ) ;
2022-04-04 18:25:38 +00:00
}
break ;
case 3 :
if ( curFileName . empty ( ) ) {
2023-04-02 07:31:37 +00:00
title = " Furnace " ;
2022-04-04 18:25:38 +00:00
} else {
2023-04-02 07:31:37 +00:00
title = fmt : : sprintf ( " %s - Furnace " , curFileName ) ;
2022-04-04 18:25:38 +00:00
}
break ;
2021-12-15 22:32:08 +00:00
}
2022-04-04 18:25:38 +00:00
if ( settings . titleBarSys ) {
2022-07-23 22:02:03 +00:00
if ( e - > song . systemName ! = " " ) {
title + = fmt : : sprintf ( " (%s) " , e - > song . systemName ) ;
}
2022-04-04 18:25:38 +00:00
}
if ( sdlWin ! = NULL ) SDL_SetWindowTitle ( sdlWin , title . c_str ( ) ) ;
2021-12-15 22:32:08 +00:00
}
2022-09-22 00:27:42 +00:00
void FurnaceGUI : : autoDetectSystem ( ) {
std : : map < DivSystem , int > sysCountMap ;
2022-12-22 18:10:08 +00:00
std : : map < DivSystem , DivConfig > sysConfMap ;
2022-09-22 00:27:42 +00:00
for ( int i = 0 ; i < e - > song . systemLen ; i + + ) {
2023-07-24 22:39:09 +00:00
auto it = sysCountMap . find ( e - > song . system [ i ] ) ;
if ( it = = sysCountMap . cend ( ) ) {
2022-09-22 00:27:42 +00:00
sysCountMap [ e - > song . system [ i ] ] = 1 ;
2023-07-24 22:39:09 +00:00
} else {
it - > second + + ;
2022-09-22 00:27:42 +00:00
}
2022-12-22 18:10:08 +00:00
sysConfMap [ e - > song . system [ i ] ] = e - > song . systemFlags [ i ] ;
2022-09-22 00:27:42 +00:00
}
logV ( " sysCountMap: " ) ;
for ( std : : pair < DivSystem , int > k : sysCountMap ) {
logV ( " %s: %d " , e - > getSystemName ( k . first ) , k . second ) ;
}
bool isMatch = false ;
std : : map < DivSystem , int > defCountMap ;
2022-12-22 18:10:08 +00:00
std : : map < DivSystem , DivConfig > defConfMap ;
2022-09-22 00:27:42 +00:00
for ( FurnaceGUISysCategory & i : sysCategories ) {
for ( FurnaceGUISysDef & j : i . systems ) {
defCountMap . clear ( ) ;
2022-12-22 18:10:08 +00:00
defConfMap . clear ( ) ;
for ( FurnaceGUISysDefChip & k : j . orig ) {
2023-07-24 22:39:09 +00:00
auto it = defCountMap . find ( k . sys ) ;
if ( it = = defCountMap . cend ( ) ) {
2022-12-22 18:10:08 +00:00
defCountMap [ k . sys ] = 1 ;
2023-07-24 22:39:09 +00:00
} else {
it - > second + + ;
2022-09-22 00:27:42 +00:00
}
2022-12-22 18:10:08 +00:00
DivConfig dc ;
dc . loadFromMemory ( k . flags ) ;
defConfMap [ k . sys ] = dc ;
2022-09-22 00:27:42 +00:00
}
if ( defCountMap . size ( ) ! = sysCountMap . size ( ) ) continue ;
isMatch = true ;
2022-12-29 04:43:58 +00:00
/*logV("trying on defCountMap: %s",j.name);
2022-09-22 00:27:42 +00:00
for ( std : : pair < DivSystem , int > k : defCountMap ) {
logV ( " - %s: %d " , e - > getSystemName ( k . first ) , k . second ) ;
2022-12-29 04:43:58 +00:00
} */
2022-09-22 00:27:42 +00:00
for ( std : : pair < DivSystem , int > k : defCountMap ) {
2023-07-24 22:39:09 +00:00
auto countI = sysCountMap . find ( k . first ) ;
if ( countI = = sysCountMap . cend ( ) ) {
isMatch = false ;
break ;
} else if ( countI - > second ! = k . second ) {
isMatch = false ;
break ;
}
auto confI = sysConfMap . find ( k . first ) ;
if ( confI = = sysConfMap . cend ( ) ) {
isMatch = false ;
break ;
}
DivConfig & sysDC = confI - > second ;
auto defConfI = defConfMap . find ( k . first ) ;
if ( defConfI = = defConfMap . cend ( ) ) {
isMatch = false ;
break ;
}
for ( std : : pair < String , String > l : defConfI - > second . configMap ( ) ) {
if ( ! sysDC . has ( l . first ) ) {
2022-09-22 00:27:42 +00:00
isMatch = false ;
break ;
}
2023-07-24 22:39:09 +00:00
if ( sysDC . getString ( l . first , " " ) ! = l . second ) {
isMatch = false ;
break ;
2022-12-22 18:10:08 +00:00
}
2022-09-22 00:27:42 +00:00
}
2023-07-24 22:39:09 +00:00
if ( ! isMatch ) break ;
2022-09-22 00:27:42 +00:00
}
if ( isMatch ) {
logV ( " match found! " ) ;
e - > song . systemName = j . name ;
break ;
}
}
if ( isMatch ) break ;
}
if ( ! isMatch ) {
bool isFirst = true ;
e - > song . systemName = " " ;
for ( std : : pair < DivSystem , int > k : sysCountMap ) {
if ( ! isFirst ) e - > song . systemName + = " + " ;
if ( k . second > 1 ) {
e - > song . systemName + = fmt : : sprintf ( " %d× " , k . second ) ;
}
2023-07-20 21:50:19 +00:00
e - > song . systemName + = e - > getSystemName ( k . first ) ;
2022-09-22 00:27:42 +00:00
isFirst = false ;
}
}
}
2022-09-18 08:51:10 +00:00
ImVec4 FurnaceGUI : : channelColor ( int ch ) {
switch ( settings . channelColors ) {
case 0 :
return uiColors [ GUI_COLOR_CHANNEL_BG ] ;
break ;
case 1 :
return uiColors [ GUI_COLOR_CHANNEL_FM + e - > getChannelType ( ch ) ] ;
break ;
case 2 :
return uiColors [ GUI_COLOR_INSTR_STD + e - > getPreferInsType ( ch ) ] ;
break ;
}
// invalid
return uiColors [ GUI_COLOR_TEXT ] ;
}
ImVec4 FurnaceGUI : : channelTextColor ( int ch ) {
switch ( settings . channelTextColors ) {
case 0 :
return uiColors [ GUI_COLOR_CHANNEL_FG ] ;
break ;
case 1 :
return uiColors [ GUI_COLOR_CHANNEL_FM + e - > getChannelType ( ch ) ] ;
break ;
case 2 :
return uiColors [ GUI_COLOR_INSTR_STD + e - > getPreferInsType ( ch ) ] ;
break ;
}
// invalid
return uiColors [ GUI_COLOR_TEXT ] ;
}
2021-12-19 21:01:24 +00:00
const char * defaultLayout = " [Window][DockSpaceViewport_11111111] \n \
Pos = 0 , 24 \ n \
2022-09-22 09:27:18 +00:00
Size = 1280 , 776 \ n \
2021-12-19 21:01:24 +00:00
Collapsed = 0 \ n \
\ n \
[ Window ] [ Debug # # Default ] \ n \
2023-02-24 09:26:17 +00:00
Pos = 54 , 43 \ n \
2021-12-19 21:01:24 +00:00
Size = 400 , 400 \ n \
Collapsed = 0 \ n \
\ n \
[ Window ] [ Play / Edit Controls ] \ n \
2022-03-14 22:40:22 +00:00
Pos = 181 , 208 \ n \
Size = 45 , 409 \ n \
2021-12-19 21:01:24 +00:00
Collapsed = 0 \ n \
\ n \
[ Window ] [ Song Information ] \ n \
2022-03-14 22:40:22 +00:00
Pos = 978 , 24 \ n \
2022-09-22 09:27:18 +00:00
Size = 302 , 179 \ n \
2021-12-19 21:01:24 +00:00
Collapsed = 0 \ n \
2022-09-22 09:27:18 +00:00
DockId = 0x0000000F , 0 \ n \
2021-12-19 21:01:24 +00:00
\ n \
[ Window ] [ Orders ] \ n \
Pos = 0 , 24 \ n \
2022-03-14 22:40:22 +00:00
Size = 345 , 217 \ n \
2021-12-19 21:01:24 +00:00
Collapsed = 0 \ n \
2022-03-14 22:40:22 +00:00
DockId = 0x00000007 , 0 \ n \
2021-12-19 21:01:24 +00:00
\ n \
[ Window ] [ Instruments ] \ n \
2022-03-14 22:40:22 +00:00
Pos = 653 , 24 \ n \
Size = 323 , 217 \ n \
2021-12-19 21:01:24 +00:00
Collapsed = 0 \ n \
2022-09-22 09:27:18 +00:00
DockId = 0x00000006 , 0 \ n \
2021-12-19 21:01:24 +00:00
\ n \
[ Window ] [ Wavetables ] \ n \
2022-03-14 22:40:22 +00:00
Pos = 653 , 24 \ n \
Size = 323 , 217 \ n \
2021-12-19 21:01:24 +00:00
Collapsed = 0 \ n \
2022-03-14 22:40:22 +00:00
DockId = 0x00000006 , 1 \ n \
2021-12-19 21:01:24 +00:00
\ n \
[ Window ] [ Samples ] \ n \
2022-03-14 22:40:22 +00:00
Pos = 653 , 24 \ n \
Size = 323 , 217 \ n \
2021-12-19 21:01:24 +00:00
Collapsed = 0 \ n \
2022-09-22 09:27:18 +00:00
DockId = 0x00000006 , 2 \ n \
2021-12-19 21:01:24 +00:00
\ n \
[ Window ] [ Pattern ] \ n \
2022-03-14 22:40:22 +00:00
Pos = 0 , 243 \ n \
2023-02-24 09:26:17 +00:00
Size = 939 , 557 \ n \
2021-12-19 21:01:24 +00:00
Collapsed = 0 \ n \
2023-02-24 09:26:17 +00:00
DockId = 0x00000017 , 0 \ n \
2021-12-19 21:01:24 +00:00
\ n \
2022-01-30 23:17:46 +00:00
[ Window ] [ Instrument Editor ] \ n \
2023-02-24 09:26:17 +00:00
Pos = 229 , 126 \ n \
Size = 856 , 652 \ n \
2022-01-30 23:17:46 +00:00
Collapsed = 0 \ n \
\ n \
[ Window ] [ Warning ] \ n \
2022-03-14 22:40:22 +00:00
Pos = 481 , 338 \ n \
2022-09-22 09:27:18 +00:00
Size = 264 , 86 \ n \
2022-01-30 23:17:46 +00:00
Collapsed = 0 \ n \
\ n \
[ Window ] [ Sample Editor ] \ n \
2023-02-24 09:26:17 +00:00
Pos = 47 , 216 \ n \
Size = 1075 , 525 \ n \
2022-01-30 23:17:46 +00:00
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 \
2022-03-14 22:40:22 +00:00
[ Window ] [ Wavetable Editor ] \ n \
Pos = 253 , 295 \ n \
Size = 748 , 378 \ n \
2022-01-30 23:17:46 +00:00
Collapsed = 0 \ n \
\ n \
2022-03-14 22:40:22 +00:00
[ Window ] [ Settings ] \ n \
Pos = 655 , 224 \ n \
2023-02-24 09:26:17 +00:00
Size = 1280 , 941 \ n \
2022-03-14 22:40:22 +00:00
Collapsed = 0 \ n \
\ n \
[ Window ] [ Error ] \ n \
Pos = 491 , 342 \ n \
Size = 514 , 71 \ n \
Collapsed = 0 \ n \
\ n \
[ Window ] [ Mixer ] \ n \
2022-09-22 09:27:18 +00:00
Pos = 429 , 198 \ n \
Size = 453 , 355 \ n \
2022-03-14 22:40:22 +00:00
Collapsed = 0 \ n \
\ n \
[ Window ] [ Oscilloscope ] \ n \
Pos = 347 , 94 \ n \
Size = 304 , 105 \ n \
Collapsed = 0 \ n \
DockId = 0x0000000E , 0 \ n \
\ n \
[ Window ] [ Volume Meter ] \ n \
Pos = 1248 , 243 \ n \
2022-09-22 09:27:18 +00:00
Size = 32 , 557 \ n \
2022-03-14 22:40:22 +00:00
Collapsed = 0 \ n \
DockId = 0x0000000C , 0 \ n \
\ n \
[ Window ] [ Debug ] \ n \
Pos = 113 , 148 \ n \
Size = 945 , 473 \ n \
Collapsed = 0 \ n \
\ n \
[ Window ] [ Load Sample # # FileDialog ] \ n \
Pos = 40 , 0 \ n \
Size = 1200 , 755 \ n \
Collapsed = 0 \ n \
\ n \
[ Window ] [ Open File # # FileDialog ] \ n \
Pos = 250 , 143 \ n \
Size = 779 , 469 \ n \
Collapsed = 0 \ n \
\ n \
[ Window ] [ Export Audio # # FileDialog ] \ n \
Pos = 339 , 177 \ n \
Size = 601 , 400 \ n \
Collapsed = 0 \ n \
\ n \
[ Window ] [ Rendering . . . ] \ n \
Pos = 585 , 342 \ n \
Size = 114 , 71 \ n \
2022-01-30 23:17:46 +00:00
Collapsed = 0 \ n \
2021-12-19 21:01:24 +00:00
\ n \
2022-03-14 22:40:22 +00:00
[ Window ] [ Export VGM # # FileDialog ] \ n \
2022-01-30 23:17:46 +00:00
Pos = 340 , 177 \ n \
Size = 600 , 400 \ n \
Collapsed = 0 \ n \
\ n \
2022-03-14 22:40:22 +00:00
[ Window ] [ Warning # # Save FileFileDialogOverWriteDialog ] \ n \
Pos = 390 , 351 \ n \
Size = 500 , 71 \ n \
2022-01-30 23:17:46 +00:00
Collapsed = 0 \ n \
\ n \
2022-03-14 22:40:22 +00:00
[ Window ] [ Statistics ] \ n \
2023-02-24 09:26:17 +00:00
Pos = 0 , 581 \ n \
Size = 1246 , 219 \ n \
2022-01-30 23:17:46 +00:00
Collapsed = 0 \ n \
2023-02-24 09:26:17 +00:00
DockId = 0x00000016 , 0 \ n \
2022-01-30 23:17:46 +00:00
\ n \
2022-03-14 22:40:22 +00:00
[ Window ] [ Warning # # Export VGMFileDialogOverWriteDialog ] \ n \
Pos = 390 , 351 \ n \
Size = 500 , 71 \ n \
Collapsed = 0 \ n \
\ n \
[ Window ] [ Compatibility Flags ] \ n \
2023-02-24 09:26:17 +00:00
Pos = 388 , 132 \ n \
Size = 580 , 641 \ n \
2022-03-14 22:40:22 +00:00
Collapsed = 0 \ n \
\ n \
[ Window ] [ Song Comments ] \ n \
Pos = 60 , 60 \ n \
Size = 395 , 171 \ n \
Collapsed = 0 \ n \
\ n \
[ Window ] [ Warning # # Export AudioFileDialogOverWriteDialog ] \ n \
Pos = 381 , 351 \ n \
Size = 500 , 71 \ n \
Collapsed = 0 \ n \
\ n \
[ Window ] [ Select Font # # FileDialog ] \ n \
2022-01-30 23:17:46 +00:00
Pos = 340 , 177 \ n \
Size = 600 , 400 \ n \
Collapsed = 0 \ n \
\ n \
2022-03-14 22:40:22 +00:00
[ Window ] [ Channels ] \ n \
2022-01-30 23:17:46 +00:00
Pos = 60 , 60 \ n \
2022-03-14 22:40:22 +00:00
Size = 368 , 449 \ n \
2022-01-30 23:17:46 +00:00
Collapsed = 0 \ n \
\ n \
2022-03-14 22:40:22 +00:00
[ Window ] [ Register View ] \ n \
2022-09-22 09:27:18 +00:00
Pos = 829 , 243 \ n \
Size = 417 , 557 \ n \
2022-01-30 23:17:46 +00:00
Collapsed = 0 \ n \
2022-09-22 09:27:18 +00:00
DockId = 0x00000014 , 0 \ n \
2022-01-30 23:17:46 +00:00
\ n \
2022-03-14 22:40:22 +00:00
[ Window ] [ New Song ] \ n \
Pos = 267 , 110 \ n \
Size = 746 , 534 \ n \
2022-01-30 23:17:46 +00:00
Collapsed = 0 \ n \
\ n \
2022-03-14 22:40:22 +00:00
[ Window ] [ Edit Controls ] \ n \
Pos = 347 , 24 \ n \
Size = 304 , 68 \ n \
Collapsed = 0 \ n \
DockId = 0x0000000D , 0 \ n \
\ n \
[ Window ] [ Play Controls ] \ n \
Pos = 347 , 201 \ n \
Size = 304 , 40 \ n \
2022-01-30 23:17:46 +00:00
Collapsed = 0 \ n \
2022-03-14 22:40:22 +00:00
DockId = 0x0000000A , 0 \ n \
2022-01-30 23:17:46 +00:00
\ n \
2022-09-22 09:27:18 +00:00
[ Window ] [ Subsongs ] \ n \
2023-02-24 09:26:17 +00:00
Pos = 978 , 24 \ n \
Size = 302 , 217 \ n \
2022-09-22 09:27:18 +00:00
Collapsed = 0 \ n \
2023-02-24 09:26:17 +00:00
DockId = 0x00000010 , 1 \ n \
2022-09-22 09:27:18 +00:00
\ n \
[ Window ] [ Oscilloscope ( per - channel ) ] \ n \
Pos = 1095 , 243 \ n \
Size = 151 , 557 \ n \
Collapsed = 0 \ n \
DockId = 0x00000012 , 0 \ n \
\ n \
[ Window ] [ Piano ] \ n \
Pos = 177 , 669 \ n \
Size = 922 , 118 \ n \
Collapsed = 0 \ n \
\ n \
[ Window ] [ Log Viewer ] \ n \
Pos = 60 , 60 \ n \
Size = 541 , 637 \ n \
Collapsed = 0 \ n \
\ n \
[ Window ] [ Pattern Manager ] \ n \
Pos = 60 , 60 \ n \
Size = 1099 , 366 \ n \
Collapsed = 0 \ n \
\ n \
[ Window ] [ Chip Manager ] \ n \
Pos = 60 , 60 \ n \
Size = 490 , 407 \ n \
Collapsed = 0 \ n \
\ n \
2023-02-24 09:26:17 +00:00
[ Window ] [ Speed ] \ n \
Pos = 978 , 24 \ n \
Size = 302 , 217 \ n \
Collapsed = 0 \ n \
DockId = 0x00000010 , 2 \ n \
\ n \
[ Window ] [ Song Info # # Song Information ] \ n \
Pos = 978 , 24 \ n \
Size = 302 , 217 \ n \
Collapsed = 0 \ n \
DockId = 0x00000010 , 0 \ n \
\ n \
[ Window ] [ Effect List ] \ n \
Pos = 941 , 243 \ n \
Size = 305 , 557 \ n \
Collapsed = 0 \ n \
DockId = 0x00000018 , 0 \ n \
\ n \
[ Window ] [ Intro ] \ n \
Pos = 0 , 0 \ n \
Size = 2560 , 1600 \ n \
Collapsed = 0 \ n \
\ n \
[ Window ] [ Welcome ] \ n \
Pos = 944 , 666 \ n \
Size = 672 , 268 \ n \
Collapsed = 0 \ n \
\ n \
[ Window ] [ Grooves ] \ n \
Pos = 416 , 314 \ n \
Size = 463 , 250 \ n \
Collapsed = 0 \ n \
\ n \
[ Window ] [ Clock ] \ n \
Pos = 60 , 60 \ n \
Size = 145 , 184 \ n \
Collapsed = 0 \ n \
\ n \
2022-01-30 23:17:46 +00:00
[ Docking ] [ Data ] \ n \
2022-09-22 09:27:18 +00:00
DockSpace ID = 0x8B93E3BD Window = 0xA787BDB4 Pos = 0 , 24 Size = 1280 , 776 Split = Y Selected = 0x6C01C512 \ n \
2022-03-14 22:40:22 +00:00
DockNode ID = 0x00000001 Parent = 0x8B93E3BD SizeRef = 1280 , 217 Split = X Selected = 0xF3094A52 \ n \
DockNode ID = 0x00000003 Parent = 0x00000001 SizeRef = 976 , 231 Split = X Selected = 0x65CC51DC \ n \
DockNode ID = 0x00000007 Parent = 0x00000003 SizeRef = 345 , 231 HiddenTabBar = 1 Selected = 0x8F5BFC9A \ n \
DockNode ID = 0x00000008 Parent = 0x00000003 SizeRef = 629 , 231 Split = X Selected = 0xD2AD486B \ n \
DockNode ID = 0x00000005 Parent = 0x00000008 SizeRef = 304 , 406 Split = Y Selected = 0x6D682373 \ n \
DockNode ID = 0x00000009 Parent = 0x00000005 SizeRef = 292 , 175 Split = Y Selected = 0x6D682373 \ n \
DockNode ID = 0x0000000D Parent = 0x00000009 SizeRef = 292 , 68 HiddenTabBar = 1 Selected = 0xE57B1A9D \ n \
DockNode ID = 0x0000000E Parent = 0x00000009 SizeRef = 292 , 105 HiddenTabBar = 1 Selected = 0x6D682373 \ n \
DockNode ID = 0x0000000A Parent = 0x00000005 SizeRef = 292 , 40 HiddenTabBar = 1 Selected = 0x0DE44CFF \ n \
2023-02-24 09:26:17 +00:00
DockNode ID = 0x00000006 Parent = 0x00000008 SizeRef = 323 , 406 Selected = 0xB75D68C7 \ n \
2022-09-22 09:27:18 +00:00
DockNode ID = 0x00000004 Parent = 0x00000001 SizeRef = 302 , 231 Split = Y Selected = 0x60B9D088 \ n \
DockNode ID = 0x0000000F Parent = 0x00000004 SizeRef = 302 , 179 Selected = 0x60B9D088 \ n \
2023-02-24 09:26:17 +00:00
DockNode ID = 0x00000010 Parent = 0x00000004 SizeRef = 302 , 36 Selected = 0x82BEE2E5 \ n \
2022-03-14 22:40:22 +00:00
DockNode ID = 0x00000002 Parent = 0x8B93E3BD SizeRef = 1280 , 512 Split = X Selected = 0x6C01C512 \ n \
2022-09-22 09:27:18 +00:00
DockNode ID = 0x0000000B Parent = 0x00000002 SizeRef = 1246 , 503 Split = X Selected = 0xB9ADD0D5 \ n \
DockNode ID = 0x00000011 Parent = 0x0000000B SizeRef = 1093 , 557 Split = X Selected = 0xB9ADD0D5 \ n \
2023-02-24 09:26:17 +00:00
DockNode ID = 0x00000013 Parent = 0x00000011 SizeRef = 827 , 557 Split = Y Selected = 0xB9ADD0D5 \ n \
DockNode ID = 0x00000015 Parent = 0x00000013 SizeRef = 1246 , 336 Split = X Selected = 0xB9ADD0D5 \ n \
DockNode ID = 0x00000017 Parent = 0x00000015 SizeRef = 939 , 557 CentralNode = 1 HiddenTabBar = 1 Selected = 0xB9ADD0D5 \ n \
DockNode ID = 0x00000018 Parent = 0x00000015 SizeRef = 305 , 557 Selected = 0xB94874DD \ n \
DockNode ID = 0x00000016 Parent = 0x00000013 SizeRef = 1246 , 219 Selected = 0xAD8E88F2 \ n \
2022-09-22 09:27:18 +00:00
DockNode ID = 0x00000014 Parent = 0x00000011 SizeRef = 417 , 557 Selected = 0x425428FB \ n \
DockNode ID = 0x00000012 Parent = 0x0000000B SizeRef = 151 , 557 HiddenTabBar = 1 Selected = 0x4C07BC58 \ n \
DockNode ID = 0x0000000C Parent = 0x00000002 SizeRef = 32 , 503 HiddenTabBar = 1 Selected = 0x644DA2C1 \ 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
2022-04-11 03:12:02 +00:00
logI ( " loading default layout. " ) ;
2022-01-20 10:04:03 +00:00
check = ps_fopen ( finalLayoutPath , " w " ) ;
2021-12-19 21:01:24 +00:00
if ( check = = NULL ) {
2022-04-11 03:12:02 +00:00
logW ( " could not write default layout! " ) ;
2021-12-19 21:01:24 +00:00
return ;
}
fwrite ( defaultLayout , 1 , strlen ( defaultLayout ) , check ) ;
fclose ( check ) ;
}
2023-02-05 07:56:39 +00:00
float FurnaceGUI : : calcBPM ( const DivGroovePattern & speeds , float hz , int vN , int vD ) {
2022-05-15 06:42:49 +00:00
float hl = e - > curSubSong - > hilightA ;
2022-03-16 04:30:15 +00:00
if ( hl < = 0.0f ) hl = 4.0f ;
2022-05-15 06:42:49 +00:00
float timeBase = e - > curSubSong - > timeBase + 1 ;
2023-02-05 07:56:39 +00:00
float speedSum = 0 ;
for ( int i = 0 ; i < MIN ( 16 , speeds . len ) ; i + + ) {
speedSum + = speeds . val [ i ] ;
}
speedSum / = MAX ( 1 , speeds . len ) ;
2022-03-16 04:30:15 +00:00
if ( timeBase < 1.0f ) timeBase = 1.0f ;
if ( speedSum < 1.0f ) speedSum = 1.0f ;
2022-05-18 05:05:25 +00:00
if ( vD < 1 ) vD = 1 ;
2023-02-05 07:56:39 +00:00
return ( 60.0f * hz / ( timeBase * hl * speedSum ) ) * ( float ) vN / ( float ) vD ;
2022-03-16 04:30:15 +00:00
}
2022-03-21 22:34:43 +00:00
void FurnaceGUI : : play ( int row ) {
2023-01-19 00:22:43 +00:00
memset ( chanOscVol , 0 , DIV_MAX_CHANS * sizeof ( float ) ) ;
memset ( chanOscPitch , 0 , DIV_MAX_CHANS * sizeof ( float ) ) ;
memset ( chanOscBright , 0 , DIV_MAX_CHANS * sizeof ( float ) ) ;
2022-03-21 22:34:43 +00:00
e - > walkSong ( loopOrder , loopRow , loopEnd ) ;
memset ( lastIns , - 1 , sizeof ( int ) * DIV_MAX_CHANS ) ;
2022-04-14 07:58:29 +00:00
if ( ! followPattern ) e - > setOrder ( curOrder ) ;
2022-03-21 22:34:43 +00:00
if ( row > 0 ) {
e - > playToRow ( row ) ;
} else {
e - > play ( ) ;
2022-01-13 06:03:57 +00:00
}
2022-03-21 22:34:43 +00:00
curNibble = false ;
orderNibble = false ;
activeNotes . clear ( ) ;
2022-01-13 06:03:57 +00:00
}
2022-04-14 07:58:29 +00:00
void FurnaceGUI : : setOrder ( unsigned char order , bool forced ) {
curOrder = order ;
if ( followPattern | | forced ) {
e - > setOrder ( order ) ;
}
}
2022-03-21 22:34:43 +00:00
void FurnaceGUI : : stop ( ) {
2023-08-29 23:54:08 +00:00
bool wasPlaying = e - > isPlaying ( ) ;
2022-03-21 22:34:43 +00:00
e - > walkSong ( loopOrder , loopRow , loopEnd ) ;
e - > stop ( ) ;
curNibble = false ;
orderNibble = false ;
2023-08-29 23:54:08 +00:00
if ( followPattern & & wasPlaying ) {
nextScroll = - 1.0f ;
nextAddScroll = 0.0f ;
cursor . y = e - > getRow ( ) ;
if ( selStart . xCoarse = = selEnd . xCoarse & & selStart . xFine = = selEnd . xFine & & selStart . y = = selEnd . y & & ! selecting ) {
selStart = cursor ;
selEnd = cursor ;
}
updateScroll ( cursor . y ) ;
}
2022-01-27 22:49:00 +00:00
}
2022-03-31 06:51:57 +00:00
void FurnaceGUI : : previewNote ( int refChan , int note , bool autoNote ) {
2022-04-14 18:54:47 +00:00
e - > setMidiBaseChan ( refChan ) ;
e - > synchronized ( [ this , note ] ( ) {
e - > autoNoteOn ( - 1 , curIns , note ) ;
} ) ;
2022-01-29 23:56:08 +00:00
}
2022-03-31 06:51:57 +00:00
void FurnaceGUI : : stopPreviewNote ( SDL_Scancode scancode , bool autoNote ) {
2023-07-24 22:39:09 +00:00
auto it = noteKeys . find ( scancode ) ;
if ( it ! = noteKeys . cend ( ) ) {
int key = it - > second ;
2022-03-21 22:34:43 +00:00
int num = 12 * curOctave + key ;
2022-03-30 09:49:15 +00:00
if ( num < - 60 ) num = - 60 ; // C-(-5)
if ( num > 119 ) num = 119 ; // B-9
2022-02-19 21:15:57 +00:00
2022-03-21 22:34:43 +00:00
if ( key = = 100 ) return ;
if ( key = = 101 ) return ;
if ( key = = 102 ) return ;
2022-01-20 06:32:16 +00:00
2022-04-14 18:54:47 +00:00
e - > synchronized ( [ this , num ] ( ) {
e - > autoNoteOff ( - 1 , num ) ;
} ) ;
2022-02-11 23:20:39 +00:00
}
}
2022-03-31 20:25:58 +00:00
void FurnaceGUI : : noteInput ( int num , int key , int vol ) {
2022-05-15 06:42:49 +00:00
DivPattern * pat = e - > curPat [ cursor . xCoarse ] . getPattern ( e - > curOrders - > ord [ cursor . xCoarse ] [ curOrder ] , true ) ;
2023-08-05 08:37:03 +00:00
bool removeIns = false ;
2022-05-26 05:24:21 +00:00
2022-03-30 20:44:27 +00:00
prepareUndo ( GUI_UNDO_PATTERN_EDIT ) ;
2022-12-10 19:32:51 +00:00
if ( key = = GUI_NOTE_OFF ) { // note off
2022-03-30 20:44:27 +00:00
pat - > data [ cursor . y ] [ 0 ] = 100 ;
pat - > data [ cursor . y ] [ 1 ] = 0 ;
2023-08-05 08:37:03 +00:00
removeIns = true ;
2022-12-10 19:32:51 +00:00
} else if ( key = = GUI_NOTE_OFF_RELEASE ) { // note off + env release
2022-03-30 20:44:27 +00:00
pat - > data [ cursor . y ] [ 0 ] = 101 ;
pat - > data [ cursor . y ] [ 1 ] = 0 ;
2023-08-05 08:37:03 +00:00
removeIns = true ;
2022-12-10 19:32:51 +00:00
} else if ( key = = GUI_NOTE_RELEASE ) { // env release only
2022-03-30 20:44:27 +00:00
pat - > data [ cursor . y ] [ 0 ] = 102 ;
pat - > data [ cursor . y ] [ 1 ] = 0 ;
2023-08-05 08:37:03 +00:00
removeIns = true ;
2022-03-30 20:44:27 +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 ] - - ;
}
pat - > data [ cursor . y ] [ 1 ] = ( unsigned char ) pat - > data [ cursor . y ] [ 1 ] ;
if ( latchIns = = - 2 ) {
2022-04-21 08:22:01 +00:00
if ( curIns > = ( int ) e - > song . ins . size ( ) ) curIns = - 1 ;
2022-04-21 08:26:34 +00:00
if ( curIns > = 0 ) {
pat - > data [ cursor . y ] [ 2 ] = curIns ;
}
2022-03-30 20:44:27 +00:00
} else if ( latchIns ! = - 1 & & ! e - > song . ins . empty ( ) ) {
pat - > data [ cursor . y ] [ 2 ] = MIN ( ( ( int ) e - > song . ins . size ( ) ) - 1 , latchIns ) ;
}
2022-03-31 20:25:58 +00:00
int maxVol = e - > getMaxVolumeChan ( cursor . xCoarse ) ;
2022-03-30 20:44:27 +00:00
if ( latchVol ! = - 1 ) {
pat - > data [ cursor . y ] [ 3 ] = MIN ( maxVol , latchVol ) ;
2022-03-31 20:25:58 +00:00
} else if ( vol ! = - 1 ) {
pat - > data [ cursor . y ] [ 3 ] = ( vol * maxVol ) / 127 ;
2022-03-30 20:44:27 +00:00
}
if ( latchEffect ! = - 1 ) pat - > data [ cursor . y ] [ 4 ] = latchEffect ;
if ( latchEffectVal ! = - 1 ) pat - > data [ cursor . y ] [ 5 ] = latchEffectVal ;
}
2023-08-05 08:37:03 +00:00
if ( removeIns ) {
if ( settings . removeInsOff ) {
pat - > data [ cursor . y ] [ 2 ] = - 1 ;
}
if ( settings . removeVolOff ) {
pat - > data [ cursor . y ] [ 3 ] = - 1 ;
}
}
2022-03-30 20:44:27 +00:00
makeUndo ( GUI_UNDO_PATTERN_EDIT ) ;
editAdvance ( ) ;
curNibble = false ;
}
2022-04-01 06:50:01 +00:00
void FurnaceGUI : : valueInput ( int num , bool direct , int target ) {
2022-05-15 06:42:49 +00:00
DivPattern * pat = e - > curPat [ cursor . xCoarse ] . getPattern ( e - > curOrders - > ord [ cursor . xCoarse ] [ curOrder ] , true ) ;
2022-04-01 06:50:01 +00:00
prepareUndo ( GUI_UNDO_PATTERN_EDIT ) ;
if ( target = = - 1 ) target = cursor . xFine + 1 ;
if ( direct ) {
pat - > data [ cursor . y ] [ target ] = num & 0xff ;
} else {
if ( pat - > data [ cursor . y ] [ target ] = = - 1 ) pat - > data [ cursor . y ] [ target ] = 0 ;
2022-04-13 22:42:55 +00:00
if ( ! settings . pushNibble & & ! curNibble ) {
pat - > data [ cursor . y ] [ target ] = num ;
} else {
pat - > data [ cursor . y ] [ target ] = ( ( pat - > data [ cursor . y ] [ target ] < < 4 ) | num ) & 0xff ;
}
2022-04-01 06:50:01 +00:00
}
if ( cursor . xFine = = 1 ) { // instrument
if ( pat - > data [ cursor . y ] [ target ] > = ( int ) e - > song . ins . size ( ) ) {
pat - > data [ cursor . y ] [ target ] & = 0x0f ;
if ( pat - > data [ cursor . y ] [ target ] > = ( int ) e - > song . ins . size ( ) ) {
pat - > data [ cursor . y ] [ target ] = ( int ) e - > song . ins . size ( ) - 1 ;
}
}
2022-04-21 07:35:50 +00:00
if ( settings . absorbInsInput ) {
curIns = pat - > data [ cursor . y ] [ target ] ;
2022-05-21 23:36:15 +00:00
wavePreviewInit = true ;
2023-03-18 09:22:50 +00:00
updateFMPreview = true ;
2022-04-21 07:35:50 +00:00
}
2022-04-01 06:50:01 +00:00
makeUndo ( GUI_UNDO_PATTERN_EDIT ) ;
if ( direct ) {
curNibble = false ;
} else {
if ( e - > song . ins . size ( ) < 16 ) {
curNibble = false ;
editAdvance ( ) ;
} else {
curNibble = ! curNibble ;
if ( ! curNibble ) editAdvance ( ) ;
}
}
} else if ( cursor . xFine = = 2 ) {
if ( curNibble ) {
if ( pat - > data [ cursor . y ] [ target ] > e - > getMaxVolumeChan ( cursor . xCoarse ) ) pat - > data [ cursor . y ] [ target ] = e - > getMaxVolumeChan ( cursor . xCoarse ) ;
} else {
pat - > data [ cursor . y ] [ target ] & = 15 ;
}
makeUndo ( GUI_UNDO_PATTERN_EDIT ) ;
if ( direct ) {
curNibble = false ;
} else {
if ( e - > getMaxVolumeChan ( cursor . xCoarse ) < 16 ) {
curNibble = false ;
editAdvance ( ) ;
} else {
curNibble = ! curNibble ;
if ( ! curNibble ) editAdvance ( ) ;
}
}
} else {
makeUndo ( GUI_UNDO_PATTERN_EDIT ) ;
if ( direct ) {
curNibble = false ;
} else {
curNibble = ! curNibble ;
2022-04-04 00:20:30 +00:00
if ( ! curNibble ) {
if ( ! settings . effectCursorDir ) {
editAdvance ( ) ;
} else {
2022-04-08 07:16:57 +00:00
if ( settings . effectCursorDir = = 2 ) {
2022-05-15 06:42:49 +00:00
if ( + + cursor . xFine > = ( 3 + ( e - > curPat [ cursor . xCoarse ] . effectCols * 2 ) ) ) {
2022-04-08 07:16:57 +00:00
cursor . xFine = 3 ;
}
2022-04-04 00:20:30 +00:00
} else {
2022-04-08 07:16:57 +00:00
if ( cursor . xFine & 1 ) {
cursor . xFine + + ;
} else {
editAdvance ( ) ;
cursor . xFine - - ;
}
2022-04-04 00:20:30 +00:00
}
}
}
2022-04-01 06:50:01 +00:00
}
}
}
2022-04-21 23:30:32 +00:00
# define changeLatch(x) \
if ( x < 0 ) x = 0 ; \
if ( ! latchNibble & & ! settings . pushNibble ) x = 0 ; \
x = ( x < < 4 ) | num ; \
latchNibble = ! latchNibble ; \
if ( ! latchNibble ) { \
if ( + + latchTarget > 4 ) latchTarget = 0 ; \
}
2022-02-11 23:20:39 +00:00
void FurnaceGUI : : keyDown ( SDL_Event & ev ) {
2023-02-24 07:03:43 +00:00
if ( introPos < 11.0 & & ! shortIntro ) return ;
2022-02-11 23:20:39 +00:00
if ( ImGuiFileDialog : : Instance ( ) - > IsOpened ( ) ) return ;
2022-02-12 07:14:25 +00:00
if ( aboutOpen ) return ;
2022-02-11 23:20:39 +00:00
int mapped = ev . key . keysym . sym ;
if ( ev . key . keysym . mod & KMOD_CTRL ) {
mapped | = FURKMOD_CTRL ;
}
if ( ev . key . keysym . mod & KMOD_ALT ) {
mapped | = FURKMOD_ALT ;
}
if ( ev . key . keysym . mod & KMOD_GUI ) {
mapped | = FURKMOD_META ;
}
if ( ev . key . keysym . mod & KMOD_SHIFT ) {
mapped | = FURKMOD_SHIFT ;
2021-12-21 22:42:27 +00:00
}
2022-02-12 06:57:55 +00:00
if ( bindSetActive ) {
if ( ! ev . key . repeat ) {
switch ( ev . key . keysym . sym ) {
case SDLK_LCTRL : case SDLK_RCTRL :
case SDLK_LALT : case SDLK_RALT :
case SDLK_LGUI : case SDLK_RGUI :
case SDLK_LSHIFT : case SDLK_RSHIFT :
bindSetPending = false ;
actionKeys [ bindSetTarget ] = ( mapped & ( ~ FURK_MASK ) ) | 0xffffff ;
break ;
default :
actionKeys [ bindSetTarget ] = mapped ;
bindSetActive = false ;
bindSetPending = false ;
bindSetTarget = 0 ;
bindSetPrevValue = 0 ;
parseKeybinds ( ) ;
break ;
}
}
return ;
}
2022-04-21 23:30:32 +00:00
if ( latchTarget ) {
if ( mapped = = SDLK_DELETE | | mapped = = SDLK_BACKSPACE ) {
switch ( latchTarget ) {
case 1 :
latchIns = - 1 ;
break ;
case 2 :
latchVol = - 1 ;
break ;
case 3 :
latchEffect = - 1 ;
break ;
case 4 :
latchEffectVal = - 1 ;
break ;
}
} else {
2023-07-24 22:39:09 +00:00
auto it = valueKeys . find ( ev . key . keysym . sym ) ;
if ( it ! = valueKeys . cend ( ) ) {
int num = it - > second ;
2022-04-21 23:30:32 +00:00
switch ( latchTarget ) {
case 1 : // instrument
changeLatch ( latchIns ) ;
break ;
case 2 : // volume
changeLatch ( latchVol ) ;
break ;
case 3 : // effect
changeLatch ( latchEffect ) ;
break ;
case 4 : // effect value
changeLatch ( latchEffectVal ) ;
break ;
}
}
}
return ;
}
2023-04-12 05:50:31 +00:00
if ( sampleMapWaitingInput ) {
if ( sampleMapColumn = = 1 ) {
// TODO: map?
if ( ev . key . keysym . scancode = = SDL_SCANCODE_DELETE ) {
alterSampleMap ( true , - 1 ) ;
return ;
}
2023-07-24 22:39:09 +00:00
auto it = noteKeys . find ( ev . key . keysym . scancode ) ;
if ( it ! = noteKeys . cend ( ) ) {
int key = it - > second ;
2023-04-12 05:50:31 +00:00
int num = 12 * curOctave + key ;
if ( num < - 60 ) num = - 60 ; // C-(-5)
if ( num > 119 ) num = 119 ; // B-9
alterSampleMap ( true , num ) ;
return ;
}
} else {
// TODO: map?
if ( ev . key . keysym . scancode = = SDL_SCANCODE_DELETE ) {
alterSampleMap ( false , - 1 ) ;
return ;
}
2023-07-24 22:39:09 +00:00
auto it = valueKeys . find ( ev . key . keysym . sym ) ;
if ( it ! = valueKeys . cend ( ) ) {
int num = it - > second ;
2023-04-12 05:50:31 +00:00
if ( num < 10 ) {
alterSampleMap ( false , num ) ;
return ;
}
}
}
}
2021-12-21 22:42:27 +00:00
// PER-WINDOW KEYS
2021-12-14 22:45:37 +00:00
switch ( curWindow ) {
2023-07-24 22:39:09 +00:00
case GUI_WINDOW_PATTERN : {
auto actionI = actionMapPat . find ( mapped ) ;
if ( actionI ! = actionMapPat . cend ( ) ) {
int action = actionI - > second ;
2022-02-11 23:20:39 +00:00
if ( action > 0 ) {
doAction ( action ) ;
return ;
}
}
// pattern input otherwise
if ( mapped & ( FURKMOD_ALT | FURKMOD_CTRL | FURKMOD_META | FURKMOD_SHIFT ) ) break ;
if ( ! ev . key . repeat ) {
if ( cursor . xFine = = 0 ) { // note
2023-07-24 22:39:09 +00:00
auto it = noteKeys . find ( ev . key . keysym . scancode ) ;
if ( it ! = noteKeys . cend ( ) ) {
int key = it - > second ;
2022-02-11 23:20:39 +00:00
int num = 12 * curOctave + key ;
2022-03-21 03:16:20 +00:00
if ( num < - 60 ) num = - 60 ; // C-(-5)
if ( num > 119 ) num = 119 ; // B-9
2022-02-11 23:20:39 +00:00
if ( edit ) {
2022-03-30 20:44:27 +00:00
noteInput ( num , key ) ;
2022-03-30 23:18:39 +00:00
}
2022-02-11 23:20:39 +00:00
}
} else if ( edit ) { // value
2023-07-24 22:39:09 +00:00
auto it = valueKeys . find ( ev . key . keysym . sym ) ;
if ( it ! = valueKeys . cend ( ) ) {
int num = it - > second ;
2022-04-01 06:50:01 +00:00
valueInput ( num ) ;
2022-02-11 23:20:39 +00:00
}
}
}
break ;
2023-07-24 22:39:09 +00:00
}
case GUI_WINDOW_ORDERS : {
auto actionI = actionMapOrders . find ( mapped ) ;
if ( actionI ! = actionMapOrders . cend ( ) ) {
int action = actionI - > second ;
2022-02-11 23:20:39 +00:00
if ( action > 0 ) {
doAction ( action ) ;
return ;
}
}
// order input otherwise
if ( mapped & ( FURKMOD_ALT | FURKMOD_CTRL | FURKMOD_META | FURKMOD_SHIFT ) ) break ;
2022-01-20 07:11:03 +00:00
if ( orderEditMode ! = 0 ) {
2023-07-24 22:39:09 +00:00
auto it = valueKeys . find ( ev . key . keysym . sym ) ;
if ( it ! = valueKeys . cend ( ) ) {
int num = it - > second ;
2022-01-20 07:11:03 +00:00
if ( orderCursor > = 0 & & orderCursor < e - > getTotalChannelCount ( ) ) {
2023-07-17 21:42:07 +00:00
prepareUndo ( GUI_UNDO_CHANGE_ORDER ) ;
2022-04-14 07:58:29 +00:00
e - > lockSave ( [ this , num ] ( ) {
2023-07-22 22:48:13 +00:00
if ( ! curNibble & & ! settings . pushNibble ) e - > curOrders - > ord [ orderCursor ] [ curOrder ] = 0 ;
2022-05-15 06:42:49 +00:00
e - > curOrders - > ord [ orderCursor ] [ curOrder ] = ( ( e - > curOrders - > ord [ orderCursor ] [ curOrder ] < < 4 ) | num ) ;
2022-03-21 21:17:51 +00:00
} ) ;
2022-09-09 05:02:43 +00:00
MARK_MODIFIED ;
2023-08-01 18:30:57 +00:00
curNibble = ! curNibble ;
2022-01-20 07:11:03 +00:00
if ( orderEditMode = = 2 | | orderEditMode = = 3 ) {
if ( ! curNibble ) {
if ( orderEditMode = = 2 ) {
orderCursor + + ;
if ( orderCursor > = e - > getTotalChannelCount ( ) ) orderCursor = 0 ;
} else if ( orderEditMode = = 3 ) {
2022-05-15 06:42:49 +00:00
if ( curOrder < e - > curSubSong - > ordersLen - 1 ) {
2022-04-14 07:58:29 +00:00
setOrder ( curOrder + 1 ) ;
2022-01-20 07:11:03 +00:00
}
}
}
}
2022-01-27 06:04:26 +00:00
e - > walkSong ( loopOrder , loopRow , loopEnd ) ;
2023-07-17 21:42:07 +00:00
makeUndo ( GUI_UNDO_CHANGE_ORDER ) ;
2022-01-20 07:11:03 +00:00
}
}
}
break ;
2023-07-24 22:39:09 +00:00
}
case GUI_WINDOW_SAMPLE_EDIT : {
auto actionI = actionMapSample . find ( mapped ) ;
if ( actionI ! = actionMapSample . cend ( ) ) {
int action = actionI - > second ;
2022-03-22 09:54:01 +00:00
if ( action > 0 ) {
doAction ( action ) ;
return ;
}
}
break ;
2023-07-24 22:39:09 +00:00
}
case GUI_WINDOW_INS_LIST : {
auto actionI = actionMapInsList . find ( mapped ) ;
if ( actionI ! = actionMapInsList . cend ( ) ) {
int action = actionI - > second ;
2022-02-11 23:20:39 +00:00
if ( action > 0 ) {
doAction ( action ) ;
return ;
2021-12-19 07:12:19 +00:00
}
2021-12-14 22:45:37 +00:00
}
break ;
2023-07-24 22:39:09 +00:00
}
case GUI_WINDOW_WAVE_LIST : {
auto actionI = actionMapWaveList . find ( mapped ) ;
if ( actionI ! = actionMapWaveList . cend ( ) ) {
int action = actionI - > second ;
2022-02-11 23:20:39 +00:00
if ( action > 0 ) {
doAction ( action ) ;
return ;
}
}
break ;
2023-07-24 22:39:09 +00:00
}
case GUI_WINDOW_SAMPLE_LIST : {
auto actionI = actionMapSampleList . find ( mapped ) ;
if ( actionI ! = actionMapSampleList . cend ( ) ) {
int action = actionI - > second ;
2022-02-11 23:20:39 +00:00
if ( action > 0 ) {
doAction ( action ) ;
return ;
}
}
break ;
2023-07-24 22:39:09 +00:00
}
2022-02-11 23:20:39 +00:00
default :
break ;
}
// GLOBAL KEYS
2023-07-24 22:39:09 +00:00
auto actionI = actionMapGlobal . find ( mapped ) ;
if ( actionI ! = actionMapGlobal . cend ( ) ) {
int action = actionI - > second ;
2022-02-11 23:20:39 +00:00
if ( action > 0 ) {
doAction ( action ) ;
return ;
2021-12-14 22:45:37 +00:00
}
2022-02-11 23:20:39 +00:00
}
2021-12-14 22:45:37 +00:00
}
void FurnaceGUI : : keyUp ( SDL_Event & ev ) {
2022-04-16 03:22:47 +00:00
// nothing for now
2021-12-14 22:45:37 +00:00
}
2023-04-06 09:22:43 +00:00
bool dirExists ( String s ) {
return dirExists ( s . c_str ( ) ) ;
2022-01-19 10:44:19 +00:00
}
2021-12-17 08:33:12 +00:00
void FurnaceGUI : : openFileDialog ( FurnaceGUIFileDialogs type ) {
2022-03-14 04:10:43 +00:00
bool hasOpened = false ;
2021-12-17 08:33:12 +00:00
switch ( type ) {
case GUI_FILE_OPEN :
2022-03-02 05:02:52 +00:00
if ( ! dirExists ( workingDirSong ) ) workingDirSong = getHomeDir ( ) ;
2022-03-14 04:10:43 +00:00
hasOpened = fileDialog - > openLoad (
" Open File " ,
2022-09-28 06:15:50 +00:00
{ " compatible files " , " *.fur *.dmf *.mod *.fc13 *.fc14 *.smod *.fc " ,
2023-01-28 23:36:43 +00:00
" all files " , " * " } ,
2022-03-14 04:10:43 +00:00
workingDirSong ,
dpiScale
) ;
2021-12-17 08:33:12 +00:00
break ;
2023-04-06 20:16:52 +00:00
case GUI_FILE_OPEN_BACKUP :
if ( ! dirExists ( backupPath ) ) {
showError ( " no backups made yet! " ) ;
break ;
}
hasOpened = fileDialog - > openLoad (
" Restore Backup " ,
{ " Furnace song " , " *.fur " } ,
2023-04-06 20:51:12 +00:00
backupPath + String ( DIR_SEPARATOR_STR ) ,
2023-04-06 20:16:52 +00:00
dpiScale
) ;
break ;
2021-12-17 08:33:12 +00:00
case GUI_FILE_SAVE :
2022-03-02 05:02:52 +00:00
if ( ! dirExists ( workingDirSong ) ) workingDirSong = getHomeDir ( ) ;
2022-03-14 04:10:43 +00:00
hasOpened = fileDialog - > openSave (
" Save File " ,
2022-09-04 07:26:29 +00:00
{ " Furnace song " , " *.fur " } ,
workingDirSong ,
dpiScale
) ;
break ;
case GUI_FILE_SAVE_DMF :
if ( ! dirExists ( workingDirSong ) ) workingDirSong = getHomeDir ( ) ;
hasOpened = fileDialog - > openSave (
" Save File " ,
{ " DefleMask 1.1.3 module " , " *.dmf " } ,
2022-03-14 04:10:43 +00:00
workingDirSong ,
dpiScale
) ;
2022-02-20 08:18:20 +00:00
break ;
case GUI_FILE_SAVE_DMF_LEGACY :
2022-03-02 05:02:52 +00:00
if ( ! dirExists ( workingDirSong ) ) workingDirSong = getHomeDir ( ) ;
2022-03-14 04:10:43 +00:00
hasOpened = fileDialog - > openSave (
" Save File " ,
{ " DefleMask 1.0/legacy module " , " *.dmf " } ,
workingDirSong ,
dpiScale
) ;
2021-12-17 08:33:12 +00:00
break ;
2022-01-19 08:15:20 +00:00
case GUI_FILE_INS_OPEN :
2022-05-05 03:55:11 +00:00
case GUI_FILE_INS_OPEN_REPLACE :
2022-04-26 06:07:28 +00:00
prevIns = - 3 ;
2022-05-05 03:55:11 +00:00
if ( prevInsData ! = NULL ) {
delete prevInsData ;
prevInsData = NULL ;
}
prevInsData = new DivInstrument ;
* prevInsData = * e - > getIns ( curIns ) ;
2022-03-02 05:02:52 +00:00
if ( ! dirExists ( workingDirIns ) ) workingDirIns = getHomeDir ( ) ;
2022-03-14 04:10:43 +00:00
hasOpened = fileDialog - > openLoad (
" Load Instrument " ,
2022-05-17 01:49:31 +00:00
{ " all compatible files " , " *.fui *.dmp *.tfi *.vgi *.s3i *.sbi *.opli *.opni *.y12 *.bnk *.ff *.gyb *.opm *.wopl *.wopn " ,
" Furnace instrument " , " *.fui " ,
" DefleMask preset " , " *.dmp " ,
" TFM Music Maker instrument " , " *.tfi " ,
" VGM Music Maker instrument " , " *.vgi " ,
" Scream Tracker 3 instrument " , " *.s3i " ,
" SoundBlaster instrument " , " *.sbi " ,
" Wohlstand OPL instrument " , " *.opli " ,
" Wohlstand OPN instrument " , " *.opni " ,
" Gens KMod patch dump " , " *.y12 " ,
" BNK file (AdLib) " , " *.bnk " ,
" FF preset bank " , " *.ff " ,
" 2612edit GYB preset bank " , " *.gyb " ,
" VOPM preset bank " , " *.opm " ,
" Wohlstand WOPL bank " , " *.wopl " ,
" Wohlstand WOPN bank " , " *.wopn " ,
2023-01-28 23:36:43 +00:00
" all files " , " * " } ,
2022-03-14 04:10:43 +00:00
workingDirIns ,
2022-04-25 23:58:17 +00:00
dpiScale ,
[ this ] ( const char * path ) {
2022-11-21 07:55:12 +00:00
int sampleCountBefore = e - > song . sampleLen ;
2022-11-21 08:01:57 +00:00
std : : vector < DivInstrument * > instruments = e - > instrumentFromFile ( path , false ) ;
2022-04-25 23:58:17 +00:00
if ( ! instruments . empty ( ) ) {
2022-11-21 07:55:12 +00:00
if ( e - > song . sampleLen ! = sampleCountBefore ) {
e - > renderSamplesP ( ) ;
}
2022-05-05 03:55:11 +00:00
if ( curFileDialog = = GUI_FILE_INS_OPEN_REPLACE ) {
if ( prevIns = = - 3 ) {
prevIns = curIns ;
}
if ( prevIns > = 0 & & prevIns < = ( int ) e - > song . ins . size ( ) ) {
* e - > song . ins [ prevIns ] = * instruments [ 0 ] ;
}
} else {
e - > loadTempIns ( instruments [ 0 ] ) ;
if ( curIns ! = - 2 ) {
prevIns = curIns ;
}
curIns = - 2 ;
2022-04-26 06:07:28 +00:00
}
2022-04-25 23:58:17 +00:00
}
for ( DivInstrument * i : instruments ) delete i ;
2022-10-28 08:44:17 +00:00
} ,
( type = = GUI_FILE_INS_OPEN )
2022-03-14 04:10:43 +00:00
) ;
2022-01-19 08:15:20 +00:00
break ;
case GUI_FILE_INS_SAVE :
2022-03-02 05:02:52 +00:00
if ( ! dirExists ( workingDirIns ) ) workingDirIns = getHomeDir ( ) ;
2022-03-14 04:10:43 +00:00
hasOpened = fileDialog - > openSave (
" Save Instrument " ,
2022-09-04 07:26:29 +00:00
{ " Furnace instrument " , " *.fui " } ,
workingDirIns ,
dpiScale
) ;
break ;
case GUI_FILE_INS_SAVE_DMP :
if ( ! dirExists ( workingDirIns ) ) workingDirIns = getHomeDir ( ) ;
hasOpened = fileDialog - > openSave (
" Save Instrument " ,
{ " DefleMask preset " , " *.dmp " } ,
2022-03-14 04:10:43 +00:00
workingDirIns ,
dpiScale
) ;
2022-01-19 08:15:20 +00:00
break ;
case GUI_FILE_WAVE_OPEN :
2022-08-13 09:17:32 +00:00
case GUI_FILE_WAVE_OPEN_REPLACE :
2022-03-02 05:02:52 +00:00
if ( ! dirExists ( workingDirWave ) ) workingDirWave = getHomeDir ( ) ;
2022-03-14 04:10:43 +00:00
hasOpened = fileDialog - > openLoad (
" Load Wavetable " ,
{ " compatible files " , " *.fuw *.dmw " ,
2023-01-28 23:36:43 +00:00
" all files " , " * " } ,
2022-03-14 04:10:43 +00:00
workingDirWave ,
2022-10-28 09:11:27 +00:00
dpiScale ,
NULL , // TODO
( type = = GUI_FILE_WAVE_OPEN )
2022-03-14 04:10:43 +00:00
) ;
2022-01-19 08:15:20 +00:00
break ;
case GUI_FILE_WAVE_SAVE :
2022-03-02 05:02:52 +00:00
if ( ! dirExists ( workingDirWave ) ) workingDirWave = getHomeDir ( ) ;
2022-03-14 04:10:43 +00:00
hasOpened = fileDialog - > openSave (
" Save Wavetable " ,
2022-09-04 07:26:29 +00:00
{ " Furnace wavetable " , " .fuw " } ,
workingDirWave ,
dpiScale
) ;
break ;
case GUI_FILE_WAVE_SAVE_DMW :
if ( ! dirExists ( workingDirWave ) ) workingDirWave = getHomeDir ( ) ;
hasOpened = fileDialog - > openSave (
" Save Wavetable " ,
{ " DefleMask wavetable " , " .dmw " } ,
workingDirWave ,
dpiScale
) ;
break ;
case GUI_FILE_WAVE_SAVE_RAW :
if ( ! dirExists ( workingDirWave ) ) workingDirWave = getHomeDir ( ) ;
hasOpened = fileDialog - > openSave (
" Save Wavetable " ,
{ " raw data " , " .raw " } ,
2022-03-14 04:10:43 +00:00
workingDirWave ,
dpiScale
) ;
2022-01-19 08:15:20 +00:00
break ;
2021-12-17 08:33:12 +00:00
case GUI_FILE_SAMPLE_OPEN :
2022-08-13 09:17:32 +00:00
case GUI_FILE_SAMPLE_OPEN_REPLACE :
2022-03-02 05:02:52 +00:00
if ( ! dirExists ( workingDirSample ) ) workingDirSample = getHomeDir ( ) ;
2022-03-14 04:10:43 +00:00
hasOpened = fileDialog - > openLoad (
" Load Sample " ,
2022-09-25 06:20:08 +00:00
{ " compatible files " , " *.wav *.dmc *.brr " ,
2023-01-28 23:36:43 +00:00
" all files " , " * " } ,
2022-03-14 04:10:43 +00:00
workingDirSample ,
2022-10-28 09:11:27 +00:00
dpiScale ,
NULL , // TODO
( type = = GUI_FILE_SAMPLE_OPEN )
2022-03-14 04:10:43 +00:00
) ;
2021-12-17 08:33:12 +00:00
break ;
2022-08-13 09:17:32 +00:00
case GUI_FILE_SAMPLE_OPEN_RAW :
case GUI_FILE_SAMPLE_OPEN_REPLACE_RAW :
if ( ! dirExists ( workingDirSample ) ) workingDirSample = getHomeDir ( ) ;
hasOpened = fileDialog - > openLoad (
" Load Raw Sample " ,
2023-01-28 23:36:43 +00:00
{ " all files " , " * " } ,
2022-08-13 09:17:32 +00:00
workingDirSample ,
dpiScale
) ;
break ;
2021-12-17 08:33:12 +00:00
case GUI_FILE_SAMPLE_SAVE :
2022-03-02 05:02:52 +00:00
if ( ! dirExists ( workingDirSample ) ) workingDirSample = getHomeDir ( ) ;
2022-03-14 04:10:43 +00:00
hasOpened = fileDialog - > openSave (
" Save Sample " ,
{ " Wave file " , " *.wav " } ,
workingDirSample ,
dpiScale
) ;
2021-12-17 08:33:12 +00:00
break ;
2023-05-02 08:57:25 +00:00
case GUI_FILE_SAMPLE_SAVE_RAW :
if ( ! dirExists ( workingDirSample ) ) workingDirSample = getHomeDir ( ) ;
hasOpened = fileDialog - > openSave (
2023-09-01 23:33:32 +00:00
" Save Raw Sample " ,
2023-05-02 08:57:25 +00:00
{ " all files " , " * " } ,
workingDirSample ,
dpiScale
) ;
break ;
2022-01-18 04:34:29 +00:00
case GUI_FILE_EXPORT_AUDIO_ONE :
2022-03-02 05:02:52 +00:00
if ( ! dirExists ( workingDirAudioExport ) ) workingDirAudioExport = getHomeDir ( ) ;
2022-03-14 04:10:43 +00:00
hasOpened = fileDialog - > openSave (
" Export Audio " ,
{ " Wave file " , " *.wav " } ,
workingDirAudioExport ,
dpiScale
) ;
2022-01-18 04:34:29 +00:00
break ;
case GUI_FILE_EXPORT_AUDIO_PER_SYS :
2022-03-02 05:02:52 +00:00
if ( ! dirExists ( workingDirAudioExport ) ) workingDirAudioExport = getHomeDir ( ) ;
2022-03-14 04:10:43 +00:00
hasOpened = fileDialog - > openSave (
" Export Audio " ,
{ " Wave file " , " *.wav " } ,
workingDirAudioExport ,
dpiScale
) ;
2022-01-18 04:34:29 +00:00
break ;
case GUI_FILE_EXPORT_AUDIO_PER_CHANNEL :
2022-03-02 05:02:52 +00:00
if ( ! dirExists ( workingDirAudioExport ) ) workingDirAudioExport = getHomeDir ( ) ;
2022-03-14 04:10:43 +00:00
hasOpened = fileDialog - > openSave (
" Export Audio " ,
{ " Wave file " , " *.wav " } ,
workingDirAudioExport ,
dpiScale
) ;
2022-01-18 04:34:29 +00:00
break ;
2022-01-24 06:10:38 +00:00
case GUI_FILE_EXPORT_VGM :
2022-03-02 05:02:52 +00:00
if ( ! dirExists ( workingDirVGMExport ) ) workingDirVGMExport = getHomeDir ( ) ;
2022-03-14 04:10:43 +00:00
hasOpened = fileDialog - > openSave (
" Export VGM " ,
{ " VGM file " , " *.vgm " } ,
workingDirVGMExport ,
dpiScale
) ;
2022-01-24 06:10:38 +00:00
break ;
2022-05-26 05:24:21 +00:00
case GUI_FILE_EXPORT_ZSM :
if ( ! dirExists ( workingDirZSMExport ) ) workingDirZSMExport = getHomeDir ( ) ;
hasOpened = fileDialog - > openSave (
" Export ZSM " ,
{ " ZSM file " , " *.zsm " } ,
workingDirZSMExport ,
dpiScale
) ;
break ;
2022-08-04 05:51:47 +00:00
case GUI_FILE_EXPORT_CMDSTREAM :
if ( ! dirExists ( workingDirROMExport ) ) workingDirROMExport = getHomeDir ( ) ;
hasOpened = fileDialog - > openSave (
" Export Command Stream " ,
2023-03-26 18:19:57 +00:00
{ " text file " , " *.txt " } ,
workingDirROMExport ,
dpiScale
) ;
break ;
case GUI_FILE_EXPORT_CMDSTREAM_BINARY :
if ( ! dirExists ( workingDirROMExport ) ) workingDirROMExport = getHomeDir ( ) ;
hasOpened = fileDialog - > openSave (
" Export Command Stream " ,
{ " binary file " , " *.bin " } ,
2022-08-04 05:51:47 +00:00
workingDirROMExport ,
dpiScale
) ;
break ;
2022-01-24 06:10:38 +00:00
case GUI_FILE_EXPORT_ROM :
2022-01-18 04:34:29 +00:00
showError ( " Coming soon! " ) ;
break ;
2022-02-14 23:18:30 +00:00
case GUI_FILE_LOAD_MAIN_FONT :
2022-03-02 05:02:52 +00:00
if ( ! dirExists ( workingDirFont ) ) workingDirFont = getHomeDir ( ) ;
2022-03-14 04:10:43 +00:00
hasOpened = fileDialog - > openLoad (
" Select Font " ,
{ " compatible files " , " *.ttf *.otf *.ttc " } ,
workingDirFont ,
dpiScale
) ;
2022-02-14 23:18:30 +00:00
break ;
2023-08-03 03:49:01 +00:00
case GUI_FILE_LOAD_HEAD_FONT :
2023-08-02 20:48:07 +00:00
if ( ! dirExists ( workingDirFont ) ) workingDirFont = getHomeDir ( ) ;
hasOpened = fileDialog - > openLoad (
" Select Font " ,
{ " compatible files " , " *.ttf *.otf *.ttc " } ,
workingDirFont ,
dpiScale
) ;
break ;
2022-02-14 23:18:30 +00:00
case GUI_FILE_LOAD_PAT_FONT :
2022-03-02 05:02:52 +00:00
if ( ! dirExists ( workingDirFont ) ) workingDirFont = getHomeDir ( ) ;
2022-03-14 04:10:43 +00:00
hasOpened = fileDialog - > openLoad (
" Select Font " ,
{ " compatible files " , " *.ttf *.otf *.ttc " } ,
workingDirFont ,
dpiScale
) ;
2022-02-14 23:18:30 +00:00
break ;
2022-04-06 18:53:39 +00:00
case GUI_FILE_IMPORT_COLORS :
if ( ! dirExists ( workingDirColors ) ) workingDirColors = getHomeDir ( ) ;
hasOpened = fileDialog - > openLoad (
" Select Color File " ,
2022-04-06 19:17:29 +00:00
{ " configuration files " , " *.cfgc " } ,
2022-04-06 18:53:39 +00:00
workingDirColors ,
dpiScale
) ;
break ;
case GUI_FILE_IMPORT_KEYBINDS :
if ( ! dirExists ( workingDirKeybinds ) ) workingDirKeybinds = getHomeDir ( ) ;
hasOpened = fileDialog - > openLoad (
" Select Keybind File " ,
2022-04-06 19:17:29 +00:00
{ " configuration files " , " *.cfgk " } ,
2022-04-06 18:53:39 +00:00
workingDirKeybinds ,
dpiScale
) ;
break ;
case GUI_FILE_IMPORT_LAYOUT :
if ( ! dirExists ( workingDirKeybinds ) ) workingDirKeybinds = getHomeDir ( ) ;
hasOpened = fileDialog - > openLoad (
" Select Layout File " ,
{ " .ini files " , " *.ini " } ,
workingDirKeybinds ,
dpiScale
) ;
break ;
case GUI_FILE_EXPORT_COLORS :
if ( ! dirExists ( workingDirColors ) ) workingDirColors = getHomeDir ( ) ;
hasOpened = fileDialog - > openSave (
" Export Colors " ,
2022-04-06 19:17:29 +00:00
{ " configuration files " , " *.cfgc " } ,
2022-04-06 18:53:39 +00:00
workingDirColors ,
dpiScale
) ;
break ;
case GUI_FILE_EXPORT_KEYBINDS :
if ( ! dirExists ( workingDirKeybinds ) ) workingDirKeybinds = getHomeDir ( ) ;
hasOpened = fileDialog - > openSave (
" Export Keybinds " ,
2022-04-06 19:17:29 +00:00
{ " configuration files " , " *.cfgk " } ,
2022-04-06 18:53:39 +00:00
workingDirKeybinds ,
dpiScale
) ;
break ;
case GUI_FILE_EXPORT_LAYOUT :
if ( ! dirExists ( workingDirKeybinds ) ) workingDirKeybinds = getHomeDir ( ) ;
hasOpened = fileDialog - > openSave (
" Export Layout " ,
{ " .ini files " , " *.ini " } ,
workingDirKeybinds ,
dpiScale
) ;
break ;
2022-05-11 21:39:36 +00:00
case GUI_FILE_YRW801_ROM_OPEN :
case GUI_FILE_TG100_ROM_OPEN :
case GUI_FILE_MU5_ROM_OPEN :
if ( ! dirExists ( workingDirSample ) ) workingDirSample = getHomeDir ( ) ;
hasOpened = fileDialog - > openLoad (
" Load ROM " ,
{ " compatible files " , " *.rom *.bin " ,
2023-01-28 23:36:43 +00:00
" all files " , " * " } ,
2022-05-13 03:15:03 +00:00
workingDirROM ,
2022-05-11 21:39:36 +00:00
dpiScale
) ;
break ;
2023-03-26 23:48:16 +00:00
case GUI_FILE_CMDSTREAM_OPEN :
if ( ! dirExists ( workingDirROM ) ) workingDirROM = getHomeDir ( ) ;
hasOpened = fileDialog - > openLoad (
" Play Command Stream " ,
{ " command stream " , " *.bin " ,
" all files " , " * " } ,
workingDirROM ,
dpiScale
) ;
break ;
2022-07-15 07:23:16 +00:00
case GUI_FILE_TEST_OPEN :
if ( ! dirExists ( workingDirTest ) ) workingDirTest = getHomeDir ( ) ;
hasOpened = fileDialog - > openLoad (
" Open Test " ,
{ " compatible files " , " *.fur *.dmf *.mod " ,
" another option " , " *.wav *.ttf " ,
2023-01-28 23:36:43 +00:00
" all files " , " * " } ,
2022-07-15 07:23:16 +00:00
workingDirTest ,
2022-10-17 00:40:14 +00:00
dpiScale ,
[ ] ( const char * path ) {
if ( path ! = NULL ) {
logI ( " Callback Result: %s " , path ) ;
} else {
logI ( " Callback Result: NULL " ) ;
}
}
2022-07-15 07:23:16 +00:00
) ;
break ;
case GUI_FILE_TEST_OPEN_MULTI :
if ( ! dirExists ( workingDirTest ) ) workingDirTest = getHomeDir ( ) ;
hasOpened = fileDialog - > openLoad (
" Open Test (Multi) " ,
{ " compatible files " , " *.fur *.dmf *.mod " ,
" another option " , " *.wav *.ttf " ,
2023-01-28 23:36:43 +00:00
" all files " , " * " } ,
2022-07-15 07:23:16 +00:00
workingDirTest ,
dpiScale ,
2022-10-17 00:40:14 +00:00
[ ] ( const char * path ) {
if ( path ! = NULL ) {
logI ( " Callback Result: %s " , path ) ;
} else {
logI ( " Callback Result: NULL " ) ;
}
} ,
2022-07-15 07:23:16 +00:00
true
) ;
break ;
case GUI_FILE_TEST_SAVE :
if ( ! dirExists ( workingDirTest ) ) workingDirTest = getHomeDir ( ) ;
hasOpened = fileDialog - > openSave (
" Save Test " ,
{ " Furnace song " , " *.fur " ,
" DefleMask module " , " *.dmf " } ,
workingDirTest ,
dpiScale
) ;
break ;
2021-12-17 08:33:12 +00:00
}
2022-03-14 04:10:43 +00:00
if ( hasOpened ) curFileDialog = type ;
2022-02-01 07:52:36 +00:00
//ImGui::GetIO().ConfigFlags|=ImGuiConfigFlags_NavEnableKeyboard;
2021-12-17 08:33:12 +00:00
}
2022-02-20 08:18:20 +00:00
int FurnaceGUI : : save ( String path , int dmfVersion ) {
2022-01-09 08:52:41 +00:00
SafeWriter * w ;
2022-12-22 18:10:08 +00:00
logD ( " saving file... " ) ;
2022-02-20 08:18:20 +00:00
if ( dmfVersion ) {
2022-08-28 06:03:23 +00:00
if ( dmfVersion < 24 ) dmfVersion = 24 ;
2022-02-20 08:18:20 +00:00
w = e - > saveDMF ( dmfVersion ) ;
2022-01-09 08:52:41 +00:00
} else {
2023-05-26 06:29:49 +00:00
w = e - > saveFur ( false , settings . newPatternFormat ) ;
2022-01-09 08:52:41 +00:00
}
2022-01-08 07:04:43 +00:00
if ( w = = NULL ) {
lastError = e - > getLastError ( ) ;
2022-12-22 18:10:08 +00:00
logE ( " couldn't save! %s " , lastError ) ;
2022-01-08 07:04:43 +00:00
return 3 ;
}
2022-12-22 18:10:08 +00:00
logV ( " opening file for writing... " ) ;
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 ) ;
2022-12-22 18:10:08 +00:00
logE ( " couldn't save! %s " , lastError ) ;
2022-01-14 05:34:22 +00:00
w - > finish ( ) ;
return 1 ;
}
2023-05-18 20:52:48 +00:00
if ( settings . 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! " ) ;
lastError = " compression error " ;
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! " ) ;
lastError = " zlib stream error " ;
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! " , strerror ( errno ) ) ;
lastError = strerror ( errno ) ;
deflateEnd ( & zl ) ;
fclose ( outFile ) ;
w - > finish ( ) ;
return 1 ;
}
}
}
2021-12-15 19:15:44 +00:00
zl . avail_out = 131072 ;
zl . next_out = zbuf ;
2023-05-18 20:52:48 +00:00
if ( ( ret = deflate ( & zl , Z_FINISH ) ) = = Z_STREAM_ERROR ) {
logE ( " zlib finish stream error! " ) ;
lastError = " zlib finish stream error " ;
2021-12-15 19:15:44 +00:00
deflateEnd ( & zl ) ;
fclose ( outFile ) ;
w - > finish ( ) ;
return 2 ;
}
2023-05-18 20:52:48 +00:00
if ( 131072 - zl . avail_out > 0 ) {
if ( fwrite ( zbuf , 1 , 131072 - zl . avail_out , outFile ) ! = ( 131072 - zl . avail_out ) ) {
2022-04-11 03:12:02 +00:00
logE ( " did not write entirely: %s! " , 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 ) ;
2023-05-18 20:52:48 +00:00
} else {
if ( fwrite ( w - > getFinalBuf ( ) , 1 , w - > size ( ) , outFile ) ! = w - > size ( ) ) {
2022-04-11 03:12:02 +00:00
logE ( " did not write entirely: %s! " , 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 ;
}
}
fclose ( outFile ) ;
w - > finish ( ) ;
2023-04-06 21:24:44 +00:00
backupLock . lock ( ) ;
2021-12-30 23:25:55 +00:00
curFileName = path ;
2023-04-06 21:24:44 +00:00
backupLock . unlock ( ) ;
2021-12-30 23:25:55 +00:00
modified = false ;
2022-04-04 18:25:38 +00:00
updateWindowTitle ( ) ;
2022-01-29 06:22:32 +00:00
if ( ! e - > getWarnings ( ) . empty ( ) ) {
showWarning ( e - > getWarnings ( ) , GUI_WARN_GENERIC ) ;
}
2022-09-10 23:53:27 +00:00
pushRecentFile ( path ) ;
2023-08-25 23:32:34 +00:00
pushRecentSys ( path . c_str ( ) ) ;
2022-12-22 18:10:08 +00:00
logD ( " save complete. " ) ;
2021-12-15 19:15:44 +00:00
return 0 ;
}
2021-12-15 05:37:27 +00:00
int FurnaceGUI : : load ( String path ) {
2023-08-05 19:43:29 +00:00
bool wasPlaying = e - > isPlaying ( ) ;
2021-12-15 05:37:27 +00:00
if ( ! path . empty ( ) ) {
2022-04-11 03:12:02 +00:00
logI ( " loading module... " ) ;
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 ) {
2022-04-11 03:12:02 +00:00
logE ( " that file is empty! " ) ;
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 ;
}
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 ) ;
return 1 ;
}
2022-04-15 06:30:21 +00:00
unsigned char * file = new unsigned char [ len ] ;
2021-12-15 05:37:27 +00:00
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 ( ) ;
2022-04-11 03:12:02 +00:00
logE ( " could not open file! " ) ;
2021-12-15 05:37:27 +00:00
return 1 ;
}
}
2023-04-06 21:24:44 +00:00
backupLock . lock ( ) ;
2021-12-30 23:25:55 +00:00
curFileName = path ;
2023-04-06 21:24:44 +00:00
backupLock . unlock ( ) ;
2021-12-30 23:25:55 +00:00
modified = false ;
2022-01-20 07:11:03 +00:00
curNibble = false ;
orderNibble = false ;
orderCursor = - 1 ;
2022-06-06 06:23:35 +00:00
curOrder = 0 ;
oldRow = 0 ;
2022-03-21 05:41:18 +00:00
samplePos = 0 ;
updateSampleTex = true ;
2022-01-20 07:11:03 +00:00
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-06-06 06:23:35 +00:00
updateScroll ( 0 ) ;
2022-01-29 06:22:32 +00:00
if ( ! e - > getWarnings ( ) . empty ( ) ) {
showWarning ( e - > getWarnings ( ) , GUI_WARN_GENERIC ) ;
}
2022-09-10 23:53:27 +00:00
pushRecentFile ( path ) ;
2023-08-05 19:43:29 +00:00
// do not auto-play a backup
if ( path . find ( backupPath ) ! = 0 ) {
if ( settings . playOnLoad = = 2 | | ( settings . playOnLoad = = 1 & & wasPlaying ) ) {
play ( ) ;
}
}
2021-12-15 05:37:27 +00:00
return 0 ;
}
2022-09-10 23:53:27 +00:00
void FurnaceGUI : : pushRecentFile ( String path ) {
if ( path . empty ( ) ) return ;
2023-04-06 09:22:43 +00:00
if ( path . find ( backupPath ) = = 0 ) return ;
2022-09-10 23:53:27 +00:00
for ( int i = 0 ; i < ( int ) recentFile . size ( ) ; i + + ) {
if ( recentFile [ i ] = = path ) {
recentFile . erase ( recentFile . begin ( ) + i ) ;
i - - ;
}
}
recentFile . push_front ( path ) ;
while ( ! recentFile . empty ( ) & & ( int ) recentFile . size ( ) > settings . maxRecentFile ) {
recentFile . pop_back ( ) ;
}
}
2023-08-25 23:32:34 +00:00
void FurnaceGUI : : pushRecentSys ( const char * path ) {
# ifdef _WIN32
WString widePath = utf8To16 ( path ) ;
SHAddToRecentDocs ( SHARD_PATHW , widePath . c_str ( ) ) ;
# endif
}
2023-04-06 09:22:43 +00:00
void FurnaceGUI : : delFirstBackup ( String name ) {
std : : vector < String > listOfFiles ;
# ifdef _WIN32
2023-04-06 11:30:43 +00:00
String findPath = backupPath + String ( DIR_SEPARATOR_STR ) + name + String ( " *.fur " ) ;
WIN32_FIND_DATAW next ;
HANDLE backDir = FindFirstFileW ( utf8To16 ( findPath . c_str ( ) ) . c_str ( ) , & next ) ;
if ( backDir ! = INVALID_HANDLE_VALUE ) {
do {
listOfFiles . push_back ( utf16To8 ( next . cFileName ) ) ;
2023-04-06 20:07:11 +00:00
} while ( FindNextFileW ( backDir , & next ) ! = 0 ) ;
2023-04-06 11:30:43 +00:00
FindClose ( backDir ) ;
}
2023-04-06 09:22:43 +00:00
# else
DIR * backDir = opendir ( backupPath . c_str ( ) ) ;
if ( backDir = = NULL ) {
logW ( " could not open backups dir! " ) ;
return ;
}
while ( true ) {
struct dirent * next = readdir ( backDir ) ;
if ( next = = NULL ) break ;
if ( strstr ( next - > d_name , name . c_str ( ) ) ! = next - > d_name ) continue ;
listOfFiles . push_back ( String ( next - > d_name ) ) ;
}
closedir ( backDir ) ;
# endif
std : : sort ( listOfFiles . begin ( ) , listOfFiles . end ( ) , [ ] ( const String & a , const String & b ) - > bool {
return strcmp ( a . c_str ( ) , b . c_str ( ) ) < 0 ;
} ) ;
2023-04-06 11:15:47 +00:00
int totalDelete = ( ( int ) listOfFiles . size ( ) ) - 5 ;
for ( int i = 0 ; i < totalDelete ; i + + ) {
String toDelete = backupPath + String ( DIR_SEPARATOR_STR ) + listOfFiles [ i ] ;
deleteFile ( toDelete . c_str ( ) ) ;
}
2023-04-06 09:22:43 +00:00
}
2023-03-26 23:48:16 +00:00
int FurnaceGUI : : loadStream ( String path ) {
if ( ! path . empty ( ) ) {
logI ( " loading stream... " ) ;
FILE * f = ps_fopen ( path . c_str ( ) , " rb " ) ;
if ( f = = NULL ) {
perror ( " error " ) ;
lastError = strerror ( errno ) ;
return 1 ;
}
if ( fseek ( f , 0 , SEEK_END ) < 0 ) {
perror ( " size error " ) ;
lastError = fmt : : sprintf ( " on seek: %s " , strerror ( errno ) ) ;
fclose ( f ) ;
return 1 ;
}
ssize_t len = ftell ( f ) ;
if ( len = = ( SIZE_MAX > > 1 ) ) {
perror ( " could not get file length " ) ;
lastError = fmt : : sprintf ( " on pre tell: %s " , strerror ( errno ) ) ;
fclose ( f ) ;
return 1 ;
}
if ( len < 1 ) {
if ( len = = 0 ) {
logE ( " that file is empty! " ) ;
lastError = " file is empty " ;
} else {
perror ( " tell error " ) ;
lastError = fmt : : sprintf ( " on tell: %s " , strerror ( errno ) ) ;
}
fclose ( f ) ;
return 1 ;
}
if ( fseek ( f , 0 , SEEK_SET ) < 0 ) {
perror ( " size error " ) ;
lastError = fmt : : sprintf ( " on get size: %s " , strerror ( errno ) ) ;
fclose ( f ) ;
return 1 ;
}
unsigned char * file = new unsigned char [ len ] ;
if ( fread ( file , 1 , ( size_t ) len , f ) ! = ( size_t ) len ) {
perror ( " read error " ) ;
lastError = fmt : : sprintf ( " on read: %s " , strerror ( errno ) ) ;
fclose ( f ) ;
delete [ ] file ;
return 1 ;
}
fclose ( f ) ;
if ( ! e - > playStream ( file , ( size_t ) len ) ) {
lastError = e - > getLastError ( ) ;
logE ( " could not open file! " ) ;
return 1 ;
}
}
return 0 ;
}
2022-01-18 04:34:29 +00:00
void FurnaceGUI : : exportAudio ( String path , DivAudioExportModes mode ) {
2022-06-06 08:05:55 +00:00
e - > saveAudio ( path . c_str ( ) , exportLoops + 1 , mode , exportFadeOut ) ;
2022-01-18 04:34:29 +00:00
displayExporting = true ;
}
2023-05-16 18:41:08 +00:00
void FurnaceGUI : : editStr ( String * which ) {
editString = which ;
displayEditString = 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-10-02 21:12:02 +00:00
String FurnaceGUI : : getLastError ( ) {
return lastError ;
}
2022-08-23 00:09:08 +00:00
// what monster did I just create here?
# define B30(tt) (macroDragBit30?((((tt)&0xc0000000)==0x40000000 || ((tt)&0xc0000000)==0x80000000)?0x40000000:0):0)
2022-08-22 20:59:45 +00:00
2022-01-21 07:54:52 +00:00
# define MACRO_DRAG(t) \
2022-08-23 08:57:21 +00:00
if ( macroDragSettingBit30 ) { \
if ( macroDragLastX ! = x | | macroDragLastY ! = y ) { \
macroDragLastX = x ; \
macroDragLastY = y ; \
if ( macroDragInitialValueSet ) { \
if ( ! macroDragInitialValue ) { \
if ( t [ x ] & 0x80000000 ) { \
t [ x ] & = ~ 0x40000000 ; \
} else { \
t [ x ] | = 0x40000000 ; \
} \
} else { \
if ( t [ x ] & 0x80000000 ) { \
t [ x ] | = 0x40000000 ; \
} else { \
t [ x ] & = ~ 0x40000000 ; \
} \
} \
} else { \
macroDragInitialValue = ( ( ( t [ x ] ) & 0xc0000000 ) = = 0x40000000 | | ( ( t [ x ] ) & 0xc0000000 ) = = 0x80000000 ) ; \
macroDragInitialValueSet = true ; \
t [ x ] ^ = 0x40000000 ; \
} \
} \
} else if ( macroDragBitMode ) { \
2022-01-21 07:54:52 +00:00
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 { \
2022-04-13 04:03:20 +00:00
if ( macroDragLineMode ) { \
if ( ! macroDragInitialValueSet ) { \
macroDragLineInitial = ImVec2 ( x , y ) ; \
2022-05-09 03:52:21 +00:00
macroDragLineInitialV = ImVec2 ( dragX , dragY ) ; \
2022-04-13 04:03:20 +00:00
macroDragInitialValueSet = true ; \
2022-05-08 23:32:16 +00:00
macroDragMouseMoved = false ; \
} else if ( ! macroDragMouseMoved ) { \
2022-05-09 03:52:21 +00:00
if ( ( pow ( dragX - macroDragLineInitialV . x , 2.0 ) + pow ( dragY - macroDragLineInitialV . y , 2.0 ) ) > = 16.0f ) { \
macroDragMouseMoved = true ; \
} \
2022-04-13 04:03:20 +00:00
} \
2022-05-08 23:32:16 +00:00
if ( macroDragMouseMoved ) { \
if ( ( int ) round ( x - macroDragLineInitial . x ) = = 0 ) { \
2022-08-23 00:09:08 +00:00
t [ x ] = B30 ( t [ x ] ) ^ ( int ) ( macroDragLineInitial . y ) ; \
2022-04-13 04:03:20 +00:00
} else { \
2022-05-08 23:32:16 +00:00
if ( ( int ) round ( x - macroDragLineInitial . x ) < 0 ) { \
for ( int i = 0 ; i < = ( int ) round ( macroDragLineInitial . x - x ) ; i + + ) { \
int index = ( int ) round ( x + i ) ; \
if ( index < 0 ) continue ; \
2022-08-23 00:09:08 +00:00
t [ index ] = B30 ( t [ index ] ) ^ ( int ) ( y + ( macroDragLineInitial . y - y ) * ( ( float ) i / ( float ) ( macroDragLineInitial . x - x ) ) ) ; \
2022-05-08 23:32:16 +00:00
} \
} else { \
for ( int i = 0 ; i < = ( int ) round ( x - macroDragLineInitial . x ) ; i + + ) { \
int index = ( int ) round ( i + macroDragLineInitial . x ) ; \
if ( index < 0 ) continue ; \
2022-08-23 00:09:08 +00:00
t [ index ] = B30 ( t [ index ] ) ^ ( int ) ( macroDragLineInitial . y + ( y - macroDragLineInitial . y ) * ( ( float ) i / ( x - macroDragLineInitial . x ) ) ) ; \
2022-05-08 23:32:16 +00:00
} \
2022-04-13 04:03:20 +00:00
} \
} \
} \
} else { \
2022-08-23 00:09:08 +00:00
t [ x ] = B30 ( t [ x ] ) ^ ( y ) ; \
2022-04-13 04:03:20 +00:00
} \
2022-01-21 07:54:52 +00:00
}
2021-12-24 03:58:43 +00:00
void FurnaceGUI : : processDrags ( int dragX , int dragY ) {
if ( macroDragActive ) {
if ( macroDragLen > 0 ) {
2022-02-15 22:22:09 +00:00
int x = ( ( dragX - macroDragStart . x ) * macroDragLen / MAX ( 1 , 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 ) {
2022-02-15 22:22:09 +00:00
y = ( int ) ( macroDragMax - ( ( dragY - macroDragStart . y ) * ( double ( macroDragMax - macroDragMin ) / ( double ) MAX ( 1 , macroDragAreaSize . y ) ) ) ) ;
2022-01-21 06:56:30 +00:00
} else {
2022-02-15 22:22:09 +00:00
y = round ( macroDragMax - ( ( dragY - macroDragStart . y ) * ( double ( macroDragMax - macroDragMin ) / ( double ) MAX ( 1 , macroDragAreaSize . y ) ) ) ) ;
2022-01-21 06:56:30 +00:00
}
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 ) {
2022-02-15 22:22:09 +00:00
int x = ( dragX - macroLoopDragStart . x ) * macroLoopDragLen / MAX ( 1 , macroLoopDragAreaSize . x ) ;
2021-12-24 03:58:43 +00:00
if ( x < 0 ) x = 0 ;
2022-05-04 23:42:36 +00:00
if ( x > = macroLoopDragLen ) {
x = - 1 ;
} else {
x + = macroDragScroll ;
}
2021-12-24 03:58:43 +00:00
* macroLoopDragTarget = x ;
}
}
if ( waveDragActive ) {
if ( waveDragLen > 0 ) {
2022-02-15 22:22:09 +00:00
int x = ( dragX - waveDragStart . x ) * waveDragLen / MAX ( 1 , waveDragAreaSize . x ) ;
2021-12-24 03:58:43 +00:00
if ( x < 0 ) x = 0 ;
if ( x > = waveDragLen ) x = waveDragLen - 1 ;
2022-02-15 22:22:09 +00:00
int y = round ( waveDragMax - ( ( dragY - waveDragStart . y ) * ( double ( waveDragMax - waveDragMin ) / ( double ) MAX ( 1 , waveDragAreaSize . y ) ) ) ) ;
2021-12-24 03:58:43 +00:00
if ( y > waveDragMax ) y = waveDragMax ;
if ( y < waveDragMin ) y = waveDragMin ;
waveDragTarget [ x ] = y ;
2023-07-15 07:50:49 +00:00
notifyWaveChange = true ;
2022-03-21 21:17:51 +00:00
MARK_MODIFIED ;
2021-12-24 03:58:43 +00:00
}
}
2022-03-20 23:25:48 +00:00
if ( sampleDragActive ) {
2022-03-21 05:41:18 +00:00
int x = samplePos + round ( double ( dragX - sampleDragStart . x ) * sampleZoom ) ;
int x1 = samplePos + round ( double ( dragX - sampleDragStart . x + 1 ) * sampleZoom ) ;
2022-03-20 23:25:48 +00:00
if ( x < 0 ) x = 0 ;
2022-03-21 05:41:18 +00:00
if ( sampleDragMode ) {
if ( x > = ( int ) sampleDragLen ) x = sampleDragLen - 1 ;
} else {
if ( x > ( int ) sampleDragLen ) x = sampleDragLen ;
}
2022-03-20 23:25:48 +00:00
if ( x1 < 0 ) x1 = 0 ;
if ( x1 > = ( int ) sampleDragLen ) x1 = sampleDragLen - 1 ;
double y = 0.5 - double ( dragY - sampleDragStart . y ) / sampleDragAreaSize . y ;
if ( sampleDragMode ) { // draw
2022-09-30 22:47:17 +00:00
if ( sampleDragTarget ) {
if ( sampleDrag16 ) {
int val = y * 65536 ;
if ( val < - 32768 ) val = - 32768 ;
if ( val > 32767 ) val = 32767 ;
for ( int i = x ; i < = x1 ; i + + ) ( ( short * ) sampleDragTarget ) [ i ] = val ;
} else {
int val = y * 256 ;
if ( val < - 128 ) val = - 128 ;
if ( val > 127 ) val = 127 ;
for ( int i = x ; i < = x1 ; i + + ) ( ( signed char * ) sampleDragTarget ) [ i ] = val ;
}
updateSampleTex = true ;
2022-03-20 23:25:48 +00:00
}
} else { // select
if ( sampleSelStart < 0 ) {
sampleSelStart = x ;
}
sampleSelEnd = x ;
}
}
2022-11-30 22:20:04 +00:00
if ( orderScrollLocked ) {
2022-11-30 22:37:48 +00:00
if ( fabs ( orderScrollRealOrigin . x - dragX ) > 2.0f * dpiScale | | fabs ( orderScrollRealOrigin . y - dragY ) > 2.0f * dpiScale ) orderScrollTolerance = false ;
2022-11-30 22:20:04 +00:00
orderScroll = ( orderScrollSlideOrigin - dragX ) / ( 40.0 * dpiScale ) ;
if ( orderScroll < 0.0f ) orderScroll = 0.0f ;
if ( orderScroll > ( float ) e - > curSubSong - > ordersLen - 1 ) orderScroll = e - > curSubSong - > ordersLen - 1 ;
}
2021-12-24 03:58:43 +00:00
}
2022-01-19 10:10:06 +00:00
# define checkExtension(x) \
2022-02-09 04:13:54 +00:00
String lowerCase = fileName ; \
for ( char & i : lowerCase ) { \
if ( i > = ' A ' & & i < = ' Z ' ) i + = ' a ' - ' A ' ; \
} \
2022-05-24 17:46:51 +00:00
if ( lowerCase . size ( ) < strlen ( x ) | | lowerCase . rfind ( x ) ! = lowerCase . size ( ) - strlen ( x ) ) { \
2022-01-19 10:10:06 +00:00
fileName + = x ; \
}
2022-03-14 04:10:43 +00:00
# define checkExtensionDual(x,y,fallback) \
String lowerCase = fileName ; \
for ( char & i : lowerCase ) { \
if ( i > = ' A ' & & i < = ' Z ' ) i + = ' a ' - ' A ' ; \
} \
if ( lowerCase . size ( ) < 4 | | ( lowerCase . rfind ( x ) ! = lowerCase . size ( ) - 4 & & lowerCase . rfind ( y ) ! = lowerCase . size ( ) - 4 ) ) { \
fileName + = fallback ; \
}
2022-08-13 20:43:13 +00:00
# define checkExtensionTriple(x,y,z,fallback) \
String lowerCase = fileName ; \
for ( char & i : lowerCase ) { \
if ( i > = ' A ' & & i < = ' Z ' ) i + = ' a ' - ' A ' ; \
} \
if ( lowerCase . size ( ) < 4 | | ( lowerCase . rfind ( x ) ! = lowerCase . size ( ) - 4 & & lowerCase . rfind ( y ) ! = lowerCase . size ( ) - 4 & & lowerCase . rfind ( z ) ! = lowerCase . size ( ) - 4 ) ) { \
fileName + = fallback ; \
}
2022-04-21 22:32:28 +00:00
# define drawOpMask(m) \
ImGui : : PushFont ( patFont ) ; \
ImGui : : PushID ( " om_ " # m ) ; \
if ( ImGui : : BeginTable ( " opMaskTable " , 5 , ImGuiTableFlags_Borders | ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_NoHostExtendX ) ) { \
ImGui : : TableNextRow ( ) ; \
ImGui : : TableNextColumn ( ) ; \
ImGui : : PushStyleColor ( ImGuiCol_Text , uiColors [ GUI_COLOR_PATTERN_ACTIVE ] ) ; \
if ( ImGui : : Selectable ( m . note ? " C-4##opMaskNote " : " ---##opMaskNote " , m . note , ImGuiSelectableFlags_DontClosePopups ) ) { \
m . note = ! m . note ; \
} \
ImGui : : PopStyleColor ( ) ; \
ImGui : : TableNextColumn ( ) ; \
ImGui : : PushStyleColor ( ImGuiCol_Text , uiColors [ GUI_COLOR_PATTERN_INS ] ) ; \
if ( ImGui : : Selectable ( m . ins ? " 01##opMaskIns " : " --##opMaskIns " , m . ins , ImGuiSelectableFlags_DontClosePopups ) ) { \
m . ins = ! m . ins ; \
} \
ImGui : : PopStyleColor ( ) ; \
ImGui : : TableNextColumn ( ) ; \
ImGui : : PushStyleColor ( ImGuiCol_Text , uiColors [ GUI_COLOR_PATTERN_VOLUME_MAX ] ) ; \
if ( ImGui : : Selectable ( m . vol ? " 7F##opMaskVol " : " --##opMaskVol " , m . vol , ImGuiSelectableFlags_DontClosePopups ) ) { \
m . vol = ! m . vol ; \
} \
ImGui : : PopStyleColor ( ) ; \
ImGui : : TableNextColumn ( ) ; \
ImGui : : PushStyleColor ( ImGuiCol_Text , uiColors [ GUI_COLOR_PATTERN_EFFECT_PITCH ] ) ; \
if ( ImGui : : Selectable ( m . effect ? " 04##opMaskEffect " : " --##opMaskEffect " , m . effect , ImGuiSelectableFlags_DontClosePopups ) ) { \
m . effect = ! m . effect ; \
} \
ImGui : : TableNextColumn ( ) ; \
if ( ImGui : : Selectable ( m . effectVal ? " 72##opMaskEffectVal " : " --##opMaskEffectVal " , m . effectVal , ImGuiSelectableFlags_DontClosePopups ) ) { \
m . effectVal = ! m . effectVal ; \
} \
ImGui : : PopStyleColor ( ) ; \
ImGui : : EndTable ( ) ; \
} \
ImGui : : PopID ( ) ; \
ImGui : : PopFont ( ) ;
2022-03-09 23:03:15 +00:00
void FurnaceGUI : : editOptions ( bool topMenu ) {
char id [ 4096 ] ;
2022-04-21 23:10:59 +00:00
editOptsVisible = true ;
2022-06-06 10:03:19 +00:00
2023-01-30 20:58:59 +00:00
if ( ImGui : : MenuItem ( " cut " , BIND_FOR ( GUI_ACTION_PAT_CUT ) ) ) doCopy ( true , true , selStart , selEnd ) ;
if ( ImGui : : MenuItem ( " copy " , BIND_FOR ( GUI_ACTION_PAT_COPY ) ) ) doCopy ( false , true , selStart , selEnd ) ;
2022-04-01 10:20:00 +00:00
if ( ImGui : : MenuItem ( " paste " , BIND_FOR ( GUI_ACTION_PAT_PASTE ) ) ) doPaste ( ) ;
2023-02-06 23:52:51 +00:00
if ( ! basicMode ) if ( ImGui : : BeginMenu ( " paste special... " ) ) {
2022-04-01 10:20:00 +00:00
if ( ImGui : : MenuItem ( " paste mix " , BIND_FOR ( GUI_ACTION_PAT_PASTE_MIX ) ) ) doPaste ( GUI_PASTE_MODE_MIX_FG ) ;
if ( ImGui : : MenuItem ( " paste mix (background) " , BIND_FOR ( GUI_ACTION_PAT_PASTE_MIX_BG ) ) ) doPaste ( GUI_PASTE_MODE_MIX_BG ) ;
2022-09-22 03:59:53 +00:00
if ( ImGui : : BeginMenu ( " paste with ins (foreground) " ) ) {
if ( e - > song . ins . empty ( ) ) {
ImGui : : Text ( " no instruments available " ) ;
}
for ( size_t i = 0 ; i < e - > song . ins . size ( ) ; i + + ) {
snprintf ( id , 4095 , " %.2X: %s " , ( int ) i , e - > song . ins [ i ] - > name . c_str ( ) ) ;
if ( ImGui : : MenuItem ( id ) ) {
doPaste ( GUI_PASTE_MODE_INS_FG , i ) ;
}
}
ImGui : : EndMenu ( ) ;
}
if ( ImGui : : BeginMenu ( " paste with ins (background) " ) ) {
if ( e - > song . ins . empty ( ) ) {
ImGui : : Text ( " no instruments available " ) ;
}
for ( size_t i = 0 ; i < e - > song . ins . size ( ) ; i + + ) {
snprintf ( id , 4095 , " %.2X: %s " , ( int ) i , e - > song . ins [ i ] - > name . c_str ( ) ) ;
if ( ImGui : : MenuItem ( id ) ) {
doPaste ( GUI_PASTE_MODE_INS_BG , i ) ;
}
}
ImGui : : EndMenu ( ) ;
}
2022-04-01 10:20:00 +00:00
if ( ImGui : : MenuItem ( " paste flood " , BIND_FOR ( GUI_ACTION_PAT_PASTE_FLOOD ) ) ) doPaste ( GUI_PASTE_MODE_FLOOD ) ;
if ( ImGui : : MenuItem ( " paste overflow " , BIND_FOR ( GUI_ACTION_PAT_PASTE_OVERFLOW ) ) ) doPaste ( GUI_PASTE_MODE_OVERFLOW ) ;
2022-03-09 23:03:15 +00:00
ImGui : : EndMenu ( ) ;
}
2022-04-01 10:20:00 +00:00
if ( ImGui : : MenuItem ( " delete " , BIND_FOR ( GUI_ACTION_PAT_DELETE ) ) ) doDelete ( ) ;
2022-03-09 23:03:15 +00:00
if ( topMenu ) {
2022-04-01 10:20:00 +00:00
if ( ImGui : : MenuItem ( " select all " , BIND_FOR ( GUI_ACTION_PAT_SELECT_ALL ) ) ) doSelectAll ( ) ;
2022-03-09 23:03:15 +00:00
}
ImGui : : Separator ( ) ;
2023-02-06 23:52:51 +00:00
if ( ! basicMode ) {
if ( ImGui : : BeginMenu ( " operation mask... " ) ) {
drawOpMask ( opMaskDelete ) ;
ImGui : : SameLine ( ) ;
ImGui : : Text ( " delete " ) ;
2022-04-21 22:32:28 +00:00
2023-02-06 23:52:51 +00:00
drawOpMask ( opMaskPullDelete ) ;
ImGui : : SameLine ( ) ;
ImGui : : Text ( " pull delete " ) ;
2022-04-21 22:32:28 +00:00
2023-02-06 23:52:51 +00:00
drawOpMask ( opMaskInsert ) ;
ImGui : : SameLine ( ) ;
ImGui : : Text ( " insert " ) ;
2022-04-21 22:32:28 +00:00
2023-02-06 23:52:51 +00:00
drawOpMask ( opMaskPaste ) ;
ImGui : : SameLine ( ) ;
ImGui : : Text ( " paste " ) ;
2022-04-21 22:32:28 +00:00
2023-02-06 23:52:51 +00:00
drawOpMask ( opMaskTransposeNote ) ;
ImGui : : SameLine ( ) ;
ImGui : : Text ( " transpose (note) " ) ;
2022-04-21 22:32:28 +00:00
2023-02-06 23:52:51 +00:00
drawOpMask ( opMaskTransposeValue ) ;
ImGui : : SameLine ( ) ;
ImGui : : Text ( " transpose (value) " ) ;
2022-04-21 22:32:28 +00:00
2023-02-06 23:52:51 +00:00
drawOpMask ( opMaskInterpolate ) ;
ImGui : : SameLine ( ) ;
ImGui : : Text ( " interpolate " ) ;
2022-04-21 22:32:28 +00:00
2023-02-06 23:52:51 +00:00
drawOpMask ( opMaskFade ) ;
ImGui : : SameLine ( ) ;
ImGui : : Text ( " fade " ) ;
2022-04-21 22:32:28 +00:00
2023-02-06 23:52:51 +00:00
drawOpMask ( opMaskInvertVal ) ;
ImGui : : SameLine ( ) ;
ImGui : : Text ( " invert values " ) ;
2022-04-21 22:32:28 +00:00
2023-02-06 23:52:51 +00:00
drawOpMask ( opMaskScale ) ;
ImGui : : SameLine ( ) ;
ImGui : : Text ( " scale " ) ;
2022-04-21 22:32:28 +00:00
2023-02-06 23:52:51 +00:00
drawOpMask ( opMaskRandomize ) ;
ImGui : : SameLine ( ) ;
ImGui : : Text ( " randomize " ) ;
2022-04-21 22:32:28 +00:00
2023-02-06 23:52:51 +00:00
drawOpMask ( opMaskFlip ) ;
ImGui : : SameLine ( ) ;
ImGui : : Text ( " flip " ) ;
2022-04-21 22:32:28 +00:00
2023-02-06 23:52:51 +00:00
drawOpMask ( opMaskCollapseExpand ) ;
ImGui : : SameLine ( ) ;
ImGui : : Text ( " collapse/expand " ) ;
2022-03-12 07:13:15 +00:00
2023-02-06 23:52:51 +00:00
ImGui : : EndMenu ( ) ;
2022-04-21 23:10:59 +00:00
}
2023-02-06 23:52:51 +00:00
ImGui : : Text ( " input latch " ) ;
ImGui : : PushFont ( patFont ) ;
if ( ImGui : : BeginTable ( " inputLatchTable " , 5 , ImGuiTableFlags_Borders | ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_NoHostExtendX ) ) {
static char id [ 64 ] ;
ImGui : : TableNextRow ( ) ;
ImGui : : TableNextColumn ( ) ;
ImGui : : PushStyleColor ( ImGuiCol_Text , uiColors [ GUI_COLOR_PATTERN_ACTIVE ] ) ;
ImGui : : Text ( " C-4 " ) ;
2022-04-21 23:30:32 +00:00
ImGui : : PopStyleColor ( ) ;
2023-02-06 23:52:51 +00:00
ImGui : : TableNextColumn ( ) ;
ImGui : : PushStyleColor ( ImGuiCol_Text , uiColors [ GUI_COLOR_PATTERN_INS ] ) ;
if ( latchIns = = - 2 ) {
strcpy ( id , " &&##LatchIns " ) ;
} else if ( latchIns = = - 1 ) {
strcpy ( id , " ..##LatchIns " ) ;
} else {
snprintf ( id , 63 , " %.2x##LatchIns " , latchIns & 0xff ) ;
}
if ( ImGui : : Selectable ( id , latchTarget = = 1 , ImGuiSelectableFlags_DontClosePopups ) ) {
latchTarget = 1 ;
latchNibble = false ;
}
if ( ImGui : : IsItemClicked ( ImGuiMouseButton_Right ) ) {
latchIns = - 2 ;
}
if ( ImGui : : IsItemHovered ( ) ) {
ImGui : : PushStyleColor ( ImGuiCol_Text , uiColors [ GUI_COLOR_TEXT ] ) ;
ImGui : : SetTooltip ( " &&: selected instrument \n ..: no instrument " ) ;
ImGui : : PopStyleColor ( ) ;
}
ImGui : : PopStyleColor ( ) ;
ImGui : : TableNextColumn ( ) ;
ImGui : : PushStyleColor ( ImGuiCol_Text , uiColors [ GUI_COLOR_PATTERN_VOLUME_MAX ] ) ;
if ( latchVol = = - 1 ) {
strcpy ( id , " ..##LatchVol " ) ;
} else {
snprintf ( id , 63 , " %.2x##LatchVol " , latchVol & 0xff ) ;
}
if ( ImGui : : Selectable ( id , latchTarget = = 2 , ImGuiSelectableFlags_DontClosePopups ) ) {
latchTarget = 2 ;
latchNibble = false ;
}
if ( ImGui : : IsItemClicked ( ImGuiMouseButton_Right ) ) {
latchVol = - 1 ;
}
ImGui : : PopStyleColor ( ) ;
ImGui : : TableNextColumn ( ) ;
if ( latchEffect = = - 1 ) {
strcpy ( id , " ..##LatchFX " ) ;
ImGui : : PushStyleColor ( ImGuiCol_Text , uiColors [ GUI_COLOR_PATTERN_INACTIVE ] ) ;
} else {
const unsigned char data = latchEffect ;
snprintf ( id , 63 , " %.2x##LatchFX " , data ) ;
ImGui : : PushStyleColor ( ImGuiCol_Text , uiColors [ fxColors [ data ] ] ) ;
}
if ( ImGui : : Selectable ( id , latchTarget = = 3 , ImGuiSelectableFlags_DontClosePopups ) ) {
latchTarget = 3 ;
latchNibble = false ;
}
if ( ImGui : : IsItemClicked ( ImGuiMouseButton_Right ) ) {
latchEffect = - 1 ;
}
ImGui : : TableNextColumn ( ) ;
if ( latchEffectVal = = - 1 ) {
strcpy ( id , " ..##LatchFXV " ) ;
} else {
snprintf ( id , 63 , " %.2x##LatchFXV " , latchEffectVal & 0xff ) ;
}
if ( ImGui : : Selectable ( id , latchTarget = = 4 , ImGuiSelectableFlags_DontClosePopups ) ) {
latchTarget = 4 ;
latchNibble = false ;
}
if ( ImGui : : IsItemClicked ( ImGuiMouseButton_Right ) ) {
latchEffectVal = - 1 ;
}
ImGui : : PopStyleColor ( ) ;
ImGui : : EndTable ( ) ;
2022-04-21 23:10:59 +00:00
}
2023-02-06 23:52:51 +00:00
ImGui : : PopFont ( ) ;
ImGui : : SameLine ( ) ;
if ( ImGui : : Button ( " Set " ) ) {
DivPattern * pat = e - > curPat [ cursor . xCoarse ] . getPattern ( e - > curOrders - > ord [ cursor . xCoarse ] [ curOrder ] , true ) ;
latchIns = pat - > data [ cursor . y ] [ 2 ] ;
latchVol = pat - > data [ cursor . y ] [ 3 ] ;
latchEffect = pat - > data [ cursor . y ] [ 4 ] ;
latchEffectVal = pat - > data [ cursor . y ] [ 5 ] ;
latchTarget = 0 ;
2022-04-21 23:30:32 +00:00
latchNibble = false ;
}
2023-02-06 23:52:51 +00:00
ImGui : : SameLine ( ) ;
if ( ImGui : : Button ( " Reset " ) ) {
latchIns = - 2 ;
2022-04-21 23:30:32 +00:00
latchVol = - 1 ;
latchEffect = - 1 ;
latchEffectVal = - 1 ;
2023-02-06 23:52:51 +00:00
latchTarget = 0 ;
latchNibble = false ;
2022-04-21 23:10:59 +00:00
}
2023-02-06 23:52:51 +00:00
ImGui : : Separator ( ) ;
2022-03-09 23:03:15 +00:00
}
2022-04-21 22:32:28 +00:00
if ( ImGui : : MenuItem ( " note up " , BIND_FOR ( GUI_ACTION_PAT_NOTE_UP ) ) ) doTranspose ( 1 , opMaskTransposeNote ) ;
if ( ImGui : : MenuItem ( " note down " , BIND_FOR ( GUI_ACTION_PAT_NOTE_DOWN ) ) ) doTranspose ( - 1 , opMaskTransposeNote ) ;
if ( ImGui : : MenuItem ( " octave up " , BIND_FOR ( GUI_ACTION_PAT_OCTAVE_UP ) ) ) doTranspose ( 12 , opMaskTransposeNote ) ;
if ( ImGui : : MenuItem ( " octave down " , BIND_FOR ( GUI_ACTION_PAT_OCTAVE_DOWN ) ) ) doTranspose ( - 12 , opMaskTransposeNote ) ;
ImGui : : Separator ( ) ;
if ( ImGui : : MenuItem ( " values up " , BIND_FOR ( GUI_ACTION_PAT_VALUE_UP ) ) ) doTranspose ( 1 , opMaskTransposeValue ) ;
if ( ImGui : : MenuItem ( " values down " , BIND_FOR ( GUI_ACTION_PAT_VALUE_DOWN ) ) ) doTranspose ( - 1 , opMaskTransposeValue ) ;
if ( ImGui : : MenuItem ( " values up (+16) " , BIND_FOR ( GUI_ACTION_PAT_VALUE_UP_COARSE ) ) ) doTranspose ( 16 , opMaskTransposeValue ) ;
if ( ImGui : : MenuItem ( " values down (-16) " , BIND_FOR ( GUI_ACTION_PAT_VALUE_DOWN_COARSE ) ) ) doTranspose ( - 16 , opMaskTransposeValue ) ;
ImGui : : Separator ( ) ;
2023-08-07 03:51:51 +00:00
ImGui : : AlignTextToFramePadding ( ) ;
2022-04-21 22:32:28 +00:00
ImGui : : Text ( " transpose " ) ;
ImGui : : SameLine ( ) ;
ImGui : : SetNextItemWidth ( 120.0f * dpiScale ) ;
2022-03-09 23:03:15 +00:00
if ( ImGui : : InputInt ( " ##TransposeAmount " , & transposeAmount , 1 , 1 ) ) {
if ( transposeAmount < - 96 ) transposeAmount = - 96 ;
if ( transposeAmount > 96 ) transposeAmount = 96 ;
}
ImGui : : SameLine ( ) ;
2022-04-21 22:32:28 +00:00
if ( ImGui : : Button ( " Notes " ) ) {
doTranspose ( transposeAmount , opMaskTransposeNote ) ;
ImGui : : CloseCurrentPopup ( ) ;
}
ImGui : : SameLine ( ) ;
if ( ImGui : : Button ( " Values " ) ) {
2022-05-05 18:23:06 +00:00
doTranspose ( transposeAmount , opMaskTransposeValue ) ;
2022-03-09 23:03:15 +00:00
ImGui : : CloseCurrentPopup ( ) ;
}
2022-05-26 05:24:21 +00:00
2022-03-09 23:03:15 +00:00
ImGui : : Separator ( ) ;
2022-04-01 10:20:00 +00:00
if ( ImGui : : MenuItem ( " interpolate " , BIND_FOR ( GUI_ACTION_PAT_INTERPOLATE ) ) ) doInterpolate ( ) ;
if ( ImGui : : BeginMenu ( " change instrument... " ) ) {
2022-03-09 23:03:15 +00:00
if ( e - > song . ins . empty ( ) ) {
ImGui : : Text ( " no instruments available " ) ;
}
for ( size_t i = 0 ; i < e - > song . ins . size ( ) ; i + + ) {
snprintf ( id , 4095 , " %.2X: %s " , ( int ) i , e - > song . ins [ i ] - > name . c_str ( ) ) ;
2022-03-11 06:31:21 +00:00
if ( ImGui : : MenuItem ( id ) ) {
doChangeIns ( i ) ;
2022-03-09 23:03:15 +00:00
}
}
ImGui : : EndMenu ( ) ;
}
2023-02-06 23:52:51 +00:00
if ( ! basicMode ) {
if ( ImGui : : BeginMenu ( " gradient/fade... " ) ) {
if ( ImGui : : InputInt ( " Start " , & fadeMin , 1 , 1 ) ) {
if ( fadeMin < 0 ) fadeMin = 0 ;
if ( fadeMode ) {
if ( fadeMin > 15 ) fadeMin = 15 ;
} else {
if ( fadeMin > 255 ) fadeMin = 255 ;
}
2022-03-12 08:04:34 +00:00
}
2023-02-06 23:52:51 +00:00
if ( ImGui : : InputInt ( " End " , & fadeMax , 1 , 1 ) ) {
if ( fadeMax < 0 ) fadeMax = 0 ;
if ( fadeMode ) {
if ( fadeMax > 15 ) fadeMax = 15 ;
} else {
if ( fadeMax > 255 ) fadeMax = 255 ;
}
2022-03-12 08:04:34 +00:00
}
2023-02-06 23:52:51 +00:00
if ( ImGui : : Checkbox ( " Nibble mode " , & fadeMode ) ) {
if ( fadeMode ) {
if ( fadeMin > 15 ) fadeMin = 15 ;
if ( fadeMax > 15 ) fadeMax = 15 ;
} else {
if ( fadeMin > 255 ) fadeMin = 255 ;
if ( fadeMax > 255 ) fadeMax = 255 ;
}
2022-03-12 08:04:34 +00:00
}
2023-02-06 23:52:51 +00:00
if ( ImGui : : Button ( " Go ahead " ) ) {
doFade ( fadeMin , fadeMax , fadeMode ) ;
ImGui : : CloseCurrentPopup ( ) ;
2022-03-12 08:40:56 +00:00
}
2023-02-06 23:52:51 +00:00
ImGui : : EndMenu ( ) ;
2022-03-12 07:13:15 +00:00
}
2023-02-06 23:52:51 +00:00
if ( ImGui : : BeginMenu ( " scale... " ) ) {
if ( ImGui : : InputFloat ( " ##ScaleMax " , & scaleMax , 1 , 1 , " %.1f%% " ) ) {
if ( scaleMax < 0.0f ) scaleMax = 0.0f ;
if ( scaleMax > 25600.0f ) scaleMax = 25600.0f ;
2022-03-12 08:40:56 +00:00
}
2023-02-06 23:52:51 +00:00
if ( ImGui : : Button ( " Scale " ) ) {
doScale ( scaleMax ) ;
ImGui : : CloseCurrentPopup ( ) ;
2022-03-12 08:40:56 +00:00
}
2023-02-06 23:52:51 +00:00
ImGui : : EndMenu ( ) ;
2022-03-12 07:13:15 +00:00
}
2023-02-06 23:52:51 +00:00
if ( ImGui : : BeginMenu ( " randomize... " ) ) {
if ( ImGui : : InputInt ( " Minimum " , & randomizeMin , 1 , 1 ) ) {
if ( randomizeMin < 0 ) randomizeMin = 0 ;
if ( randomMode ) {
if ( randomizeMin > 15 ) randomizeMin = 15 ;
} else {
if ( randomizeMin > 255 ) randomizeMin = 255 ;
}
if ( randomizeMin > randomizeMax ) randomizeMin = randomizeMax ;
}
if ( ImGui : : InputInt ( " Maximum " , & randomizeMax , 1 , 1 ) ) {
if ( randomizeMax < 0 ) randomizeMax = 0 ;
if ( randomizeMax < randomizeMin ) randomizeMax = randomizeMin ;
if ( randomMode ) {
if ( randomizeMax > 15 ) randomizeMax = 15 ;
} else {
if ( randomizeMax > 255 ) randomizeMax = 255 ;
}
}
if ( ImGui : : Checkbox ( " Nibble mode " , & randomMode ) ) {
if ( randomMode ) {
if ( randomizeMin > 15 ) randomizeMin = 15 ;
if ( randomizeMax > 15 ) randomizeMax = 15 ;
} else {
if ( randomizeMin > 255 ) randomizeMin = 255 ;
if ( randomizeMax > 255 ) randomizeMax = 255 ;
}
}
// TODO: add an option to set effect to specific value?
if ( ImGui : : Button ( " Randomize " ) ) {
doRandomize ( randomizeMin , randomizeMax , randomMode ) ;
ImGui : : CloseCurrentPopup ( ) ;
}
ImGui : : EndMenu ( ) ;
2022-03-09 23:03:15 +00:00
}
2023-02-06 23:52:51 +00:00
if ( ImGui : : MenuItem ( " invert values " , BIND_FOR ( GUI_ACTION_PAT_INVERT_VALUES ) ) ) doInvertValues ( ) ;
2022-03-09 23:03:15 +00:00
2023-02-06 23:52:51 +00:00
ImGui : : Separator ( ) ;
2022-03-09 23:03:15 +00:00
2023-02-06 23:52:51 +00:00
if ( ImGui : : MenuItem ( " flip selection " , BIND_FOR ( GUI_ACTION_PAT_FLIP_SELECTION ) ) ) doFlip ( ) ;
2023-05-15 22:43:27 +00:00
ImGui : : SetNextItemWidth ( 120.0f * dpiScale ) ;
if ( ImGui : : InputInt ( " collapse/expand amount##CollapseAmount " , & collapseAmount , 1 , 1 ) ) {
if ( collapseAmount < 2 ) collapseAmount = 2 ;
if ( collapseAmount > 256 ) collapseAmount = 256 ;
}
if ( ImGui : : MenuItem ( " collapse " , BIND_FOR ( GUI_ACTION_PAT_COLLAPSE_ROWS ) ) ) doCollapse ( collapseAmount , selStart , selEnd ) ;
if ( ImGui : : MenuItem ( " expand " , BIND_FOR ( GUI_ACTION_PAT_EXPAND_ROWS ) ) ) doExpand ( collapseAmount , selStart , selEnd ) ;
2022-03-09 23:03:15 +00:00
2023-04-27 06:23:54 +00:00
if ( topMenu ) {
ImGui : : Separator ( ) ;
if ( ImGui : : MenuItem ( " collapse pattern " , BIND_FOR ( GUI_ACTION_PAT_COLLAPSE_PAT ) ) ) doAction ( GUI_ACTION_PAT_COLLAPSE_PAT ) ;
if ( ImGui : : MenuItem ( " expand pattern " , BIND_FOR ( GUI_ACTION_PAT_EXPAND_PAT ) ) ) doAction ( GUI_ACTION_PAT_EXPAND_PAT ) ;
}
}
if ( topMenu ) {
ImGui : : Separator ( ) ;
if ( ImGui : : MenuItem ( " collapse song " , BIND_FOR ( GUI_ACTION_PAT_COLLAPSE_SONG ) ) ) doAction ( GUI_ACTION_PAT_COLLAPSE_SONG ) ;
if ( ImGui : : MenuItem ( " expand song " , BIND_FOR ( GUI_ACTION_PAT_EXPAND_SONG ) ) ) doAction ( GUI_ACTION_PAT_EXPAND_SONG ) ;
}
if ( ! basicMode ) {
2023-02-06 23:52:51 +00:00
if ( topMenu ) {
ImGui : : Separator ( ) ;
if ( ImGui : : MenuItem ( " find/replace " , BIND_FOR ( GUI_ACTION_WINDOW_FIND ) , findOpen ) ) {
if ( findOpen ) {
findOpen = false ;
} else {
nextWindow = GUI_WINDOW_FIND ;
}
2022-06-06 10:03:19 +00:00
}
}
}
2022-03-09 23:03:15 +00:00
}
2022-05-18 23:42:59 +00:00
void FurnaceGUI : : toggleMobileUI ( bool enable , bool force ) {
if ( mobileUI ! = enable | | force ) {
if ( ! mobileUI & & enable ) {
2023-04-06 00:08:04 +00:00
if ( ! ImGui : : SaveIniSettingsToDisk ( finalLayoutPath , true ) ) {
2023-04-04 21:01:45 +00:00
reportError ( fmt : : sprintf ( " could NOT save layout! %s " , strerror ( errno ) ) ) ;
}
2022-05-26 05:24:21 +00:00
}
2022-05-18 23:42:59 +00:00
mobileUI = enable ;
if ( mobileUI ) {
ImGui : : GetIO ( ) . IniFilename = NULL ;
2022-12-01 00:42:51 +00:00
ImGui : : GetIO ( ) . ConfigFlags | = ImGuiConfigFlags_InertialScrollEnable ;
2022-12-03 05:51:57 +00:00
ImGui : : GetIO ( ) . ConfigFlags | = ImGuiConfigFlags_NoHoverColors ;
fileDialog - > mobileUI = true ;
2022-05-18 23:42:59 +00:00
} else {
2022-09-08 18:16:57 +00:00
ImGui : : GetIO ( ) . IniFilename = NULL ;
2023-04-06 00:08:04 +00:00
if ( ! ImGui : : LoadIniSettingsFromDisk ( finalLayoutPath , true ) ) {
2023-04-04 21:01:45 +00:00
reportError ( fmt : : sprintf ( " could NOT load layout! %s " , strerror ( errno ) ) ) ;
2023-04-06 00:08:04 +00:00
ImGui : : LoadIniSettingsFromMemory ( defaultLayout ) ;
2023-04-04 21:01:45 +00:00
}
2022-12-01 00:42:51 +00:00
ImGui : : GetIO ( ) . ConfigFlags & = ~ ImGuiConfigFlags_InertialScrollEnable ;
2022-12-03 05:51:57 +00:00
ImGui : : GetIO ( ) . ConfigFlags & = ~ ImGuiConfigFlags_NoHoverColors ;
fileDialog - > mobileUI = false ;
2022-05-18 23:42:59 +00:00
}
2022-05-26 05:24:21 +00:00
}
2022-05-18 23:42:59 +00:00
}
2022-09-11 04:50:53 +00:00
void FurnaceGUI : : pushToggleColors ( bool status ) {
ImVec4 toggleColor = status ? uiColors [ GUI_COLOR_TOGGLE_ON ] : uiColors [ GUI_COLOR_TOGGLE_OFF ] ;
ImGui : : PushStyleColor ( ImGuiCol_Button , toggleColor ) ;
2022-12-03 05:51:57 +00:00
if ( ! mobileUI ) {
if ( settings . guiColorsBase ) {
toggleColor . x * = 0.8f ;
toggleColor . y * = 0.8f ;
toggleColor . z * = 0.8f ;
} else {
toggleColor . x = CLAMP ( toggleColor . x * 1.3f , 0.0f , 1.0f ) ;
toggleColor . y = CLAMP ( toggleColor . y * 1.3f , 0.0f , 1.0f ) ;
toggleColor . z = CLAMP ( toggleColor . z * 1.3f , 0.0f , 1.0f ) ;
}
2022-09-11 04:50:53 +00:00
}
ImGui : : PushStyleColor ( ImGuiCol_ButtonHovered , toggleColor ) ;
if ( settings . guiColorsBase ) {
toggleColor . x * = 0.8f ;
toggleColor . y * = 0.8f ;
toggleColor . z * = 0.8f ;
} else {
toggleColor . x = CLAMP ( toggleColor . x * 1.5f , 0.0f , 1.0f ) ;
toggleColor . y = CLAMP ( toggleColor . y * 1.5f , 0.0f , 1.0f ) ;
toggleColor . z = CLAMP ( toggleColor . z * 1.5f , 0.0f , 1.0f ) ;
}
ImGui : : PushStyleColor ( ImGuiCol_ButtonActive , toggleColor ) ;
}
void FurnaceGUI : : popToggleColors ( ) {
ImGui : : PopStyleColor ( 3 ) ;
}
2022-04-16 03:22:47 +00:00
int _processEvent ( void * instance , SDL_Event * event ) {
return ( ( FurnaceGUI * ) instance ) - > processEvent ( event ) ;
}
2023-06-04 22:09:18 +00:00
# if SDL_VERSION_ATLEAST(2,0,17)
# define VALID_MODS KMOD_NUM|KMOD_CAPS|KMOD_SCROLL
# else
# define VALID_MODS KMOD_NUM|KMOD_CAPS
# endif
2022-04-16 03:22:47 +00:00
int FurnaceGUI : : processEvent ( SDL_Event * ev ) {
2023-02-24 07:03:43 +00:00
if ( introPos < 11.0 & & ! shortIntro ) return 1 ;
2022-05-17 17:46:52 +00:00
# ifdef IS_MOBILE
2022-11-10 21:53:18 +00:00
if ( ev - > type = = SDL_APP_TERMINATING ) {
// TODO: save last song state here
} else if ( ev - > type = = SDL_APP_WILLENTERBACKGROUND ) {
2022-11-10 21:47:53 +00:00
commitState ( ) ;
e - > saveConf ( ) ;
2022-05-17 17:46:52 +00:00
}
# endif
2022-04-16 03:22:47 +00:00
if ( ev - > type = = SDL_KEYDOWN ) {
2023-06-04 22:09:18 +00:00
if ( ! ev - > key . repeat & & latchTarget = = 0 & & ! wantCaptureKeyboard & & ! sampleMapWaitingInput & & ( ev - > key . keysym . mod & ( ~ ( VALID_MODS ) ) ) = = 0 ) {
2022-04-16 18:13:19 +00:00
if ( settings . notePreviewBehavior = = 0 ) return 1 ;
2022-04-16 04:47:39 +00:00
switch ( curWindow ) {
case GUI_WINDOW_SAMPLE_EDIT :
2023-07-24 22:39:09 +00:00
case GUI_WINDOW_SAMPLE_LIST : {
auto it = noteKeys . find ( ev - > key . keysym . scancode ) ;
if ( it ! = noteKeys . cend ( ) ) {
int key = it - > second ;
2022-04-16 04:47:39 +00:00
int num = 12 * curOctave + key ;
if ( key ! = 100 & & key ! = 101 & & key ! = 102 ) {
2022-05-29 07:13:08 +00:00
int pStart = - 1 ;
int pEnd = - 1 ;
if ( curWindow = = GUI_WINDOW_SAMPLE_EDIT ) {
if ( sampleSelStart ! = sampleSelEnd ) {
pStart = sampleSelStart ;
pEnd = sampleSelEnd ;
if ( pStart > pEnd ) {
pStart ^ = pEnd ;
pEnd ^ = pStart ;
pStart ^ = pEnd ;
}
}
}
e - > previewSample ( curSample , num , pStart , pEnd ) ;
2022-04-16 04:47:39 +00:00
samplePreviewOn = true ;
samplePreviewKey = ev - > key . keysym . scancode ;
samplePreviewNote = num ;
}
}
break ;
2023-07-24 22:39:09 +00:00
}
2022-04-16 04:47:39 +00:00
case GUI_WINDOW_WAVE_LIST :
2023-07-24 22:39:09 +00:00
case GUI_WINDOW_WAVE_EDIT : {
auto it = noteKeys . find ( ev - > key . keysym . scancode ) ;
if ( it ! = noteKeys . cend ( ) ) {
int key = it - > second ;
2022-04-16 04:47:39 +00:00
int num = 12 * curOctave + key ;
if ( key ! = 100 & & key ! = 101 & & key ! = 102 ) {
e - > previewWave ( curWave , num ) ;
wavePreviewOn = true ;
wavePreviewKey = ev - > key . keysym . scancode ;
wavePreviewNote = num ;
}
}
break ;
2023-07-24 22:39:09 +00:00
}
2022-04-16 04:47:39 +00:00
case GUI_WINDOW_ORDERS : // ignore here
break ;
2022-04-16 18:13:19 +00:00
case GUI_WINDOW_PATTERN :
if ( settings . notePreviewBehavior = = 1 ) {
if ( cursor . xFine ! = 0 ) break ;
} else if ( settings . notePreviewBehavior = = 2 ) {
if ( edit & & cursor . xFine ! = 0 ) break ;
}
// fall-through
2023-07-24 22:39:09 +00:00
default : {
auto it = noteKeys . find ( ev - > key . keysym . scancode ) ;
if ( it ! = noteKeys . cend ( ) ) {
int key = it - > second ;
2022-04-16 04:47:39 +00:00
int num = 12 * curOctave + key ;
2022-04-16 03:22:47 +00:00
2022-04-16 04:47:39 +00:00
if ( num < - 60 ) num = - 60 ; // C-(-5)
if ( num > 119 ) num = 119 ; // B-9
2022-04-16 03:22:47 +00:00
2022-04-16 04:47:39 +00:00
if ( key ! = 100 & & key ! = 101 & & key ! = 102 ) {
previewNote ( cursor . xCoarse , num ) ;
}
}
break ;
2023-07-24 22:39:09 +00:00
}
2022-04-16 03:22:47 +00:00
}
}
} else if ( ev - > type = = SDL_KEYUP ) {
stopPreviewNote ( ev - > key . keysym . scancode , true ) ;
if ( wavePreviewOn ) {
if ( ev - > key . keysym . scancode = = wavePreviewKey ) {
wavePreviewOn = false ;
e - > stopWavePreview ( ) ;
}
}
if ( samplePreviewOn ) {
if ( ev - > key . keysym . scancode = = samplePreviewKey ) {
samplePreviewOn = false ;
e - > stopSamplePreview ( ) ;
}
}
}
return 1 ;
}
2022-05-17 17:46:52 +00:00
# define FIND_POINT(p,pid) \
for ( TouchPoint & i : activePoints ) { \
if ( i . id = = pid ) { \
p = & i ; \
} \
}
void FurnaceGUI : : processPoint ( SDL_Event & ev ) {
switch ( ev . type ) {
case SDL_MOUSEMOTION : {
TouchPoint * point = NULL ;
FIND_POINT ( point , - 1 ) ;
if ( point ! = NULL ) {
2022-10-20 07:34:14 +00:00
point - > x = ( double ) ev . motion . x * ( ( double ) canvasW / ( double ) scrW ) ;
point - > y = ( double ) ev . motion . y * ( ( double ) canvasH / ( double ) scrH ) ;
2022-05-17 17:46:52 +00:00
}
break ;
}
case SDL_MOUSEBUTTONDOWN : {
2022-05-18 05:23:13 +00:00
if ( ev . button . button ! = SDL_BUTTON_LEFT ) break ;
2022-05-17 17:46:52 +00:00
for ( size_t i = 0 ; i < activePoints . size ( ) ; i + + ) {
TouchPoint & point = activePoints [ i ] ;
if ( point . id = = - 1 ) {
releasedPoints . push_back ( point ) ;
activePoints . erase ( activePoints . begin ( ) + i ) ;
break ;
}
}
TouchPoint newPoint ( ev . button . x , ev . button . y ) ;
# ifdef __APPLE__
2022-05-17 20:48:37 +00:00
newPoint . x * = dpiScale ;
newPoint . y * = dpiScale ;
2022-05-17 17:46:52 +00:00
# endif
activePoints . push_back ( newPoint ) ;
pressedPoints . push_back ( newPoint ) ;
break ;
}
case SDL_MOUSEBUTTONUP : {
2022-05-18 05:23:13 +00:00
if ( ev . button . button ! = SDL_BUTTON_LEFT ) break ;
2022-05-17 17:46:52 +00:00
for ( size_t i = 0 ; i < activePoints . size ( ) ; i + + ) {
TouchPoint & point = activePoints [ i ] ;
if ( point . id = = - 1 ) {
releasedPoints . push_back ( point ) ;
activePoints . erase ( activePoints . begin ( ) + i ) ;
break ;
}
}
break ;
}
case SDL_FINGERMOTION : {
TouchPoint * point = NULL ;
FIND_POINT ( point , ev . tfinger . fingerId ) ;
if ( point ! = NULL ) {
2022-09-09 23:53:20 +00:00
float prevX = point - > x ;
float prevY = point - > y ;
2022-10-20 07:34:14 +00:00
point - > x = ev . tfinger . x * canvasW ;
point - > y = ev . tfinger . y * canvasH ;
2022-05-17 17:46:52 +00:00
point - > z = ev . tfinger . pressure ;
2022-05-27 21:10:37 +00:00
if ( point - > id = = 0 ) {
ImGui : : GetIO ( ) . AddMousePosEvent ( point - > x , point - > y ) ;
2022-09-09 23:53:20 +00:00
pointMotion ( point - > x , point - > y , point - > x - prevX , point - > y - prevY ) ;
2022-05-27 21:10:37 +00:00
}
2022-05-17 17:46:52 +00:00
}
break ;
}
case SDL_FINGERDOWN : {
for ( size_t i = 0 ; i < activePoints . size ( ) ; i + + ) {
TouchPoint & point = activePoints [ i ] ;
if ( point . id = = ev . tfinger . fingerId ) {
releasedPoints . push_back ( point ) ;
activePoints . erase ( activePoints . begin ( ) + i ) ;
break ;
}
}
2022-10-20 07:34:14 +00:00
TouchPoint newPoint ( ev . tfinger . fingerId , ev . tfinger . x * canvasW , ev . tfinger . y * canvasH , ev . tfinger . pressure ) ;
2022-05-17 17:46:52 +00:00
activePoints . push_back ( newPoint ) ;
pressedPoints . push_back ( newPoint ) ;
2022-05-27 21:10:37 +00:00
if ( newPoint . id = = 0 ) {
ImGui : : GetIO ( ) . AddMousePosEvent ( newPoint . x , newPoint . y ) ;
ImGui : : GetIO ( ) . AddMouseButtonEvent ( ImGuiMouseButton_Left , true ) ;
2022-09-09 23:53:20 +00:00
pointDown ( newPoint . x , newPoint . y , 0 ) ;
2022-05-27 21:10:37 +00:00
}
2022-05-17 17:46:52 +00:00
break ;
}
case SDL_FINGERUP : {
for ( size_t i = 0 ; i < activePoints . size ( ) ; i + + ) {
TouchPoint & point = activePoints [ i ] ;
if ( point . id = = ev . tfinger . fingerId ) {
2022-05-27 21:10:37 +00:00
if ( point . id = = 0 ) {
ImGui : : GetIO ( ) . AddMouseButtonEvent ( ImGuiMouseButton_Left , false ) ;
2022-09-09 00:15:19 +00:00
//ImGui::GetIO().AddMousePosEvent(-FLT_MAX,-FLT_MAX);
2022-09-09 23:53:20 +00:00
pointUp ( point . x , point . y , 0 ) ;
2022-05-27 21:10:37 +00:00
}
2022-09-09 23:53:20 +00:00
releasedPoints . push_back ( point ) ;
activePoints . erase ( activePoints . begin ( ) + i ) ;
2022-05-17 17:46:52 +00:00
break ;
}
}
break ;
}
}
}
2022-09-09 23:53:20 +00:00
void FurnaceGUI : : pointDown ( int x , int y , int button ) {
aboutOpen = false ;
if ( bindSetActive ) {
bindSetActive = false ;
bindSetPending = false ;
actionKeys [ bindSetTarget ] = bindSetPrevValue ;
bindSetTarget = 0 ;
bindSetPrevValue = 0 ;
}
2023-02-24 07:03:43 +00:00
if ( introPos < 11.0 & & ! shortIntro ) {
2023-02-19 05:08:37 +00:00
introSkipDo = true ;
}
2022-09-09 23:53:20 +00:00
}
void FurnaceGUI : : pointUp ( int x , int y , int button ) {
2022-09-30 22:47:17 +00:00
if ( macroDragActive | | macroLoopDragActive | | waveDragActive | | ( sampleDragActive & & sampleDragMode & & sampleDragTarget ) ) {
2022-09-09 23:53:20 +00:00
MARK_MODIFIED ;
}
if ( macroDragActive & & macroDragLineMode & & ! macroDragMouseMoved ) {
displayMacroMenu = true ;
}
macroDragActive = false ;
macroDragBitMode = false ;
macroDragInitialValue = false ;
macroDragInitialValueSet = false ;
macroDragLastX = - 1 ;
macroDragLastY = - 1 ;
macroLoopDragActive = false ;
waveDragActive = false ;
2023-02-24 07:03:43 +00:00
if ( introPos < 11.0 & & introSkip < 0.5 & & ! shortIntro ) {
2023-02-19 05:08:37 +00:00
introSkipDo = false ;
}
2022-09-09 23:53:20 +00:00
if ( sampleDragActive ) {
logD ( " stopping sample drag " ) ;
if ( sampleDragMode ) {
e - > renderSamplesP ( ) ;
} else {
if ( sampleSelStart > sampleSelEnd ) {
sampleSelStart ^ = sampleSelEnd ;
sampleSelEnd ^ = sampleSelStart ;
sampleSelStart ^ = sampleSelEnd ;
}
}
}
sampleDragActive = false ;
2022-11-30 22:20:04 +00:00
if ( orderScrollLocked ) {
int targetOrder = round ( orderScroll ) ;
2022-11-30 22:37:48 +00:00
if ( orderScrollTolerance ) {
2022-12-03 06:13:13 +00:00
targetOrder = round ( orderScroll + ( orderScrollRealOrigin . x - ( ( float ) canvasW / 2.0f ) ) / ( 40.0f * dpiScale ) ) ;
2022-11-30 22:37:48 +00:00
}
2022-11-30 22:20:04 +00:00
if ( targetOrder < 0 ) targetOrder = 0 ;
if ( targetOrder > e - > curSubSong - > ordersLen - 1 ) targetOrder = e - > curSubSong - > ordersLen - 1 ;
if ( curOrder ! = targetOrder ) setOrder ( targetOrder ) ;
}
orderScrollLocked = false ;
2022-11-30 22:37:48 +00:00
orderScrollTolerance = false ;
2022-12-04 22:19:21 +00:00
if ( dragMobileMenu ) {
dragMobileMenu = false ;
if ( mobileMenuOpen ) {
mobileMenuOpen = ( mobileMenuPos > = 0.85f ) ;
} else {
mobileMenuOpen = ( mobileMenuPos > = 0.15f ) ;
}
}
2022-12-07 03:40:23 +00:00
if ( dragMobileEditButton ) {
dragMobileEditButton = false ;
}
2022-09-09 23:53:20 +00:00
}
void FurnaceGUI : : pointMotion ( int x , int y , int xrel , int yrel ) {
if ( selecting ) {
// detect whether we have to scroll
if ( y < patWindowPos . y + 2.0f * dpiScale ) {
addScroll ( - 1 ) ;
}
if ( y > patWindowPos . y + patWindowSize . y - 2.0f * dpiScale ) {
addScroll ( 1 ) ;
}
}
2022-11-30 22:20:04 +00:00
if ( macroDragActive | | macroLoopDragActive | | waveDragActive | | sampleDragActive | | orderScrollLocked ) {
2022-09-09 23:53:20 +00:00
int distance = fabs ( ( double ) xrel ) ;
if ( distance < 1 ) distance = 1 ;
float start = x - xrel ;
float end = x ;
float startY = y - yrel ;
float endY = y ;
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 ) ;
}
}
}
2022-08-22 19:05:16 +00:00
// how many pixels should be visible at least at x/y dir
# define OOB_PIXELS_SAFETY 25
2023-04-30 21:07:46 +00:00
bool FurnaceGUI : : detectOutOfBoundsWindow ( SDL_Rect & failing ) {
2022-09-08 22:04:38 +00:00
int count = SDL_GetNumVideoDisplays ( ) ;
if ( count < 1 ) {
2023-04-30 21:07:46 +00:00
logW ( " bounds check: error: %s " , SDL_GetError ( ) ) ;
2022-08-22 19:05:16 +00:00
return false ;
}
SDL_Rect rect ;
2022-09-08 22:04:38 +00:00
for ( int i = 0 ; i < count ; i + + ) {
if ( SDL_GetDisplayUsableBounds ( i , & rect ) ! = 0 ) {
2023-04-30 21:07:46 +00:00
logW ( " bounds check: error in display %d: %s " , i , SDL_GetError ( ) ) ;
continue ;
2022-08-22 19:05:16 +00:00
}
2022-09-08 22:04:38 +00:00
bool xbound = ( ( rect . x + OOB_PIXELS_SAFETY ) < = ( scrX + scrW ) ) & & ( ( rect . x + rect . w - OOB_PIXELS_SAFETY ) > = scrX ) ;
bool ybound = ( ( rect . y + OOB_PIXELS_SAFETY ) < = ( scrY + scrH ) ) & & ( ( rect . y + rect . h - OOB_PIXELS_SAFETY ) > = scrY ) ;
logD ( " bounds check: display %d is at %dx%dx%dx%d: %s%s " , i , rect . x + OOB_PIXELS_SAFETY , rect . y + OOB_PIXELS_SAFETY , rect . x + rect . w - OOB_PIXELS_SAFETY , rect . y + rect . h - OOB_PIXELS_SAFETY , xbound ? " x " : " " , ybound ? " y " : " " ) ;
2022-08-22 19:05:16 +00:00
2022-09-08 22:04:38 +00:00
if ( xbound & & ybound ) {
2022-08-22 19:05:16 +00:00
return true ;
}
}
2023-05-01 06:36:47 +00:00
failing = rect ;
2022-08-22 19:05:16 +00:00
return false ;
}
2023-04-14 00:43:48 +00:00
# define DECLARE_METRIC(_n) \
int __perfM # # _n ;
# define MEASURE_BEGIN(_n) \
__perfM # # _n = SDL_GetPerformanceCounter ( ) ;
# define MEASURE_END(_n) \
if ( perfMetricsLen < 64 ) { \
perfMetrics [ perfMetricsLen + + ] = FurnaceGUIPerfMetric ( # _n , SDL_GetPerformanceCounter ( ) - __perfM # # _n ) ; \
}
# define MEASURE(_n,_x) \
MEASURE_BEGIN ( _n ) \
_x ; \
MEASURE_END ( _n )
2021-12-14 09:45:44 +00:00
bool FurnaceGUI : : loop ( ) {
2023-04-14 00:43:48 +00:00
DECLARE_METRIC ( calcChanOsc )
DECLARE_METRIC ( mobileControls )
DECLARE_METRIC ( mobileOrderSel )
DECLARE_METRIC ( subSongs )
DECLARE_METRIC ( findReplace )
DECLARE_METRIC ( spoiler )
DECLARE_METRIC ( pattern )
DECLARE_METRIC ( editControls )
DECLARE_METRIC ( speed )
DECLARE_METRIC ( grooves )
DECLARE_METRIC ( songInfo )
DECLARE_METRIC ( orders )
DECLARE_METRIC ( intro )
DECLARE_METRIC ( sampleList )
DECLARE_METRIC ( sampleEdit )
DECLARE_METRIC ( waveList )
DECLARE_METRIC ( waveEdit )
DECLARE_METRIC ( insList )
DECLARE_METRIC ( insEdit )
DECLARE_METRIC ( mixer )
DECLARE_METRIC ( readOsc )
DECLARE_METRIC ( osc )
DECLARE_METRIC ( chanOsc )
DECLARE_METRIC ( volMeter )
DECLARE_METRIC ( settings )
DECLARE_METRIC ( debug )
DECLARE_METRIC ( stats )
DECLARE_METRIC ( compatFlags )
DECLARE_METRIC ( piano )
DECLARE_METRIC ( notes )
DECLARE_METRIC ( channels )
DECLARE_METRIC ( patManager )
DECLARE_METRIC ( sysManager )
DECLARE_METRIC ( clock )
DECLARE_METRIC ( regView )
DECLARE_METRIC ( log )
DECLARE_METRIC ( effectList )
DECLARE_METRIC ( popup )
2022-11-10 21:53:18 +00:00
# ifdef IS_MOBILE
bool doThreadedInput = true ;
# else
2022-07-20 05:32:06 +00:00
bool doThreadedInput = ! settings . noThreadedInput ;
2022-11-10 21:53:18 +00:00
# endif
2022-07-20 05:32:06 +00:00
if ( doThreadedInput ) {
logD ( " key input: event filter " ) ;
SDL_SetEventFilter ( _processEvent , this ) ;
} else {
logD ( " key input: main thread " ) ;
}
2022-04-16 03:22:47 +00:00
2021-12-14 09:45:44 +00:00
while ( ! quit ) {
SDL_Event ev ;
2022-04-16 23:35:25 +00:00
if ( e - > isPlaying ( ) ) {
WAKE_UP ;
}
if ( - - drawHalt < = 0 ) {
drawHalt = 0 ;
if ( settings . powerSave ) SDL_WaitEventTimeout ( NULL , 500 ) ;
}
2023-04-14 00:43:48 +00:00
memcpy ( perfMetricsLast , perfMetrics , 64 * sizeof ( FurnaceGUIPerfMetric ) ) ;
perfMetricsLastLen = perfMetricsLen ;
perfMetricsLen = 0 ;
2022-05-27 05:19:10 +00:00
eventTimeBegin = SDL_GetPerformanceCounter ( ) ;
2022-09-09 23:53:20 +00:00
bool updateWindow = false ;
2022-11-05 23:17:54 +00:00
if ( injectBackUp ) {
ImGui : : GetIO ( ) . AddKeyEvent ( ImGuiKey_Backspace , false ) ;
injectBackUp = false ;
}
2021-12-14 09:45:44 +00:00
while ( SDL_PollEvent ( & ev ) ) {
2022-04-16 23:35:25 +00:00
WAKE_UP ;
2021-12-14 09:45:44 +00:00
ImGui_ImplSDL2_ProcessEvent ( & ev ) ;
2022-05-17 17:46:52 +00:00
processPoint ( ev ) ;
2022-07-20 05:32:06 +00:00
if ( ! doThreadedInput ) processEvent ( & ev ) ;
2021-12-14 09:45:44 +00:00
switch ( ev . type ) {
2022-02-08 07:04:23 +00:00
case SDL_MOUSEMOTION : {
2022-10-20 07:34:14 +00:00
int motionX = ( double ) ev . motion . x * ( ( double ) canvasW / ( double ) scrW ) ;
int motionY = ( double ) ev . motion . y * ( ( double ) canvasH / ( double ) scrH ) ;
int motionXrel = ( double ) ev . motion . xrel * ( ( double ) canvasW / ( double ) scrW ) ;
int motionYrel = ( double ) ev . motion . yrel * ( ( double ) canvasH / ( double ) scrH ) ;
2022-09-09 23:53:20 +00:00
pointMotion ( motionX , motionY , motionXrel , motionYrel ) ;
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 :
2022-09-09 23:53:20 +00:00
pointUp ( ev . button . x , ev . button . y , ev . button . button ) ;
2021-12-14 09:45:44 +00:00
break ;
2021-12-19 04:03:50 +00:00
case SDL_MOUSEBUTTONDOWN :
2022-09-09 23:53:20 +00:00
pointDown ( ev . button . x , ev . button . y , ev . button . button ) ;
2021-12-19 04:03:50 +00:00
break ;
2022-04-02 05:11:44 +00:00
case SDL_MOUSEWHEEL :
wheelX + = ev . wheel . x ;
wheelY + = ev . wheel . y ;
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
scrW = ev . window . data1 ;
scrH = ev . window . data2 ;
2022-09-08 22:04:38 +00:00
portrait = ( scrW < scrH ) ;
2022-09-09 00:15:19 +00:00
logV ( " portrait: %d (%dx%d) " , portrait , scrW , scrH ) ;
2022-10-25 03:03:27 +00:00
logD ( " window resized to %dx%d " , scrW , scrH ) ;
2022-08-22 00:47:00 +00:00
updateWindow = true ;
2023-06-13 00:43:26 +00:00
rend - > resized ( ev ) ;
2022-08-22 00:47:00 +00:00
break ;
case SDL_WINDOWEVENT_MOVED :
scrX = ev . window . data1 ;
scrY = ev . window . data2 ;
updateWindow = true ;
2023-08-31 06:24:06 +00:00
shallDetectScale = 2 ;
2022-12-24 03:36:14 +00:00
logV ( " window moved to %dx%d " , scrX , scrY ) ;
break ;
case SDL_WINDOWEVENT_SIZE_CHANGED :
logV ( " window size changed to %dx%d " , ev . window . data1 , ev . window . data2 ) ;
break ;
case SDL_WINDOWEVENT_MINIMIZED :
logV ( " window minimized " ) ;
2022-08-22 00:47:00 +00:00
break ;
case SDL_WINDOWEVENT_MAXIMIZED :
scrMax = true ;
updateWindow = true ;
2022-12-24 03:36:14 +00:00
logV ( " window maximized " ) ;
2022-08-22 00:47:00 +00:00
break ;
case SDL_WINDOWEVENT_RESTORED :
scrMax = false ;
updateWindow = true ;
2022-12-24 03:36:14 +00:00
logV ( " window restored " ) ;
break ;
case SDL_WINDOWEVENT_SHOWN :
logV ( " window shown " ) ;
break ;
case SDL_WINDOWEVENT_HIDDEN :
logV ( " window hidden " ) ;
break ;
case SDL_WINDOWEVENT_EXPOSED :
logV ( " window exposed " ) ;
2021-12-14 09:45:44 +00:00
break ;
}
break ;
2023-07-02 10:41:51 +00:00
# if SDL_VERSION_ATLEAST(2,0,4)
case SDL_RENDER_DEVICE_RESET :
killGraphics = true ;
break ;
# endif
2023-06-04 22:09:18 +00:00
# if SDL_VERSION_ATLEAST(2,0,17)
2022-10-25 03:03:27 +00:00
case SDL_DISPLAYEVENT : {
switch ( ev . display . event ) {
2023-01-17 22:57:42 +00:00
case SDL_DISPLAYEVENT_CONNECTED :
logD ( " display %d connected! " , ev . display . display ) ;
updateWindow = true ;
2023-08-27 08:58:01 +00:00
shallDetectScale = 16 ;
2023-01-17 22:57:42 +00:00
break ;
case SDL_DISPLAYEVENT_DISCONNECTED :
logD ( " display %d disconnected! " , ev . display . display ) ;
updateWindow = true ;
2023-08-27 08:58:01 +00:00
shallDetectScale = 16 ;
2023-01-17 22:57:42 +00:00
break ;
2022-10-25 03:03:27 +00:00
case SDL_DISPLAYEVENT_ORIENTATION :
logD ( " display oriented to %d " , ev . display . data1 ) ;
updateWindow = true ;
break ;
}
break ;
}
2023-06-04 22:09:18 +00:00
# endif
2021-12-14 22:45:37 +00:00
case SDL_KEYDOWN :
if ( ! ImGui : : GetIO ( ) . WantCaptureKeyboard ) {
keyDown ( ev ) ;
}
2022-11-05 23:17:54 +00:00
# ifdef IS_MOBILE
injectBackUp = true ;
# endif
2021-12-14 22:45:37 +00:00
break ;
case SDL_KEYUP :
2022-04-16 03:22:47 +00:00
// for now
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 ) {
2022-11-21 07:55:12 +00:00
int sampleCountBefore = e - > song . sampleLen ;
2022-05-28 23:51:05 +00:00
std : : vector < DivInstrument * > instruments = e - > instrumentFromFile ( ev . drop . file ) ;
2022-08-13 09:17:32 +00:00
DivWavetable * droppedWave = NULL ;
2023-06-11 00:22:44 +00:00
DivSample * droppedSample = NULL ;
2022-05-28 23:51:05 +00:00
if ( ! instruments . empty ( ) ) {
2022-11-21 07:55:12 +00:00
if ( e - > song . sampleLen ! = sampleCountBefore ) {
e - > renderSamplesP ( ) ;
}
2022-05-28 23:51:05 +00:00
if ( ! e - > getWarnings ( ) . empty ( ) ) {
showWarning ( e - > getWarnings ( ) , GUI_WARN_GENERIC ) ;
}
for ( DivInstrument * i : instruments ) {
e - > addInstrumentPtr ( i ) ;
}
nextWindow = GUI_WINDOW_INS_LIST ;
MARK_MODIFIED ;
2022-08-13 09:17:32 +00:00
} else if ( ( droppedWave = e - > waveFromFile ( ev . drop . file , false ) ) ! = NULL ) {
e - > addWavePtr ( droppedWave ) ;
2022-05-28 23:51:05 +00:00
nextWindow = GUI_WINDOW_WAVE_LIST ;
MARK_MODIFIED ;
2022-08-13 09:17:32 +00:00
} else if ( ( droppedSample = e - > sampleFromFile ( ev . drop . file ) ) ! = NULL ) {
e - > addSamplePtr ( droppedSample ) ;
2022-05-28 23:51:05 +00:00
nextWindow = GUI_WINDOW_SAMPLE_LIST ;
MARK_MODIFIED ;
} else if ( modified ) {
2022-02-01 08:09:53 +00:00
nextFile = ev . drop . file ;
2022-04-13 07:09:59 +00:00
showWarning ( " Unsaved changes! Save changes before opening file? " , GUI_WARN_OPEN_DROP ) ;
2022-02-01 08:09:53 +00:00
} 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 ) {
2022-04-13 07:09:59 +00:00
showWarning ( " Unsaved changes! Save changes before quitting? " , GUI_WARN_QUIT ) ;
2021-12-30 23:52:36 +00:00
} 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
}
2022-04-16 04:47:39 +00:00
2022-08-22 00:47:00 +00:00
// update config x/y/w/h values based on scrMax state
2022-09-08 22:04:38 +00:00
if ( updateWindow ) {
2022-10-23 07:51:38 +00:00
logV ( " updateWindow is true " ) ;
2023-06-12 05:12:02 +00:00
if ( ! scrMax & & ! fullScreen ) {
logV ( " updating scrConf " ) ;
2022-08-22 00:47:00 +00:00
scrConfX = scrX ;
scrConfY = scrY ;
scrConfW = scrW ;
scrConfH = scrH ;
}
2022-10-24 19:57:12 +00:00
}
// update canvas size as well
2023-06-03 01:21:37 +00:00
if ( ! rend - > getOutputSize ( canvasW , canvasH ) ) {
logW ( " loop: error while getting output size! " ) ;
2022-10-24 19:57:12 +00:00
} else {
//logV("updateWindow: canvas size %dx%d",canvasW,canvasH);
// and therefore window size
2022-12-24 03:36:14 +00:00
int prevScrW = scrW ;
int prevScrH = scrH ;
2022-10-24 20:18:35 +00:00
SDL_GetWindowSize ( sdlWin , & scrW , & scrH ) ;
2022-12-24 03:36:14 +00:00
if ( prevScrW ! = scrW | | prevScrH ! = scrH ) {
logV ( " size change 2: %dx%d (from %dx%d) " , scrW , scrH , prevScrW , prevScrH ) ;
}
2023-08-30 10:21:33 +00:00
ImGui : : GetIO ( ) . InputScale = ( float ) canvasW / ( float ) scrW ;
2022-08-22 00:47:00 +00:00
}
2022-04-25 23:23:12 +00:00
wantCaptureKeyboard = ImGui : : GetIO ( ) . WantTextInput ;
2022-05-04 23:42:36 +00:00
2022-05-11 21:09:23 +00:00
if ( wantCaptureKeyboard ! = oldWantCaptureKeyboard ) {
oldWantCaptureKeyboard = wantCaptureKeyboard ;
if ( wantCaptureKeyboard ) {
SDL_StartTextInput ( ) ;
} else {
SDL_StopTextInput ( ) ;
}
}
2022-05-04 23:42:36 +00:00
if ( wantCaptureKeyboard ) {
WAKE_UP ;
}
2022-12-01 23:33:48 +00:00
if ( ImGui : : GetIO ( ) . IsSomethingHappening ) {
WAKE_UP ;
}
2022-05-04 23:42:36 +00:00
if ( ImGui : : GetIO ( ) . MouseDown [ 0 ] | | ImGui : : GetIO ( ) . MouseDown [ 1 ] | | ImGui : : GetIO ( ) . MouseDown [ 2 ] | | ImGui : : GetIO ( ) . MouseDown [ 3 ] | | ImGui : : GetIO ( ) . MouseDown [ 4 ] ) {
WAKE_UP ;
}
2022-05-26 05:24:21 +00:00
2022-03-28 23:19:47 +00:00
while ( true ) {
midiLock . lock ( ) ;
if ( midiQueue . empty ( ) ) {
midiLock . unlock ( ) ;
break ;
}
TAMidiMessage msg = midiQueue . front ( ) ;
midiLock . unlock ( ) ;
2022-05-08 07:01:32 +00:00
if ( msg . type = = TA_MIDI_SYSEX ) {
unsigned char * data = msg . sysExData . get ( ) ;
for ( size_t i = 0 ; i < msg . sysExLen ; i + + ) {
if ( ( i & 15 ) = = 0 ) printf ( " \n " ) ;
printf ( " %.2x " , data [ i ] ) ;
}
printf ( " \n " ) ;
if ( ! parseSysEx ( data , msg . sysExLen ) ) {
logW ( " error while parsing SysEx data! " ) ;
}
}
2022-03-28 23:19:47 +00:00
// parse message here
2022-03-31 23:39:01 +00:00
if ( learning ! = - 1 ) {
if ( learning > = 0 & & learning < ( int ) midiMap . binds . size ( ) ) {
midiMap . binds [ learning ] . type = msg . type > > 4 ;
midiMap . binds [ learning ] . channel = msg . type & 15 ;
midiMap . binds [ learning ] . data1 = msg . data [ 0 ] ;
2022-04-01 06:50:01 +00:00
switch ( msg . type & 0xf0 ) {
2022-03-31 23:39:01 +00:00
case TA_MIDI_NOTE_OFF :
case TA_MIDI_NOTE_ON :
case TA_MIDI_AFTERTOUCH :
case TA_MIDI_PITCH_BEND :
case TA_MIDI_CONTROL :
midiMap . binds [ learning ] . data2 = msg . data [ 1 ] ;
break ;
default :
midiMap . binds [ learning ] . data2 = 128 ;
break ;
2022-03-30 20:44:27 +00:00
}
2022-03-31 23:39:01 +00:00
}
learning = - 1 ;
} else {
int action = midiMap . at ( msg ) ;
if ( action ! = 0 ) {
doAction ( action ) ;
} else switch ( msg . type & 0xf0 ) {
case TA_MIDI_NOTE_ON :
2022-04-01 06:50:01 +00:00
if ( midiMap . valueInputStyle = = 0 | | midiMap . valueInputStyle > 3 | | cursor . xFine = = 0 ) {
if ( midiMap . noteInput & & edit & & msg . data [ 1 ] ! = 0 ) {
noteInput (
msg . data [ 0 ] - 12 ,
0 ,
midiMap . volInput ? ( ( int ) ( pow ( ( double ) msg . data [ 1 ] / 127.0 , midiMap . volExp ) * 127.0 ) ) : - 1
) ;
}
} else {
if ( edit & & msg . data [ 1 ] ! = 0 ) {
switch ( midiMap . valueInputStyle ) {
case 1 : {
int val = msg . data [ 0 ] % 24 ;
if ( val < 16 ) {
valueInput ( val ) ;
}
break ;
}
case 2 :
valueInput ( msg . data [ 0 ] & 15 ) ;
break ;
case 3 :
int val = altValues [ msg . data [ 0 ] % 24 ] ;
if ( val > = 0 ) {
valueInput ( val ) ;
}
break ;
}
}
2022-03-31 23:39:01 +00:00
}
break ;
case TA_MIDI_PROGRAM :
if ( midiMap . programChange ) {
curIns = msg . data [ 0 ] ;
if ( curIns > = ( int ) e - > song . ins . size ( ) ) curIns = e - > song . ins . size ( ) - 1 ;
2022-05-21 23:36:15 +00:00
wavePreviewInit = true ;
2023-03-18 09:22:50 +00:00
updateFMPreview = true ;
2022-03-31 23:39:01 +00:00
}
break ;
2022-04-01 06:50:01 +00:00
case TA_MIDI_CONTROL :
bool gchanged = false ;
if ( msg . data [ 0 ] = = midiMap . valueInputControlMSB ) {
midiMap . valueInputCurMSB = msg . data [ 1 ] ;
gchanged = true ;
}
if ( msg . data [ 0 ] = = midiMap . valueInputControlLSB ) {
midiMap . valueInputCurLSB = msg . data [ 1 ] ;
gchanged = true ;
}
if ( msg . data [ 0 ] = = midiMap . valueInputControlSingle ) {
midiMap . valueInputCurSingle = msg . data [ 1 ] ;
gchanged = true ;
}
if ( gchanged & & cursor . xFine > 0 ) {
switch ( midiMap . valueInputStyle ) {
case 4 : // dual CC
valueInput ( ( ( midiMap . valueInputCurMSB > > 3 ) < < 4 ) | ( midiMap . valueInputCurLSB > > 3 ) , true ) ;
break ;
case 5 : // 14-bit
valueInput ( ( midiMap . valueInputCurMSB < < 1 ) | ( midiMap . valueInputCurLSB > > 6 ) , true ) ;
break ;
case 6 : // single CC
valueInput ( ( midiMap . valueInputCurSingle * 255 ) / 127 , true ) ;
break ;
}
}
for ( int i = 0 ; i < 18 ; i + + ) {
bool changed = false ;
if ( midiMap . valueInputSpecificStyle [ i ] ! = 0 ) {
if ( msg . data [ 0 ] = = midiMap . valueInputSpecificMSB [ i ] ) {
changed = true ;
midiMap . valueInputCurMSBS [ i ] = msg . data [ 1 ] ;
}
if ( msg . data [ 0 ] = = midiMap . valueInputSpecificLSB [ i ] ) {
changed = true ;
midiMap . valueInputCurLSBS [ i ] = msg . data [ 1 ] ;
}
if ( msg . data [ 0 ] = = midiMap . valueInputSpecificSingle [ i ] ) {
changed = true ;
midiMap . valueInputCurSingleS [ i ] = msg . data [ 1 ] ;
}
if ( changed ) switch ( midiMap . valueInputStyle ) {
case 1 : // dual CC
valueInput ( ( ( midiMap . valueInputCurMSBS [ i ] > > 3 ) < < 4 ) | ( midiMap . valueInputCurLSBS [ i ] > > 3 ) , true , i + 2 ) ;
break ;
case 2 : // 14-bit
valueInput ( ( midiMap . valueInputCurMSBS [ i ] < < 1 ) | ( midiMap . valueInputCurLSBS [ i ] > > 6 ) , true , i + 2 ) ;
break ;
case 3 : // single CC
valueInput ( ( midiMap . valueInputCurSingleS [ i ] * 255 ) / 127 , true , i + 2 ) ;
break ;
}
}
}
break ;
2022-03-31 23:39:01 +00:00
}
2022-03-30 20:44:27 +00:00
}
2022-03-28 23:19:47 +00:00
midiLock . lock ( ) ;
midiQueue . pop ( ) ;
midiLock . unlock ( ) ;
}
2022-05-27 05:19:10 +00:00
2023-07-15 07:50:49 +00:00
if ( notifyWaveChange ) {
notifyWaveChange = false ;
e - > notifyWaveChange ( curWave ) ;
}
2022-05-27 05:19:10 +00:00
eventTimeEnd = SDL_GetPerformanceCounter ( ) ;
2023-01-23 21:21:58 +00:00
if ( SDL_GetWindowFlags ( sdlWin ) & SDL_WINDOW_MINIMIZED ) {
2023-01-23 21:40:56 +00:00
SDL_Delay ( 30 ) ;
drawHalt = 0 ;
2023-01-23 21:21:58 +00:00
continue ;
}
2023-02-24 05:38:32 +00:00
if ( firstFrame ) {
if ( ! tutorial . introPlayed | | settings . alwaysPlayIntro = = 3 | | ( settings . alwaysPlayIntro = = 2 & & curFileName . empty ( ) ) ) {
unsigned char * introTemp = new unsigned char [ intro_fur_len ] ;
memcpy ( introTemp , intro_fur , intro_fur_len ) ;
e - > load ( introTemp , intro_fur_len ) ;
}
}
2023-04-06 06:42:52 +00:00
if ( ! e - > isRunning ( ) ) {
activeNotes . clear ( ) ;
memset ( chanOscVol , 0 , DIV_MAX_CHANS * sizeof ( float ) ) ;
memset ( chanOscPitch , 0 , DIV_MAX_CHANS * sizeof ( float ) ) ;
memset ( chanOscBright , 0 , DIV_MAX_CHANS * sizeof ( float ) ) ;
e - > synchronized ( [ this ] ( ) {
for ( int i = 0 ; i < e - > getTotalChannelCount ( ) ; i + + ) {
DivDispatchOscBuffer * buf = e - > getOscBuffer ( i ) ;
2023-04-06 07:20:48 +00:00
if ( buf ! = NULL ) {
buf - > needle = 0 ;
buf - > readNeedle = 0 ;
}
2023-04-06 06:42:52 +00:00
}
} ) ;
}
2023-07-02 05:09:39 +00:00
// recover from dead graphics
if ( rend - > isDead ( ) | | killGraphics ) {
killGraphics = false ;
logW ( " graphics are dead! restarting... " ) ;
if ( sampleTex ! = NULL ) {
rend - > destroyTexture ( sampleTex ) ;
sampleTex = NULL ;
}
if ( chanOscGradTex ! = NULL ) {
rend - > destroyTexture ( chanOscGradTex ) ;
chanOscGradTex = NULL ;
}
for ( auto & i : images ) {
if ( i . second - > tex ! = NULL ) {
rend - > destroyTexture ( i . second - > tex ) ;
i . second - > tex = NULL ;
}
}
commitState ( ) ;
rend - > quitGUI ( ) ;
rend - > quit ( ) ;
ImGui_ImplSDL2_Shutdown ( ) ;
int initAttempts = 0 ;
SDL_Delay ( 500 ) ;
logD ( " starting render backend... " ) ;
while ( + + initAttempts < = 5 ) {
if ( rend - > init ( sdlWin ) ) {
break ;
}
SDL_Delay ( 1000 ) ;
logV ( " trying again... " ) ;
}
if ( initAttempts > 5 ) {
reportError ( " can't keep going without graphics! Furnace will quit now. " ) ;
quit = true ;
break ;
}
rend - > clear ( ImVec4 ( 0.0 , 0.0 , 0.0 , 1.0 ) ) ;
rend - > present ( ) ;
logD ( " preparing user interface... " ) ;
rend - > initGUI ( sdlWin ) ;
logD ( " building font... " ) ;
if ( ! ImGui : : GetIO ( ) . Fonts - > Build ( ) ) {
logE ( " error while building font atlas! " ) ;
showError ( " error while loading fonts! please check your settings. " ) ;
ImGui : : GetIO ( ) . Fonts - > Clear ( ) ;
mainFont = ImGui : : GetIO ( ) . Fonts - > AddFontDefault ( ) ;
patFont = mainFont ;
2023-07-10 19:38:26 +00:00
bigFont = mainFont ;
2023-08-03 05:59:45 +00:00
headFont = mainFont ;
2023-07-02 05:09:39 +00:00
if ( rend ) rend - > destroyFontsTexture ( ) ;
if ( ! ImGui : : GetIO ( ) . Fonts - > Build ( ) ) {
logE ( " error again while building font atlas! " ) ;
}
}
firstFrame = true ;
mustClear = 2 ;
initialScreenWipe = 1.0f ;
continue ;
}
2023-05-03 06:22:54 +00:00
bool fontsFailed = false ;
2022-05-27 05:19:10 +00:00
layoutTimeBegin = SDL_GetPerformanceCounter ( ) ;
2022-05-27 18:00:23 +00:00
2023-06-03 06:41:34 +00:00
if ( ! rend - > newFrame ( ) ) {
2023-05-03 06:22:54 +00:00
fontsFailed = true ;
}
2021-12-14 09:45:44 +00:00
ImGui_ImplSDL2_NewFrame ( sdlWin ) ;
ImGui : : NewFrame ( ) ;
2022-05-05 01:56:26 +00:00
curWindowLast = curWindow ;
2021-12-14 22:45:37 +00:00
curWindow = GUI_WINDOW_NOTHING ;
2022-04-21 23:10:59 +00:00
editOptsVisible = false ;
2021-12-14 22:45:37 +00:00
2022-05-18 23:42:59 +00:00
if ( ! mobileUI ) {
ImGui : : BeginMainMenuBar ( ) ;
2023-08-10 03:47:06 +00:00
if ( ImGui : : BeginMenu ( settings . capitalMenuBar ? " File " : " file " ) ) {
2023-04-02 21:39:06 +00:00
if ( ImGui : : MenuItem ( " new... " , BIND_FOR ( GUI_ACTION_NEW ) ) ) {
2022-05-18 23:42:59 +00:00
if ( modified ) {
showWarning ( " Unsaved changes! Save changes before creating a new song? " , GUI_WARN_NEW ) ;
} else {
displayNew = true ;
2021-12-30 23:25:55 +00:00
}
}
2022-05-18 23:42:59 +00:00
if ( ImGui : : MenuItem ( " open... " , BIND_FOR ( GUI_ACTION_OPEN ) ) ) {
if ( modified ) {
showWarning ( " Unsaved changes! Save changes before opening another file? " , GUI_WARN_OPEN ) ;
} else {
openFileDialog ( GUI_FILE_OPEN ) ;
}
2022-01-18 04:34:29 +00:00
}
2022-09-10 23:53:27 +00:00
if ( ImGui : : BeginMenu ( " open recent " ) ) {
2023-05-24 06:58:12 +00:00
exitDisabledTimer = 1 ;
2022-09-10 23:53:27 +00:00
for ( int i = 0 ; i < ( int ) recentFile . size ( ) ; i + + ) {
String item = recentFile [ i ] ;
if ( ImGui : : MenuItem ( item . c_str ( ) ) ) {
if ( modified ) {
nextFile = item ;
showWarning ( " Unsaved changes! Save changes before opening file? " , GUI_WARN_OPEN_DROP ) ;
} else {
recentFile . erase ( recentFile . begin ( ) + i ) ;
i - - ;
if ( load ( item ) > 0 ) {
showError ( fmt : : sprintf ( " Error while loading file! (%s) " , lastError ) ) ;
}
}
}
}
if ( recentFile . empty ( ) ) {
ImGui : : Text ( " nothing here yet " ) ;
2022-10-02 06:36:37 +00:00
} else {
ImGui : : Separator ( ) ;
if ( ImGui : : MenuItem ( " clear history " ) ) {
showWarning ( " Are you sure you want to clear the recent file list? " , GUI_WARN_CLEAR_HISTORY ) ;
}
2022-09-10 23:53:27 +00:00
}
ImGui : : EndMenu ( ) ;
}
2022-05-18 23:42:59 +00:00
ImGui : : Separator ( ) ;
if ( ImGui : : MenuItem ( " save " , BIND_FOR ( GUI_ACTION_SAVE ) ) ) {
2023-04-06 09:22:43 +00:00
if ( curFileName = = " " | | ( curFileName . find ( backupPath ) = = 0 ) | | e - > song . version > = 0xff00 ) {
2022-05-18 23:42:59 +00:00
openFileDialog ( GUI_FILE_SAVE ) ;
} else {
if ( save ( curFileName , e - > song . isDMF ? e - > song . version : 0 ) > 0 ) {
showError ( fmt : : sprintf ( " Error while saving file! (%s) " , lastError ) ) ;
}
}
2022-01-18 04:34:29 +00:00
}
2022-05-18 23:42:59 +00:00
if ( ImGui : : MenuItem ( " save as... " , BIND_FOR ( GUI_ACTION_SAVE_AS ) ) ) {
openFileDialog ( GUI_FILE_SAVE ) ;
2022-01-18 04:34:29 +00:00
}
2022-09-04 07:27:00 +00:00
if ( ImGui : : MenuItem ( " save as .dmf (1.1.3+)... " ) ) {
2022-09-04 07:26:29 +00:00
openFileDialog ( GUI_FILE_SAVE_DMF ) ;
}
2022-09-04 07:27:00 +00:00
if ( ImGui : : MenuItem ( " save as .dmf (1.0/legacy)... " ) ) {
2022-05-18 23:42:59 +00:00
openFileDialog ( GUI_FILE_SAVE_DMF_LEGACY ) ;
2022-01-18 04:34:29 +00:00
}
2022-05-18 23:42:59 +00:00
ImGui : : Separator ( ) ;
if ( ImGui : : BeginMenu ( " export audio... " ) ) {
2023-05-24 06:58:12 +00:00
exitDisabledTimer = 1 ;
2022-05-18 23:42:59 +00:00
if ( ImGui : : MenuItem ( " one file " ) ) {
openFileDialog ( GUI_FILE_EXPORT_AUDIO_ONE ) ;
}
2022-08-11 10:38:31 +00:00
if ( ImGui : : MenuItem ( " multiple files (one per chip) " ) ) {
2023-04-02 07:31:36 +00:00
openFileDialog ( GUI_FILE_EXPORT_AUDIO_PER_SYS ) ;
2022-05-18 23:42:59 +00:00
}
if ( ImGui : : MenuItem ( " multiple files (one per channel) " ) ) {
2023-04-02 07:31:36 +00:00
openFileDialog ( GUI_FILE_EXPORT_AUDIO_PER_CHANNEL ) ;
2022-04-02 02:40:32 +00:00
}
2022-05-18 23:42:59 +00:00
if ( ImGui : : InputInt ( " Loops " , & exportLoops , 1 , 2 ) ) {
if ( exportLoops < 0 ) exportLoops = 0 ;
}
2022-06-06 08:05:55 +00:00
if ( ImGui : : InputDouble ( " Fade out (seconds) " , & exportFadeOut , 1.0 , 2.0 , " %.1f " ) ) {
if ( exportFadeOut < 0.0 ) exportFadeOut = 0.0 ;
}
2022-05-18 23:42:59 +00:00
ImGui : : EndMenu ( ) ;
2022-04-02 02:40:32 +00:00
}
2022-05-18 23:42:59 +00:00
if ( ImGui : : BeginMenu ( " export VGM... " ) ) {
2023-05-24 06:58:12 +00:00
exitDisabledTimer = 1 ;
2023-04-02 07:31:36 +00:00
ImGui : : Text ( " settings: " ) ;
if ( ImGui : : BeginCombo ( " format version " , fmt : : sprintf ( " %d.%.2x " , vgmExportVersion > > 8 , vgmExportVersion & 0xff ) . c_str ( ) ) ) {
for ( int i = 0 ; i < 7 ; i + + ) {
if ( ImGui : : Selectable ( fmt : : sprintf ( " %d.%.2x " , vgmVersions [ i ] > > 8 , vgmVersions [ i ] & 0xff ) . c_str ( ) , vgmExportVersion = = vgmVersions [ i ] ) ) {
vgmExportVersion = vgmVersions [ i ] ;
2022-05-18 23:42:59 +00:00
}
}
2023-04-02 07:31:36 +00:00
ImGui : : EndCombo ( ) ;
}
ImGui : : Checkbox ( " loop " , & vgmExportLoop ) ;
if ( vgmExportLoop & & e - > song . loopModality = = 2 ) {
2023-04-15 21:08:38 +00:00
ImGui : : Text ( " loop trail: " ) ;
2023-08-06 02:18:53 +00:00
ImGui : : Indent ( ) ;
2023-04-02 07:31:36 +00:00
if ( ImGui : : RadioButton ( " auto-detect " , vgmExportTrailingTicks = = - 1 ) ) {
vgmExportTrailingTicks = - 1 ;
2023-02-09 00:25:03 +00:00
}
2023-04-15 21:08:38 +00:00
if ( ImGui : : RadioButton ( " add one loop " , vgmExportTrailingTicks = = - 2 ) ) {
2023-04-02 07:31:36 +00:00
vgmExportTrailingTicks = - 2 ;
2023-02-09 00:25:03 +00:00
}
2023-04-02 07:31:36 +00:00
if ( ImGui : : RadioButton ( " custom " , vgmExportTrailingTicks > = 0 ) ) {
vgmExportTrailingTicks = 0 ;
2023-02-09 00:25:03 +00:00
}
2023-04-02 07:31:36 +00:00
if ( vgmExportTrailingTicks > = 0 ) {
ImGui : : SameLine ( ) ;
if ( ImGui : : InputInt ( " ##TrailTicks " , & vgmExportTrailingTicks , 1 , 100 ) ) {
if ( vgmExportTrailingTicks < 0 ) vgmExportTrailingTicks = 0 ;
2023-02-09 00:25:03 +00:00
}
}
2023-08-06 02:18:53 +00:00
ImGui : : Unindent ( ) ;
2023-04-02 07:31:36 +00:00
}
ImGui : : Checkbox ( " add pattern change hints " , & vgmExportPatternHints ) ;
if ( ImGui : : IsItemHovered ( ) ) {
ImGui : : SetTooltip (
" inserts data blocks on pattern changes. \n "
" useful if you are writing a playback routine. \n \n "
" the format of a pattern change data block is: \n "
" 67 66 FE ll ll ll ll 01 oo rr pp pp pp ... \n "
" - ll: length, a 32-bit little-endian number \n "
" - oo: order \n "
" - rr: initial row (a 0Dxx effect is able to select a different row) \n "
" - pp: pattern index (one per channel) \n \n "
" pattern indexes are ordered as they appear in the song. "
) ;
}
ImGui : : Checkbox ( " direct stream mode " , & vgmExportDirectStream ) ;
if ( ImGui : : IsItemHovered ( ) ) {
ImGui : : SetTooltip (
" required for DualPCM and MSM6258 export. \n \n "
" allows for volume/direction changes when playing samples, \n "
" at the cost of a massive increase in file size. "
) ;
}
ImGui : : Text ( " chips to export: " ) ;
bool hasOneAtLeast = false ;
for ( int i = 0 ; i < e - > song . systemLen ; i + + ) {
int minVersion = e - > minVGMVersion ( e - > song . system [ i ] ) ;
ImGui : : BeginDisabled ( minVersion > vgmExportVersion | | minVersion = = 0 ) ;
ImGui : : Checkbox ( fmt : : sprintf ( " %d. %s##_SYSV%d " , i + 1 , getSystemName ( e - > song . system [ i ] ) , i ) . c_str ( ) , & willExport [ i ] ) ;
ImGui : : EndDisabled ( ) ;
if ( minVersion > vgmExportVersion ) {
if ( ImGui : : IsItemHovered ( ImGuiHoveredFlags_AllowWhenDisabled ) ) {
ImGui : : SetTooltip ( " this chip is only available in VGM %d.%.2x and higher! " , minVersion > > 8 , minVersion & 0xff ) ;
}
} else if ( minVersion = = 0 ) {
if ( ImGui : : IsItemHovered ( ImGuiHoveredFlags_AllowWhenDisabled ) ) {
ImGui : : SetTooltip ( " this chip is not supported by the VGM format! " ) ;
2022-05-18 23:42:59 +00:00
}
} else {
2023-04-02 07:31:36 +00:00
if ( willExport [ i ] ) hasOneAtLeast = true ;
}
}
ImGui : : Text ( " select the chip you wish to export, " ) ;
ImGui : : Text ( " but only up to %d of each type. " , ( vgmExportVersion > = 0x151 ) ? 2 : 1 ) ;
if ( hasOneAtLeast ) {
if ( ImGui : : MenuItem ( " click to export " ) ) {
openFileDialog ( GUI_FILE_EXPORT_VGM ) ;
2022-01-26 05:26:15 +00:00
}
2023-04-02 07:31:36 +00:00
} else {
ImGui : : Text ( " nothing to export " ) ;
2022-01-26 05:26:15 +00:00
}
2022-05-18 23:42:59 +00:00
ImGui : : EndMenu ( ) ;
2022-01-26 05:26:15 +00:00
}
2022-05-26 05:24:21 +00:00
int numZSMCompat = 0 ;
for ( int i = 0 ; i < e - > song . systemLen ; i + + ) {
if ( ( e - > song . system [ i ] = = DIV_SYSTEM_VERA ) | | ( e - > song . system [ i ] = = DIV_SYSTEM_YM2151 ) ) numZSMCompat + + ;
}
if ( numZSMCompat > 0 ) {
if ( ImGui : : BeginMenu ( " export ZSM... " ) ) {
2023-05-24 06:58:12 +00:00
exitDisabledTimer = 1 ;
2023-03-13 09:20:54 +00:00
ImGui : : Text ( " Commander X16 Zsound Music File " ) ;
if ( ImGui : : InputInt ( " Tick Rate (Hz) " , & zsmExportTickRate , 1 , 2 ) ) {
if ( zsmExportTickRate < 1 ) zsmExportTickRate = 1 ;
if ( zsmExportTickRate > 44100 ) zsmExportTickRate = 44100 ;
}
ImGui : : Checkbox ( " loop " , & zsmExportLoop ) ;
ImGui : : SameLine ( ) ;
2023-08-11 20:03:37 +00:00
ImGui : : Checkbox ( " optimize size " , & zsmExportOptimize ) ;
ImGui : : SameLine ( ) ;
2023-03-13 09:20:54 +00:00
if ( ImGui : : Button ( " Begin Export " ) ) {
openFileDialog ( GUI_FILE_EXPORT_ZSM ) ;
ImGui : : CloseCurrentPopup ( ) ;
}
ImGui : : EndMenu ( ) ;
}
}
int numAmiga = 0 ;
for ( int i = 0 ; i < e - > song . systemLen ; i + + ) {
if ( e - > song . system [ i ] = = DIV_SYSTEM_AMIGA ) numAmiga + + ;
}
if ( numAmiga & & settings . iCannotWait ) {
if ( ImGui : : BeginMenu ( " export Amiga validation data... " ) ) {
2023-05-24 06:58:12 +00:00
exitDisabledTimer = 1 ;
2023-03-13 09:20:54 +00:00
ImGui : : Text (
" this is NOT ROM export! only use for making sure the \n "
" Furnace Amiga emulator is working properly by \n "
" comparing it with real Amiga output. "
) ;
2023-08-07 03:51:51 +00:00
ImGui : : AlignTextToFramePadding ( ) ;
2023-03-13 09:20:54 +00:00
ImGui : : Text ( " Directory " ) ;
ImGui : : SameLine ( ) ;
ImGui : : InputText ( " ##AVDPath " , & workingDirROMExport ) ;
if ( ImGui : : Button ( " Bake Data " ) ) {
2023-03-14 01:01:01 +00:00
std : : vector < DivROMExportOutput > out = e - > buildROM ( DIV_ROM_AMIGA_VALIDATION ) ;
2023-03-14 06:27:45 +00:00
if ( workingDirROMExport . size ( ) > 0 ) {
if ( workingDirROMExport [ workingDirROMExport . size ( ) - 1 ] ! = DIR_SEPARATOR ) workingDirROMExport + = DIR_SEPARATOR_STR ;
}
for ( DivROMExportOutput & i : out ) {
String path = workingDirROMExport + i . name ;
FILE * outFile = ps_fopen ( path . c_str ( ) , " wb " ) ;
if ( outFile ! = NULL ) {
fwrite ( i . data - > getFinalBuf ( ) , 1 , i . data - > size ( ) , outFile ) ;
fclose ( outFile ) ;
}
i . data - > finish ( ) ;
delete i . data ;
}
showError ( fmt : : sprintf ( " Done! Baked %d files. " , ( int ) out . size ( ) ) ) ;
2023-03-13 09:20:54 +00:00
ImGui : : CloseCurrentPopup ( ) ;
}
ImGui : : EndMenu ( ) ;
2022-05-26 05:24:21 +00:00
}
}
2023-04-02 07:31:36 +00:00
if ( ImGui : : BeginMenu ( " export command stream... " ) ) {
2023-05-24 06:58:12 +00:00
exitDisabledTimer = 1 ;
2022-08-04 05:51:47 +00:00
ImGui : : Text (
" this option exports a text or binary file which \n "
" contains a dump of the internal command stream \n "
" produced when playing the song. \n \n "
" technical/development use only! "
) ;
2023-03-26 18:19:57 +00:00
if ( ImGui : : Button ( " export (binary) " ) ) {
openFileDialog ( GUI_FILE_EXPORT_CMDSTREAM_BINARY ) ;
}
if ( ImGui : : Button ( " export (text) " ) ) {
2022-08-04 05:51:47 +00:00
openFileDialog ( GUI_FILE_EXPORT_CMDSTREAM ) ;
}
ImGui : : EndMenu ( ) ;
}
2023-02-24 08:47:53 +00:00
ImGui : : Separator ( ) ;
2023-08-28 22:00:39 +00:00
if ( ! settings . classicChipOptions ) {
if ( ImGui : : MenuItem ( " manage chips " ) ) {
nextWindow = GUI_WINDOW_SYS_MANAGER ;
}
} else {
if ( ImGui : : BeginMenu ( " add chip... " ) ) {
exitDisabledTimer = 1 ;
DivSystem picked = systemPicker ( ) ;
if ( picked ! = DIV_SYSTEM_NULL ) {
if ( ! e - > addSystem ( picked ) ) {
showError ( " cannot add chip! ( " + e - > getLastError ( ) + " ) " ) ;
} else {
MARK_MODIFIED ;
}
ImGui : : CloseCurrentPopup ( ) ;
if ( e - > song . autoSystem ) {
autoDetectSystem ( ) ;
}
updateWindowTitle ( ) ;
2022-05-18 23:42:59 +00:00
}
2023-08-28 22:00:39 +00:00
ImGui : : EndMenu ( ) ;
2022-01-28 23:12:56 +00:00
}
2023-08-28 22:00:39 +00:00
if ( ImGui : : BeginMenu ( " configure chip... " ) ) {
exitDisabledTimer = 1 ;
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 ( ) ) ) {
drawSysConf ( i , e - > song . system [ i ] , e - > song . systemFlags [ i ] , true , true ) ;
ImGui : : TreePop ( ) ;
}
2022-03-21 22:34:43 +00:00
}
2023-08-28 22:00:39 +00:00
ImGui : : EndMenu ( ) ;
2022-01-09 21:36:47 +00:00
}
2023-08-28 22:00:39 +00:00
if ( ImGui : : BeginMenu ( " change chip... " ) ) {
exitDisabledTimer = 1 ;
ImGui : : Checkbox ( " Preserve channel positions " , & preserveChanPos ) ;
for ( int i = 0 ; i < e - > song . systemLen ; i + + ) {
if ( ImGui : : BeginMenu ( fmt : : sprintf ( " %d. %s##_SYSC%d " , i + 1 , getSystemName ( e - > song . system [ i ] ) , i ) . c_str ( ) ) ) {
DivSystem picked = systemPicker ( ) ;
if ( picked ! = DIV_SYSTEM_NULL ) {
e - > changeSystem ( i , picked , preserveChanPos ) ;
MARK_MODIFIED ;
if ( e - > song . autoSystem ) {
autoDetectSystem ( ) ;
}
updateWindowTitle ( ) ;
ImGui : : CloseCurrentPopup ( ) ;
2023-02-06 23:52:51 +00:00
}
2023-08-28 22:00:39 +00:00
ImGui : : EndMenu ( ) ;
2022-09-22 00:27:42 +00:00
}
2022-01-09 21:36:47 +00:00
}
2023-08-28 22:00:39 +00:00
ImGui : : EndMenu ( ) ;
2022-01-09 21:36:47 +00:00
}
2023-08-28 22:00:39 +00:00
if ( ImGui : : BeginMenu ( " remove chip... " ) ) {
exitDisabledTimer = 1 ;
ImGui : : Checkbox ( " Preserve channel positions " , & preserveChanPos ) ;
for ( int i = 0 ; i < e - > song . systemLen ; i + + ) {
if ( ImGui : : MenuItem ( fmt : : sprintf ( " %d. %s##_SYSR%d " , i + 1 , getSystemName ( e - > song . system [ i ] ) , i ) . c_str ( ) ) ) {
if ( ! e - > removeSystem ( i , preserveChanPos ) ) {
showError ( " cannot remove chip! ( " + e - > getLastError ( ) + " ) " ) ;
} else {
MARK_MODIFIED ;
}
if ( e - > song . autoSystem ) {
autoDetectSystem ( ) ;
updateWindowTitle ( ) ;
}
2023-02-24 08:47:53 +00:00
}
}
2023-08-28 22:00:39 +00:00
ImGui : : EndMenu ( ) ;
2023-02-24 08:47:53 +00:00
}
2022-05-18 23:42:59 +00:00
}
2023-05-24 06:58:12 +00:00
ImGui : : BeginDisabled ( exitDisabledTimer ) ;
2022-05-18 23:42:59 +00:00
ImGui : : Separator ( ) ;
if ( ImGui : : MenuItem ( " restore backup " , BIND_FOR ( GUI_ACTION_OPEN_BACKUP ) ) ) {
doAction ( GUI_ACTION_OPEN_BACKUP ) ;
}
ImGui : : Separator ( ) ;
if ( ImGui : : MenuItem ( " exit " ) ) {
if ( modified ) {
showWarning ( " Unsaved changes! Save before quitting? " , GUI_WARN_QUIT ) ;
} else {
quit = true ;
}
2022-01-09 21:36:47 +00:00
}
2023-05-24 06:58:12 +00:00
ImGui : : EndDisabled ( ) ;
2021-12-18 03:14:41 +00:00
ImGui : : EndMenu ( ) ;
2023-05-24 06:58:12 +00:00
} else {
exitDisabledTimer = 0 ;
2021-12-18 03:14:41 +00:00
}
2023-08-10 03:47:06 +00:00
if ( ImGui : : BeginMenu ( settings . capitalMenuBar ? " Edit " : " edit " ) ) {
2022-06-06 23:04:19 +00:00
ImGui : : Text ( " ... " ) ;
ImGui : : Separator ( ) ;
2022-05-18 23:42:59 +00:00
if ( ImGui : : MenuItem ( " undo " , BIND_FOR ( GUI_ACTION_UNDO ) ) ) doUndo ( ) ;
if ( ImGui : : MenuItem ( " redo " , BIND_FOR ( GUI_ACTION_REDO ) ) ) doRedo ( ) ;
ImGui : : Separator ( ) ;
editOptions ( true ) ;
ImGui : : Separator ( ) ;
if ( ImGui : : MenuItem ( " clear... " ) ) {
2022-12-11 17:36:41 +00:00
doAction ( GUI_ACTION_CLEAR ) ;
2022-05-18 23:42:59 +00:00
}
ImGui : : EndMenu ( ) ;
2022-03-21 19:32:33 +00:00
}
2023-08-10 03:47:06 +00:00
if ( ImGui : : BeginMenu ( settings . capitalMenuBar ? " Settings " : " settings " ) ) {
2022-05-18 23:42:59 +00:00
# ifndef IS_MOBILE
if ( ImGui : : MenuItem ( " full screen " , BIND_FOR ( GUI_ACTION_FULLSCREEN ) , fullScreen ) ) {
doAction ( GUI_ACTION_FULLSCREEN ) ;
}
# endif
2022-05-22 23:20:53 +00:00
if ( ImGui : : MenuItem ( " lock layout " , NULL , lockLayout ) ) {
2022-05-18 23:42:59 +00:00
lockLayout = ! lockLayout ;
2021-12-30 23:52:36 +00:00
}
2023-02-06 23:52:51 +00:00
if ( ImGui : : MenuItem ( " basic mode " , NULL , basicMode ) ) {
if ( basicMode ) {
showWarning ( " prepare to unlock the full power of Furnace! " , GUI_WARN_BASIC_MODE ) ;
} else {
showWarning ( " are you sure? this will disable several things. " , GUI_WARN_BASIC_MODE ) ;
}
}
2022-05-18 23:42:59 +00:00
if ( ImGui : : MenuItem ( " visualizer " , NULL , fancyPattern ) ) {
fancyPattern = ! fancyPattern ;
e - > enableCommandStream ( fancyPattern ) ;
e - > getCommandStream ( cmdStream ) ;
cmdStream . clear ( ) ;
}
if ( ImGui : : MenuItem ( " reset layout " ) ) {
showWarning ( " Are you sure you want to reset the workspace layout? " , GUI_WARN_RESET_LAYOUT ) ;
}
2022-09-10 00:23:53 +00:00
# ifdef IS_MOBILE
if ( ImGui : : MenuItem ( " switch to mobile view " ) ) {
toggleMobileUI ( ! mobileUI ) ;
}
# endif
2022-05-18 23:42:59 +00:00
if ( ImGui : : MenuItem ( " settings... " , BIND_FOR ( GUI_ACTION_WINDOW_SETTINGS ) ) ) {
syncSettings ( ) ;
settingsOpen = true ;
}
ImGui : : EndMenu ( ) ;
2021-12-14 09:45:44 +00:00
}
2023-08-10 03:47:06 +00:00
if ( ImGui : : BeginMenu ( settings . capitalMenuBar ? " Window " : " window " ) ) {
2022-05-18 23:42:59 +00:00
if ( ImGui : : MenuItem ( " song information " , BIND_FOR ( GUI_ACTION_WINDOW_SONG_INFO ) , songInfoOpen ) ) songInfoOpen = ! songInfoOpen ;
if ( ImGui : : MenuItem ( " subsongs " , BIND_FOR ( GUI_ACTION_WINDOW_SUBSONGS ) , subSongsOpen ) ) subSongsOpen = ! subSongsOpen ;
2023-02-04 22:01:32 +00:00
if ( ImGui : : MenuItem ( " speed " , BIND_FOR ( GUI_ACTION_WINDOW_SPEED ) , speedOpen ) ) speedOpen = ! speedOpen ;
2022-05-29 07:59:11 +00:00
if ( settings . unifiedDataView ) {
if ( ImGui : : MenuItem ( " assets " , BIND_FOR ( GUI_ACTION_WINDOW_INS_LIST ) , insListOpen ) ) insListOpen = ! insListOpen ;
} else {
if ( ImGui : : MenuItem ( " instruments " , BIND_FOR ( GUI_ACTION_WINDOW_INS_LIST ) , insListOpen ) ) insListOpen = ! insListOpen ;
if ( ImGui : : MenuItem ( " wavetables " , BIND_FOR ( GUI_ACTION_WINDOW_WAVE_LIST ) , waveListOpen ) ) waveListOpen = ! waveListOpen ;
if ( ImGui : : MenuItem ( " samples " , BIND_FOR ( GUI_ACTION_WINDOW_SAMPLE_LIST ) , sampleListOpen ) ) sampleListOpen = ! sampleListOpen ;
}
2022-05-18 23:42:59 +00:00
if ( ImGui : : MenuItem ( " orders " , BIND_FOR ( GUI_ACTION_WINDOW_ORDERS ) , ordersOpen ) ) ordersOpen = ! ordersOpen ;
if ( ImGui : : MenuItem ( " pattern " , BIND_FOR ( GUI_ACTION_WINDOW_PATTERN ) , patternOpen ) ) patternOpen = ! patternOpen ;
2023-02-24 08:47:53 +00:00
if ( ImGui : : MenuItem ( " mixer " , BIND_FOR ( GUI_ACTION_WINDOW_MIXER ) , mixerOpen ) ) mixerOpen = ! mixerOpen ;
2023-02-06 23:52:51 +00:00
if ( ! basicMode ) {
if ( ImGui : : MenuItem ( " grooves " , BIND_FOR ( GUI_ACTION_WINDOW_GROOVES ) , groovesOpen ) ) groovesOpen = ! groovesOpen ;
if ( ImGui : : MenuItem ( " channels " , BIND_FOR ( GUI_ACTION_WINDOW_CHANNELS ) , channelsOpen ) ) channelsOpen = ! channelsOpen ;
2023-02-24 08:47:53 +00:00
}
if ( ImGui : : MenuItem ( " pattern manager " , BIND_FOR ( GUI_ACTION_WINDOW_PAT_MANAGER ) , patManagerOpen ) ) patManagerOpen = ! patManagerOpen ;
if ( ! basicMode ) {
2023-02-06 23:52:51 +00:00
if ( ImGui : : MenuItem ( " chip manager " , BIND_FOR ( GUI_ACTION_WINDOW_SYS_MANAGER ) , sysManagerOpen ) ) sysManagerOpen = ! sysManagerOpen ;
if ( ImGui : : MenuItem ( " compatibility flags " , BIND_FOR ( GUI_ACTION_WINDOW_COMPAT_FLAGS ) , compatFlagsOpen ) ) compatFlagsOpen = ! compatFlagsOpen ;
}
2022-05-18 23:42:59 +00:00
if ( ImGui : : MenuItem ( " song comments " , BIND_FOR ( GUI_ACTION_WINDOW_NOTES ) , notesOpen ) ) notesOpen = ! notesOpen ;
ImGui : : Separator ( ) ;
if ( ImGui : : MenuItem ( " instrument editor " , BIND_FOR ( GUI_ACTION_WINDOW_INS_EDIT ) , insEditOpen ) ) insEditOpen = ! insEditOpen ;
if ( ImGui : : MenuItem ( " wavetable editor " , BIND_FOR ( GUI_ACTION_WINDOW_WAVE_EDIT ) , waveEditOpen ) ) waveEditOpen = ! waveEditOpen ;
if ( ImGui : : MenuItem ( " sample editor " , BIND_FOR ( GUI_ACTION_WINDOW_SAMPLE_EDIT ) , sampleEditOpen ) ) sampleEditOpen = ! sampleEditOpen ;
ImGui : : Separator ( ) ;
if ( ImGui : : MenuItem ( " play/edit controls " , BIND_FOR ( GUI_ACTION_WINDOW_EDIT_CONTROLS ) , editControlsOpen ) ) editControlsOpen = ! editControlsOpen ;
if ( ImGui : : MenuItem ( " piano/input pad " , BIND_FOR ( GUI_ACTION_WINDOW_PIANO ) , pianoOpen ) ) pianoOpen = ! pianoOpen ;
if ( ImGui : : MenuItem ( " oscilloscope (master) " , BIND_FOR ( GUI_ACTION_WINDOW_OSCILLOSCOPE ) , oscOpen ) ) oscOpen = ! oscOpen ;
if ( ImGui : : MenuItem ( " oscilloscope (per-channel) " , BIND_FOR ( GUI_ACTION_WINDOW_CHAN_OSC ) , chanOscOpen ) ) chanOscOpen = ! chanOscOpen ;
if ( ImGui : : MenuItem ( " volume meter " , BIND_FOR ( GUI_ACTION_WINDOW_VOL_METER ) , volMeterOpen ) ) volMeterOpen = ! volMeterOpen ;
2022-11-10 06:26:59 +00:00
if ( ImGui : : MenuItem ( " clock " , BIND_FOR ( GUI_ACTION_WINDOW_CLOCK ) , clockOpen ) ) clockOpen = ! clockOpen ;
2022-05-18 23:42:59 +00:00
if ( ImGui : : MenuItem ( " register view " , BIND_FOR ( GUI_ACTION_WINDOW_REGISTER_VIEW ) , regViewOpen ) ) regViewOpen = ! regViewOpen ;
if ( ImGui : : MenuItem ( " log viewer " , BIND_FOR ( GUI_ACTION_WINDOW_LOG ) , logOpen ) ) logOpen = ! logOpen ;
if ( ImGui : : MenuItem ( " statistics " , BIND_FOR ( GUI_ACTION_WINDOW_STATS ) , statsOpen ) ) statsOpen = ! statsOpen ;
2022-06-20 20:20:02 +00:00
if ( spoilerOpen ) if ( ImGui : : MenuItem ( " spoiler " , NULL , spoilerOpen ) ) spoilerOpen = ! spoilerOpen ;
2022-08-16 16:24:18 +00:00
2022-05-18 23:42:59 +00:00
ImGui : : EndMenu ( ) ;
2022-04-24 21:57:58 +00:00
}
2023-08-10 03:47:06 +00:00
if ( ImGui : : BeginMenu ( settings . capitalMenuBar ? " Help " : " help " ) ) {
2022-05-18 23:42:59 +00:00
if ( ImGui : : MenuItem ( " effect list " , BIND_FOR ( GUI_ACTION_WINDOW_EFFECT_LIST ) , effectListOpen ) ) effectListOpen = ! effectListOpen ;
if ( ImGui : : MenuItem ( " debug menu " , BIND_FOR ( GUI_ACTION_WINDOW_DEBUG ) ) ) debugOpen = ! debugOpen ;
2023-08-30 18:12:25 +00:00
if ( ImGui : : MenuItem ( " inspector " ) ) inspectorOpen = ! inspectorOpen ;
2023-04-02 07:31:37 +00:00
if ( ImGui : : MenuItem ( " panic " , BIND_FOR ( GUI_ACTION_PANIC ) ) ) e - > syncReset ( ) ;
2022-05-18 23:42:59 +00:00
if ( ImGui : : MenuItem ( " about... " , BIND_FOR ( GUI_ACTION_WINDOW_ABOUT ) ) ) {
aboutOpen = true ;
aboutScroll = 0 ;
}
ImGui : : EndMenu ( ) ;
2022-04-17 06:54:42 +00:00
}
2022-05-18 23:42:59 +00:00
ImGui : : PushStyleColor ( ImGuiCol_Text , uiColors [ GUI_COLOR_PLAYBACK_STAT ] ) ;
if ( e - > isPlaying ( ) ) {
int totalTicks = e - > getTotalTicks ( ) ;
int totalSeconds = e - > getTotalSeconds ( ) ;
2023-02-05 07:56:39 +00:00
String info ;
DivGroovePattern gp = e - > getSpeeds ( ) ;
if ( gp . len = = 2 ) {
info = fmt : : sprintf ( " | Speed %d:%d " , gp . val [ 0 ] , gp . val [ 1 ] ) ;
} else if ( gp . len = = 1 ) {
info = fmt : : sprintf ( " | Speed %d " , gp . val [ 0 ] ) ;
} else {
info = " | Groove " ;
}
info + = fmt : : sprintf ( " @ %gHz (%g BPM) | Order %d/%d | Row %d/%d | %d:%.2d:%.2d.%.2d " , e - > getCurHz ( ) , calcBPM ( e - > getSpeeds ( ) , e - > getCurHz ( ) , e - > curSubSong - > virtualTempoN , e - > curSubSong - > virtualTempoD ) , e - > getOrder ( ) , e - > curSubSong - > ordersLen , e - > getRow ( ) , e - > curSubSong - > patLen , totalSeconds / 3600 , ( totalSeconds / 60 ) % 60 , totalSeconds % 60 , totalTicks / 10000 ) ;
ImGui : : TextUnformatted ( info . c_str ( ) ) ;
2022-05-18 23:42:59 +00:00
} else {
bool hasInfo = false ;
String info ;
if ( cursor . xCoarse > = 0 & & cursor . xCoarse < e - > getTotalChannelCount ( ) ) {
DivPattern * p = e - > curPat [ cursor . xCoarse ] . getPattern ( e - > curOrders - > ord [ cursor . xCoarse ] [ curOrder ] , false ) ;
if ( cursor . xFine > = 0 ) switch ( cursor . xFine ) {
case 0 : // note
if ( p - > data [ cursor . y ] [ 0 ] > 0 ) {
if ( p - > data [ cursor . y ] [ 0 ] = = 100 ) {
info = fmt : : sprintf ( " Note off (cut) " ) ;
} else if ( p - > data [ cursor . y ] [ 0 ] = = 101 ) {
info = fmt : : sprintf ( " Note off (release) " ) ;
} else if ( p - > data [ cursor . y ] [ 0 ] = = 102 ) {
info = fmt : : sprintf ( " Macro release only " ) ;
} else {
info = fmt : : sprintf ( " Note on: %s " , noteName ( p - > data [ cursor . y ] [ 0 ] , p - > data [ cursor . y ] [ 1 ] ) ) ;
}
hasInfo = true ;
2022-02-15 06:46:03 +00:00
}
2022-05-18 23:42:59 +00:00
break ;
case 1 : // instrument
if ( p - > data [ cursor . y ] [ 2 ] > - 1 ) {
if ( p - > data [ cursor . y ] [ 2 ] > = ( int ) e - > song . ins . size ( ) ) {
info = fmt : : sprintf ( " Ins %d: <invalid> " , p - > data [ cursor . y ] [ 2 ] ) ;
} else {
DivInstrument * ins = e - > getIns ( p - > data [ cursor . y ] [ 2 ] ) ;
info = fmt : : sprintf ( " Ins %d: %s " , p - > data [ cursor . y ] [ 2 ] , ins - > name ) ;
}
hasInfo = true ;
2022-02-15 06:46:03 +00:00
}
2022-05-18 23:42:59 +00:00
break ;
case 2 : // volume
if ( p - > data [ cursor . y ] [ 3 ] > - 1 ) {
int maxVol = e - > getMaxVolumeChan ( cursor . xCoarse ) ;
if ( maxVol < 1 | | p - > data [ cursor . y ] [ 3 ] > maxVol ) {
info = fmt : : sprintf ( " Set volume: %d (%.2X, INVALID!) " , p - > data [ cursor . y ] [ 3 ] , p - > data [ cursor . y ] [ 3 ] ) ;
} else {
info = fmt : : sprintf ( " Set volume: %d (%.2X, %d%%) " , p - > data [ cursor . y ] [ 3 ] , p - > data [ cursor . y ] [ 3 ] , ( p - > data [ cursor . y ] [ 3 ] * 100 ) / maxVol ) ;
}
hasInfo = true ;
2022-02-15 06:46:03 +00:00
}
2022-05-18 23:42:59 +00:00
break ;
default : // effect
int actualCursor = ( ( cursor . xFine + 1 ) & ( ~ 1 ) ) ;
if ( p - > data [ cursor . y ] [ actualCursor ] > - 1 ) {
info = e - > getEffectDesc ( p - > data [ cursor . y ] [ actualCursor ] , cursor . xCoarse , true ) ;
hasInfo = true ;
}
break ;
}
}
if ( hasInfo & & ( settings . statusDisplay = = 0 | | settings . statusDisplay = = 2 ) ) {
ImGui : : Text ( " | %s " , info . c_str ( ) ) ;
} else if ( settings . statusDisplay = = 1 | | settings . statusDisplay = = 2 ) {
if ( curFileName ! = " " ) ImGui : : Text ( " | %s " , curFileName . c_str ( ) ) ;
2022-02-15 06:46:03 +00:00
}
}
2022-05-18 23:42:59 +00:00
ImGui : : PopStyleColor ( ) ;
if ( modified ) {
ImGui : : Text ( " | modified " ) ;
}
ImGui : : EndMainMenuBar ( ) ;
}
2023-04-14 00:43:48 +00:00
MEASURE ( calcChanOsc , calcChanOsc ( ) ) ;
2022-09-20 07:32:23 +00:00
2023-08-12 00:26:42 +00:00
if ( followPattern ) {
curOrder = e - > getOrder ( ) ;
}
2022-05-18 23:42:59 +00:00
if ( mobileUI ) {
2022-05-26 18:28:18 +00:00
globalWinFlags = ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoBringToFrontOnFocus ;
2022-09-09 00:15:19 +00:00
//globalWinFlags=ImGuiWindowFlags_NoTitleBar;
2022-09-09 04:20:33 +00:00
// scene handling goes here!
2023-04-14 00:43:48 +00:00
MEASURE ( mobileControls , drawMobileControls ( ) ) ;
2022-09-09 20:31:29 +00:00
switch ( mobScene ) {
case GUI_SCENE_ORDERS :
ordersOpen = true ;
2022-09-09 23:53:20 +00:00
curWindow = GUI_WINDOW_ORDERS ;
2023-04-14 00:43:48 +00:00
MEASURE ( orders , drawOrders ( ) ) ;
2022-09-09 20:31:29 +00:00
break ;
case GUI_SCENE_INSTRUMENT :
insEditOpen = true ;
2022-09-09 23:53:20 +00:00
curWindow = GUI_WINDOW_INS_EDIT ;
2023-04-14 00:43:48 +00:00
MEASURE ( insEdit , drawInsEdit ( ) ) ;
MEASURE ( piano , drawPiano ( ) ) ;
2022-09-09 20:31:29 +00:00
break ;
case GUI_SCENE_WAVETABLE :
waveEditOpen = true ;
2022-09-09 23:53:20 +00:00
curWindow = GUI_WINDOW_WAVE_EDIT ;
2023-04-14 00:43:48 +00:00
MEASURE ( waveEdit , drawWaveEdit ( ) ) ;
MEASURE ( piano , drawPiano ( ) ) ;
2022-09-09 20:31:29 +00:00
break ;
case GUI_SCENE_SAMPLE :
sampleEditOpen = true ;
2022-09-09 23:53:20 +00:00
curWindow = GUI_WINDOW_SAMPLE_EDIT ;
2023-04-14 00:43:48 +00:00
MEASURE ( sampleEdit , drawSampleEdit ( ) ) ;
MEASURE ( piano , drawPiano ( ) ) ;
2022-09-09 20:31:29 +00:00
break ;
2022-12-01 23:41:04 +00:00
case GUI_SCENE_CHANNELS :
channelsOpen = true ;
curWindow = GUI_WINDOW_CHANNELS ;
2023-04-14 00:43:48 +00:00
MEASURE ( channels , drawChannels ( ) ) ;
2022-12-01 23:41:04 +00:00
break ;
2022-11-29 21:09:50 +00:00
case GUI_SCENE_CHIPS :
sysManagerOpen = true ;
curWindow = GUI_WINDOW_SYS_MANAGER ;
2023-04-14 00:43:48 +00:00
MEASURE ( sysManager , drawSysManager ( ) ) ;
2022-11-29 21:09:50 +00:00
break ;
2023-01-07 21:26:36 +00:00
case GUI_SCENE_MIXER :
mixerOpen = true ;
curWindow = GUI_WINDOW_MIXER ;
2023-04-14 00:43:48 +00:00
MEASURE ( mixer , drawMixer ( ) ) ;
2023-01-07 21:26:36 +00:00
break ;
2022-09-10 00:23:53 +00:00
default :
patternOpen = true ;
curWindow = GUI_WINDOW_PATTERN ;
2023-04-14 00:43:48 +00:00
MEASURE ( pattern , drawPattern ( ) ) ;
MEASURE ( piano , drawPiano ( ) ) ;
MEASURE ( mobileOrderSel , drawMobileOrderSel ( ) ) ;
2022-12-11 18:34:58 +00:00
globalWinFlags = 0 ;
2023-04-14 00:43:48 +00:00
MEASURE ( findReplace , drawFindReplace ( ) ) ;
2022-09-10 00:23:53 +00:00
break ;
2022-09-09 20:31:29 +00:00
}
2022-11-05 23:17:54 +00:00
globalWinFlags = 0 ;
2023-04-14 00:43:48 +00:00
MEASURE ( settings , drawSettings ( ) ) ;
MEASURE ( debug , drawDebug ( ) ) ;
MEASURE ( log , drawLog ( ) ) ;
MEASURE ( compatFlags , drawCompatFlags ( ) ) ;
MEASURE ( stats , drawStats ( ) ) ;
2023-06-06 21:24:15 +00:00
MEASURE ( chanOsc , drawChanOsc ( ) ) ;
2023-08-29 21:43:37 +00:00
MEASURE ( regView , drawRegView ( ) ) ;
2022-05-18 23:42:59 +00:00
} else {
2022-05-24 07:38:10 +00:00
globalWinFlags = 0 ;
ImGui : : DockSpaceOverViewport ( NULL , lockLayout ? ( ImGuiDockNodeFlags_NoWindowMenuButton | ImGuiDockNodeFlags_NoMove | ImGuiDockNodeFlags_NoResize | ImGuiDockNodeFlags_NoCloseButton | ImGuiDockNodeFlags_NoDocking | ImGuiDockNodeFlags_NoDockingSplitMe | ImGuiDockNodeFlags_NoDockingSplitOther ) : 0 ) ;
2022-05-19 21:35:00 +00:00
2023-04-14 00:43:48 +00:00
MEASURE ( subSongs , drawSubSongs ( ) ) ;
MEASURE ( findReplace , drawFindReplace ( ) ) ;
MEASURE ( spoiler , drawSpoiler ( ) ) ;
MEASURE ( pattern , drawPattern ( ) ) ;
MEASURE ( editControls , drawEditControls ( ) ) ;
MEASURE ( speed , drawSpeed ( ) ) ;
if ( ! basicMode ) {
MEASURE ( grooves , drawGrooves ( ) ) ;
}
MEASURE ( songInfo , drawSongInfo ( ) ) ;
MEASURE ( orders , drawOrders ( ) ) ;
MEASURE ( sampleList , drawSampleList ( ) ) ;
MEASURE ( sampleEdit , drawSampleEdit ( ) ) ;
MEASURE ( waveList , drawWaveList ( ) ) ;
MEASURE ( waveEdit , drawWaveEdit ( ) ) ;
MEASURE ( insList , drawInsList ( ) ) ;
MEASURE ( insEdit , drawInsEdit ( ) ) ;
MEASURE ( mixer , drawMixer ( ) ) ;
MEASURE ( readOsc , readOsc ( ) ) ;
MEASURE ( osc , drawOsc ( ) ) ;
MEASURE ( chanOsc , drawChanOsc ( ) ) ;
MEASURE ( volMeter , drawVolMeter ( ) ) ;
MEASURE ( settings , drawSettings ( ) ) ;
MEASURE ( debug , drawDebug ( ) ) ;
MEASURE ( stats , drawStats ( ) ) ;
2023-02-06 23:52:51 +00:00
if ( ! basicMode ) {
2023-04-14 00:43:48 +00:00
MEASURE ( compatFlags , drawCompatFlags ( ) ) ;
2023-02-24 08:47:53 +00:00
}
2023-04-14 00:43:48 +00:00
MEASURE ( piano , drawPiano ( ) ) ;
MEASURE ( notes , drawNotes ( ) ) ;
2023-02-24 08:47:53 +00:00
if ( ! basicMode ) {
2023-04-14 00:43:48 +00:00
MEASURE ( channels , drawChannels ( ) ) ;
2023-02-06 23:52:51 +00:00
}
2023-04-14 00:43:48 +00:00
MEASURE ( patManager , drawPatManager ( ) ) ;
if ( ! basicMode ) {
MEASURE ( sysManager , drawSysManager ( ) ) ;
}
MEASURE ( clock , drawClock ( ) ) ;
MEASURE ( regView , drawRegView ( ) ) ;
MEASURE ( log , drawLog ( ) ) ;
MEASURE ( effectList , drawEffectList ( ) ) ;
2021-12-30 23:25:55 +00:00
}
2021-12-12 09:21:09 +00:00
2023-07-27 05:04:48 +00:00
// release selection if mouse released
if ( ImGui : : IsMouseReleased ( ImGuiMouseButton_Left ) & & selecting ) {
if ( ! selectingFull ) cursor = selEnd ;
finishSelection ( ) ;
if ( ! mobileUI ) {
demandScrollX = true ;
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 ) {
if ( ! settings . cursorMoveNoScroll ) {
updateScroll ( cursor . y ) ;
}
}
}
2021-12-30 23:25:55 +00:00
}
2021-12-12 09:21:09 +00:00
2023-08-02 01:22:44 +00:00
for ( int i = 0 ; i < e - > getTotalChannelCount ( ) ; i + + ) {
keyHit1 [ i ] - = 0.2f ;
if ( keyHit1 [ i ] < 0.0f ) keyHit1 [ i ] = 0.0f ;
}
2023-02-26 09:21:27 +00:00
activateTutorial ( GUI_TUTORIAL_OVERVIEW ) ;
2022-03-21 05:52:38 +00:00
if ( inspectorOpen ) ImGui : : ShowMetricsWindow ( & inspectorOpen ) ;
2022-03-18 04:28:01 +00:00
2022-03-11 03:10:52 +00:00
if ( firstFrame ) {
firstFrame = false ;
2022-09-09 20:31:29 +00:00
# ifdef IS_MOBILE
SDL_GetWindowSize ( sdlWin , & scrW , & scrH ) ;
portrait = ( scrW < scrH ) ;
logV ( " portrait: %d (%dx%d) " , portrait , scrW , scrH ) ;
2022-10-20 07:34:14 +00:00
2023-06-03 01:21:37 +00:00
rend - > getOutputSize ( canvasW , canvasH ) ;
2022-09-09 20:31:29 +00:00
# endif
2022-03-11 03:10:52 +00:00
if ( patternOpen ) nextWindow = GUI_WINDOW_PATTERN ;
2022-03-22 20:37:36 +00:00
# ifdef __APPLE__
SDL_RaiseWindow ( sdlWin ) ;
# endif
2022-03-11 03:10:52 +00:00
}
2022-06-19 23:51:51 +00:00
# ifndef NFD_NON_THREADED
2022-04-30 07:02:55 +00:00
if ( fileDialog - > isOpen ( ) & & settings . sysFileDialog ) {
ImGui : : OpenPopup ( " System File Dialog Pending " ) ;
}
if ( ImGui : : BeginPopupModal ( " System File Dialog Pending " , NULL , ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoBackground | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove ) ) {
if ( ! fileDialog - > isOpen ( ) ) {
ImGui : : CloseCurrentPopup ( ) ;
}
ImDrawList * dl = ImGui : : GetForegroundDrawList ( ) ;
2022-10-20 07:34:14 +00:00
dl - > AddRectFilled ( ImVec2 ( 0.0f , 0.0f ) , ImVec2 ( canvasW , canvasH ) , ImGui : : ColorConvertFloat4ToU32 ( uiColors [ GUI_COLOR_MODAL_BACKDROP ] ) ) ;
2022-04-30 07:02:55 +00:00
ImGui : : EndPopup ( ) ;
}
2022-06-19 23:51:51 +00:00
# endif
2022-04-30 07:02:55 +00:00
2022-11-05 23:49:54 +00:00
if ( fileDialog - > render ( mobileUI ? ImVec2 ( canvasW - ( portrait ? 0 : ( 60.0 * dpiScale ) ) , canvasH - 60.0 * dpiScale ) : ImVec2 ( 600.0f * dpiScale , 400.0f * dpiScale ) , ImVec2 ( canvasW - ( ( mobileUI & & ! portrait ) ? ( 60.0 * dpiScale ) : 0 ) , canvasH - ( mobileUI ? ( 60.0 * dpiScale ) : 0 ) ) ) ) {
2022-04-13 07:09:59 +00:00
bool openOpen = false ;
2022-02-01 07:52:36 +00:00
//ImGui::GetIO().ConfigFlags&=~ImGuiConfigFlags_NavEnableKeyboard;
2022-05-05 03:55:11 +00:00
if ( ( curFileDialog = = GUI_FILE_INS_OPEN | | curFileDialog = = GUI_FILE_INS_OPEN_REPLACE ) & & prevIns ! = - 3 ) {
if ( curFileDialog = = GUI_FILE_INS_OPEN_REPLACE ) {
if ( prevInsData ! = NULL ) {
if ( prevIns > = 0 & & prevIns < ( int ) e - > song . ins . size ( ) ) {
* e - > song . ins [ prevIns ] = * prevInsData ;
}
}
} else {
curIns = prevIns ;
2022-05-21 23:36:15 +00:00
wavePreviewInit = true ;
2023-03-18 09:22:50 +00:00
updateFMPreview = true ;
2022-05-05 03:55:11 +00:00
}
2022-04-29 09:34:20 +00:00
prevIns = - 3 ;
}
2022-03-02 05:02:52 +00:00
switch ( curFileDialog ) {
case GUI_FILE_OPEN :
case GUI_FILE_SAVE :
2022-09-04 07:26:29 +00:00
case GUI_FILE_SAVE_DMF :
2022-03-02 05:02:52 +00:00
case GUI_FILE_SAVE_DMF_LEGACY :
2022-03-13 23:32:35 +00:00
workingDirSong = fileDialog - > getPath ( ) + DIR_SEPARATOR_STR ;
2022-03-02 05:02:52 +00:00
break ;
case GUI_FILE_INS_OPEN :
2022-05-05 03:55:11 +00:00
case GUI_FILE_INS_OPEN_REPLACE :
2022-03-02 05:02:52 +00:00
case GUI_FILE_INS_SAVE :
2022-09-04 07:26:29 +00:00
case GUI_FILE_INS_SAVE_DMP :
2022-03-13 23:32:35 +00:00
workingDirIns = fileDialog - > getPath ( ) + DIR_SEPARATOR_STR ;
2022-03-02 05:02:52 +00:00
break ;
case GUI_FILE_WAVE_OPEN :
2022-08-13 09:17:32 +00:00
case GUI_FILE_WAVE_OPEN_REPLACE :
2022-03-02 05:02:52 +00:00
case GUI_FILE_WAVE_SAVE :
2022-09-04 07:26:29 +00:00
case GUI_FILE_WAVE_SAVE_DMW :
case GUI_FILE_WAVE_SAVE_RAW :
2022-03-13 23:32:35 +00:00
workingDirWave = fileDialog - > getPath ( ) + DIR_SEPARATOR_STR ;
2022-03-02 05:02:52 +00:00
break ;
case GUI_FILE_SAMPLE_OPEN :
2022-08-13 09:17:32 +00:00
case GUI_FILE_SAMPLE_OPEN_RAW :
case GUI_FILE_SAMPLE_OPEN_REPLACE :
case GUI_FILE_SAMPLE_OPEN_REPLACE_RAW :
2022-03-02 05:02:52 +00:00
case GUI_FILE_SAMPLE_SAVE :
2023-05-02 08:57:25 +00:00
case GUI_FILE_SAMPLE_SAVE_RAW :
2022-03-13 23:32:35 +00:00
workingDirSample = fileDialog - > getPath ( ) + DIR_SEPARATOR_STR ;
2022-03-02 05:02:52 +00:00
break ;
case GUI_FILE_EXPORT_AUDIO_ONE :
case GUI_FILE_EXPORT_AUDIO_PER_SYS :
case GUI_FILE_EXPORT_AUDIO_PER_CHANNEL :
2022-03-13 23:32:35 +00:00
workingDirAudioExport = fileDialog - > getPath ( ) + DIR_SEPARATOR_STR ;
2022-03-02 05:02:52 +00:00
break ;
case GUI_FILE_EXPORT_VGM :
2022-03-13 23:32:35 +00:00
workingDirVGMExport = fileDialog - > getPath ( ) + DIR_SEPARATOR_STR ;
2022-03-02 05:02:52 +00:00
break ;
2022-05-26 05:24:21 +00:00
case GUI_FILE_EXPORT_ZSM :
workingDirZSMExport = fileDialog - > getPath ( ) + DIR_SEPARATOR_STR ;
break ;
2022-08-04 05:51:47 +00:00
case GUI_FILE_EXPORT_ROM :
case GUI_FILE_EXPORT_CMDSTREAM :
2023-03-26 18:19:57 +00:00
case GUI_FILE_EXPORT_CMDSTREAM_BINARY :
2022-08-04 05:51:47 +00:00
workingDirROMExport = fileDialog - > getPath ( ) + DIR_SEPARATOR_STR ;
break ;
2022-03-02 05:02:52 +00:00
case GUI_FILE_LOAD_MAIN_FONT :
2023-08-03 03:49:01 +00:00
case GUI_FILE_LOAD_HEAD_FONT :
2022-03-02 05:02:52 +00:00
case GUI_FILE_LOAD_PAT_FONT :
2022-03-13 23:32:35 +00:00
workingDirFont = fileDialog - > getPath ( ) + DIR_SEPARATOR_STR ;
2022-03-02 05:02:52 +00:00
break ;
2022-04-06 18:53:39 +00:00
case GUI_FILE_IMPORT_COLORS :
case GUI_FILE_EXPORT_COLORS :
workingDirColors = fileDialog - > getPath ( ) + DIR_SEPARATOR_STR ;
break ;
case GUI_FILE_IMPORT_KEYBINDS :
case GUI_FILE_EXPORT_KEYBINDS :
workingDirKeybinds = fileDialog - > getPath ( ) + DIR_SEPARATOR_STR ;
break ;
case GUI_FILE_IMPORT_LAYOUT :
case GUI_FILE_EXPORT_LAYOUT :
workingDirLayout = fileDialog - > getPath ( ) + DIR_SEPARATOR_STR ;
break ;
2022-05-11 21:39:36 +00:00
case GUI_FILE_YRW801_ROM_OPEN :
case GUI_FILE_TG100_ROM_OPEN :
case GUI_FILE_MU5_ROM_OPEN :
2022-05-13 03:15:03 +00:00
workingDirROM = fileDialog - > getPath ( ) + DIR_SEPARATOR_STR ;
2022-05-11 21:39:36 +00:00
break ;
2023-03-26 23:48:16 +00:00
case GUI_FILE_CMDSTREAM_OPEN :
workingDirROM = fileDialog - > getPath ( ) + DIR_SEPARATOR_STR ;
break ;
2022-07-15 07:23:16 +00:00
case GUI_FILE_TEST_OPEN :
case GUI_FILE_TEST_OPEN_MULTI :
case GUI_FILE_TEST_SAVE :
workingDirTest = fileDialog - > getPath ( ) + DIR_SEPARATOR_STR ;
break ;
2023-04-06 20:16:52 +00:00
case GUI_FILE_OPEN_BACKUP :
break ;
2022-03-02 05:02:52 +00:00
}
2022-07-14 06:59:55 +00:00
if ( fileDialog - > isError ( ) ) {
# if defined(_WIN32) || defined(__APPLE__)
showError ( " there was an error in the file dialog! you may want to report this issue to: \n https://github.com/tildearrow/furnace/issues \n check the Log Viewer (window > log viewer) for more information. \n \n for now please disable the system file picker in Settings > General. " ) ;
2022-11-05 21:22:15 +00:00
# else
# ifdef ANDROID
showError ( " can't do anything without Storage permissions! " ) ;
2022-07-14 06:59:55 +00:00
# else
showError ( " Zenity/KDialog not available! \n please install one of these, or disable the system file picker in Settings > General. " ) ;
2022-11-05 21:22:15 +00:00
# endif
2022-07-14 06:59:55 +00:00
# endif
2022-03-02 05:02:52 +00:00
}
2022-03-13 23:32:35 +00:00
if ( fileDialog - > accepted ( ) ) {
2022-07-15 07:23:16 +00:00
if ( fileDialog - > getFileName ( ) . empty ( ) ) {
fileName = " " ;
} else {
fileName = fileDialog - > getFileName ( ) [ 0 ] ;
}
2021-12-15 05:37:27 +00:00
if ( fileName ! = " " ) {
2021-12-17 08:33:12 +00:00
if ( curFileDialog = = GUI_FILE_SAVE ) {
2022-09-04 07:26:29 +00:00
checkExtension ( " .fur " ) ;
}
if ( curFileDialog = = GUI_FILE_SAVE_DMF ) {
checkExtension ( " .dmf " ) ;
2021-12-15 05:37:27 +00:00
}
2022-02-25 07:40:30 +00:00
if ( curFileDialog = = GUI_FILE_SAVE_DMF_LEGACY ) {
checkExtension ( " .dmf " ) ;
}
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 ) {
2022-09-04 07:26:29 +00:00
checkExtension ( " .fui " ) ;
}
if ( curFileDialog = = GUI_FILE_INS_SAVE_DMP ) {
checkExtension ( " .dmp " ) ;
2022-01-21 23:17:05 +00:00
}
if ( curFileDialog = = GUI_FILE_WAVE_SAVE ) {
2022-09-04 07:26:29 +00:00
checkExtension ( " .fuw " ) ;
}
if ( curFileDialog = = GUI_FILE_WAVE_SAVE_DMW ) {
checkExtension ( " .dmw " ) ;
}
if ( curFileDialog = = GUI_FILE_WAVE_SAVE_RAW ) {
checkExtension ( " .raw " ) ;
2022-01-21 23:17:05 +00:00
}
2022-01-24 06:10:38 +00:00
if ( curFileDialog = = GUI_FILE_EXPORT_VGM ) {
checkExtension ( " .vgm " ) ;
}
2022-05-26 05:24:21 +00:00
if ( curFileDialog = = GUI_FILE_EXPORT_ZSM ) {
checkExtension ( " .zsm " ) ;
}
2022-08-04 05:51:47 +00:00
if ( curFileDialog = = GUI_FILE_EXPORT_CMDSTREAM ) {
2023-03-26 18:19:57 +00:00
checkExtension ( " .txt " ) ;
}
if ( curFileDialog = = GUI_FILE_EXPORT_CMDSTREAM_BINARY ) {
checkExtension ( " .bin " ) ;
2022-08-04 05:51:47 +00:00
}
2022-04-06 19:45:58 +00:00
if ( curFileDialog = = GUI_FILE_EXPORT_COLORS ) {
checkExtension ( " .cfgc " ) ;
}
if ( curFileDialog = = GUI_FILE_EXPORT_KEYBINDS ) {
checkExtension ( " .cfgk " ) ;
}
if ( curFileDialog = = GUI_FILE_EXPORT_LAYOUT ) {
checkExtension ( " .ini " ) ;
}
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 :
2023-04-06 20:16:52 +00:00
case GUI_FILE_OPEN_BACKUP :
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 ;
2022-03-14 04:10:43 +00:00
case GUI_FILE_SAVE : {
2022-04-13 07:09:59 +00:00
bool saveWasSuccessful = true ;
2022-09-04 07:26:29 +00:00
if ( save ( copyOfName , 0 ) > 0 ) {
showError ( fmt : : sprintf ( " Error while saving file! (%s) " , lastError ) ) ;
saveWasSuccessful = false ;
2022-02-20 08:18:20 +00:00
}
2022-04-13 07:09:59 +00:00
if ( saveWasSuccessful & & postWarnAction ! = GUI_WARN_GENERIC ) {
switch ( postWarnAction ) {
case GUI_WARN_QUIT :
quit = true ;
break ;
case GUI_WARN_NEW :
displayNew = true ;
break ;
case GUI_WARN_OPEN :
openOpen = true ;
break ;
case GUI_WARN_OPEN_DROP :
if ( load ( nextFile ) > 0 ) {
showError ( fmt : : sprintf ( " Error while loading file! (%s) " , lastError ) ) ;
}
nextFile = " " ;
break ;
case GUI_WARN_OPEN_BACKUP :
2023-04-06 20:16:52 +00:00
openFileDialog ( GUI_FILE_OPEN_BACKUP ) ;
2022-04-13 07:09:59 +00:00
break ;
default :
break ;
}
postWarnAction = GUI_WARN_GENERIC ;
} else if ( postWarnAction = = GUI_WARN_OPEN_DROP ) {
nextFile = " " ;
}
2022-02-20 08:18:20 +00:00
break ;
2022-03-14 04:10:43 +00:00
}
2022-09-04 07:26:29 +00:00
case GUI_FILE_SAVE_DMF :
logD ( " saving: %s " , copyOfName . c_str ( ) ) ;
if ( save ( copyOfName , 26 ) > 0 ) {
showError ( fmt : : sprintf ( " Error while saving file! (%s) " , lastError ) ) ;
}
break ;
2022-02-20 08:18:20 +00:00
case GUI_FILE_SAVE_DMF_LEGACY :
2022-04-11 03:12:02 +00:00
logD ( " saving: %s " , copyOfName . c_str ( ) ) ;
2022-02-20 08:18:20 +00:00
if ( save ( copyOfName , 24 ) > 0 ) {
2021-12-21 04:20:30 +00:00
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 ( ) ) {
2023-08-25 23:32:34 +00:00
if ( e - > song . ins [ curIns ] - > save ( copyOfName . c_str ( ) , false , & e - > song ) ) {
pushRecentSys ( copyOfName . c_str ( ) ) ;
}
2022-11-21 00:19:24 +00:00
}
break ;
2022-09-04 07:26:29 +00:00
case GUI_FILE_INS_SAVE_DMP :
if ( curIns > = 0 & & curIns < ( int ) e - > song . ins . size ( ) ) {
if ( ! e - > song . ins [ curIns ] - > saveDMP ( copyOfName . c_str ( ) ) ) {
showError ( " error while saving instrument! make sure your instrument is compatible. " ) ;
2023-08-25 23:32:34 +00:00
} else {
pushRecentSys ( copyOfName . c_str ( ) ) ;
2022-08-13 20:43:13 +00:00
}
2022-01-19 08:28:29 +00:00
}
break ;
2022-01-19 10:10:06 +00:00
case GUI_FILE_WAVE_SAVE :
if ( curWave > = 0 & & curWave < ( int ) e - > song . wave . size ( ) ) {
2023-08-25 23:32:34 +00:00
if ( e - > song . wave [ curWave ] - > save ( copyOfName . c_str ( ) ) ) {
pushRecentSys ( copyOfName . c_str ( ) ) ;
}
2022-09-04 07:26:29 +00:00
}
break ;
case GUI_FILE_WAVE_SAVE_DMW :
if ( curWave > = 0 & & curWave < ( int ) e - > song . wave . size ( ) ) {
2023-08-25 23:32:34 +00:00
if ( e - > song . wave [ curWave ] - > saveDMW ( copyOfName . c_str ( ) ) ) {
pushRecentSys ( copyOfName . c_str ( ) ) ;
}
2022-09-04 07:26:29 +00:00
}
break ;
case GUI_FILE_WAVE_SAVE_RAW :
if ( curWave > = 0 & & curWave < ( int ) e - > song . wave . size ( ) ) {
2023-08-25 23:32:34 +00:00
if ( e - > song . wave [ curWave ] - > saveRaw ( copyOfName . c_str ( ) ) ) {
pushRecentSys ( copyOfName . c_str ( ) ) ;
}
2022-01-19 10:10:06 +00:00
}
break ;
2022-08-13 09:17:32 +00:00
case GUI_FILE_SAMPLE_OPEN : {
2022-10-28 09:11:27 +00:00
String errs = " there were some errors while loading wavetables: \n " ;
bool warn = false ;
for ( String i : fileDialog - > getFileName ( ) ) {
DivSample * s = e - > sampleFromFile ( i . c_str ( ) ) ;
if ( s = = NULL ) {
if ( fileDialog - > getFileName ( ) . size ( ) > 1 ) {
warn = true ;
errs + = fmt : : sprintf ( " - %s: %s \n " , i , e - > getLastError ( ) ) ;
} else {
showError ( e - > getLastError ( ) ) ;
}
2022-08-13 09:17:32 +00:00
} else {
2022-10-28 09:11:27 +00:00
if ( e - > addSamplePtr ( s ) = = - 1 ) {
if ( fileDialog - > getFileName ( ) . size ( ) > 1 ) {
warn = true ;
errs + = fmt : : sprintf ( " - %s: %s \n " , i , e - > getLastError ( ) ) ;
} else {
showError ( e - > getLastError ( ) ) ;
}
} else {
MARK_MODIFIED ;
}
2022-08-13 09:17:32 +00:00
}
2022-01-19 10:10:06 +00:00
}
2022-10-28 09:11:27 +00:00
if ( warn ) {
showWarning ( errs , GUI_WARN_GENERIC ) ;
}
2022-01-19 10:10:06 +00:00
break ;
2022-08-13 09:17:32 +00:00
}
case GUI_FILE_SAMPLE_OPEN_REPLACE : {
DivSample * s = e - > sampleFromFile ( copyOfName . c_str ( ) ) ;
if ( s = = NULL ) {
2022-03-23 21:39:08 +00:00
showError ( e - > getLastError ( ) ) ;
} else {
2022-08-13 09:17:32 +00:00
if ( curSample > = 0 & & curSample < ( int ) e - > song . sample . size ( ) ) {
e - > lockEngine ( [ this , s ] ( ) {
// if it crashes here please tell me...
DivSample * oldSample = e - > song . sample [ curSample ] ;
e - > song . sample [ curSample ] = s ;
delete oldSample ;
e - > renderSamples ( ) ;
MARK_MODIFIED ;
} ) ;
} else {
showError ( " ...but you haven't selected a sample! " ) ;
delete s ;
}
2022-03-23 21:39:08 +00:00
}
2021-12-17 08:33:12 +00:00
break ;
2022-08-13 09:17:32 +00:00
}
case GUI_FILE_SAMPLE_OPEN_RAW :
case GUI_FILE_SAMPLE_OPEN_REPLACE_RAW :
pendingRawSample = copyOfName ;
2023-07-17 21:31:55 +00:00
pendingRawSampleReplace = ( curFileDialog = = GUI_FILE_SAMPLE_OPEN_REPLACE_RAW ) ;
2022-08-13 09:17:32 +00:00
displayPendingRawSample = true ;
break ;
2021-12-17 08:33:12 +00:00
case GUI_FILE_SAMPLE_SAVE :
2021-12-18 06:03:59 +00:00
if ( curSample > = 0 & & curSample < ( int ) e - > song . sample . size ( ) ) {
2023-05-02 08:57:25 +00:00
if ( ! e - > song . sample [ curSample ] - > save ( copyOfName . c_str ( ) ) ) {
showError ( " could not save sample! open Log Viewer for more information. " ) ;
2023-08-25 23:32:34 +00:00
} else {
pushRecentSys ( copyOfName . c_str ( ) ) ;
2023-05-02 08:57:25 +00:00
}
}
break ;
case GUI_FILE_SAMPLE_SAVE_RAW :
if ( curSample > = 0 & & curSample < ( int ) e - > song . sample . size ( ) ) {
if ( ! e - > song . sample [ curSample ] - > saveRaw ( copyOfName . c_str ( ) ) ) {
showError ( " could not save sample! open Log Viewer for more information. " ) ;
2023-08-25 23:32:34 +00:00
} else {
pushRecentSys ( copyOfName . c_str ( ) ) ;
2023-05-02 08:57:25 +00:00
}
2021-12-18 06:03:59 +00:00
}
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-04-03 06:56:49 +00:00
case GUI_FILE_INS_OPEN : {
2022-10-28 08:44:17 +00:00
std : : vector < DivInstrument * > instruments ;
bool ask = false ;
bool warn = false ;
String warns = " there were some warnings/errors while loading instruments: \n " ;
2022-11-21 07:55:12 +00:00
int sampleCountBefore = e - > song . sampleLen ;
2022-10-28 08:44:17 +00:00
for ( String i : fileDialog - > getFileName ( ) ) {
std : : vector < DivInstrument * > insTemp = e - > instrumentFromFile ( i . c_str ( ) ) ;
if ( insTemp . empty ( ) ) {
warn = true ;
warns + = fmt : : sprintf ( " > %s: cannot load instrument! (%s) \n " , i , e - > getLastError ( ) ) ;
} else if ( ! e - > getWarnings ( ) . empty ( ) ) {
warn = true ;
warns + = fmt : : sprintf ( " > %s: \n %s \n " , i , e - > getWarnings ( ) ) ;
2022-01-29 09:25:28 +00:00
}
2022-10-28 08:44:17 +00:00
if ( insTemp . size ( ) > 1 ) ask = true ;
for ( DivInstrument * j : insTemp ) {
instruments . push_back ( j ) ;
}
}
2022-11-21 07:55:12 +00:00
if ( e - > song . sampleLen ! = sampleCountBefore ) {
e - > renderSamplesP ( ) ;
}
2022-10-28 08:44:17 +00:00
if ( warn ) {
if ( instruments . empty ( ) ) {
if ( fileDialog - > getFileName ( ) . size ( ) > 1 ) {
showError ( warns ) ;
} else {
showError ( " cannot load instrument! ( " + e - > getLastError ( ) + " ) " ) ;
}
} else {
showWarning ( warns , GUI_WARN_GENERIC ) ;
}
} else if ( instruments . empty ( ) ) {
showError ( " congratulations! you managed to load nothing. \n you are entitled to a bug report. " ) ;
}
if ( ! instruments . empty ( ) ) {
if ( ask ) { // ask which instruments to load
2022-06-06 00:04:41 +00:00
for ( DivInstrument * i : instruments ) {
pendingIns . push_back ( std : : make_pair ( i , false ) ) ;
}
displayPendingIns = true ;
pendingInsSingle = false ;
} else { // load the only instrument
for ( DivInstrument * i : instruments ) {
e - > addInstrumentPtr ( i ) ;
}
2022-04-03 06:56:49 +00:00
}
2022-01-29 06:22:32 +00:00
}
2022-01-21 22:59:48 +00:00
break ;
2022-04-03 06:56:49 +00:00
}
2022-05-05 03:55:11 +00:00
case GUI_FILE_INS_OPEN_REPLACE : {
2022-11-21 07:55:12 +00:00
int sampleCountBefore = e - > song . sampleLen ;
2022-05-05 03:55:11 +00:00
std : : vector < DivInstrument * > instruments = e - > instrumentFromFile ( copyOfName . c_str ( ) ) ;
if ( ! instruments . empty ( ) ) {
2022-11-21 07:55:12 +00:00
if ( e - > song . sampleLen ! = sampleCountBefore ) {
e - > renderSamplesP ( ) ;
}
2022-05-05 03:55:11 +00:00
if ( ! e - > getWarnings ( ) . empty ( ) ) {
showWarning ( e - > getWarnings ( ) , GUI_WARN_GENERIC ) ;
}
2022-06-06 00:04:41 +00:00
if ( instruments . size ( ) > 1 ) { // ask which instrument
for ( DivInstrument * i : instruments ) {
pendingIns . push_back ( std : : make_pair ( i , false ) ) ;
}
displayPendingIns = true ;
pendingInsSingle = true ;
} else { // replace with the only instrument
if ( curIns > = 0 & & curIns < ( int ) e - > song . ins . size ( ) ) {
* e - > song . ins [ curIns ] = * instruments [ 0 ] ;
} else {
showError ( " ...but you haven't selected an instrument! " ) ;
}
for ( DivInstrument * i : instruments ) {
delete i ;
}
2022-05-05 03:55:11 +00:00
}
} else {
showError ( " cannot load instrument! ( " + e - > getLastError ( ) + " ) " ) ;
}
break ;
}
2022-08-13 09:17:32 +00:00
case GUI_FILE_WAVE_OPEN : {
2022-10-28 09:11:27 +00:00
String errs = " there were some errors while loading wavetables: \n " ;
bool warn = false ;
for ( String i : fileDialog - > getFileName ( ) ) {
DivWavetable * wave = e - > waveFromFile ( i . c_str ( ) ) ;
if ( wave = = NULL ) {
if ( fileDialog - > getFileName ( ) . size ( ) > 1 ) {
warn = true ;
errs + = fmt : : sprintf ( " - %s: %s \n " , i , e - > getLastError ( ) ) ;
} else {
showError ( " cannot load wavetable! ( " + e - > getLastError ( ) + " ) " ) ;
}
2022-08-13 09:17:32 +00:00
} else {
2022-10-28 09:11:27 +00:00
if ( e - > addWavePtr ( wave ) = = - 1 ) {
if ( fileDialog - > getFileName ( ) . size ( ) > 1 ) {
warn = true ;
errs + = fmt : : sprintf ( " - %s: %s \n " , i , e - > getLastError ( ) ) ;
} else {
showError ( " cannot load wavetable! ( " + e - > getLastError ( ) + " ) " ) ;
}
} else {
MARK_MODIFIED ;
RESET_WAVE_MACRO_ZOOM ;
}
2022-08-13 09:17:32 +00:00
}
2022-05-14 22:51:05 +00:00
}
2022-10-28 09:11:27 +00:00
if ( warn ) {
showWarning ( errs , GUI_WARN_GENERIC ) ;
}
2022-01-21 22:59:48 +00:00
break ;
2022-08-13 09:17:32 +00:00
}
case GUI_FILE_WAVE_OPEN_REPLACE : {
DivWavetable * wave = e - > waveFromFile ( copyOfName . c_str ( ) ) ;
if ( wave = = NULL ) {
2022-05-14 22:51:05 +00:00
showError ( " cannot load wavetable! ( " + e - > getLastError ( ) + " ) " ) ;
} else {
2022-08-13 09:17:32 +00:00
if ( curWave > = 0 & & curWave < ( int ) e - > song . wave . size ( ) ) {
e - > lockEngine ( [ this , wave ] ( ) {
* e - > song . wave [ curWave ] = * wave ;
MARK_MODIFIED ;
} ) ;
} else {
showError ( " ...but you haven't selected a wavetable! " ) ;
}
delete wave ;
2022-05-14 22:51:05 +00:00
}
2022-01-21 22:59:48 +00:00
break ;
2022-08-13 09:17:32 +00:00
}
2022-01-24 06:10:38 +00:00
case GUI_FILE_EXPORT_VGM : {
2023-02-09 00:25:03 +00:00
SafeWriter * w = e - > saveVGM ( willExport , vgmExportLoop , vgmExportVersion , vgmExportPatternHints , vgmExportDirectStream , vgmExportTrailingTicks ) ;
2022-01-24 06:10:38 +00:00
if ( w ! = NULL ) {
2022-04-06 07:46:09 +00:00
FILE * f = ps_fopen ( copyOfName . c_str ( ) , " wb " ) ;
2022-01-24 06:10:38 +00:00
if ( f ! = NULL ) {
fwrite ( w - > getFinalBuf ( ) , 1 , w - > size ( ) , f ) ;
fclose ( f ) ;
2023-08-25 23:32:34 +00:00
pushRecentSys ( copyOfName . c_str ( ) ) ;
2022-01-24 06:10:38 +00:00
} 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 {
2022-04-02 02:40:32 +00:00
showError ( fmt : : sprintf ( " could not write VGM! (%s) " , e - > getLastError ( ) ) ) ;
2022-01-24 06:10:38 +00:00
}
break ;
}
2022-05-26 05:24:21 +00:00
case GUI_FILE_EXPORT_ZSM : {
2023-08-11 20:03:37 +00:00
SafeWriter * w = e - > saveZSM ( zsmExportTickRate , zsmExportLoop , zsmExportOptimize ) ;
2022-05-26 05:24:21 +00:00
if ( w ! = NULL ) {
FILE * f = ps_fopen ( copyOfName . c_str ( ) , " wb " ) ;
if ( f ! = NULL ) {
fwrite ( w - > getFinalBuf ( ) , 1 , w - > size ( ) , f ) ;
fclose ( f ) ;
2023-08-25 23:32:34 +00:00
pushRecentSys ( copyOfName . c_str ( ) ) ;
2022-05-26 05:24:21 +00:00
} else {
showError ( " could not open file! " ) ;
}
w - > finish ( ) ;
delete w ;
if ( ! e - > getWarnings ( ) . empty ( ) ) {
showWarning ( e - > getWarnings ( ) , GUI_WARN_GENERIC ) ;
}
} else {
showError ( fmt : : sprintf ( " Could not write ZSM! (%s) " , e - > getLastError ( ) ) ) ;
}
break ;
}
2022-01-18 04:34:29 +00:00
case GUI_FILE_EXPORT_ROM :
showError ( " Coming soon! " ) ;
break ;
2023-03-26 18:19:57 +00:00
case GUI_FILE_EXPORT_CMDSTREAM :
case GUI_FILE_EXPORT_CMDSTREAM_BINARY : {
bool isBinary = ( curFileDialog = = GUI_FILE_EXPORT_CMDSTREAM_BINARY ) ;
2022-08-04 05:51:47 +00:00
SafeWriter * w = e - > saveCommand ( isBinary ) ;
if ( w ! = NULL ) {
FILE * f = ps_fopen ( copyOfName . c_str ( ) , " wb " ) ;
if ( f ! = NULL ) {
fwrite ( w - > getFinalBuf ( ) , 1 , w - > size ( ) , f ) ;
fclose ( f ) ;
2023-08-25 23:32:34 +00:00
pushRecentSys ( copyOfName . c_str ( ) ) ;
2022-08-04 05:51:47 +00:00
} else {
showError ( " could not open file! " ) ;
}
w - > finish ( ) ;
delete w ;
if ( ! e - > getWarnings ( ) . empty ( ) ) {
showWarning ( e - > getWarnings ( ) , GUI_WARN_GENERIC ) ;
}
} else {
showError ( fmt : : sprintf ( " could not write command stream! (%s) " , e - > getLastError ( ) ) ) ;
}
break ;
}
2022-02-14 23:18:30 +00:00
case GUI_FILE_LOAD_MAIN_FONT :
settings . mainFontPath = copyOfName ;
break ;
2023-08-03 03:49:01 +00:00
case GUI_FILE_LOAD_HEAD_FONT :
settings . headFontPath = copyOfName ;
2023-08-02 20:48:07 +00:00
break ;
2022-02-14 23:18:30 +00:00
case GUI_FILE_LOAD_PAT_FONT :
settings . patFontPath = copyOfName ;
break ;
2022-04-06 18:53:39 +00:00
case GUI_FILE_IMPORT_COLORS :
importColors ( copyOfName ) ;
break ;
case GUI_FILE_IMPORT_KEYBINDS :
importKeybinds ( copyOfName ) ;
break ;
case GUI_FILE_IMPORT_LAYOUT :
importLayout ( copyOfName ) ;
break ;
case GUI_FILE_EXPORT_COLORS :
exportColors ( copyOfName ) ;
break ;
case GUI_FILE_EXPORT_KEYBINDS :
exportKeybinds ( copyOfName ) ;
break ;
case GUI_FILE_EXPORT_LAYOUT :
exportLayout ( copyOfName ) ;
break ;
2022-05-11 21:39:36 +00:00
case GUI_FILE_YRW801_ROM_OPEN :
settings . yrw801Path = copyOfName ;
break ;
case GUI_FILE_TG100_ROM_OPEN :
settings . tg100Path = copyOfName ;
break ;
case GUI_FILE_MU5_ROM_OPEN :
settings . mu5Path = copyOfName ;
2023-03-26 23:48:16 +00:00
break ;
case GUI_FILE_CMDSTREAM_OPEN :
if ( loadStream ( copyOfName ) > 0 ) {
showError ( fmt : : sprintf ( " Error while loading file! (%s) " , lastError ) ) ;
}
2022-05-11 21:39:36 +00:00
break ;
2022-07-15 07:23:16 +00:00
case GUI_FILE_TEST_OPEN :
showWarning ( fmt : : sprintf ( " You opened: %s " , copyOfName ) , GUI_WARN_GENERIC ) ;
break ;
case GUI_FILE_TEST_OPEN_MULTI : {
String msg = " You opened: " ;
for ( String i : fileDialog - > getFileName ( ) ) {
msg + = fmt : : sprintf ( " \n - %s " , i ) ;
}
showWarning ( msg , GUI_WARN_GENERIC ) ;
break ;
}
case GUI_FILE_TEST_SAVE :
showWarning ( fmt : : sprintf ( " You saved: %s " , copyOfName ) , GUI_WARN_GENERIC ) ;
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
}
}
2022-03-13 23:32:35 +00:00
fileDialog - > close ( ) ;
2022-04-13 07:09:59 +00:00
postWarnAction = GUI_WARN_GENERIC ;
if ( openOpen ) {
openFileDialog ( GUI_FILE_OPEN ) ;
}
2021-12-15 05:37:27 +00:00
}
2023-02-24 07:03:43 +00:00
if ( warnQuit & & introPos > = 11.0 ) {
2021-12-30 23:52:36 +00:00
warnQuit = false ;
ImGui : : OpenPopup ( " Warning " ) ;
}
2023-02-24 07:03:43 +00:00
if ( displayError & & introPos > = 11.0 ) {
2022-01-09 21:36:47 +00:00
displayError = false ;
ImGui : : OpenPopup ( " Error " ) ;
}
2022-06-06 00:04:41 +00:00
if ( displayPendingIns ) {
displayPendingIns = false ;
ImGui : : OpenPopup ( " Select Instrument " ) ;
}
2022-08-13 09:17:32 +00:00
if ( displayPendingRawSample ) {
displayPendingRawSample = false ;
ImGui : : OpenPopup ( " Import Raw Sample " ) ;
}
2022-11-13 23:29:37 +00:00
if ( displayInsTypeList ) {
displayInsTypeList = false ;
ImGui : : OpenPopup ( " InsTypeList " ) ;
}
2022-01-18 04:34:29 +00:00
if ( displayExporting ) {
displayExporting = false ;
ImGui : : OpenPopup ( " Rendering... " ) ;
}
2022-03-01 22:19:52 +00:00
if ( displayNew ) {
2023-04-03 14:11:26 +00:00
newSongQuery = " " ;
newSongFirstFrame = true ;
2022-03-01 22:19:52 +00:00
displayNew = false ;
2023-06-24 23:55:55 +00:00
if ( settings . newSongBehavior = = 1 ) {
e - > createNewFromDefaults ( ) ;
undoHist . clear ( ) ;
redoHist . clear ( ) ;
curFileName = " " ;
modified = false ;
curNibble = false ;
orderNibble = false ;
orderCursor = - 1 ;
samplePos = 0 ;
updateSampleTex = true ;
selStart = SelectionPoint ( ) ;
selEnd = SelectionPoint ( ) ;
cursor = SelectionPoint ( ) ;
updateWindowTitle ( ) ;
} else {
ImGui : : OpenPopup ( " New Song " ) ;
}
2022-03-01 22:19:52 +00:00
}
2023-05-16 18:41:08 +00:00
if ( displayEditString ) {
ImGui : : OpenPopup ( " EditString " ) ;
}
2022-02-12 07:14:25 +00:00
if ( nextWindow = = GUI_WINDOW_ABOUT ) {
aboutOpen = true ;
nextWindow = GUI_WINDOW_NOTHING ;
}
2021-12-19 04:03:50 +00:00
if ( aboutOpen ) drawAbout ( ) ;
2023-04-14 00:43:48 +00:00
MEASURE_BEGIN ( popup ) ;
2023-08-10 07:42:42 +00:00
centerNextWindow ( " Rendering... " , canvasW , canvasH ) ;
2022-01-18 04:34:29 +00:00
if ( ImGui : : BeginPopupModal ( " Rendering... " , NULL , ImGuiWindowFlags_AlwaysAutoResize ) ) {
2022-04-11 03:12:02 +00:00
ImGui : : Text ( " Please wait... " ) ;
2022-01-18 04:34:29 +00:00
if ( ImGui : : Button ( " Abort " ) ) {
if ( e - > haltAudioFile ( ) ) {
ImGui : : CloseCurrentPopup ( ) ;
}
}
if ( ! e - > isExporting ( ) ) {
2023-08-21 19:14:09 +00:00
e - > finishAudioFile ( ) ;
2022-01-18 04:34:29 +00:00
ImGui : : CloseCurrentPopup ( ) ;
}
ImGui : : EndPopup ( ) ;
}
2023-05-24 09:19:45 +00:00
drawTutorial ( ) ;
2023-02-24 09:19:39 +00:00
2022-11-13 21:57:47 +00:00
ImVec2 newSongMinSize = mobileUI ? ImVec2 ( canvasW - ( portrait ? 0 : ( 60.0 * dpiScale ) ) , canvasH - 60.0 * dpiScale ) : ImVec2 ( 400.0f * dpiScale , 200.0f * dpiScale ) ;
ImVec2 newSongMaxSize = ImVec2 ( canvasW - ( ( mobileUI & & ! portrait ) ? ( 60.0 * dpiScale ) : 0 ) , canvasH - ( mobileUI ? ( 60.0 * dpiScale ) : 0 ) ) ;
ImGui : : SetNextWindowSizeConstraints ( newSongMinSize , newSongMaxSize ) ;
2022-05-14 09:05:29 +00:00
if ( ImGui : : BeginPopupModal ( " New Song " , NULL , ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoScrollWithMouse | ImGuiWindowFlags_NoScrollbar ) ) {
2022-10-20 07:34:14 +00:00
ImGui : : SetWindowPos ( ImVec2 ( ( ( canvasW ) - ImGui : : GetWindowSize ( ) . x ) * 0.5 , ( ( canvasH ) - ImGui : : GetWindowSize ( ) . y ) * 0.5 ) ) ;
2022-11-13 21:57:47 +00:00
if ( ImGui : : GetWindowSize ( ) . x < newSongMinSize . x | | ImGui : : GetWindowSize ( ) . y < newSongMinSize . y ) {
ImGui : : SetWindowSize ( newSongMinSize , ImGuiCond_Always ) ;
}
2022-03-01 22:19:52 +00:00
drawNewSong ( ) ;
ImGui : : EndPopup ( ) ;
}
2023-08-10 07:42:42 +00:00
centerNextWindow ( " Error " , canvasW , canvasH ) ;
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 ( ) ;
}
2023-08-10 07:42:42 +00:00
centerNextWindow ( " Warning " , canvasW , canvasH ) ;
2021-12-30 23:52:36 +00:00
if ( ImGui : : BeginPopupModal ( " Warning " , NULL , ImGuiWindowFlags_AlwaysAutoResize ) ) {
ImGui : : Text ( " %s " , warnString . c_str ( ) ) ;
2022-04-13 07:09:59 +00:00
switch ( warnAction ) {
case GUI_WARN_QUIT :
if ( ImGui : : Button ( " Yes " ) ) {
ImGui : : CloseCurrentPopup ( ) ;
2023-04-06 09:22:43 +00:00
if ( curFileName = = " " | | curFileName . find ( backupPath ) = = 0 | | e - > song . version > = 0xff00 ) {
2022-04-13 07:09:59 +00:00
openFileDialog ( GUI_FILE_SAVE ) ;
postWarnAction = GUI_WARN_QUIT ;
} else {
if ( save ( curFileName , e - > song . isDMF ? e - > song . version : 0 ) > 0 ) {
showError ( fmt : : sprintf ( " Error while saving file! (%s) " , lastError ) ) ;
} else {
quit = true ;
}
}
}
ImGui : : SameLine ( ) ;
if ( ImGui : : Button ( " No " ) ) {
ImGui : : CloseCurrentPopup ( ) ;
2022-04-01 10:20:00 +00:00
quit = true ;
2022-04-13 07:09:59 +00:00
}
ImGui : : SameLine ( ) ;
2023-07-11 14:14:35 +00:00
if ( ImGui : : Button ( " Cancel " ) | | ImGui : : IsKeyPressed ( ImGuiKey_Escape ) ) {
2022-04-13 07:09:59 +00:00
ImGui : : CloseCurrentPopup ( ) ;
}
break ;
case GUI_WARN_NEW :
if ( ImGui : : Button ( " Yes " ) ) {
ImGui : : CloseCurrentPopup ( ) ;
2023-04-06 09:22:43 +00:00
if ( curFileName = = " " | | curFileName . find ( backupPath ) = = 0 | | e - > song . version > = 0xff00 ) {
2022-04-13 07:09:59 +00:00
openFileDialog ( GUI_FILE_SAVE ) ;
postWarnAction = GUI_WARN_NEW ;
} else {
if ( save ( curFileName , e - > song . isDMF ? e - > song . version : 0 ) > 0 ) {
showError ( fmt : : sprintf ( " Error while saving file! (%s) " , lastError ) ) ;
} else {
displayNew = true ;
}
}
}
ImGui : : SameLine ( ) ;
if ( ImGui : : Button ( " No " ) ) {
ImGui : : CloseCurrentPopup ( ) ;
2022-04-01 10:20:00 +00:00
displayNew = true ;
2022-04-13 07:09:59 +00:00
}
ImGui : : SameLine ( ) ;
2023-07-11 14:14:35 +00:00
if ( ImGui : : Button ( " Cancel " ) | | ImGui : : IsKeyPressed ( ImGuiKey_Escape ) ) {
2022-04-13 07:09:59 +00:00
ImGui : : CloseCurrentPopup ( ) ;
}
break ;
case GUI_WARN_OPEN :
if ( ImGui : : Button ( " Yes " ) ) {
ImGui : : CloseCurrentPopup ( ) ;
2023-04-06 09:22:43 +00:00
if ( curFileName = = " " | | curFileName . find ( backupPath ) = = 0 | | e - > song . version > = 0xff00 ) {
2022-04-13 07:09:59 +00:00
openFileDialog ( GUI_FILE_SAVE ) ;
postWarnAction = GUI_WARN_OPEN ;
} else {
if ( save ( curFileName , e - > song . isDMF ? e - > song . version : 0 ) > 0 ) {
showError ( fmt : : sprintf ( " Error while saving file! (%s) " , lastError ) ) ;
} else {
openFileDialog ( GUI_FILE_OPEN ) ;
}
}
}
ImGui : : SameLine ( ) ;
if ( ImGui : : Button ( " No " ) ) {
ImGui : : CloseCurrentPopup ( ) ;
2022-04-01 10:20:00 +00:00
openFileDialog ( GUI_FILE_OPEN ) ;
2022-04-13 07:09:59 +00:00
}
ImGui : : SameLine ( ) ;
2023-07-11 14:14:35 +00:00
if ( ImGui : : Button ( " Cancel " ) | | ImGui : : IsKeyPressed ( ImGuiKey_Escape ) ) {
2022-04-13 07:09:59 +00:00
ImGui : : CloseCurrentPopup ( ) ;
}
break ;
case GUI_WARN_OPEN_BACKUP :
if ( ImGui : : Button ( " Yes " ) ) {
ImGui : : CloseCurrentPopup ( ) ;
2023-04-06 09:22:43 +00:00
if ( curFileName = = " " | | curFileName . find ( backupPath ) = = 0 | | e - > song . version > = 0xff00 ) {
2022-04-13 07:09:59 +00:00
openFileDialog ( GUI_FILE_SAVE ) ;
postWarnAction = GUI_WARN_OPEN_BACKUP ;
} else {
if ( save ( curFileName , e - > song . isDMF ? e - > song . version : 0 ) > 0 ) {
showError ( fmt : : sprintf ( " Error while saving file! (%s) " , lastError ) ) ;
} else {
2023-04-06 20:16:52 +00:00
openFileDialog ( GUI_FILE_OPEN_BACKUP ) ;
2022-04-13 07:09:59 +00:00
}
}
}
ImGui : : SameLine ( ) ;
if ( ImGui : : Button ( " No " ) ) {
ImGui : : CloseCurrentPopup ( ) ;
2023-04-06 20:16:52 +00:00
openFileDialog ( GUI_FILE_OPEN_BACKUP ) ;
2022-04-13 07:09:59 +00:00
}
ImGui : : SameLine ( ) ;
2023-07-11 14:14:35 +00:00
if ( ImGui : : Button ( " Cancel " ) | | ImGui : : IsKeyPressed ( ImGuiKey_Escape ) ) {
2022-04-13 07:09:59 +00:00
ImGui : : CloseCurrentPopup ( ) ;
}
break ;
case GUI_WARN_OPEN_DROP :
if ( ImGui : : Button ( " Yes " ) ) {
ImGui : : CloseCurrentPopup ( ) ;
2023-04-06 09:22:43 +00:00
if ( curFileName = = " " | | curFileName . find ( backupPath ) = = 0 | | e - > song . version > = 0xff00 ) {
2022-04-13 07:09:59 +00:00
openFileDialog ( GUI_FILE_SAVE ) ;
postWarnAction = GUI_WARN_OPEN_DROP ;
} else {
if ( save ( curFileName , e - > song . isDMF ? e - > song . version : 0 ) > 0 ) {
showError ( fmt : : sprintf ( " Error while saving file! (%s) " , lastError ) ) ;
nextFile = " " ;
} else {
if ( load ( nextFile ) > 0 ) {
showError ( fmt : : sprintf ( " Error while loading file! (%s) " , lastError ) ) ;
}
nextFile = " " ;
}
}
}
ImGui : : SameLine ( ) ;
if ( ImGui : : Button ( " No " ) ) {
ImGui : : CloseCurrentPopup ( ) ;
2022-04-01 10:20:00 +00:00
if ( load ( nextFile ) > 0 ) {
showError ( fmt : : sprintf ( " Error while loading file! (%s) " , lastError ) ) ;
}
nextFile = " " ;
2022-04-13 07:09:59 +00:00
}
ImGui : : SameLine ( ) ;
2023-07-11 14:14:35 +00:00
if ( ImGui : : Button ( " Cancel " ) | | ImGui : : IsKeyPressed ( ImGuiKey_Escape ) ) {
2022-04-13 07:09:59 +00:00
ImGui : : CloseCurrentPopup ( ) ;
nextFile = " " ;
}
break ;
case GUI_WARN_RESET_LAYOUT :
if ( ImGui : : Button ( " Yes " ) ) {
ImGui : : CloseCurrentPopup ( ) ;
2022-05-18 23:42:59 +00:00
if ( ! mobileUI ) {
ImGui : : LoadIniSettingsFromMemory ( defaultLayout ) ;
2023-04-06 00:08:04 +00:00
if ( ! ImGui : : SaveIniSettingsToDisk ( finalLayoutPath , true ) ) {
2023-04-04 21:01:45 +00:00
reportError ( fmt : : sprintf ( " could NOT save layout! %s " , strerror ( errno ) ) ) ;
}
2022-05-18 23:42:59 +00:00
}
2022-04-13 07:09:59 +00:00
}
ImGui : : SameLine ( ) ;
if ( ImGui : : Button ( " No " ) ) {
ImGui : : CloseCurrentPopup ( ) ;
}
break ;
case GUI_WARN_RESET_KEYBINDS :
if ( ImGui : : Button ( " Yes " ) ) {
ImGui : : CloseCurrentPopup ( ) ;
2022-04-06 18:53:39 +00:00
resetKeybinds ( ) ;
2022-04-13 07:09:59 +00:00
}
ImGui : : SameLine ( ) ;
if ( ImGui : : Button ( " No " ) ) {
ImGui : : CloseCurrentPopup ( ) ;
}
break ;
case GUI_WARN_RESET_COLORS :
if ( ImGui : : Button ( " Yes " ) ) {
ImGui : : CloseCurrentPopup ( ) ;
2022-04-06 18:53:39 +00:00
resetColors ( ) ;
2022-04-11 07:53:21 +00:00
applyUISettings ( false ) ;
2022-04-13 07:09:59 +00:00
}
ImGui : : SameLine ( ) ;
if ( ImGui : : Button ( " No " ) ) {
ImGui : : CloseCurrentPopup ( ) ;
}
break ;
case GUI_WARN_CLOSE_SETTINGS :
if ( ImGui : : Button ( " Yes " ) ) {
ImGui : : CloseCurrentPopup ( ) ;
settingsOpen = false ;
willCommit = true ;
}
ImGui : : SameLine ( ) ;
if ( ImGui : : Button ( " No " ) ) {
ImGui : : CloseCurrentPopup ( ) ;
settingsOpen = false ;
syncSettings ( ) ;
}
ImGui : : SameLine ( ) ;
2023-07-11 14:14:35 +00:00
if ( ImGui : : Button ( " Cancel " ) | | ImGui : : IsKeyPressed ( ImGuiKey_Escape ) ) {
2022-04-13 07:09:59 +00:00
ImGui : : CloseCurrentPopup ( ) ;
}
break ;
2022-04-24 21:57:58 +00:00
case GUI_WARN_CLEAR :
2022-05-17 06:15:31 +00:00
if ( ImGui : : Button ( " All subsongs " ) ) {
stop ( ) ;
2022-05-17 06:42:21 +00:00
e - > clearSubSongs ( ) ;
2022-05-17 06:15:31 +00:00
curOrder = 0 ;
oldOrder = 0 ;
oldOrder1 = 0 ;
MARK_MODIFIED ;
ImGui : : CloseCurrentPopup ( ) ;
}
ImGui : : SameLine ( ) ;
if ( ImGui : : Button ( " Current subsong " ) ) {
2022-04-24 22:39:18 +00:00
stop ( ) ;
e - > lockEngine ( [ this ] ( ) {
2022-05-17 06:15:31 +00:00
e - > curSubSong - > clearData ( ) ;
2022-04-24 22:39:18 +00:00
} ) ;
e - > setOrder ( 0 ) ;
curOrder = 0 ;
oldOrder = 0 ;
oldOrder1 = 0 ;
MARK_MODIFIED ;
2022-04-24 21:57:58 +00:00
ImGui : : CloseCurrentPopup ( ) ;
}
ImGui : : SameLine ( ) ;
2022-05-17 06:46:34 +00:00
if ( ImGui : : Button ( " Orders " ) ) {
stop ( ) ;
e - > lockEngine ( [ this ] ( ) {
2022-12-09 05:30:27 +00:00
memset ( e - > curOrders - > ord , 0 , DIV_MAX_CHANS * DIV_MAX_PATTERNS ) ;
2022-05-17 06:46:34 +00:00
e - > curSubSong - > ordersLen = 1 ;
} ) ;
e - > setOrder ( 0 ) ;
curOrder = 0 ;
oldOrder = 0 ;
oldOrder1 = 0 ;
MARK_MODIFIED ;
ImGui : : CloseCurrentPopup ( ) ;
}
ImGui : : SameLine ( ) ;
2022-04-24 21:57:58 +00:00
if ( ImGui : : Button ( " Pattern " ) ) {
2022-04-24 22:39:18 +00:00
stop ( ) ;
e - > lockEngine ( [ this ] ( ) {
for ( int i = 0 ; i < e - > getTotalChannelCount ( ) ; i + + ) {
2022-05-15 06:42:49 +00:00
DivPattern * pat = e - > curPat [ i ] . getPattern ( e - > curOrders - > ord [ i ] [ curOrder ] , true ) ;
2022-12-09 05:30:27 +00:00
memset ( pat - > data , - 1 , DIV_MAX_ROWS * DIV_MAX_COLS * sizeof ( short ) ) ;
for ( int j = 0 ; j < DIV_MAX_ROWS ; j + + ) {
2022-04-24 22:39:18 +00:00
pat - > data [ j ] [ 0 ] = 0 ;
pat - > data [ j ] [ 1 ] = 0 ;
}
}
} ) ;
MARK_MODIFIED ;
2022-04-24 21:57:58 +00:00
ImGui : : CloseCurrentPopup ( ) ;
}
ImGui : : SameLine ( ) ;
if ( ImGui : : Button ( " Instruments " ) ) {
2022-04-24 22:39:18 +00:00
stop ( ) ;
e - > lockEngine ( [ this ] ( ) {
e - > song . clearInstruments ( ) ;
} ) ;
curIns = - 1 ;
MARK_MODIFIED ;
2022-04-24 21:57:58 +00:00
ImGui : : CloseCurrentPopup ( ) ;
}
ImGui : : SameLine ( ) ;
if ( ImGui : : Button ( " Wavetables " ) ) {
2022-04-24 22:39:18 +00:00
stop ( ) ;
e - > lockEngine ( [ this ] ( ) {
e - > song . clearWavetables ( ) ;
} ) ;
curWave = 0 ;
MARK_MODIFIED ;
2022-04-24 21:57:58 +00:00
ImGui : : CloseCurrentPopup ( ) ;
}
ImGui : : SameLine ( ) ;
if ( ImGui : : Button ( " Samples " ) ) {
2022-04-24 22:39:18 +00:00
stop ( ) ;
e - > lockEngine ( [ this ] ( ) {
e - > song . clearSamples ( ) ;
} ) ;
curSample = 0 ;
2022-04-24 21:57:58 +00:00
ImGui : : CloseCurrentPopup ( ) ;
}
2023-07-11 14:14:35 +00:00
if ( ImGui : : Button ( " Wait! What am I doing? Cancel! " ) | | ImGui : : IsKeyPressed ( ImGuiKey_Escape ) ) {
2022-04-24 21:57:58 +00:00
ImGui : : CloseCurrentPopup ( ) ;
}
break ;
2022-05-17 22:21:29 +00:00
case GUI_WARN_SUBSONG_DEL :
if ( ImGui : : Button ( " Yes " ) ) {
if ( e - > removeSubSong ( e - > getCurrentSubSong ( ) ) ) {
undoHist . clear ( ) ;
redoHist . clear ( ) ;
updateScroll ( 0 ) ;
oldOrder = 0 ;
oldOrder1 = 0 ;
oldRow = 0 ;
cursor . xCoarse = 0 ;
cursor . xFine = 0 ;
cursor . y = 0 ;
selStart = cursor ;
selEnd = cursor ;
curOrder = 0 ;
MARK_MODIFIED ;
}
ImGui : : CloseCurrentPopup ( ) ;
}
ImGui : : SameLine ( ) ;
if ( ImGui : : Button ( " No " ) ) {
ImGui : : CloseCurrentPopup ( ) ;
}
break ;
2022-08-26 23:51:17 +00:00
case GUI_WARN_SYSTEM_DEL :
if ( ImGui : : Button ( " Yes " ) ) {
e - > removeSystem ( sysToDelete , preserveChanPos ) ;
2022-09-22 00:27:42 +00:00
if ( e - > song . autoSystem ) {
autoDetectSystem ( ) ;
updateWindowTitle ( ) ;
2022-10-16 23:28:42 +00:00
MARK_MODIFIED ;
2022-09-22 00:27:42 +00:00
}
2022-08-26 23:51:17 +00:00
ImGui : : CloseCurrentPopup ( ) ;
}
ImGui : : SameLine ( ) ;
if ( ImGui : : Button ( " No " ) ) {
ImGui : : CloseCurrentPopup ( ) ;
}
break ;
2022-10-02 06:36:37 +00:00
case GUI_WARN_CLEAR_HISTORY :
if ( ImGui : : Button ( " Yes " ) ) {
recentFile . clear ( ) ;
ImGui : : CloseCurrentPopup ( ) ;
}
ImGui : : SameLine ( ) ;
if ( ImGui : : Button ( " No " ) ) {
ImGui : : CloseCurrentPopup ( ) ;
}
break ;
2023-02-06 23:52:51 +00:00
case GUI_WARN_BASIC_MODE :
if ( ImGui : : Button ( " Yes " ) ) {
basicMode = ! basicMode ;
ImGui : : CloseCurrentPopup ( ) ;
}
ImGui : : SameLine ( ) ;
if ( ImGui : : Button ( " No " ) ) {
ImGui : : CloseCurrentPopup ( ) ;
}
break ;
2022-04-13 07:09:59 +00:00
case GUI_WARN_GENERIC :
if ( ImGui : : Button ( " OK " ) ) {
ImGui : : CloseCurrentPopup ( ) ;
}
break ;
2021-12-30 23:52:36 +00:00
}
ImGui : : EndPopup ( ) ;
}
2022-11-13 23:29:37 +00:00
if ( ImGui : : BeginPopup ( " InsTypeList " , ImGuiWindowFlags_NoMove | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoSavedSettings ) ) {
char temp [ 1024 ] ;
for ( DivInstrumentType & i : makeInsTypeList ) {
2023-08-15 01:02:10 +00:00
strncpy ( temp , insTypes [ i ] [ 0 ] , 1023 ) ;
2022-11-13 23:29:37 +00:00
if ( ImGui : : MenuItem ( temp ) ) {
// create ins
curIns = e - > addInstrument ( - 1 , i ) ;
if ( curIns = = - 1 ) {
showError ( " too many instruments! " ) ;
} else {
if ( displayInsTypeListMakeInsSample > = 0 & & displayInsTypeListMakeInsSample < ( int ) e - > song . sample . size ( ) ) {
e - > song . ins [ curIns ] - > type = i ;
e - > song . ins [ curIns ] - > name = e - > song . sample [ displayInsTypeListMakeInsSample ] - > name ;
e - > song . ins [ curIns ] - > amiga . initSample = displayInsTypeListMakeInsSample ;
if ( i ! = DIV_INS_AMIGA ) e - > song . ins [ curIns ] - > amiga . useSample = true ;
nextWindow = GUI_WINDOW_INS_EDIT ;
wavePreviewInit = true ;
2023-03-18 09:22:50 +00:00
updateFMPreview = true ;
2022-11-13 23:29:37 +00:00
}
2023-08-09 21:06:38 +00:00
if ( settings . blankIns ) {
e - > song . ins [ curIns ] - > fm . fb = 0 ;
for ( int i = 0 ; i < 4 ; i + + ) {
e - > song . ins [ curIns ] - > fm . op [ i ] = DivInstrumentFM : : Operator ( ) ;
e - > song . ins [ curIns ] - > fm . op [ i ] . ar = 31 ;
e - > song . ins [ curIns ] - > fm . op [ i ] . dr = 31 ;
e - > song . ins [ curIns ] - > fm . op [ i ] . rr = 15 ;
e - > song . ins [ curIns ] - > fm . op [ i ] . tl = 127 ;
e - > song . ins [ curIns ] - > fm . op [ i ] . dt = 3 ;
}
}
2022-11-13 23:29:37 +00:00
MARK_MODIFIED ;
}
}
}
ImGui : : EndPopup ( ) ;
}
2022-06-06 00:04:41 +00:00
// TODO:
// - multiple selection
// - replace instrument
2023-08-10 07:42:42 +00:00
centerNextWindow ( " Select Instrument " , canvasW , canvasH ) ;
2022-06-06 00:04:41 +00:00
if ( ImGui : : BeginPopupModal ( " Select Instrument " , NULL , ImGuiWindowFlags_AlwaysAutoResize ) ) {
bool quitPlease = false ;
if ( pendingInsSingle ) {
ImGui : : Text ( " this is an instrument bank! select which one to use: " ) ;
} else {
2023-08-07 03:51:51 +00:00
ImGui : : AlignTextToFramePadding ( ) ;
2022-06-06 00:04:41 +00:00
ImGui : : Text ( " this is an instrument bank! select which ones to load: " ) ;
2022-06-06 04:44:52 +00:00
ImGui : : SameLine ( ) ;
if ( ImGui : : Button ( " All " ) ) {
for ( std : : pair < DivInstrument * , bool > & i : pendingIns ) {
i . second = true ;
}
}
ImGui : : SameLine ( ) ;
if ( ImGui : : Button ( " None " ) ) {
for ( std : : pair < DivInstrument * , bool > & i : pendingIns ) {
i . second = false ;
}
}
2022-06-06 00:04:41 +00:00
}
2022-06-06 04:34:58 +00:00
bool anySelected = false ;
float sizeY = ImGui : : GetFrameHeightWithSpacing ( ) * pendingIns . size ( ) ;
2022-10-20 07:34:14 +00:00
if ( sizeY > ( canvasH - 180.0 * dpiScale ) ) {
sizeY = canvasH - 180.0 * dpiScale ;
2022-06-06 04:34:58 +00:00
if ( sizeY < 60.0 * dpiScale ) sizeY = 60.0 * dpiScale ;
}
if ( ImGui : : BeginTable ( " PendingInsList " , 1 , ImGuiTableFlags_ScrollY , ImVec2 ( 0.0f , sizeY ) ) ) {
for ( size_t i = 0 ; i < pendingIns . size ( ) ; i + + ) {
ImGui : : TableNextRow ( ) ;
ImGui : : TableNextColumn ( ) ;
String id = fmt : : sprintf ( " %d: %s " , ( int ) i , pendingIns [ i ] . first - > name ) ;
if ( pendingInsSingle ) {
if ( ImGui : : Selectable ( id . c_str ( ) ) ) {
pendingIns [ i ] . second = true ;
quitPlease = true ;
}
} else {
ImGui : : Checkbox ( id . c_str ( ) , & pendingIns [ i ] . second ) ;
}
if ( pendingIns [ i ] . second ) anySelected = true ;
}
ImGui : : EndTable ( ) ;
}
if ( ! pendingInsSingle ) {
ImGui : : BeginDisabled ( ! anySelected ) ;
if ( ImGui : : Button ( " OK " ) ) {
2022-06-06 00:04:41 +00:00
quitPlease = true ;
}
2022-06-06 04:34:58 +00:00
ImGui : : EndDisabled ( ) ;
ImGui : : SameLine ( ) ;
}
2023-07-11 14:14:35 +00:00
if ( ImGui : : Button ( " Cancel " ) | | ImGui : : IsKeyPressed ( ImGuiKey_Escape ) ) {
2022-06-06 04:34:58 +00:00
for ( std : : pair < DivInstrument * , bool > & i : pendingIns ) {
i . second = false ;
}
quitPlease = true ;
2022-06-06 00:04:41 +00:00
}
if ( quitPlease ) {
ImGui : : CloseCurrentPopup ( ) ;
2022-06-06 04:34:58 +00:00
for ( std : : pair < DivInstrument * , bool > & i : pendingIns ) {
if ( ! i . second | | pendingInsSingle ) {
if ( i . second ) {
if ( curIns > = 0 & & curIns < ( int ) e - > song . ins . size ( ) ) {
* e - > song . ins [ curIns ] = * i . first ;
} else {
showError ( " ...but you haven't selected an instrument! " ) ;
}
}
2022-06-06 00:04:41 +00:00
delete i . first ;
2022-06-06 04:34:58 +00:00
} else {
e - > addInstrumentPtr ( i . first ) ;
2022-06-06 00:04:41 +00:00
}
}
pendingIns . clear ( ) ;
}
ImGui : : EndPopup ( ) ;
}
2023-08-10 07:42:42 +00:00
centerNextWindow ( " Import Raw Sample " , canvasW , canvasH ) ;
2022-08-13 09:17:32 +00:00
if ( ImGui : : BeginPopupModal ( " Import Raw Sample " , NULL , ImGuiWindowFlags_AlwaysAutoResize ) ) {
2022-08-13 10:50:36 +00:00
ImGui : : Text ( " Data type: " ) ;
for ( int i = 0 ; i < DIV_SAMPLE_DEPTH_MAX ; i + + ) {
if ( sampleDepths [ i ] = = NULL ) continue ;
if ( ImGui : : RadioButton ( sampleDepths [ i ] , pendingRawSampleDepth = = i ) ) pendingRawSampleDepth = i ;
}
if ( pendingRawSampleDepth ! = DIV_SAMPLE_DEPTH_8BIT & & pendingRawSampleDepth ! = DIV_SAMPLE_DEPTH_16BIT ) {
pendingRawSampleChannels = 1 ;
2022-08-13 09:17:32 +00:00
}
2022-08-13 10:50:36 +00:00
if ( pendingRawSampleDepth ! = DIV_SAMPLE_DEPTH_16BIT ) {
pendingRawSampleBigEndian = false ;
}
2023-08-19 23:01:12 +00:00
if ( pendingRawSampleDepth = = DIV_SAMPLE_DEPTH_8BIT | | pendingRawSampleDepth = = DIV_SAMPLE_DEPTH_16BIT ) {
ImGui : : AlignTextToFramePadding ( ) ;
ImGui : : Text ( " Channels " ) ;
ImGui : : SameLine ( ) ;
ImGui : : SetNextItemWidth ( 120.0f * dpiScale ) ;
if ( ImGui : : InputInt ( " ##RSChans " , & pendingRawSampleChannels ) ) {
}
ImGui : : Text ( " (will be mixed down to mono) " ) ;
ImGui : : Checkbox ( " Unsigned " , & pendingRawSampleUnsigned ) ;
}
if ( pendingRawSampleDepth = = DIV_SAMPLE_DEPTH_16BIT ) {
ImGui : : Checkbox ( " Big endian " , & pendingRawSampleBigEndian ) ;
2022-08-13 09:17:32 +00:00
}
2023-08-19 23:01:12 +00:00
if ( pendingRawSampleDepth = = DIV_SAMPLE_DEPTH_YMZ_ADPCM | |
pendingRawSampleDepth = = DIV_SAMPLE_DEPTH_QSOUND_ADPCM | |
pendingRawSampleDepth = = DIV_SAMPLE_DEPTH_ADPCM_A | |
pendingRawSampleDepth = = DIV_SAMPLE_DEPTH_ADPCM_B | |
pendingRawSampleDepth = = DIV_SAMPLE_DEPTH_VOX ) {
ImGui : : Checkbox ( " Swap nibbles " , & pendingRawSampleSwapNibbles ) ;
}
if ( pendingRawSampleDepth = = DIV_SAMPLE_DEPTH_MULAW ) {
ImGui : : Text ( " Encoding: " ) ;
ImGui : : Indent ( ) ;
if ( ImGui : : RadioButton ( " G.711 " , pendingRawSampleSwapNibbles = = 0 ) ) {
pendingRawSampleSwapNibbles = 0 ;
}
if ( ImGui : : RadioButton ( " Namco " , pendingRawSampleSwapNibbles = = 1 ) ) {
pendingRawSampleSwapNibbles = 1 ;
}
ImGui : : Unindent ( ) ;
}
2022-08-13 09:17:32 +00:00
2023-08-19 23:01:12 +00:00
if ( pendingRawSampleDepth = = DIV_SAMPLE_DEPTH_1BIT | |
pendingRawSampleDepth = = DIV_SAMPLE_DEPTH_1BIT_DPCM ) {
ImGui : : Checkbox ( " Reverse bit order " , & pendingRawSampleSwapNibbles ) ;
}
2022-12-18 03:45:08 +00:00
2022-08-13 10:50:36 +00:00
if ( ImGui : : Button ( " OK " ) ) {
2022-12-18 03:45:08 +00:00
DivSample * s = e - > sampleFromFileRaw ( pendingRawSample . c_str ( ) , ( DivSampleDepth ) pendingRawSampleDepth , pendingRawSampleChannels , pendingRawSampleBigEndian , pendingRawSampleUnsigned , pendingRawSampleSwapNibbles ) ;
2022-08-13 10:50:36 +00:00
if ( s = = NULL ) {
showError ( e - > getLastError ( ) ) ;
} else {
2023-07-17 21:31:55 +00:00
if ( pendingRawSampleReplace ) {
if ( curSample > = 0 & & curSample < ( int ) e - > song . sample . size ( ) ) {
e - > lockEngine ( [ this , s ] ( ) {
// if it crashes here please tell me...
DivSample * oldSample = e - > song . sample [ curSample ] ;
e - > song . sample [ curSample ] = s ;
delete oldSample ;
e - > renderSamples ( ) ;
MARK_MODIFIED ;
} ) ;
} else {
showError ( " ...but you haven't selected a sample! " ) ;
delete s ;
}
2022-08-13 10:50:36 +00:00
} else {
2023-07-17 21:31:55 +00:00
if ( e - > addSamplePtr ( s ) = = - 1 ) {
showError ( e - > getLastError ( ) ) ;
} else {
MARK_MODIFIED ;
}
2022-08-13 10:50:36 +00:00
}
}
ImGui : : CloseCurrentPopup ( ) ;
}
ImGui : : SameLine ( ) ;
2023-07-11 14:14:35 +00:00
if ( ImGui : : Button ( " Cancel " ) | | ImGui : : IsKeyPressed ( ImGuiKey_Escape ) ) {
2022-08-13 09:17:32 +00:00
ImGui : : CloseCurrentPopup ( ) ;
}
ImGui : : EndPopup ( ) ;
}
2023-05-16 18:41:08 +00:00
if ( ImGui : : BeginPopup ( " EditString " , ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoSavedSettings ) ) {
if ( editString = = NULL ) {
ImGui : : Text ( " Error! No string provided! " ) ;
} else {
if ( displayEditString ) {
ImGui : : SetItemDefaultFocus ( ) ;
ImGui : : SetKeyboardFocusHere ( ) ;
}
ImGui : : InputText ( " ##StringVal " , editString ) ;
}
displayEditString = false ;
ImGui : : SameLine ( ) ;
if ( ImGui : : Button ( " OK " ) | | ImGui : : IsKeyPressed ( ImGuiKey_Enter , false ) ) {
editString = NULL ;
ImGui : : CloseCurrentPopup ( ) ;
}
ImGui : : EndPopup ( ) ;
} else {
editString = NULL ;
}
2023-04-14 00:43:48 +00:00
MEASURE_END ( popup ) ;
2023-02-19 05:08:37 +00:00
if ( ! tutorial . introPlayed | | settings . alwaysPlayIntro ! = 0 ) {
2023-04-14 00:43:48 +00:00
MEASURE_BEGIN ( intro ) ;
2023-02-16 10:40:06 +00:00
initialScreenWipe = 0 ;
2023-02-19 05:08:37 +00:00
if ( settings . alwaysPlayIntro = = 1 ) {
shortIntro = true ;
}
2023-02-19 20:58:56 +00:00
drawIntro ( introPos ) ;
2023-04-14 00:43:48 +00:00
MEASURE_END ( intro ) ;
2023-02-19 05:08:37 +00:00
} else {
2023-02-24 07:03:43 +00:00
introPos = 12.0 ;
2023-02-15 21:25:35 +00:00
}
2023-07-10 01:34:44 +00:00
# ifdef DIV_UNSTABLE
{
ImDrawList * dl = ImGui : : GetForegroundDrawList ( ) ;
2023-07-10 09:32:56 +00:00
ImVec2 markPos = ImVec2 ( canvasW - ImGui : : CalcTextSize ( DIV_VERSION ) . x - 6.0 * dpiScale , 4.0 * dpiScale ) ;
2023-07-10 01:34:44 +00:00
ImVec4 markColor = uiColors [ GUI_COLOR_TEXT ] ;
markColor . w = 0.67f ;
dl - > AddText ( markPos , ImGui : : ColorConvertFloat4ToU32 ( markColor ) , DIV_VERSION ) ;
}
# endif
2022-05-27 05:19:10 +00:00
layoutTimeEnd = SDL_GetPerformanceCounter ( ) ;
2022-03-21 19:11:28 +00:00
// backup trigger
if ( modified ) {
if ( backupTimer > 0 ) {
2022-05-16 08:09:59 +00:00
backupTimer = ( backupTimer - ImGui : : GetIO ( ) . DeltaTime ) ;
2022-03-21 19:11:28 +00:00
if ( backupTimer < = 0 ) {
backupTask = std : : async ( std : : launch : : async , [ this ] ( ) - > bool {
2023-04-06 21:24:44 +00:00
backupLock . lock ( ) ;
2023-04-06 21:08:06 +00:00
logV ( " backupPath: %s " , backupPath ) ;
logV ( " curFileName: %s " , curFileName ) ;
2023-04-06 09:22:43 +00:00
if ( curFileName . find ( backupPath ) = = 0 ) {
2022-04-11 03:12:02 +00:00
logD ( " backup file open. not saving backup. " ) ;
2023-04-06 21:08:06 +00:00
backupTimer = 30.0 ;
2023-04-06 21:24:44 +00:00
backupLock . unlock ( ) ;
2022-03-21 19:11:28 +00:00
return true ;
}
2023-04-06 09:22:43 +00:00
if ( ! dirExists ( backupPath . c_str ( ) ) ) {
if ( ! makeDir ( backupPath . c_str ( ) ) ) {
logW ( " could not create backup directory! " ) ;
2023-04-06 21:08:06 +00:00
backupTimer = 30.0 ;
2023-04-06 21:24:44 +00:00
backupLock . unlock ( ) ;
2023-04-06 09:22:43 +00:00
return false ;
}
}
2022-04-11 03:12:02 +00:00
logD ( " saving backup... " ) ;
2023-05-26 06:29:49 +00:00
SafeWriter * w = e - > saveFur ( true , true ) ;
2022-12-22 18:10:08 +00:00
logV ( " writing file... " ) ;
2022-05-26 05:24:21 +00:00
2022-03-21 19:11:28 +00:00
if ( w ! = NULL ) {
2023-04-06 09:22:43 +00:00
size_t sepPos = curFileName . rfind ( DIR_SEPARATOR ) ;
2023-04-06 19:48:13 +00:00
String backupPreBaseName ;
2023-04-06 09:22:43 +00:00
String backupBaseName ;
String backupFileName ;
if ( sepPos = = String : : npos ) {
2023-04-06 19:48:13 +00:00
backupPreBaseName = curFileName ;
2023-04-06 09:22:43 +00:00
} else {
2023-04-06 19:48:13 +00:00
backupPreBaseName = curFileName . substr ( sepPos + 1 ) ;
2023-04-06 09:22:43 +00:00
}
2023-04-06 19:48:13 +00:00
size_t dotPos = backupPreBaseName . rfind ( ' . ' ) ;
2023-04-06 09:22:43 +00:00
if ( dotPos ! = String : : npos ) {
2023-04-06 19:48:13 +00:00
backupPreBaseName = backupPreBaseName . substr ( 0 , dotPos ) ;
2023-04-06 09:22:43 +00:00
}
2023-04-06 19:48:13 +00:00
for ( char i : backupPreBaseName ) {
if ( backupBaseName . size ( ) > = 48 ) break ;
if ( ( i > = ' 0 ' & & i < = ' 9 ' ) | | ( i > = ' A ' & & i < = ' Z ' ) | | ( i > = ' a ' & & i < = ' z ' ) | | i = = ' _ ' | | i = = ' - ' | | i = = ' ' ) backupBaseName + = i ;
}
if ( backupBaseName . empty ( ) ) backupBaseName = " untitled " ;
2023-04-06 09:22:43 +00:00
backupFileName = backupBaseName ;
time_t curTime = time ( NULL ) ;
struct tm curTM ;
# ifdef _WIN32
struct tm * tempTM = localtime ( & curTime ) ;
if ( tempTM = = NULL ) {
backupFileName + = " -unknownTime.fur " ;
} else {
curTM = * tempTM ;
backupFileName + = fmt : : sprintf ( " -%d%.2d%.2d-%.2d%.2d%.2d.fur " , curTM . tm_year + 1900 , curTM . tm_mon + 1 , curTM . tm_mday , curTM . tm_hour , curTM . tm_min , curTM . tm_sec ) ;
}
# else
if ( localtime_r ( & curTime , & curTM ) = = NULL ) {
backupFileName + = " -unknownTime.fur " ;
} else {
backupFileName + = fmt : : sprintf ( " -%d%.2d%.2d-%.2d%.2d%.2d.fur " , curTM . tm_year + 1900 , curTM . tm_mon + 1 , curTM . tm_mday , curTM . tm_hour , curTM . tm_min , curTM . tm_sec ) ;
}
# endif
String finalPath = backupPath + String ( DIR_SEPARATOR_STR ) + backupFileName ;
FILE * outFile = ps_fopen ( finalPath . c_str ( ) , " wb " ) ;
2022-03-21 19:11:28 +00:00
if ( outFile ! = NULL ) {
if ( fwrite ( w - > getFinalBuf ( ) , 1 , w - > size ( ) , outFile ) ! = w - > size ( ) ) {
2022-04-11 03:12:02 +00:00
logW ( " did not write backup entirely: %s! " , strerror ( errno ) ) ;
2022-03-21 19:11:28 +00:00
}
2022-03-22 02:47:27 +00:00
fclose ( outFile ) ;
2022-03-21 19:11:28 +00:00
} else {
2022-04-11 03:12:02 +00:00
logW ( " could not save backup: %s! " , strerror ( errno ) ) ;
2022-03-21 19:11:28 +00:00
}
2023-07-12 00:30:13 +00:00
w - > finish ( ) ;
2023-04-06 09:22:43 +00:00
// delete previous backup if there are too many
delFirstBackup ( backupBaseName ) ;
2022-03-21 19:11:28 +00:00
}
2022-12-22 18:10:08 +00:00
logD ( " backup saved. " ) ;
2022-03-21 19:11:28 +00:00
backupTimer = 30.0 ;
2023-04-06 21:24:44 +00:00
backupLock . unlock ( ) ;
2022-03-21 19:11:28 +00:00
return true ;
} ) ;
}
}
}
2023-04-12 00:41:20 +00:00
sampleMapWaitingInput = ( curWindow = = GUI_WINDOW_INS_EDIT & & sampleMapFocused ) ;
2022-11-06 07:06:51 +00:00
curWindowThreadSafe = curWindow ;
2022-03-21 19:11:28 +00:00
2023-04-09 20:27:17 +00:00
if ( curWindow ! = curWindowLast ) {
int curWindowCat = 0 ;
int lastWindowCat = 0 ;
switch ( curWindow ) {
case GUI_WINDOW_WAVE_LIST :
case GUI_WINDOW_WAVE_EDIT :
curWindowCat = 1 ;
break ;
case GUI_WINDOW_SAMPLE_LIST :
case GUI_WINDOW_SAMPLE_EDIT :
curWindowCat = 2 ;
break ;
default :
curWindowCat = 0 ;
break ;
}
switch ( curWindowLast ) {
case GUI_WINDOW_WAVE_LIST :
case GUI_WINDOW_WAVE_EDIT :
lastWindowCat = 1 ;
break ;
case GUI_WINDOW_SAMPLE_LIST :
case GUI_WINDOW_SAMPLE_EDIT :
lastWindowCat = 2 ;
break ;
default :
lastWindowCat = 0 ;
break ;
}
if ( curWindowCat ! = lastWindowCat ) {
switch ( lastWindowCat ) {
case 0 :
e - > autoNoteOffAll ( ) ;
break ;
case 1 :
e - > stopWavePreview ( ) ;
break ;
case 2 :
e - > stopSamplePreview ( ) ;
break ;
}
}
}
2023-06-08 09:15:57 +00:00
if ( ! settings . renderClearPos ) {
rend - > clear ( uiColors [ GUI_COLOR_BACKGROUND ] ) ;
}
2022-05-27 05:19:10 +00:00
renderTimeBegin = SDL_GetPerformanceCounter ( ) ;
2021-12-11 08:11:40 +00:00
ImGui : : Render ( ) ;
2022-05-27 05:19:10 +00:00
renderTimeEnd = SDL_GetPerformanceCounter ( ) ;
2023-06-12 20:58:16 +00:00
drawTimeBegin = SDL_GetPerformanceCounter ( ) ;
2023-06-03 01:21:37 +00:00
rend - > renderGUI ( ) ;
2023-02-16 10:40:06 +00:00
if ( mustClear ) {
2023-06-03 01:21:37 +00:00
rend - > clear ( ImVec4 ( 0 , 0 , 0 , 0 ) ) ;
2023-02-16 10:40:06 +00:00
mustClear - - ;
} else {
2023-02-16 10:54:46 +00:00
if ( initialScreenWipe > 0.0f & & ! settings . disableFadeIn ) {
2023-02-16 10:40:06 +00:00
WAKE_UP ;
initialScreenWipe - = ImGui : : GetIO ( ) . DeltaTime * 5.0f ;
if ( initialScreenWipe > 0.0f ) {
2023-06-03 01:21:37 +00:00
rend - > wipe ( pow ( initialScreenWipe , 2.0f ) ) ;
2023-02-16 10:40:06 +00:00
}
}
}
2023-06-12 20:58:16 +00:00
drawTimeEnd = SDL_GetPerformanceCounter ( ) ;
2023-06-13 00:43:26 +00:00
rend - > present ( ) ;
2023-06-08 09:15:57 +00:00
if ( settings . renderClearPos ) {
rend - > clear ( uiColors [ GUI_COLOR_BACKGROUND ] ) ;
}
2021-12-20 03:51:02 +00:00
2022-05-27 05:19:10 +00:00
layoutTimeDelta = layoutTimeEnd - layoutTimeBegin ;
renderTimeDelta = renderTimeEnd - renderTimeBegin ;
2023-06-12 20:58:16 +00:00
drawTimeDelta = drawTimeEnd - drawTimeBegin ;
2022-05-27 05:19:10 +00:00
eventTimeDelta = eventTimeEnd - eventTimeBegin ;
2023-01-14 19:07:50 +00:00
soloTimeout - = ImGui : : GetIO ( ) . DeltaTime ;
2023-01-14 18:51:02 +00:00
if ( soloTimeout < 0 ) {
soloTimeout = 0 ;
} else {
WAKE_UP ;
}
2022-01-20 07:28:55 +00:00
2023-05-24 06:58:12 +00:00
if ( ! ImGui : : IsMouseDown ( ImGuiMouseButton_Left ) ) {
exitDisabledTimer = 0 ;
}
2022-04-02 05:11:44 +00:00
wheelX = 0 ;
wheelY = 0 ;
2022-05-19 18:06:26 +00:00
wantScrollList = false ;
2022-04-02 05:11:44 +00:00
2022-05-17 17:46:52 +00:00
pressedPoints . clear ( ) ;
releasedPoints . clear ( ) ;
2021-12-20 03:51:02 +00:00
if ( willCommit ) {
commitSettings ( ) ;
willCommit = false ;
}
2022-03-02 05:09:28 +00:00
2023-08-27 08:58:01 +00:00
if ( shallDetectScale ) {
if ( - - shallDetectScale < 1 ) {
if ( settings . dpiScale < 0.5f ) {
2023-08-31 06:24:06 +00:00
const char * videoBackend = SDL_GetCurrentVideoDriver ( ) ;
double newScale = getScaleFactor ( videoBackend , sdlWin ) ;
if ( newScale < 0.1f ) {
logW ( " scale what? " ) ;
newScale = 1.0f ;
}
if ( newScale ! = dpiScale ) {
logD ( " auto UI scale changed (%f != %f) - applying settings... " , newScale , dpiScale ) ;
ImGui : : GetIO ( ) . Fonts - > Clear ( ) ;
applyUISettings ( ) ;
if ( rend ) rend - > destroyFontsTexture ( ) ;
if ( ! ImGui : : GetIO ( ) . Fonts - > Build ( ) ) {
logE ( " error while building font atlas! " ) ;
showError ( " error while loading fonts! please check your settings. " ) ;
ImGui : : GetIO ( ) . Fonts - > Clear ( ) ;
mainFont = ImGui : : GetIO ( ) . Fonts - > AddFontDefault ( ) ;
patFont = mainFont ;
bigFont = mainFont ;
headFont = mainFont ;
if ( rend ) rend - > destroyFontsTexture ( ) ;
if ( ! ImGui : : GetIO ( ) . Fonts - > Build ( ) ) {
logE ( " error again while building font atlas! " ) ;
} else {
rend - > createFontsTexture ( ) ;
}
} else {
rend - > createFontsTexture ( ) ;
}
}
2023-08-27 08:58:01 +00:00
}
}
}
2023-05-03 06:22:54 +00:00
if ( fontsFailed ) {
showError ( " it appears I couldn't load these fonts. any setting you can check? " ) ;
logE ( " couldn't load fonts " ) ;
ImGui : : GetIO ( ) . Fonts - > Clear ( ) ;
mainFont = ImGui : : GetIO ( ) . Fonts - > AddFontDefault ( ) ;
patFont = mainFont ;
2023-07-10 19:36:44 +00:00
bigFont = mainFont ;
2023-08-03 05:59:45 +00:00
headFont = mainFont ;
2023-06-03 06:41:34 +00:00
if ( rend ) rend - > destroyFontsTexture ( ) ;
2023-05-03 06:22:54 +00:00
if ( ! ImGui : : GetIO ( ) . Fonts - > Build ( ) ) {
logE ( " error again while building font atlas! " ) ;
2023-06-03 06:41:34 +00:00
} else {
rend - > createFontsTexture ( ) ;
2023-05-03 06:22:54 +00:00
}
}
2022-04-21 23:10:59 +00:00
if ( ! editOptsVisible ) {
latchTarget = 0 ;
2022-04-21 23:30:32 +00:00
latchNibble = false ;
2022-04-21 23:10:59 +00:00
}
2022-03-02 05:09:28 +00:00
if ( SDL_GetWindowFlags ( sdlWin ) & SDL_WINDOW_MINIMIZED ) {
SDL_Delay ( 100 ) ;
}
2021-12-11 08:11:40 +00:00
}
return false ;
}
2021-12-31 03:34:42 +00:00
bool FurnaceGUI : : init ( ) {
2022-10-20 06:49:33 +00:00
logI ( " initializing GUI. " ) ;
2021-12-31 03:34:42 +00:00
2022-03-02 05:02:52 +00:00
String homeDir = getHomeDir ( ) ;
workingDir = e - > getConfString ( " lastDir " , homeDir ) ;
workingDirSong = e - > getConfString ( " lastDirSong " , workingDir ) ;
workingDirIns = e - > getConfString ( " lastDirIns " , workingDir ) ;
workingDirWave = e - > getConfString ( " lastDirWave " , workingDir ) ;
workingDirSample = e - > getConfString ( " lastDirSample " , workingDir ) ;
workingDirAudioExport = e - > getConfString ( " lastDirAudioExport " , workingDir ) ;
workingDirVGMExport = e - > getConfString ( " lastDirVGMExport " , workingDir ) ;
2022-05-26 05:24:21 +00:00
workingDirZSMExport = e - > getConfString ( " lastDirZSMExport " , workingDir ) ;
2022-08-04 05:51:47 +00:00
workingDirROMExport = e - > getConfString ( " lastDirROMExport " , workingDir ) ;
2022-03-02 05:02:52 +00:00
workingDirFont = e - > getConfString ( " lastDirFont " , workingDir ) ;
2022-04-06 18:53:39 +00:00
workingDirColors = e - > getConfString ( " lastDirColors " , workingDir ) ;
workingDirKeybinds = e - > getConfString ( " lastDirKeybinds " , workingDir ) ;
workingDirLayout = e - > getConfString ( " lastDirLayout " , workingDir ) ;
2022-07-15 07:23:16 +00:00
workingDirTest = e - > getConfString ( " lastDirTest " , workingDir ) ;
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-04-30 08:58:30 +00:00
chanOscOpen = e - > getConfBool ( " chanOscOpen " , false ) ;
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 ) ;
2022-12-11 18:34:58 +00:00
# ifdef IS_MOBILE
pianoOpen = e - > getConfBool ( " pianoOpen " , true ) ;
# else
pianoOpen = e - > getConfBool ( " pianoOpen " , false ) ;
# endif
2022-02-03 05:34:48 +00:00
notesOpen = e - > getConfBool ( " notesOpen " , false ) ;
2022-02-05 06:48:35 +00:00
channelsOpen = e - > getConfBool ( " channelsOpen " , false ) ;
2022-08-16 08:42:17 +00:00
patManagerOpen = e - > getConfBool ( " patManagerOpen " , false ) ;
2022-08-19 09:41:45 +00:00
sysManagerOpen = e - > getConfBool ( " sysManagerOpen " , false ) ;
2022-11-10 06:26:59 +00:00
clockOpen = e - > getConfBool ( " clockOpen " , false ) ;
2023-02-04 22:01:32 +00:00
speedOpen = e - > getConfBool ( " speedOpen " , true ) ;
2023-02-05 07:56:39 +00:00
groovesOpen = e - > getConfBool ( " groovesOpen " , false ) ;
2022-02-22 03:31:27 +00:00
regViewOpen = e - > getConfBool ( " regViewOpen " , false ) ;
2022-04-11 03:12:02 +00:00
logOpen = e - > getConfBool ( " logOpen " , false ) ;
2023-02-24 09:26:17 +00:00
effectListOpen = e - > getConfBool ( " effectListOpen " , true ) ;
2022-05-15 06:42:49 +00:00
subSongsOpen = e - > getConfBool ( " subSongsOpen " , true ) ;
2022-06-07 18:49:12 +00:00
findOpen = e - > getConfBool ( " findOpen " , false ) ;
2022-06-20 20:20:02 +00:00
spoilerOpen = e - > getConfBool ( " spoilerOpen " , false ) ;
2022-01-29 06:54:30 +00:00
2023-02-06 23:52:51 +00:00
if ( e - > hasConf ( " lastDir " ) ) {
basicMode = e - > getConfBool ( " basicMode " , false ) ;
} else {
basicMode = true ;
}
2023-05-15 06:36:02 +00:00
insListDir = e - > getConfBool ( " insListDir " , false ) ;
waveListDir = e - > getConfBool ( " waveListDir " , false ) ;
sampleListDir = e - > getConfBool ( " sampleListDir " , false ) ;
2022-03-16 06:27:34 +00:00
tempoView = e - > getConfBool ( " tempoView " , true ) ;
2022-03-30 05:28:49 +00:00
waveHex = e - > getConfBool ( " waveHex " , false ) ;
2022-09-11 03:35:21 +00:00
waveSigned = e - > getConfBool ( " waveSigned " , false ) ;
2022-07-21 08:14:52 +00:00
waveGenVisible = e - > getConfBool ( " waveGenVisible " , false ) ;
2022-07-21 07:49:19 +00:00
waveEditStyle = e - > getConfInt ( " waveEditStyle " , 0 ) ;
2023-03-15 04:04:57 +00:00
extraChannelButtons = e - > getConfInt ( " extraChannelButtons " , 0 ) ;
2022-04-02 20:07:47 +00:00
lockLayout = e - > getConfBool ( " lockLayout " , false ) ;
2022-05-11 21:09:23 +00:00
# ifdef IS_MOBILE
fullScreen = true ;
# else
2022-04-17 06:54:42 +00:00
fullScreen = e - > getConfBool ( " fullScreen " , false ) ;
2022-05-11 21:09:23 +00:00
# endif
2022-05-09 03:52:21 +00:00
mobileUI = e - > getConfBool ( " mobileUI " , MOBILE_UI_DEFAULT ) ;
2022-05-14 06:53:14 +00:00
edit = e - > getConfBool ( " edit " , false ) ;
followOrders = e - > getConfBool ( " followOrders " , true ) ;
followPattern = e - > getConfBool ( " followPattern " , true ) ;
2022-06-03 23:05:07 +00:00
noteInputPoly = e - > getConfBool ( " noteInputPoly " , true ) ;
2022-11-05 01:27:55 +00:00
exportLoops = e - > getConfInt ( " exportLoops " , 0 ) ;
if ( exportLoops < 0 ) exportLoops = 0 ;
exportFadeOut = e - > getConfDouble ( " exportFadeOut " , 0.0 ) ;
if ( exportFadeOut < 0.0 ) exportFadeOut = 0.0 ;
2022-05-14 06:56:27 +00:00
orderEditMode = e - > getConfInt ( " orderEditMode " , 0 ) ;
if ( orderEditMode < 0 ) orderEditMode = 0 ;
if ( orderEditMode > 3 ) orderEditMode = 3 ;
2022-03-16 06:27:34 +00:00
2022-05-31 02:40:07 +00:00
oscZoom = e - > getConfFloat ( " oscZoom " , 0.5f ) ;
2022-05-31 03:22:53 +00:00
oscZoomSlider = e - > getConfBool ( " oscZoomSlider " , false ) ;
2022-05-31 02:40:07 +00:00
oscWindowSize = e - > getConfFloat ( " oscWindowSize " , 20.0f ) ;
2022-05-27 06:13:33 +00:00
pianoOctaves = e - > getConfInt ( " pianoOctaves " , pianoOctaves ) ;
pianoOctavesEdit = e - > getConfInt ( " pianoOctavesEdit " , pianoOctavesEdit ) ;
pianoOptions = e - > getConfBool ( " pianoOptions " , pianoOptions ) ;
pianoSharePosition = e - > getConfBool ( " pianoSharePosition " , pianoSharePosition ) ;
pianoOptionsSet = e - > getConfBool ( " pianoOptionsSet " , pianoOptionsSet ) ;
2023-05-24 15:47:20 +00:00
pianoReadonly = e - > getConfBool ( " pianoReadonly " , false ) ;
2022-05-27 06:13:33 +00:00
pianoOffset = e - > getConfInt ( " pianoOffset " , pianoOffset ) ;
pianoOffsetEdit = e - > getConfInt ( " pianoOffsetEdit " , pianoOffsetEdit ) ;
pianoView = e - > getConfInt ( " pianoView " , pianoView ) ;
pianoInputPadMode = e - > getConfInt ( " pianoInputPadMode " , pianoInputPadMode ) ;
2023-09-03 09:22:00 +00:00
chanOscCols = e - > getConfInt ( " chanOscCols " , 3 ) ;
2023-08-03 10:25:26 +00:00
chanOscAutoColsType = e - > getConfInt ( " chanOscAutoColsType " , 0 ) ;
2022-06-23 09:02:41 +00:00
chanOscColorX = e - > getConfInt ( " chanOscColorX " , GUI_OSCREF_CENTER ) ;
chanOscColorY = e - > getConfInt ( " chanOscColorY " , GUI_OSCREF_CENTER ) ;
2023-06-18 09:27:22 +00:00
chanOscTextX = e - > getConfFloat ( " chanOscTextX " , 0.0f ) ;
chanOscTextY = e - > getConfFloat ( " chanOscTextY " , 0.0f ) ;
chanOscAmplify = e - > getConfFloat ( " chanOscAmplify " , 0.95f ) ;
2022-06-23 09:02:41 +00:00
chanOscWindowSize = e - > getConfFloat ( " chanOscWindowSize " , 20.0f ) ;
chanOscWaveCorr = e - > getConfBool ( " chanOscWaveCorr " , true ) ;
chanOscOptions = e - > getConfBool ( " chanOscOptions " , false ) ;
2023-06-18 09:27:22 +00:00
chanOscNormalize = e - > getConfBool ( " chanOscNormalize " , false ) ;
chanOscTextFormat = e - > getConfString ( " chanOscTextFormat " , " %c " ) ;
2022-06-23 09:02:41 +00:00
chanOscColor . x = e - > getConfFloat ( " chanOscColorR " , 1.0f ) ;
chanOscColor . y = e - > getConfFloat ( " chanOscColorG " , 1.0f ) ;
chanOscColor . z = e - > getConfFloat ( " chanOscColorB " , 1.0f ) ;
chanOscColor . w = e - > getConfFloat ( " chanOscColorA " , 1.0f ) ;
2023-06-18 09:27:22 +00:00
chanOscTextColor . x = e - > getConfFloat ( " chanOscTextColorR " , 1.0f ) ;
chanOscTextColor . y = e - > getConfFloat ( " chanOscTextColorG " , 1.0f ) ;
chanOscTextColor . z = e - > getConfFloat ( " chanOscTextColorB " , 1.0f ) ;
chanOscTextColor . w = e - > getConfFloat ( " chanOscTextColorA " , 0.75f ) ;
2022-06-23 09:02:41 +00:00
chanOscUseGrad = e - > getConfBool ( " chanOscUseGrad " , false ) ;
chanOscGrad . fromString ( e - > getConfString ( " chanOscGrad " , " " ) ) ;
2022-06-24 08:17:40 +00:00
chanOscGrad . render ( ) ;
2022-06-23 09:02:41 +00:00
2022-01-16 22:25:43 +00:00
syncSettings ( ) ;
2023-02-19 05:08:37 +00:00
syncTutorial ( ) ;
2021-12-31 03:34:42 +00:00
2022-11-06 05:37:57 +00:00
if ( ! settings . persistFadeOut ) {
exportLoops = settings . exportLoops ;
exportFadeOut = settings . exportFadeOut ;
}
2022-09-10 23:53:27 +00:00
for ( int i = 0 ; i < settings . maxRecentFile ; i + + ) {
String r = e - > getConfString ( fmt : : sprintf ( " recentFile%d " , i ) , " " ) ;
if ( ! r . empty ( ) ) {
recentFile . push_back ( r ) ;
}
}
2022-05-14 07:38:38 +00:00
initSystemPresets ( ) ;
2023-02-25 23:04:17 +00:00
initTutorial ( ) ;
2022-05-14 07:38:38 +00:00
2022-06-03 23:05:07 +00:00
e - > setAutoNotePoly ( noteInputPoly ) ;
2022-10-19 20:33:20 +00:00
SDL_SetHint ( SDL_HINT_VIDEO_ALLOW_SCREENSAVER , " 1 " ) ;
2023-06-04 22:09:18 +00:00
# if SDL_VERSION_ATLEAST(2,0,17)
2022-10-19 20:33:20 +00:00
SDL_SetHint ( SDL_HINT_MOUSE_TOUCH_EVENTS , " 0 " ) ;
2023-06-04 22:09:18 +00:00
# endif
2022-10-19 20:33:20 +00:00
SDL_SetHint ( SDL_HINT_TOUCH_MOUSE_EVENTS , " 0 " ) ;
// don't disable compositing on KWin
# if SDL_VERSION_ATLEAST(2,0,22)
2022-10-20 06:49:33 +00:00
logV ( " setting window type to NORMAL. " ) ;
2022-10-19 20:33:20 +00:00
SDL_SetHint ( SDL_HINT_X11_WINDOW_TYPE , " _NET_WM_WINDOW_TYPE_NORMAL " ) ;
# endif
// initialize SDL
2023-06-05 03:37:32 +00:00
logD ( " initializing video... " ) ;
2023-06-02 19:11:47 +00:00
if ( SDL_Init ( SDL_INIT_VIDEO ) ! = 0 ) {
logE ( " could not initialize video! %s " , SDL_GetError ( ) ) ;
return false ;
}
2023-06-05 03:37:32 +00:00
# ifdef IS_MOBILE
logD ( " initializing haptic... " ) ;
2023-06-02 19:11:47 +00:00
if ( SDL_Init ( SDL_INIT_HAPTIC ) ! = 0 ) {
logW ( " could not initialize haptic! %s " , SDL_GetError ( ) ) ;
}
2023-06-05 03:37:32 +00:00
# endif
2022-10-19 20:33:20 +00:00
const char * videoBackend = SDL_GetCurrentVideoDriver ( ) ;
if ( videoBackend ! = NULL ) {
2022-10-20 06:49:33 +00:00
logV ( " video backend: %s " , videoBackend ) ;
2022-10-19 20:33:20 +00:00
if ( strcmp ( videoBackend , " wayland " ) = = 0 | |
strcmp ( videoBackend , " cocoa " ) = = 0 | |
strcmp ( videoBackend , " uikit " ) = = 0 ) {
sysManagedScale = true ;
2022-10-20 06:49:33 +00:00
logV ( " scaling managed by system. " ) ;
} else {
logV ( " scaling managed by application. " ) ;
2022-10-19 20:33:20 +00:00
}
2022-10-20 06:49:33 +00:00
} else {
logV ( " could not get video backend name! " ) ;
2022-10-19 20:33:20 +00:00
}
2022-10-20 06:49:33 +00:00
// get scale factor
if ( settings . dpiScale > = 0.5f ) {
logD ( " setting UI scale factor from config (%f). " , settings . dpiScale ) ;
dpiScale = settings . dpiScale ;
} else {
logD ( " auto-detecting UI scale factor. " ) ;
2023-08-31 06:24:06 +00:00
dpiScale = getScaleFactor ( videoBackend , sdlWin ) ;
2022-10-20 06:49:33 +00:00
logD ( " scale factor: %f " , dpiScale ) ;
2023-02-03 20:31:02 +00:00
if ( dpiScale < 0.1f ) {
logW ( " scale what? " ) ;
dpiScale = 1.0f ;
}
2022-10-20 06:49:33 +00:00
}
2022-10-19 20:33:20 +00:00
2022-01-20 06:46:03 +00:00
# if !(defined(__APPLE__) || defined(_WIN32))
2022-10-19 20:33:20 +00:00
// get the icon (on macOS and Windows the icon is bundled with the app)
2023-02-15 23:32:31 +00:00
const FurnaceGUIImage * furIcon = getImage ( GUI_IMAGE_ICON ) ;
SDL_Surface * icon = NULL ;
2023-02-15 23:59:49 +00:00
if ( furIcon ! = NULL ) {
2023-02-16 03:04:14 +00:00
icon = SDL_CreateRGBSurfaceFrom ( furIcon - > data , furIcon - > width , furIcon - > height , 32 , 256 * 4 , 0xff , 0xff00 , 0xff0000 , 0xff000000 ) ;
2023-02-15 23:59:49 +00:00
} else {
logE ( " furIcon is NULL! " ) ;
}
2022-01-07 08:29:56 +00:00
# endif
2022-09-09 20:31:29 +00:00
# ifdef IS_MOBILE
scrW = 960 ;
scrH = 540 ;
scrX = 0 ;
scrY = 0 ;
# else
2022-10-20 06:49:33 +00:00
scrW = scrConfW = e - > getConfInt ( " lastWindowWidth " , 1280 ) ;
scrH = scrConfH = e - > getConfInt ( " lastWindowHeight " , 800 ) ;
2022-08-22 00:47:00 +00:00
scrX = scrConfX = e - > getConfInt ( " lastWindowX " , SDL_WINDOWPOS_CENTERED ) ;
scrY = scrConfY = e - > getConfInt ( " lastWindowY " , SDL_WINDOWPOS_CENTERED ) ;
scrMax = e - > getConfBool ( " lastWindowMax " , false ) ;
2022-09-09 20:31:29 +00:00
# endif
2022-09-08 22:04:38 +00:00
portrait = ( scrW < scrH ) ;
2022-09-09 00:15:19 +00:00
logV ( " portrait: %d (%dx%d) " , portrait , scrW , scrH ) ;
2022-01-29 22:27:51 +00:00
2022-10-20 06:49:33 +00:00
// if old config, scale size as it was stored unscaled before
if ( e - > getConfInt ( " configVersion " , 0 ) < 122 & & ! sysManagedScale ) {
logD ( " scaling window size to scale factor because configVersion is not present. " ) ;
scrW * = dpiScale ;
scrH * = dpiScale ;
}
// predict the canvas size
if ( sysManagedScale ) {
canvasW = scrW * dpiScale ;
canvasH = scrH * dpiScale ;
} else {
canvasW = scrW ;
canvasH = scrH ;
}
2022-10-20 07:34:14 +00:00
# ifndef IS_MOBILE
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-09-09 20:31:29 +00:00
# ifndef IS_MOBILE
2022-08-22 19:05:16 +00:00
// if window would spawn out of bounds, force it to be get default position
2023-04-30 21:07:46 +00:00
SDL_Rect bounds ;
if ( ! detectOutOfBoundsWindow ( bounds ) ) {
2022-09-08 22:04:38 +00:00
scrMax = false ;
2022-08-22 19:05:16 +00:00
scrX = scrConfX = SDL_WINDOWPOS_CENTERED ;
scrY = scrConfY = SDL_WINDOWPOS_CENTERED ;
2023-04-30 21:07:46 +00:00
// make sure our window isn't big
2023-05-01 06:36:47 +00:00
/*if (bounds.w<scrW) {
2023-04-30 21:07:46 +00:00
logD ( " resizing width because it does not fit " ) ;
scrW = bounds . w - OOB_PIXELS_SAFETY * 2 ;
if ( scrW < 200 ) scrW = 200 ;
}
if ( bounds . h < scrH ) {
logD ( " resizing height because it does not fit " ) ;
scrH = bounds . h - OOB_PIXELS_SAFETY * 2 ;
if ( scrH < 100 ) scrH = 100 ;
2023-05-01 06:36:47 +00:00
} */
2022-08-22 19:05:16 +00:00
}
2022-09-09 20:31:29 +00:00
# endif
2022-08-22 19:05:16 +00:00
2022-10-20 06:49:33 +00:00
logV ( " window size: %dx%d " , scrW , scrH ) ;
2023-06-03 06:41:34 +00:00
if ( ! initRender ( ) ) {
2023-07-09 03:26:51 +00:00
if ( settings . renderBackend ! = " SDL " ) {
settings . renderBackend = " SDL " ;
e - > setConf ( " renderBackend " , " SDL " ) ;
2023-06-03 06:41:34 +00:00
e - > saveConf ( ) ;
2023-07-09 08:32:38 +00:00
lastError = fmt : : sprintf ( " could not init renderer! \r \n the render backend has been set to a safe value. please restart Furnace. " ) ;
2023-06-03 06:41:34 +00:00
} else {
lastError = fmt : : sprintf ( " could not init renderer! %s " , SDL_GetError ( ) ) ;
if ( ! settings . renderDriver . empty ( ) ) {
settings . renderDriver = " " ;
e - > setConf ( " renderDriver " , " " ) ;
e - > saveConf ( ) ;
2023-07-09 08:32:38 +00:00
lastError + = fmt : : sprintf ( " \r \n the render driver has been set to a safe value. please restart Furnace. " ) ;
2023-06-03 06:41:34 +00:00
}
}
return false ;
}
rend - > preInit ( ) ;
2023-06-05 04:55:57 +00:00
logD ( " creating window... " ) ;
2023-06-03 06:41:34 +00:00
sdlWin = SDL_CreateWindow ( " Furnace " , scrX , scrY , scrW , scrH , SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI | ( scrMax ? SDL_WINDOW_MAXIMIZED : 0 ) | ( fullScreen ? SDL_WINDOW_FULLSCREEN_DESKTOP : 0 ) | rend - > getWindowFlags ( ) ) ;
2021-12-11 08:11:40 +00:00
if ( sdlWin = = NULL ) {
2022-10-02 21:12:02 +00:00
lastError = fmt : : sprintf ( " could not open window! %s " , SDL_GetError ( ) ) ;
2021-12-11 08:11:40 +00:00
return false ;
}
2022-01-07 08:29:56 +00:00
2022-10-20 07:34:14 +00:00
# ifndef IS_MOBILE
2022-10-20 06:49:33 +00:00
if ( SDL_GetDisplayUsableBounds ( SDL_GetWindowDisplayIndex ( sdlWin ) , & displaySize ) = = 0 ) {
bool mustChange = false ;
if ( scrW > ( ( displaySize . w ) - 48 ) & & scrH > ( ( displaySize . h ) - 64 ) ) {
// maximize
SDL_MaximizeWindow ( sdlWin ) ;
logD ( " maximizing as it doesn't fit (%dx%d+%d+%d). " , displaySize . w , displaySize . h , displaySize . x , displaySize . y ) ;
2022-04-17 06:54:42 +00:00
}
2022-10-20 06:49:33 +00:00
if ( scrW > displaySize . w ) {
scrW = ( displaySize . w ) - 32 ;
mustChange = true ;
}
if ( scrH > displaySize . h ) {
scrH = ( displaySize . h ) - 32 ;
mustChange = true ;
}
if ( mustChange ) {
2022-09-08 22:04:38 +00:00
portrait = ( scrW < scrH ) ;
2022-09-09 00:15:19 +00:00
logV ( " portrait: %d (%dx%d) " , portrait , scrW , scrH ) ;
2022-04-17 06:54:42 +00:00
if ( ! fullScreen ) {
2022-10-20 06:49:33 +00:00
logD ( " setting window size to %dx%d as it goes off bounds (%dx%d+%d+%d). " , scrW , scrH , displaySize . w , displaySize . h , displaySize . x , displaySize . y ) ;
SDL_SetWindowSize ( sdlWin , scrW , scrH ) ;
2022-04-17 06:54:42 +00:00
}
2022-02-15 22:42:56 +00:00
}
2022-01-29 22:23:45 +00:00
}
2022-10-20 07:34:14 +00:00
# endif
2022-01-29 22:23:45 +00:00
2022-05-17 17:46:52 +00:00
# ifdef IS_MOBILE
SDL_GetWindowSize ( sdlWin , & scrW , & scrH ) ;
2022-09-09 00:15:19 +00:00
portrait = ( scrW < scrH ) ;
logV ( " portrait: %d (%dx%d) " , portrait , scrW , scrH ) ;
2022-05-17 17:46:52 +00:00
# endif
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 ) ;
} else {
2022-04-11 03:12:02 +00:00
logW ( " could not create icon! " ) ;
2022-01-07 08:29:56 +00:00
}
# endif
2023-07-07 02:14:25 +00:00
int numDriversA = SDL_GetNumAudioDrivers ( ) ;
if ( numDriversA < 0 ) {
logW ( " could not list audio drivers! %s " , SDL_GetError ( ) ) ;
} else {
for ( int i = 0 ; i < numDriversA ; i + + ) {
const char * r = SDL_GetAudioDriver ( i ) ;
if ( r = = NULL ) continue ;
if ( strcmp ( r , " disk " ) = = 0 ) continue ;
if ( strcmp ( r , " dummy " ) = = 0 ) continue ;
availAudioDrivers . push_back ( String ( r ) ) ;
}
}
2023-02-05 20:24:11 +00:00
int numDrivers = SDL_GetNumRenderDrivers ( ) ;
if ( numDrivers < 0 ) {
logW ( " could not list render drivers! %s " , SDL_GetError ( ) ) ;
} else {
SDL_RendererInfo ri ;
2023-08-28 08:02:35 +00:00
logV ( " available render drivers: " ) ;
2023-02-05 20:24:11 +00:00
for ( int i = 0 ; i < numDrivers ; i + + ) {
int r = SDL_GetRenderDriverInfo ( i , & ri ) ;
if ( r ! = 0 ) continue ;
availRenderDrivers . push_back ( String ( ri . name ) ) ;
2023-08-28 08:02:35 +00:00
logV ( " - %s " , ri . name ) ;
2023-02-05 20:24:11 +00:00
}
}
if ( ! settings . renderDriver . empty ( ) ) {
SDL_SetHint ( SDL_HINT_RENDER_DRIVER , settings . renderDriver . c_str ( ) ) ;
}
2023-06-05 04:55:57 +00:00
logD ( " starting render backend... " ) ;
2023-06-03 06:41:34 +00:00
if ( ! rend - > init ( sdlWin ) ) {
2023-08-28 08:02:35 +00:00
logE ( " it failed... " ) ;
2023-07-06 09:04:33 +00:00
if ( settings . renderBackend ! = " SDL " ) {
settings . renderBackend = " SDL " ;
2023-07-09 08:32:38 +00:00
e - > setConf ( " renderBackend " , " SDL " ) ;
2023-07-09 03:26:51 +00:00
e - > saveConf ( ) ;
2023-07-09 08:32:38 +00:00
lastError = fmt : : sprintf ( " could not init renderer! \r \n the render backend has been set to a safe value. please restart Furnace. " ) ;
2023-06-03 01:21:37 +00:00
} else {
lastError = fmt : : sprintf ( " could not init renderer! %s " , SDL_GetError ( ) ) ;
if ( ! settings . renderDriver . empty ( ) ) {
settings . renderDriver = " " ;
e - > setConf ( " renderDriver " , " " ) ;
e - > saveConf ( ) ;
2023-07-09 08:32:38 +00:00
lastError + = fmt : : sprintf ( " \r \n the render driver has been set to a safe value. please restart Furnace. " ) ;
2023-06-03 01:21:37 +00:00
}
2023-02-05 20:24:11 +00:00
}
2021-12-11 08:11:40 +00:00
return false ;
}
2023-08-28 08:02:35 +00:00
logV ( " render backend started " ) ;
2021-12-11 08:11:40 +00:00
2022-10-20 06:49:33 +00:00
// try acquiring the canvas size
2023-06-03 01:21:37 +00:00
if ( ! rend - > getOutputSize ( canvasW , canvasH ) ) {
logW ( " could not get renderer output size! " ) ;
2022-10-20 06:49:33 +00:00
} else {
logV ( " canvas size: %dx%d " , canvasW , canvasH ) ;
}
// special consideration for Wayland
if ( settings . dpiScale < 0.5f ) {
if ( strcmp ( videoBackend , " wayland " ) = = 0 ) {
2023-06-12 05:12:02 +00:00
int realW = scrW ;
int realH = scrH ;
SDL_GetWindowSize ( sdlWin , & realW , & realH ) ;
if ( realW < 1 ) {
2023-06-02 19:06:25 +00:00
logW ( " screen width is zero! \n " ) ;
dpiScale = 1.0 ;
} else {
2023-06-12 05:12:02 +00:00
dpiScale = ( double ) canvasW / ( double ) realW ;
logV ( " we're on Wayland... scaling factor: %f " , dpiScale ) ;
2023-06-02 19:06:25 +00:00
}
2022-10-20 06:49:33 +00:00
}
}
2022-02-08 07:04:23 +00:00
2023-06-05 04:55:57 +00:00
updateWindowTitle ( ) ;
rend - > clear ( ImVec4 ( 0.0 , 0.0 , 0.0 , 1.0 ) ) ;
rend - > present ( ) ;
logD ( " preparing user interface... " ) ;
2023-07-02 05:09:39 +00:00
IMGUI_CHECKVERSION ( ) ;
ImGui : : CreateContext ( ) ;
2023-06-03 01:21:37 +00:00
rend - > initGUI ( sdlWin ) ;
2021-12-11 08:11:40 +00:00
2022-01-22 06:50:52 +00:00
applyUISettings ( ) ;
2021-12-11 08:11:40 +00:00
2023-06-05 04:55:57 +00:00
logD ( " building font... " ) ;
2022-02-18 02:40:31 +00:00
if ( ! ImGui : : GetIO ( ) . Fonts - > Build ( ) ) {
2022-04-11 03:12:02 +00:00
logE ( " error while building font atlas! " ) ;
2022-02-18 02:40:31 +00:00
showError ( " error while loading fonts! please check your settings. " ) ;
ImGui : : GetIO ( ) . Fonts - > Clear ( ) ;
mainFont = ImGui : : GetIO ( ) . Fonts - > AddFontDefault ( ) ;
patFont = mainFont ;
2023-07-10 19:38:26 +00:00
bigFont = mainFont ;
2023-08-03 06:20:59 +00:00
headFont = mainFont ;
2023-06-03 06:41:34 +00:00
if ( rend ) rend - > destroyFontsTexture ( ) ;
2022-02-18 02:40:31 +00:00
if ( ! ImGui : : GetIO ( ) . Fonts - > Build ( ) ) {
2022-04-11 03:12:02 +00:00
logE ( " error again while building font atlas! " ) ;
2022-02-18 02:40:31 +00:00
}
}
2023-06-05 04:55:57 +00:00
logD ( " preparing layout... " ) ;
2021-12-19 21:01:24 +00:00
strncpy ( finalLayoutPath , ( e - > getConfigPath ( ) + String ( LAYOUT_INI ) ) . c_str ( ) , 4095 ) ;
2023-04-06 21:08:06 +00:00
backupPath = e - > getConfigPath ( ) ;
if ( backupPath . size ( ) > 0 ) {
if ( backupPath [ backupPath . size ( ) - 1 ] = = DIR_SEPARATOR ) backupPath . resize ( backupPath . size ( ) - 1 ) ;
}
backupPath + = String ( BACKUPS_DIR ) ;
2021-12-19 21:01:24 +00:00
prepareLayout ( ) ;
2021-12-19 08:16:24 +00:00
2021-12-14 01:55:40 +00:00
ImGui : : GetIO ( ) . ConfigFlags | = ImGuiConfigFlags_DockingEnable ;
2022-05-18 23:42:59 +00:00
toggleMobileUI ( mobileUI , true ) ;
2021-12-14 01:55:40 +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
2022-03-11 03:10:52 +00:00
firstFrame = true ;
2022-03-28 23:19:47 +00:00
// TODO: MIDI mapping time!
e - > setMidiCallback ( [ this ] ( const TAMidiMessage & msg ) - > int {
2023-02-24 07:03:43 +00:00
if ( introPos < 11.0 ) return - 2 ;
2022-03-28 23:19:47 +00:00
midiLock . lock ( ) ;
midiQueue . push ( msg ) ;
midiLock . unlock ( ) ;
2022-03-31 06:51:57 +00:00
e - > setMidiBaseChan ( cursor . xCoarse ) ;
2022-05-08 07:01:32 +00:00
if ( msg . type = = TA_MIDI_SYSEX ) return - 2 ;
2022-04-01 06:50:01 +00:00
if ( midiMap . valueInputStyle ! = 0 & & cursor . xFine ! = 0 & & edit ) return - 2 ;
if ( ! midiMap . noteInput ) return - 2 ;
2022-03-31 23:39:01 +00:00
if ( learning ! = - 1 ) return - 2 ;
2022-03-29 22:38:30 +00:00
if ( midiMap . at ( msg ) ) return - 2 ;
2022-11-06 07:06:51 +00:00
if ( curWindowThreadSafe = = GUI_WINDOW_WAVE_EDIT | | curWindowThreadSafe = = GUI_WINDOW_WAVE_LIST ) {
if ( ( msg . type & 0xf0 ) = = TA_MIDI_NOTE_ON ) {
e - > previewWaveNoLock ( curWave , msg . data [ 0 ] - 12 ) ;
wavePreviewNote = msg . data [ 0 ] - 12 ;
} else if ( ( msg . type & 0xf0 ) = = TA_MIDI_NOTE_OFF ) {
if ( wavePreviewNote = = msg . data [ 0 ] - 12 ) {
e - > stopWavePreviewNoLock ( ) ;
}
}
return - 2 ;
}
if ( curWindowThreadSafe = = GUI_WINDOW_SAMPLE_EDIT | | curWindowThreadSafe = = GUI_WINDOW_SAMPLE_LIST ) {
if ( ( msg . type & 0xf0 ) = = TA_MIDI_NOTE_ON ) {
e - > previewSampleNoLock ( curSample , msg . data [ 0 ] - 12 ) ;
samplePreviewNote = msg . data [ 0 ] - 12 ;
} else if ( ( msg . type & 0xf0 ) = = TA_MIDI_NOTE_OFF ) {
if ( samplePreviewNote = = msg . data [ 0 ] - 12 ) {
e - > stopSamplePreviewNoLock ( ) ;
}
}
return - 2 ;
}
2022-03-28 23:19:47 +00:00
return curIns ;
2022-03-28 20:24:09 +00:00
} ) ;
2023-06-05 04:55:57 +00:00
# ifdef IS_MOBILE
2022-12-02 21:52:47 +00:00
vibrator = SDL_HapticOpen ( 0 ) ;
if ( vibrator = = NULL ) {
logD ( " could not open vibration device: %s " , SDL_GetError ( ) ) ;
} else {
if ( SDL_HapticRumbleInit ( vibrator ) = = 0 ) {
vibratorAvailable = true ;
} else {
logD ( " vibration not available: %s " , SDL_GetError ( ) ) ;
}
}
2023-06-05 04:55:57 +00:00
# endif
2022-12-02 21:52:47 +00:00
2023-09-05 09:38:57 +00:00
cpuCores = SDL_GetCPUCount ( ) ;
if ( cpuCores < 1 ) cpuCores = 1 ;
2023-06-05 04:55:57 +00:00
logI ( " done! " ) ;
2021-12-11 08:11:40 +00:00
return true ;
2021-12-19 21:01:24 +00:00
}
2022-11-10 21:47:53 +00:00
void FurnaceGUI : : commitState ( ) {
2022-05-18 23:42:59 +00:00
if ( ! mobileUI ) {
2023-04-06 00:08:04 +00:00
if ( ! ImGui : : SaveIniSettingsToDisk ( finalLayoutPath , true ) ) {
2023-04-04 21:01:45 +00:00
reportError ( fmt : : sprintf ( " could NOT save layout! %s " , strerror ( errno ) ) ) ;
}
2022-05-18 23:42:59 +00:00
}
2021-12-26 23:05:18 +00:00
2022-10-20 06:49:33 +00:00
e - > setConf ( " configVersion " , ( int ) DIV_ENGINE_VERSION ) ;
2021-12-31 03:34:42 +00:00
e - > setConf ( " lastDir " , workingDir ) ;
2022-03-02 05:02:52 +00:00
e - > setConf ( " lastDirSong " , workingDirSong ) ;
e - > setConf ( " lastDirIns " , workingDirIns ) ;
e - > setConf ( " lastDirWave " , workingDirWave ) ;
e - > setConf ( " lastDirSample " , workingDirSample ) ;
e - > setConf ( " lastDirAudioExport " , workingDirAudioExport ) ;
e - > setConf ( " lastDirVGMExport " , workingDirVGMExport ) ;
2022-05-26 05:24:21 +00:00
e - > setConf ( " lastDirZSMExport " , workingDirZSMExport ) ;
2022-08-04 05:51:47 +00:00
e - > setConf ( " lastDirROMExport " , workingDirROMExport ) ;
2022-03-02 05:02:52 +00:00
e - > setConf ( " lastDirFont " , workingDirFont ) ;
2022-04-06 18:53:39 +00:00
e - > setConf ( " lastDirColors " , workingDirColors ) ;
e - > setConf ( " lastDirKeybinds " , workingDirKeybinds ) ;
e - > setConf ( " lastDirLayout " , workingDirLayout ) ;
2022-07-15 07:23:16 +00:00
e - > setConf ( " lastDirTest " , workingDirTest ) ;
2021-12-31 03:34:42 +00:00
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-04-30 08:58:30 +00:00
e - > setConf ( " chanOscOpen " , chanOscOpen ) ;
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-08-16 08:42:17 +00:00
e - > setConf ( " patManagerOpen " , patManagerOpen ) ;
2022-08-19 09:41:45 +00:00
e - > setConf ( " sysManagerOpen " , sysManagerOpen ) ;
2022-11-10 06:26:59 +00:00
e - > setConf ( " clockOpen " , clockOpen ) ;
2023-02-04 22:01:32 +00:00
e - > setConf ( " speedOpen " , speedOpen ) ;
2023-02-05 07:56:39 +00:00
e - > setConf ( " groovesOpen " , groovesOpen ) ;
2022-02-22 03:31:27 +00:00
e - > setConf ( " regViewOpen " , regViewOpen ) ;
2022-04-11 03:12:02 +00:00
e - > setConf ( " logOpen " , logOpen ) ;
2022-04-19 23:44:05 +00:00
e - > setConf ( " effectListOpen " , effectListOpen ) ;
2022-05-15 06:42:49 +00:00
e - > setConf ( " subSongsOpen " , subSongsOpen ) ;
2022-06-07 18:49:12 +00:00
e - > setConf ( " findOpen " , findOpen ) ;
2022-06-20 20:20:02 +00:00
e - > setConf ( " spoilerOpen " , spoilerOpen ) ;
2023-02-06 23:52:51 +00:00
e - > setConf ( " basicMode " , basicMode ) ;
2022-01-29 06:54:30 +00:00
2023-05-15 06:36:02 +00:00
// commit dir state
e - > setConf ( " insListDir " , insListDir ) ;
e - > setConf ( " waveListDir " , waveListDir ) ;
e - > setConf ( " sampleListDir " , sampleListDir ) ;
2022-01-29 22:27:51 +00:00
// commit last window size
2022-08-22 00:47:00 +00:00
e - > setConf ( " lastWindowWidth " , scrConfW ) ;
e - > setConf ( " lastWindowHeight " , scrConfH ) ;
2022-08-22 19:17:19 +00:00
e - > setConf ( " lastWindowX " , settings . saveWindowPos ? scrConfX : ( int ) SDL_WINDOWPOS_CENTERED ) ;
e - > setConf ( " lastWindowY " , settings . saveWindowPos ? scrConfY : ( int ) SDL_WINDOWPOS_CENTERED ) ;
2022-08-22 00:47:00 +00:00
e - > setConf ( " lastWindowMax " , scrMax ) ;
2022-01-29 22:27:51 +00:00
2022-03-16 06:27:34 +00:00
e - > setConf ( " tempoView " , tempoView ) ;
2022-03-30 05:28:49 +00:00
e - > setConf ( " waveHex " , waveHex ) ;
2022-09-11 03:35:21 +00:00
e - > setConf ( " waveSigned " , waveSigned ) ;
2022-07-21 08:14:52 +00:00
e - > setConf ( " waveGenVisible " , waveGenVisible ) ;
2022-07-21 07:49:19 +00:00
e - > setConf ( " waveEditStyle " , waveEditStyle ) ;
2023-03-15 04:04:57 +00:00
e - > setConf ( " extraChannelButtons " , extraChannelButtons ) ;
2022-04-02 20:07:47 +00:00
e - > setConf ( " lockLayout " , lockLayout ) ;
2022-04-17 06:54:42 +00:00
e - > setConf ( " fullScreen " , fullScreen ) ;
2022-05-09 03:52:21 +00:00
e - > setConf ( " mobileUI " , mobileUI ) ;
2022-05-14 06:53:14 +00:00
e - > setConf ( " edit " , edit ) ;
e - > setConf ( " followOrders " , followOrders ) ;
e - > setConf ( " followPattern " , followPattern ) ;
2022-05-14 06:56:27 +00:00
e - > setConf ( " orderEditMode " , orderEditMode ) ;
2022-06-03 23:05:07 +00:00
e - > setConf ( " noteInputPoly " , noteInputPoly ) ;
2022-11-06 05:37:57 +00:00
if ( settings . persistFadeOut ) {
e - > setConf ( " exportLoops " , exportLoops ) ;
e - > setConf ( " exportFadeOut " , exportFadeOut ) ;
}
2022-03-16 06:27:34 +00:00
2022-05-31 02:40:07 +00:00
// commit oscilloscope state
e - > setConf ( " oscZoom " , oscZoom ) ;
2022-05-31 03:22:53 +00:00
e - > setConf ( " oscZoomSlider " , oscZoomSlider ) ;
2022-05-31 02:40:07 +00:00
e - > setConf ( " oscWindowSize " , oscWindowSize ) ;
2022-03-16 06:27:34 +00:00
2022-05-27 06:13:33 +00:00
// commit piano state
e - > setConf ( " pianoOctaves " , pianoOctaves ) ;
e - > setConf ( " pianoOctavesEdit " , pianoOctavesEdit ) ;
e - > setConf ( " pianoOptions " , pianoOptions ) ;
e - > setConf ( " pianoSharePosition " , pianoSharePosition ) ;
e - > setConf ( " pianoOptionsSet " , pianoOptionsSet ) ;
2023-05-24 15:47:20 +00:00
e - > setConf ( " pianoReadonly " , pianoReadonly ) ;
2022-05-27 06:13:33 +00:00
e - > setConf ( " pianoOffset " , pianoOffset ) ;
e - > setConf ( " pianoOffsetEdit " , pianoOffsetEdit ) ;
e - > setConf ( " pianoView " , pianoView ) ;
e - > setConf ( " pianoInputPadMode " , pianoInputPadMode ) ;
2022-06-23 09:02:41 +00:00
// commit per-chan osc state
e - > setConf ( " chanOscCols " , chanOscCols ) ;
2023-08-03 10:25:26 +00:00
e - > setConf ( " chanOscAutoColsType " , chanOscAutoColsType ) ;
2022-06-23 09:02:41 +00:00
e - > setConf ( " chanOscColorX " , chanOscColorX ) ;
e - > setConf ( " chanOscColorY " , chanOscColorY ) ;
2023-06-18 09:27:22 +00:00
e - > setConf ( " chanOscTextX " , chanOscTextX ) ;
e - > setConf ( " chanOscTextY " , chanOscTextY ) ;
e - > setConf ( " chanOscAmplify " , chanOscAmplify ) ;
2022-06-23 09:02:41 +00:00
e - > setConf ( " chanOscWindowSize " , chanOscWindowSize ) ;
e - > setConf ( " chanOscWaveCorr " , chanOscWaveCorr ) ;
e - > setConf ( " chanOscOptions " , chanOscOptions ) ;
2023-06-18 09:27:22 +00:00
e - > setConf ( " chanOscNormalize " , chanOscNormalize ) ;
e - > setConf ( " chanOscTextFormat " , chanOscTextFormat ) ;
2022-06-23 09:02:41 +00:00
e - > setConf ( " chanOscColorR " , chanOscColor . x ) ;
e - > setConf ( " chanOscColorG " , chanOscColor . y ) ;
e - > setConf ( " chanOscColorB " , chanOscColor . z ) ;
e - > setConf ( " chanOscColorA " , chanOscColor . w ) ;
2023-06-18 09:27:22 +00:00
e - > setConf ( " chanOscTextColorR " , chanOscTextColor . x ) ;
e - > setConf ( " chanOscTextColorG " , chanOscTextColor . y ) ;
e - > setConf ( " chanOscTextColorB " , chanOscTextColor . z ) ;
e - > setConf ( " chanOscTextColorA " , chanOscTextColor . w ) ;
2022-06-23 09:02:41 +00:00
e - > setConf ( " chanOscUseGrad " , chanOscUseGrad ) ;
e - > setConf ( " chanOscGrad " , chanOscGrad . toString ( ) ) ;
2022-09-10 23:53:27 +00:00
// commit recent files
for ( int i = 0 ; i < 30 ; i + + ) {
String key = fmt : : sprintf ( " recentFile%d " , i ) ;
if ( i > = settings . maxRecentFile | | i > = ( int ) recentFile . size ( ) ) {
e - > setConf ( key , " " ) ;
} else {
e - > setConf ( key , recentFile [ i ] ) ;
}
}
2022-11-10 21:47:53 +00:00
}
bool FurnaceGUI : : finish ( ) {
commitState ( ) ;
2023-06-03 01:21:37 +00:00
rend - > quitGUI ( ) ;
2022-11-10 21:47:53 +00:00
ImGui_ImplSDL2_Shutdown ( ) ;
2023-06-03 01:21:37 +00:00
quitRender ( ) ;
2023-07-02 05:09:39 +00:00
ImGui : : DestroyContext ( ) ;
2022-11-10 21:47:53 +00:00
SDL_DestroyWindow ( sdlWin ) ;
2022-09-10 23:53:27 +00:00
2022-12-02 21:52:47 +00:00
if ( vibrator ) {
SDL_HapticClose ( vibrator ) ;
}
2023-08-05 08:26:36 +00:00
for ( int i = 0 ; i < DIV_MAX_OUTPUTS ; i + + ) {
if ( oscValues [ i ] ) {
delete [ ] oscValues [ i ] ;
oscValues [ i ] = NULL ;
}
}
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 ] ;
}
2022-03-21 19:11:28 +00:00
if ( backupTask . valid ( ) ) {
backupTask . get ( ) ;
}
2023-09-05 09:38:57 +00:00
if ( chanOscWorkPool ! = NULL ) {
delete chanOscWorkPool ;
}
2021-12-19 21:01:24 +00:00
return true ;
2021-12-11 08:11:40 +00:00
}
2023-07-10 00:19:37 +00:00
void FurnaceGUI : : requestQuit ( ) {
quit = true ;
}
2021-12-11 07:10:09 +00:00
FurnaceGUI : : FurnaceGUI ( ) :
2021-12-11 08:11:40 +00:00
e ( NULL ) ,
2023-06-03 06:41:34 +00:00
renderBackend ( GUI_BACKEND_SDL ) ,
rend ( NULL ) ,
2022-04-04 18:25:38 +00:00
sdlWin ( NULL ) ,
2022-12-02 21:52:47 +00:00
vibrator ( NULL ) ,
vibratorAvailable ( false ) ,
2022-03-17 08:43:02 +00:00
sampleTex ( NULL ) ,
sampleTexW ( 0 ) ,
sampleTexH ( 0 ) ,
updateSampleTex ( true ) ,
2021-12-11 08:11:40 +00:00
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 ) ,
2022-05-26 05:24:21 +00:00
zsmExportLoop ( true ) ,
2023-08-11 20:03:37 +00:00
zsmExportOptimize ( true ) ,
2022-08-03 23:44:45 +00:00
vgmExportPatternHints ( false ) ,
2022-10-17 09:17:00 +00:00
vgmExportDirectStream ( false ) ,
2022-11-13 23:29:37 +00:00
displayInsTypeList ( false ) ,
2022-09-08 22:04:38 +00:00
portrait ( false ) ,
2022-11-05 23:17:54 +00:00
injectBackUp ( false ) ,
2022-09-09 00:15:19 +00:00
mobileMenuOpen ( false ) ,
2023-06-23 00:49:45 +00:00
warnColorPushed ( false ) ,
2022-04-16 04:47:39 +00:00
wantCaptureKeyboard ( false ) ,
2022-05-11 21:09:23 +00:00
oldWantCaptureKeyboard ( false ) ,
2022-05-08 23:32:16 +00:00
displayMacroMenu ( false ) ,
2022-03-01 22:19:52 +00:00
displayNew ( false ) ,
2022-04-17 06:54:42 +00:00
fullScreen ( false ) ,
2022-04-28 08:36:15 +00:00
preserveChanPos ( false ) ,
2022-05-19 18:06:26 +00:00
wantScrollList ( false ) ,
2022-06-03 23:05:07 +00:00
noteInputPoly ( true ) ,
2023-07-15 07:50:49 +00:00
notifyWaveChange ( false ) ,
2022-06-06 00:04:41 +00:00
displayPendingIns ( false ) ,
pendingInsSingle ( false ) ,
2022-08-13 09:17:32 +00:00
displayPendingRawSample ( false ) ,
2022-11-03 08:22:25 +00:00
snesFilterHex ( false ) ,
2023-02-19 03:40:15 +00:00
modTableHex ( false ) ,
2023-05-16 18:41:08 +00:00
displayEditString ( false ) ,
2022-12-08 23:04:18 +00:00
mobileEdit ( false ) ,
2023-07-02 05:09:39 +00:00
killGraphics ( false ) ,
2023-08-31 04:14:47 +00:00
audioEngineChanged ( false ) ,
settingsChanged ( false ) ,
2023-09-03 09:22:00 +00:00
debugFFT ( false ) ,
2022-04-02 02:40:32 +00:00
vgmExportVersion ( 0x171 ) ,
2023-02-09 00:25:03 +00:00
vgmExportTrailingTicks ( - 1 ) ,
2022-04-16 23:35:25 +00:00
drawHalt ( 10 ) ,
2022-05-26 05:24:21 +00:00
zsmExportTickRate ( 60 ) ,
2022-04-29 10:39:18 +00:00
macroPointSize ( 16 ) ,
2022-07-21 07:49:19 +00:00
waveEditStyle ( 0 ) ,
2022-11-13 23:29:37 +00:00
displayInsTypeListMakeInsSample ( - 1 ) ,
2022-12-11 17:36:41 +00:00
mobileEditPage ( 0 ) ,
2023-08-22 07:30:33 +00:00
wheelCalmDown ( 0 ) ,
2023-08-27 08:58:01 +00:00
shallDetectScale ( 0 ) ,
2022-09-09 00:15:19 +00:00
mobileMenuPos ( 0.0f ) ,
2022-12-08 20:41:10 +00:00
autoButtonSize ( 0.0f ) ,
2022-12-08 23:04:18 +00:00
mobileEditAnim ( 0.0f ) ,
mobileEditButtonPos ( 0.7f , 0.7f ) ,
mobileEditButtonSize ( 60.0f , 60.0f ) ,
2022-08-27 04:35:16 +00:00
curSysSection ( NULL ) ,
2023-03-18 09:22:50 +00:00
updateFMPreview ( true ) ,
fmPreviewOn ( false ) ,
fmPreviewPaused ( false ) ,
fmPreviewOPN ( NULL ) ,
2023-08-21 01:18:27 +00:00
fmPreviewOPM ( NULL ) ,
fmPreviewOPL ( NULL ) ,
fmPreviewOPLL ( NULL ) ,
fmPreviewOPZ ( NULL ) ,
2023-08-22 03:41:35 +00:00
fmPreviewOPZInterface ( NULL ) ,
2023-05-16 18:41:08 +00:00
editString ( NULL ) ,
2022-08-13 11:25:11 +00:00
pendingRawSampleDepth ( 8 ) ,
pendingRawSampleChannels ( 1 ) ,
pendingRawSampleUnsigned ( false ) ,
pendingRawSampleBigEndian ( false ) ,
2022-12-18 03:45:08 +00:00
pendingRawSampleSwapNibbles ( false ) ,
2023-07-17 21:31:55 +00:00
pendingRawSampleReplace ( false ) ,
2022-05-19 21:35:00 +00:00
globalWinFlags ( 0 ) ,
2021-12-17 08:33:12 +00:00
curFileDialog ( GUI_FILE_OPEN ) ,
2021-12-30 23:52:36 +00:00
warnAction ( GUI_WARN_OPEN ) ,
2022-04-13 07:09:59 +00:00
postWarnAction ( GUI_WARN_GENERIC ) ,
2022-09-09 04:20:33 +00:00
mobScene ( GUI_SCENE_PATTERN ) ,
2022-03-13 23:32:35 +00:00
fileDialog ( NULL ) ,
2021-12-11 08:11:40 +00:00
scrW ( 1280 ) ,
scrH ( 800 ) ,
2022-09-08 06:37:16 +00:00
scrConfW ( 1280 ) ,
scrConfH ( 800 ) ,
2022-10-20 06:49:33 +00:00
canvasW ( 1280 ) ,
canvasH ( 800 ) ,
2022-09-08 06:37:16 +00:00
scrX ( SDL_WINDOWPOS_CENTERED ) ,
scrY ( SDL_WINDOWPOS_CENTERED ) ,
scrConfX ( SDL_WINDOWPOS_CENTERED ) ,
scrConfY ( SDL_WINDOWPOS_CENTERED ) ,
scrMax ( false ) ,
2022-10-19 20:33:20 +00:00
sysManagedScale ( false ) ,
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 ) ,
2022-03-21 19:32:33 +00:00
backupTimer ( 15.0 ) ,
2022-03-31 23:39:01 +00:00
learning ( - 1 ) ,
2022-03-22 04:36:17 +00:00
mainFont ( NULL ) ,
iconFont ( NULL ) ,
2023-08-15 01:02:10 +00:00
furIconFont ( NULL ) ,
2022-03-22 04:36:17 +00:00
patFont ( NULL ) ,
bigFont ( NULL ) ,
2023-08-03 05:59:45 +00:00
headFont ( NULL ) ,
2022-03-22 04:36:17 +00:00
fontRange ( NULL ) ,
2022-05-05 03:55:11 +00:00
prevInsData ( NULL ) ,
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 ) ,
2022-04-14 07:58:29 +00:00
curOrder ( 0 ) ,
2022-04-26 06:07:28 +00:00
prevIns ( 0 ) ,
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 ) ,
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 ) ,
2022-02-21 08:05:00 +00:00
extraChannelButtons ( 0 ) ,
2022-03-02 07:22:51 +00:00
newSongCategory ( 0 ) ,
2022-04-21 23:10:59 +00:00
latchTarget ( 0 ) ,
2022-04-02 05:11:44 +00:00
wheelX ( 0 ) ,
wheelY ( 0 ) ,
2022-06-18 08:52:03 +00:00
dragSourceX ( 0 ) ,
dragSourceY ( 0 ) ,
dragDestinationX ( 0 ) ,
dragDestinationY ( 0 ) ,
2022-11-10 06:26:59 +00:00
oldBeat ( - 1 ) ,
oldBar ( - 1 ) ,
2023-02-05 07:56:39 +00:00
curGroove ( - 1 ) ,
2023-05-24 06:58:12 +00:00
exitDisabledTimer ( 0 ) ,
2023-01-14 18:51:02 +00:00
soloTimeout ( 0.0f ) ,
2022-06-06 08:05:55 +00:00
exportFadeOut ( 5.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-03-21 05:52:38 +00:00
inspectorOpen ( 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 ) ,
2022-02-22 03:31:27 +00:00
regViewOpen ( false ) ,
2022-04-11 03:12:02 +00:00
logOpen ( false ) ,
2022-04-19 23:44:05 +00:00
effectListOpen ( false ) ,
2022-04-30 08:58:30 +00:00
chanOscOpen ( false ) ,
2022-05-15 06:42:49 +00:00
subSongsOpen ( true ) ,
2022-06-06 10:03:19 +00:00
findOpen ( false ) ,
2022-06-20 20:20:02 +00:00
spoilerOpen ( false ) ,
2022-08-16 08:42:17 +00:00
patManagerOpen ( false ) ,
2022-08-19 09:41:45 +00:00
sysManagerOpen ( false ) ,
2022-11-10 06:26:59 +00:00
clockOpen ( false ) ,
2023-02-04 22:01:32 +00:00
speedOpen ( true ) ,
2023-02-05 07:56:39 +00:00
groovesOpen ( false ) ,
2023-02-06 23:52:51 +00:00
basicMode ( true ) ,
2023-05-15 06:36:02 +00:00
shortIntro ( false ) ,
insListDir ( false ) ,
waveListDir ( false ) ,
sampleListDir ( false ) ,
2022-11-10 06:26:59 +00:00
clockShowReal ( true ) ,
clockShowRow ( true ) ,
clockShowBeat ( true ) ,
clockShowMetro ( true ) ,
clockShowTime ( true ) ,
2021-12-14 22:45:37 +00:00
selecting ( false ) ,
2022-05-14 06:46:06 +00:00
selectingFull ( false ) ,
2022-06-18 08:52:03 +00:00
dragging ( false ) ,
2021-12-14 22:45:37 +00:00
curNibble ( false ) ,
2022-01-20 07:11:03 +00:00
orderNibble ( false ) ,
2021-12-21 22:42:27 +00:00
followOrders ( true ) ,
followPattern ( true ) ,
2021-12-22 21:22:47 +00:00
changeAllOrders ( false ) ,
2022-05-09 03:52:21 +00:00
mobileUI ( MOBILE_UI_DEFAULT ) ,
2022-02-11 23:20:39 +00:00
collapseWindow ( false ) ,
2022-02-15 07:59:20 +00:00
demandScrollX ( false ) ,
2022-02-15 18:38:59 +00:00
fancyPattern ( false ) ,
2022-03-11 03:10:52 +00:00
firstFrame ( true ) ,
2022-03-16 06:27:34 +00:00
tempoView ( true ) ,
2022-04-02 20:07:47 +00:00
waveHex ( false ) ,
2022-09-11 03:35:21 +00:00
waveSigned ( false ) ,
2022-07-21 08:14:52 +00:00
waveGenVisible ( false ) ,
2022-04-02 20:07:47 +00:00
lockLayout ( false ) ,
2022-04-21 23:10:59 +00:00
editOptsVisible ( false ) ,
2022-04-21 23:30:32 +00:00
latchNibble ( false ) ,
2022-04-26 20:24:45 +00:00
nonLatchNibble ( false ) ,
2022-09-30 23:59:56 +00:00
keepLoopAlive ( false ) ,
2023-02-05 07:56:39 +00:00
keepGrooveAlive ( false ) ,
2022-11-30 22:20:04 +00:00
orderScrollLocked ( false ) ,
2022-11-30 22:37:48 +00:00
orderScrollTolerance ( false ) ,
2022-12-04 22:19:21 +00:00
dragMobileMenu ( false ) ,
2022-12-07 03:40:23 +00:00
dragMobileEditButton ( false ) ,
2023-02-05 07:56:39 +00:00
wantGrooveListFocus ( false ) ,
2023-05-17 00:00:05 +00:00
lastAssetType ( 0 ) ,
2021-12-14 22:45:37 +00:00
curWindow ( GUI_WINDOW_NOTHING ) ,
2022-02-11 23:20:39 +00:00
nextWindow ( GUI_WINDOW_NOTHING ) ,
2022-05-05 01:56:26 +00:00
curWindowLast ( GUI_WINDOW_NOTHING ) ,
2022-11-06 07:06:51 +00:00
curWindowThreadSafe ( GUI_WINDOW_NOTHING ) ,
2022-10-04 00:22:24 +00:00
lastPatternWidth ( 0.0f ) ,
2022-12-02 21:52:47 +00:00
longThreshold ( 0.48f ) ,
2022-12-07 03:40:23 +00:00
buttonLongThreshold ( 0.20f ) ,
2022-03-12 07:13:15 +00:00
latchNote ( - 1 ) ,
2022-03-13 09:51:05 +00:00
latchIns ( - 2 ) ,
2022-03-12 07:13:15 +00:00
latchVol ( - 1 ) ,
latchEffect ( - 1 ) ,
latchEffectVal ( - 1 ) ,
2022-05-21 23:36:15 +00:00
wavePreviewLen ( 32 ) ,
wavePreviewHeight ( 255 ) ,
wavePreviewInit ( true ) ,
2023-05-02 06:53:39 +00:00
wavePreviewPaused ( false ) ,
2022-06-09 23:52:38 +00:00
pgSys ( 0 ) ,
pgAddr ( 0 ) ,
pgVal ( 0 ) ,
curQueryRangeX ( false ) ,
curQueryBackwards ( false ) ,
curQueryRangeXMin ( 0 ) , curQueryRangeXMax ( 0 ) ,
curQueryRangeY ( 0 ) ,
curQueryEffectPos ( 0 ) ,
queryReplaceEffectCount ( 0 ) ,
2023-02-13 23:33:25 +00:00
queryReplaceEffectPos ( 1 ) ,
2022-06-09 23:52:38 +00:00
queryReplaceNoteMode ( 0 ) ,
queryReplaceInsMode ( 0 ) ,
queryReplaceVolMode ( 0 ) ,
queryReplaceNote ( 0 ) ,
queryReplaceIns ( 0 ) ,
queryReplaceVol ( 0 ) ,
queryReplaceNoteDo ( false ) ,
queryReplaceInsDo ( false ) ,
queryReplaceVolDo ( false ) ,
2022-06-11 07:14:30 +00:00
queryViewingResults ( false ) ,
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 ) ,
2023-04-11 00:49:14 +00:00
sampleMapSelStart ( - 1 ) ,
sampleMapSelEnd ( - 1 ) ,
sampleMapDigit ( 0 ) ,
sampleMapColumn ( 0 ) ,
sampleMapFocused ( false ) ,
2023-04-12 06:38:44 +00:00
sampleMapWaitingInput ( false ) ,
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 ) ,
2022-08-22 20:59:45 +00:00
macroDragBit30 ( false ) ,
2022-08-23 08:57:21 +00:00
macroDragSettingBit30 ( false ) ,
2022-04-13 04:03:20 +00:00
macroDragLineMode ( false ) ,
2022-05-08 23:32:16 +00:00
macroDragMouseMoved ( false ) ,
2022-04-13 04:03:20 +00:00
macroDragLineInitial ( 0 , 0 ) ,
2022-05-09 03:52:21 +00:00
macroDragLineInitialV ( 0 , 0 ) ,
2021-12-13 22:09:46 +00:00
macroDragActive ( false ) ,
2022-05-08 23:32:16 +00:00
lastMacroDesc ( NULL , NULL , 0 , 0 , 0.0f ) ,
macroOffX ( 0 ) ,
macroOffY ( 0 ) ,
macroScaleX ( 100.0f ) ,
macroScaleY ( 100.0f ) ,
2022-09-16 05:18:14 +00:00
macroRandMin ( 0 ) ,
macroRandMax ( 0 ) ,
2022-02-12 06:57:55 +00:00
macroLoopDragStart ( 0 , 0 ) ,
macroLoopDragAreaSize ( 0 , 0 ) ,
macroLoopDragTarget ( NULL ) ,
macroLoopDragLen ( 0 ) ,
macroLoopDragActive ( false ) ,
waveDragStart ( 0 , 0 ) ,
waveDragAreaSize ( 0 , 0 ) ,
waveDragTarget ( NULL ) ,
waveDragLen ( 0 ) ,
waveDragMin ( 0 ) ,
waveDragMax ( 0 ) ,
waveDragActive ( false ) ,
bindSetTarget ( 0 ) ,
bindSetPrevValue ( 0 ) ,
bindSetActive ( false ) ,
bindSetPending ( false ) ,
2021-12-24 03:14:59 +00:00
nextScroll ( - 1.0f ) ,
2021-12-26 23:05:18 +00:00
nextAddScroll ( 0.0f ) ,
2022-11-30 22:20:04 +00:00
orderScroll ( 0.0f ) ,
orderScrollSlideOrigin ( 0.0f ) ,
2022-11-30 22:37:48 +00:00
orderScrollRealOrigin ( 0.0f , 0.0f ) ,
2022-12-04 22:19:21 +00:00
dragMobileMenuOrigin ( 0.0f , 0.0f ) ,
2022-05-27 05:19:10 +00:00
layoutTimeBegin ( 0 ) ,
layoutTimeEnd ( 0 ) ,
layoutTimeDelta ( 0 ) ,
renderTimeBegin ( 0 ) ,
renderTimeEnd ( 0 ) ,
renderTimeDelta ( 0 ) ,
2023-06-12 20:58:16 +00:00
drawTimeBegin ( 0 ) ,
drawTimeEnd ( 0 ) ,
drawTimeDelta ( 0 ) ,
2022-05-27 05:19:10 +00:00
eventTimeBegin ( 0 ) ,
eventTimeEnd ( 0 ) ,
eventTimeDelta ( 0 ) ,
2023-04-14 00:43:48 +00:00
perfMetricsLen ( 0 ) ,
2022-05-27 06:04:12 +00:00
chanToMove ( - 1 ) ,
2022-08-26 23:51:17 +00:00
sysToMove ( - 1 ) ,
sysToDelete ( - 1 ) ,
2022-09-11 04:20:22 +00:00
opToMove ( - 1 ) ,
2023-05-15 22:43:27 +00:00
assetToMove ( - 1 ) ,
dirToMove ( - 1 ) ,
2022-03-09 20:43:30 +00:00
transposeAmount ( 0 ) ,
randomizeMin ( 0 ) ,
randomizeMax ( 255 ) ,
2022-03-12 08:04:34 +00:00
fadeMin ( 0 ) ,
fadeMax ( 255 ) ,
2023-05-15 22:43:27 +00:00
collapseAmount ( 2 ) ,
2022-03-09 20:43:30 +00:00
scaleMax ( 100.0f ) ,
2022-03-12 08:04:34 +00:00
fadeMode ( false ) ,
2022-03-12 08:40:56 +00:00
randomMode ( false ) ,
2022-04-13 23:16:55 +00:00
haveHitBounds ( false ) ,
2023-07-15 00:24:57 +00:00
pendingStepUpdate ( 0 ) ,
2022-03-17 23:08:59 +00:00
oldOrdersLen ( 0 ) ,
sampleZoom ( 1.0 ) ,
2022-03-21 05:41:18 +00:00
prevSampleZoom ( 1.0 ) ,
2022-11-23 08:17:04 +00:00
minSampleZoom ( 1.0 ) ,
2022-03-19 08:42:44 +00:00
samplePos ( 0 ) ,
resizeSize ( 1024 ) ,
2022-03-22 22:01:06 +00:00
silenceSize ( 1024 ) ,
2022-03-19 08:42:44 +00:00
resampleTarget ( 32000 ) ,
resampleStrat ( 5 ) ,
amplifyVol ( 100.0 ) ,
sampleSelStart ( - 1 ) ,
sampleSelEnd ( - 1 ) ,
2022-11-26 08:58:19 +00:00
sampleInfo ( true ) ,
2022-12-08 08:32:20 +00:00
sampleCompatRate ( false ) ,
2022-03-19 08:42:44 +00:00
sampleDragActive ( false ) ,
2022-03-19 21:14:11 +00:00
sampleDragMode ( false ) ,
sampleDrag16 ( false ) ,
2022-03-21 05:41:18 +00:00
sampleZoomAuto ( true ) ,
2023-05-05 07:56:52 +00:00
sampleSelTarget ( 0 ) ,
2022-03-19 21:14:11 +00:00
sampleDragTarget ( NULL ) ,
sampleDragStart ( 0 , 0 ) ,
2022-03-21 08:45:20 +00:00
sampleDragAreaSize ( 0 , 0 ) ,
sampleDragLen ( 0 ) ,
sampleFilterL ( 1.0f ) ,
sampleFilterB ( 0.0f ) ,
sampleFilterH ( 0.0f ) ,
sampleFilterRes ( 0.25f ) ,
sampleFilterCutStart ( 16000.0f ) ,
sampleFilterCutEnd ( 100.0f ) ,
2022-03-22 06:57:06 +00:00
sampleFilterPower ( 1 ) ,
sampleClipboard ( NULL ) ,
2022-03-22 09:54:01 +00:00
sampleClipboardLen ( 0 ) ,
openSampleResizeOpt ( false ) ,
openSampleResampleOpt ( false ) ,
openSampleAmplifyOpt ( false ) ,
2022-03-22 22:01:06 +00:00
openSampleSilenceOpt ( false ) ,
2022-04-09 07:42:58 +00:00
openSampleFilterOpt ( false ) ,
2023-01-10 19:17:06 +00:00
selectedPortSet ( 0x1fff ) ,
selectedSubPort ( - 1 ) ,
hoveredPortSet ( 0x1fff ) ,
hoveredSubPort ( - 1 ) ,
portDragActive ( false ) ,
2023-01-10 20:58:15 +00:00
displayHiddenPorts ( false ) ,
2023-01-11 00:09:26 +00:00
displayInternalPorts ( false ) ,
2023-01-10 19:17:06 +00:00
subPortPos ( 0.0f , 0.0f ) ,
2022-04-09 10:02:24 +00:00
oscTotal ( 0 ) ,
2023-08-05 07:52:02 +00:00
oscWidth ( 512 ) ,
2022-04-09 10:02:24 +00:00
oscZoom ( 0.5f ) ,
2022-05-31 02:40:07 +00:00
oscWindowSize ( 20.0f ) ,
2023-08-05 07:52:02 +00:00
oscInput ( 0.0f ) ,
oscInput1 ( 0.0f ) ,
2022-04-11 04:01:55 +00:00
oscZoomSlider ( false ) ,
2022-04-30 08:58:30 +00:00
chanOscCols ( 3 ) ,
2023-08-03 10:25:26 +00:00
chanOscAutoColsType ( 0 ) ,
2022-06-22 20:10:53 +00:00
chanOscColorX ( GUI_OSCREF_CENTER ) ,
chanOscColorY ( GUI_OSCREF_CENTER ) ,
2022-05-01 23:29:16 +00:00
chanOscWindowSize ( 20.0f ) ,
2023-06-18 09:27:22 +00:00
chanOscTextX ( 0.0f ) ,
chanOscTextY ( 0.0f ) ,
chanOscAmplify ( 0.95f ) ,
2022-05-01 23:29:16 +00:00
chanOscWaveCorr ( true ) ,
2022-06-21 23:01:53 +00:00
chanOscOptions ( false ) ,
updateChanOscGradTex ( true ) ,
2022-06-22 20:10:53 +00:00
chanOscUseGrad ( false ) ,
2023-06-18 09:27:22 +00:00
chanOscNormalize ( false ) ,
chanOscTextFormat ( " %c " ) ,
2022-06-22 20:10:53 +00:00
chanOscColor ( 1.0f , 1.0f , 1.0f , 1.0f ) ,
2023-06-18 09:27:22 +00:00
chanOscTextColor ( 1.0f , 1.0f , 1.0f , 0.75f ) ,
2022-06-21 23:01:53 +00:00
chanOscGrad ( 64 , 64 ) ,
chanOscGradTex ( NULL ) ,
2023-09-05 09:38:57 +00:00
chanOscWorkPool ( NULL ) ,
2022-04-13 08:24:49 +00:00
followLog ( true ) ,
2022-05-17 20:20:56 +00:00
# ifdef IS_MOBILE
pianoOctaves ( 7 ) ,
pianoOctavesEdit ( 2 ) ,
pianoOptions ( true ) ,
pianoSharePosition ( false ) ,
2022-05-17 23:55:44 +00:00
pianoOptionsSet ( false ) ,
2023-05-24 15:47:20 +00:00
pianoReadonly ( false ) ,
2022-05-17 20:20:56 +00:00
pianoOffset ( 6 ) ,
pianoOffsetEdit ( 9 ) ,
2022-12-10 19:32:51 +00:00
pianoView ( PIANO_LAYOUT_AUTOMATIC ) ,
pianoInputPadMode ( PIANO_INPUT_PAD_SPLIT_AUTO ) ,
2022-05-17 20:20:56 +00:00
# else
2022-04-13 08:24:49 +00:00
pianoOctaves ( 7 ) ,
2022-05-17 17:46:52 +00:00
pianoOctavesEdit ( 4 ) ,
2022-04-13 08:24:49 +00:00
pianoOptions ( false ) ,
2022-05-17 20:20:56 +00:00
pianoSharePosition ( true ) ,
2023-05-24 15:47:20 +00:00
pianoReadonly ( false ) ,
2022-05-08 07:01:32 +00:00
pianoOffset ( 6 ) ,
2022-05-17 17:46:52 +00:00
pianoOffsetEdit ( 6 ) ,
2022-12-10 19:32:51 +00:00
pianoView ( PIANO_LAYOUT_STANDARD ) ,
pianoInputPadMode ( PIANO_INPUT_PAD_DISABLE ) ,
2022-05-17 20:20:56 +00:00
# endif
2022-07-26 23:23:01 +00:00
hasACED ( false ) ,
waveGenBaseShape ( 0 ) ,
2022-10-04 09:43:14 +00:00
waveInterpolation ( 0 ) ,
2022-07-27 07:23:29 +00:00
waveGenDuty ( 0.5f ) ,
waveGenPower ( 1 ) ,
waveGenInvertPoint ( 1.0f ) ,
2022-09-10 21:01:22 +00:00
waveGenScaleX ( 32 ) ,
2023-02-06 09:02:29 +00:00
waveGenScaleY ( 32 ) ,
2022-09-10 21:01:22 +00:00
waveGenOffsetX ( 0 ) ,
waveGenOffsetY ( 0 ) ,
waveGenSmooth ( 1 ) ,
waveGenAmplify ( 1.0f ) ,
2023-02-15 21:25:35 +00:00
waveGenFM ( false ) ,
2023-02-16 10:40:06 +00:00
introPos ( 0.0 ) ,
2023-02-19 05:08:37 +00:00
introSkip ( 0.0 ) ,
2023-02-19 21:32:05 +00:00
monitorPos ( 0.0 ) ,
2023-02-16 10:40:06 +00:00
mustClear ( 2 ) ,
2023-02-19 05:08:37 +00:00
initialScreenWipe ( 1.0f ) ,
2023-02-25 23:04:17 +00:00
introSkipDo ( false ) ,
2023-06-12 07:18:50 +00:00
introStopped ( false ) ,
2023-02-25 23:04:17 +00:00
curTutorial ( - 1 ) ,
curTutorialStep ( 0 ) {
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-02-15 22:47:07 +00:00
valueKeys [ SDLK_KP_0 ] = 0 ;
valueKeys [ SDLK_KP_1 ] = 1 ;
valueKeys [ SDLK_KP_2 ] = 2 ;
valueKeys [ SDLK_KP_3 ] = 3 ;
valueKeys [ SDLK_KP_4 ] = 4 ;
valueKeys [ SDLK_KP_5 ] = 5 ;
valueKeys [ SDLK_KP_6 ] = 6 ;
valueKeys [ SDLK_KP_7 ] = 7 ;
valueKeys [ SDLK_KP_8 ] = 8 ;
valueKeys [ SDLK_KP_9 ] = 9 ;
2022-03-01 22:19:52 +00:00
2022-12-09 05:30:27 +00:00
memset ( willExport , 1 , DIV_MAX_CHIPS * sizeof ( bool ) ) ;
2022-01-29 23:56:08 +00:00
2023-01-05 07:40:17 +00:00
memset ( peak , 0 , DIV_MAX_OUTPUTS * sizeof ( float ) ) ;
2022-02-10 22:44:27 +00:00
2022-04-21 22:32:28 +00:00
opMaskTransposeNote . note = true ;
opMaskTransposeNote . ins = false ;
opMaskTransposeNote . vol = false ;
opMaskTransposeNote . effect = false ;
opMaskTransposeNote . effectVal = false ;
opMaskTransposeValue . note = false ;
opMaskTransposeValue . ins = true ;
opMaskTransposeValue . vol = true ;
2022-04-21 23:11:34 +00:00
opMaskTransposeValue . effect = false ;
2022-04-21 22:32:28 +00:00
opMaskTransposeValue . effectVal = true ;
2022-02-10 22:44:27 +00:00
memset ( actionKeys , 0 , GUI_ACTION_MAX * sizeof ( int ) ) ;
2022-02-15 18:38:59 +00:00
memset ( patChanX , 0 , sizeof ( float ) * ( DIV_MAX_CHANS + 1 ) ) ;
memset ( patChanSlideY , 0 , sizeof ( float ) * ( DIV_MAX_CHANS + 1 ) ) ;
2022-02-22 05:13:32 +00:00
memset ( lastIns , - 1 , sizeof ( int ) * DIV_MAX_CHANS ) ;
2023-08-05 08:26:36 +00:00
memset ( oscValues , 0 , sizeof ( void * ) * DIV_MAX_OUTPUTS ) ;
2022-05-01 23:29:16 +00:00
memset ( chanOscLP0 , 0 , sizeof ( float ) * DIV_MAX_CHANS ) ;
memset ( chanOscLP1 , 0 , sizeof ( float ) * DIV_MAX_CHANS ) ;
2022-06-22 20:10:53 +00:00
memset ( chanOscVol , 0 , sizeof ( float ) * DIV_MAX_CHANS ) ;
memset ( chanOscPitch , 0 , sizeof ( float ) * DIV_MAX_CHANS ) ;
memset ( chanOscBright , 0 , sizeof ( float ) * DIV_MAX_CHANS ) ;
2022-05-01 23:29:16 +00:00
memset ( lastCorrPos , 0 , sizeof ( short ) * DIV_MAX_CHANS ) ;
2022-05-08 07:01:32 +00:00
memset ( acedData , 0 , 23 ) ;
2022-05-17 20:20:56 +00:00
2022-07-27 06:20:26 +00:00
memset ( waveGenAmp , 0 , sizeof ( float ) * 16 ) ;
memset ( waveGenPhase , 0 , sizeof ( float ) * 16 ) ;
2022-09-09 08:23:18 +00:00
waveGenTL [ 0 ] = 0.0f ;
waveGenTL [ 1 ] = 0.0f ;
waveGenTL [ 2 ] = 0.0f ;
waveGenTL [ 3 ] = 1.0f ;
2023-02-06 06:29:01 +00:00
fmWaveform [ 0 ] = 0 ;
fmWaveform [ 1 ] = 0 ;
fmWaveform [ 2 ] = 0 ;
fmWaveform [ 3 ] = 0 ;
2022-09-09 08:23:18 +00:00
waveGenMult [ 0 ] = 1 ;
waveGenMult [ 1 ] = 1 ;
waveGenMult [ 2 ] = 1 ;
waveGenMult [ 3 ] = 1 ;
memset ( waveGenFB , 0 , sizeof ( int ) * 4 ) ;
2023-02-06 06:29:01 +00:00
memset ( waveGenFMCon0 , 0 , sizeof ( bool ) * 5 ) ;
memset ( waveGenFMCon1 , 0 , sizeof ( bool ) * 5 ) ;
memset ( waveGenFMCon2 , 0 , sizeof ( bool ) * 5 ) ;
memset ( waveGenFMCon3 , 0 , sizeof ( bool ) * 5 ) ;
memset ( waveGenFMCon4 , 0 , sizeof ( bool ) * 5 ) ;
2022-07-27 06:20:26 +00:00
waveGenAmp [ 0 ] = 1.0f ;
2023-02-06 06:29:01 +00:00
waveGenFMCon0 [ 0 ] = false ;
waveGenFMCon1 [ 0 ] = true ;
waveGenFMCon2 [ 1 ] = true ;
waveGenFMCon3 [ 2 ] = true ;
waveGenFMCon4 [ 0 ] = false ;
waveGenFMCon0 [ 4 ] = false ;
waveGenFMCon1 [ 4 ] = false ;
waveGenFMCon2 [ 4 ] = false ;
waveGenFMCon3 [ 4 ] = true ;
2022-07-27 06:20:26 +00:00
2022-09-20 07:57:56 +00:00
memset ( keyHit , 0 , sizeof ( float ) * DIV_MAX_CHANS ) ;
memset ( keyHit1 , 0 , sizeof ( float ) * DIV_MAX_CHANS ) ;
2022-05-17 20:20:56 +00:00
memset ( pianoKeyHit , 0 , sizeof ( float ) * 180 ) ;
memset ( pianoKeyPressed , 0 , sizeof ( bool ) * 180 ) ;
2022-06-09 23:52:38 +00:00
memset ( queryReplaceEffectMode , 0 , sizeof ( int ) * 8 ) ;
memset ( queryReplaceEffectValMode , 0 , sizeof ( int ) * 8 ) ;
memset ( queryReplaceEffect , 0 , sizeof ( int ) * 8 ) ;
memset ( queryReplaceEffectVal , 0 , sizeof ( int ) * 8 ) ;
memset ( queryReplaceEffectDo , 0 , sizeof ( bool ) * 8 ) ;
memset ( queryReplaceEffectValDo , 0 , sizeof ( bool ) * 8 ) ;
2022-06-21 23:01:53 +00:00
chanOscGrad . bgColor = ImVec4 ( 0.0f , 0.0f , 0.0f , 1.0f ) ;
2022-08-13 23:00:29 +00:00
memset ( noteOffLabel , 0 , 32 ) ;
memset ( noteRelLabel , 0 , 32 ) ;
memset ( macroRelLabel , 0 , 32 ) ;
memset ( emptyLabel , 0 , 32 ) ;
memset ( emptyLabel2 , 0 , 32 ) ;
2023-07-29 07:07:20 +00:00
//effect sorting
memset ( effectsShow , 1 , sizeof ( bool ) * 10 ) ;
2022-08-13 23:00:29 +00:00
2022-08-13 23:16:24 +00:00
strncpy ( noteOffLabel , " OFF " , 32 ) ;
strncpy ( noteRelLabel , " === " , 32 ) ;
strncpy ( macroRelLabel , " REL " , 32 ) ;
strncpy ( emptyLabel , " ... " , 32 ) ;
strncpy ( emptyLabel2 , " .. " , 32 ) ;
2022-03-28 20:24:09 +00:00
}