mirror of
https://github.com/tildearrow/furnace.git
synced 2024-11-27 06:53:01 +00:00
lots of changes
- GUI: ability to load files - GUI: arrow key navigation - fix sample volumes
This commit is contained in:
parent
29d7be032a
commit
52087edceb
30 changed files with 377 additions and 37 deletions
|
@ -22,12 +22,12 @@ if (WIN32)
|
|||
add_subdirectory(extern/zlib)
|
||||
set(HAVE_SDL2 SDL2-static)
|
||||
set(HAVE_Z zlibstatic)
|
||||
include_directories(extern/imgui extern/imgui/backends extern/zlib ${CMAKE_CURRENT_BINARY_DIR}/extern/zlib extern/fmt/include)
|
||||
include_directories(extern/imgui extern/imgui/backends extern/igfd extern/zlib ${CMAKE_CURRENT_BINARY_DIR}/extern/zlib extern/fmt/include)
|
||||
else()
|
||||
if (BUILD_GUI)
|
||||
set(SDL_SHARED ON)
|
||||
add_subdirectory(extern/SDL)
|
||||
include_directories(extern/SDL/include extern/imgui extern/imgui/backends extern/fmt/include)
|
||||
include_directories(extern/SDL/include extern/imgui extern/imgui/backends extern/igfd extern/fmt/include)
|
||||
if (APPLE)
|
||||
set(HAVE_SDL2 SDL2-static)
|
||||
else()
|
||||
|
|
|
@ -117,5 +117,12 @@ class DivDispatch {
|
|||
* @return the number of channels allocated.
|
||||
*/
|
||||
virtual int init(DivEngine* parent, int channels, int sugRate, bool pal);
|
||||
|
||||
/**
|
||||
* quit the DivDispatch.
|
||||
*/
|
||||
virtual void quit();
|
||||
|
||||
virtual ~DivDispatch();
|
||||
};
|
||||
#endif
|
||||
|
|
|
@ -1023,7 +1023,7 @@ void DivEngine::renderSamples() {
|
|||
|
||||
// step 1: render to PCM
|
||||
unsigned int k=0;
|
||||
float mult=(float)(s->vol+100)/150.0f;
|
||||
float mult=(float)(s->vol)/50.0f;
|
||||
for (double j=0; j<s->length; j+=samplePitches[s->pitch]) {
|
||||
if (k>=s->rendLength) {
|
||||
break;
|
||||
|
@ -1257,6 +1257,27 @@ void DivEngine::initDispatch() {
|
|||
|
||||
void DivEngine::quitDispatch() {
|
||||
if (dispatch==NULL) return;
|
||||
isBusy.lock();
|
||||
dispatch->quit();
|
||||
delete dispatch;
|
||||
dispatch=NULL;
|
||||
chans=0;
|
||||
playing=false;
|
||||
speedAB=false;
|
||||
endOfSong=false;
|
||||
ticks=0;
|
||||
cycles=0;
|
||||
curRow=0;
|
||||
curOrder=0;
|
||||
nextSpeed=3;
|
||||
clockDrift=0;
|
||||
changeOrd=-1;
|
||||
changePos=0;
|
||||
totalTicks=0;
|
||||
totalCmds=0;
|
||||
lastCmds=0;
|
||||
cmdsPerSecond=0;
|
||||
isBusy.unlock();
|
||||
}
|
||||
|
||||
bool DivEngine::init(String outName) {
|
||||
|
|
|
@ -90,7 +90,6 @@ class DivEngine {
|
|||
void processRow(int i, bool afterDelay);
|
||||
void nextOrder();
|
||||
void nextRow();
|
||||
void reset();
|
||||
// returns true if end of song.
|
||||
bool nextTick();
|
||||
bool perSystemEffect(int ch, unsigned char effect, unsigned char effectVal);
|
||||
|
@ -113,6 +112,9 @@ class DivEngine {
|
|||
// stop
|
||||
void stop();
|
||||
|
||||
// reset playback state
|
||||
void reset();
|
||||
|
||||
// get sys channel count
|
||||
int getChannelCount(DivSystem sys);
|
||||
|
||||
|
|
|
@ -24,3 +24,9 @@ bool DivDispatch::keyOffAffectsArp(int ch) {
|
|||
int DivDispatch::init(DivEngine* p, int channels, int sugRate, bool pal) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void DivDispatch::quit() {
|
||||
}
|
||||
|
||||
DivDispatch::~DivDispatch() {
|
||||
}
|
|
@ -377,3 +377,9 @@ int DivPlatformArcade::init(DivEngine* p, int channels, int sugRate, bool pal) {
|
|||
|
||||
return 13;
|
||||
}
|
||||
|
||||
void DivPlatformArcade::quit() {
|
||||
}
|
||||
|
||||
DivPlatformArcade::~DivPlatformArcade() {
|
||||
}
|
|
@ -53,5 +53,7 @@ class DivPlatformArcade: public DivDispatch {
|
|||
void tick();
|
||||
bool isStereo();
|
||||
int init(DivEngine* parent, int channels, int sugRate, bool pal);
|
||||
void quit();
|
||||
~DivPlatformArcade();
|
||||
};
|
||||
#endif
|
||||
|
|
|
@ -314,3 +314,9 @@ int DivPlatformC64::init(DivEngine* p, int channels, int sugRate, bool pal) {
|
|||
|
||||
return 3;
|
||||
}
|
||||
|
||||
void DivPlatformC64::quit() {
|
||||
}
|
||||
|
||||
DivPlatformC64::~DivPlatformC64() {
|
||||
}
|
|
@ -59,6 +59,8 @@ class DivPlatformC64: public DivDispatch {
|
|||
void tick();
|
||||
int init(DivEngine* parent, int channels, int sugRate, bool pal);
|
||||
void setChipModel(bool is6581);
|
||||
void quit();
|
||||
~DivPlatformC64();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -75,3 +75,9 @@ int DivPlatformDummy::init(DivEngine* p, int channels, int sugRate, bool pal) {
|
|||
reset();
|
||||
return channels;
|
||||
}
|
||||
|
||||
void DivPlatformDummy::quit() {
|
||||
}
|
||||
|
||||
DivPlatformDummy::~DivPlatformDummy() {
|
||||
}
|
|
@ -20,4 +20,6 @@ class DivPlatformDummy: public DivDispatch {
|
|||
void reset();
|
||||
void tick();
|
||||
int init(DivEngine* parent, int channels, int sugRate, bool pal);
|
||||
void quit();
|
||||
~DivPlatformDummy();
|
||||
};
|
||||
|
|
|
@ -295,3 +295,10 @@ int DivPlatformGB::init(DivEngine* p, int channels, int sugRate, bool pal) {
|
|||
reset();
|
||||
return 4;
|
||||
}
|
||||
|
||||
void DivPlatformGB::quit() {
|
||||
delete gb;
|
||||
}
|
||||
|
||||
DivPlatformGB::~DivPlatformGB() {
|
||||
}
|
|
@ -42,6 +42,8 @@ class DivPlatformGB: public DivDispatch {
|
|||
void tick();
|
||||
bool isStereo();
|
||||
int init(DivEngine* parent, int channels, int sugRate, bool pal);
|
||||
void quit();
|
||||
~DivPlatformGB();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -413,3 +413,10 @@ int DivPlatformGenesis::init(DivEngine* p, int channels, int sugRate, bool pal)
|
|||
reset();
|
||||
return 10;
|
||||
}
|
||||
|
||||
void DivPlatformGenesis::quit() {
|
||||
psg.quit();
|
||||
}
|
||||
|
||||
DivPlatformGenesis::~DivPlatformGenesis() {
|
||||
}
|
|
@ -56,5 +56,7 @@ class DivPlatformGenesis: public DivDispatch {
|
|||
bool isStereo();
|
||||
bool keyOffAffectsArp(int ch);
|
||||
int init(DivEngine* parent, int channels, int sugRate, bool pal);
|
||||
void quit();
|
||||
~DivPlatformGenesis();
|
||||
};
|
||||
#endif
|
||||
|
|
|
@ -277,3 +277,10 @@ int DivPlatformGenesisExt::init(DivEngine* parent, int channels, int sugRate, bo
|
|||
reset();
|
||||
return 13;
|
||||
}
|
||||
|
||||
void DivPlatformGenesisExt::quit() {
|
||||
DivPlatformGenesis::quit();
|
||||
}
|
||||
|
||||
DivPlatformGenesisExt::~DivPlatformGenesisExt() {
|
||||
}
|
|
@ -20,4 +20,6 @@ class DivPlatformGenesisExt: public DivPlatformGenesis {
|
|||
void tick();
|
||||
bool keyOffAffectsArp(int ch);
|
||||
int init(DivEngine* parent, int channels, int sugRate, bool pal);
|
||||
void quit();
|
||||
~DivPlatformGenesisExt();
|
||||
};
|
||||
|
|
|
@ -310,3 +310,9 @@ int DivPlatformNES::init(DivEngine* p, int channels, int sugRate, bool pal) {
|
|||
reset();
|
||||
return 5;
|
||||
}
|
||||
|
||||
void DivPlatformNES::quit() {
|
||||
}
|
||||
|
||||
DivPlatformNES::~DivPlatformNES() {
|
||||
}
|
|
@ -48,6 +48,8 @@ class DivPlatformNES: public DivDispatch {
|
|||
void tick();
|
||||
bool keyOffAffectsArp(int ch);
|
||||
int init(DivEngine* parent, int channels, int sugRate, bool pal);
|
||||
void quit();
|
||||
~DivPlatformNES();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -304,3 +304,10 @@ int DivPlatformPCE::init(DivEngine* p, int channels, int sugRate, bool pal) {
|
|||
reset();
|
||||
return 6;
|
||||
}
|
||||
|
||||
void DivPlatformPCE::quit() {
|
||||
delete pce;
|
||||
}
|
||||
|
||||
DivPlatformPCE::~DivPlatformPCE() {
|
||||
}
|
|
@ -60,6 +60,8 @@ class DivPlatformPCE: public DivDispatch {
|
|||
bool isStereo();
|
||||
bool keyOffAffectsArp(int ch);
|
||||
int init(DivEngine* parent, int channels, int sugRate, bool pal);
|
||||
void quit();
|
||||
~DivPlatformPCE();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -183,3 +183,10 @@ int DivPlatformSMS::init(DivEngine* p, int channels, int sugRate, bool pal) {
|
|||
reset();
|
||||
return 4;
|
||||
}
|
||||
|
||||
void DivPlatformSMS::quit() {
|
||||
delete sn;
|
||||
}
|
||||
|
||||
DivPlatformSMS::~DivPlatformSMS() {
|
||||
}
|
|
@ -38,6 +38,8 @@ class DivPlatformSMS: public DivDispatch {
|
|||
void tick();
|
||||
bool keyOffAffectsArp(int ch);
|
||||
int init(DivEngine* parent, int channels, int sugRate, bool pal);
|
||||
void quit();
|
||||
~DivPlatformSMS();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -529,3 +529,10 @@ int DivPlatformYM2610::init(DivEngine* p, int channels, int sugRate, bool pal) {
|
|||
reset();
|
||||
return 10;
|
||||
}
|
||||
|
||||
void DivPlatformYM2610::quit() {
|
||||
delete fm;
|
||||
}
|
||||
|
||||
DivPlatformYM2610::~DivPlatformYM2610() {
|
||||
}
|
|
@ -66,5 +66,7 @@ class DivPlatformYM2610: public DivDispatch {
|
|||
bool isStereo();
|
||||
bool keyOffAffectsArp(int ch);
|
||||
int init(DivEngine* parent, int channels, int sugRate, bool pal);
|
||||
void quit();
|
||||
~DivPlatformYM2610();
|
||||
};
|
||||
#endif
|
||||
|
|
|
@ -256,3 +256,10 @@ int DivPlatformYM2610Ext::init(DivEngine* parent, int channels, int sugRate, boo
|
|||
reset();
|
||||
return 16;
|
||||
}
|
||||
|
||||
void DivPlatformYM2610Ext::quit() {
|
||||
DivPlatformYM2610::quit();
|
||||
}
|
||||
|
||||
DivPlatformYM2610Ext::~DivPlatformYM2610Ext() {
|
||||
}
|
|
@ -20,4 +20,6 @@ class DivPlatformYM2610Ext: public DivPlatformYM2610 {
|
|||
void tick();
|
||||
bool keyOffAffectsArp(int ch);
|
||||
int init(DivEngine* parent, int channels, int sugRate, bool pal);
|
||||
void quit();
|
||||
~DivPlatformYM2610Ext();
|
||||
};
|
||||
|
|
|
@ -778,7 +778,7 @@ bool DivEngine::nextTick() {
|
|||
}
|
||||
|
||||
void DivEngine::nextBuf(float** in, float** out, int inChans, int outChans, unsigned int size) {
|
||||
if (!playing) {
|
||||
if (!playing || dispatch==NULL) {
|
||||
memset(out[0],0,size*sizeof(float));
|
||||
memset(out[1],0,size*sizeof(float));
|
||||
return;
|
||||
|
@ -821,7 +821,6 @@ void DivEngine::nextBuf(float** in, float** out, int inChans, int outChans, unsi
|
|||
}
|
||||
}
|
||||
}
|
||||
isBusy.unlock();
|
||||
totalProcessed=(1+runPos)*got.rate/dispatch->rate;
|
||||
|
||||
for (size_t i=0; i<runtotal; i++) {
|
||||
|
@ -844,7 +843,10 @@ void DivEngine::nextBuf(float** in, float** out, int inChans, int outChans, unsi
|
|||
blip_read_samples(bb[1],bbOut[1],size,0);
|
||||
}
|
||||
|
||||
if (out==NULL) return;
|
||||
if (out==NULL) {
|
||||
isBusy.unlock();
|
||||
return;
|
||||
}
|
||||
|
||||
if (dispatch->isStereo()) {
|
||||
for (size_t i=0; i<size; i++) {
|
||||
|
@ -857,4 +859,5 @@ void DivEngine::nextBuf(float** in, float** out, int inChans, int outChans, unsi
|
|||
out[1][i]=(float)bbOut[0][i]/16384.0;
|
||||
}
|
||||
}
|
||||
isBusy.unlock();
|
||||
}
|
||||
|
|
258
src/gui/gui.cpp
258
src/gui/gui.cpp
|
@ -1,16 +1,23 @@
|
|||
#include "gui.h"
|
||||
#include "SDL_events.h"
|
||||
#include "SDL_keycode.h"
|
||||
#include "SDL_render.h"
|
||||
#include "SDL_video.h"
|
||||
#include "fonts.h"
|
||||
#include "../ta-log.h"
|
||||
#include "imgui.h"
|
||||
#include "imgui_internal.h"
|
||||
#include "ImGuiFileDialog.h"
|
||||
#include "misc/cpp/imgui_stdlib.h"
|
||||
#include <cstdio>
|
||||
#include <fmt/printf.h>
|
||||
#include <stdexcept>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#else
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
const int _ZERO=0;
|
||||
const int _ONE=1;
|
||||
const int _THREE=3;
|
||||
|
@ -601,6 +608,7 @@ void FurnaceGUI::drawPattern() {
|
|||
} else {
|
||||
int volColor=(pat->data[i][3]*127)/chanVolMax;
|
||||
if (volColor>127) volColor=127;
|
||||
if (volColor<0) volColor=0;
|
||||
sprintf(id,"%.2X##PV_%d_%d",pat->data[i][3],i,j);
|
||||
ImGui::PushStyleColor(ImGuiCol_Text,volColors[volColor]);
|
||||
}
|
||||
|
@ -672,12 +680,7 @@ void FurnaceGUI::drawPattern() {
|
|||
ImGui::PopStyleVar();
|
||||
ImGui::PopFont();
|
||||
}
|
||||
if (ImGui::IsWindowFocused()) {
|
||||
curWindow=GUI_WINDOW_PATTERN;
|
||||
} else {
|
||||
// TODO: what?!
|
||||
curWindow=GUI_WINDOW_PATTERN;
|
||||
}
|
||||
if (ImGui::IsWindowFocused(ImGuiFocusedFlags_ChildWindows)) curWindow=GUI_WINDOW_PATTERN;
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
|
@ -721,36 +724,140 @@ void FurnaceGUI::finishSelection() {
|
|||
selecting=false;
|
||||
}
|
||||
|
||||
void FurnaceGUI::moveCursor(int x, int y) {
|
||||
finishSelection();
|
||||
if (x!=0) {
|
||||
if (x>0) {
|
||||
for (int i=0; i<x; i++) {
|
||||
if (++selStart.xFine>=3+e->song.pat[selStart.xCoarse].effectRows*2) {
|
||||
selStart.xFine=0;
|
||||
if (++selStart.xCoarse>=e->getChannelCount(e->song.system)) {
|
||||
selStart.xCoarse=e->getChannelCount(e->song.system)-1;
|
||||
selStart.xFine=2+e->song.pat[selStart.xCoarse].effectRows*2;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (int i=0; i<-x; i++) {
|
||||
if (--selStart.xFine<0) {
|
||||
if (--selStart.xCoarse<0) {
|
||||
selStart.xCoarse=0;
|
||||
selStart.xFine=0;
|
||||
} else {
|
||||
selStart.xFine=2+e->song.pat[selStart.xCoarse].effectRows*2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (y!=0) {
|
||||
selStart.y+=y;
|
||||
if (selStart.y<0) selStart.y=0;
|
||||
if (selStart.y>=e->song.patLen) selStart.y=e->song.patLen-1;
|
||||
}
|
||||
selEnd=selStart;
|
||||
updateScroll(selStart.y);
|
||||
}
|
||||
|
||||
void FurnaceGUI::editAdvance() {
|
||||
finishSelection();
|
||||
selStart.y+=editStep;
|
||||
if (selStart.y>=e->song.patLen) selStart.y=e->song.patLen-1;
|
||||
selEnd=selStart;
|
||||
updateScroll(selStart.y);
|
||||
}
|
||||
|
||||
void FurnaceGUI::doDelete() {
|
||||
finishSelection();
|
||||
|
||||
int iCoarse=selStart.xCoarse;
|
||||
int iFine=selStart.xFine;
|
||||
int ord=e->getOrder();
|
||||
for (; iCoarse<=selEnd.xCoarse; iCoarse++) {
|
||||
DivPattern* pat=e->song.pat[iCoarse].getPattern(e->song.orders.ord[iCoarse][ord],true);
|
||||
for (; iFine<3+e->song.pat[iCoarse].effectRows*2 && (iCoarse<selEnd.xCoarse || iFine<=selEnd.xFine); iFine++) {
|
||||
for (int j=selStart.y; j<=selEnd.y; j++) {
|
||||
//printf("deleting from: %d, %d, %d\n",iCoarse,iFine,j);
|
||||
if (iFine==0) {
|
||||
pat->data[j][iFine]=0;
|
||||
}
|
||||
pat->data[j][iFine+1]=(iFine<1)?0:-1;
|
||||
}
|
||||
}
|
||||
iFine=0;
|
||||
}
|
||||
}
|
||||
|
||||
void FurnaceGUI::keyDown(SDL_Event& ev) {
|
||||
printf("CUR WINDOW: %d\n",curWindow);
|
||||
switch (curWindow) {
|
||||
case GUI_WINDOW_PATTERN: {
|
||||
if (selStart.xFine==0) { // note
|
||||
try {
|
||||
int num=12*curOctave+noteKeys.at(ev.key.keysym.sym);
|
||||
DivPattern* pat=e->song.pat[selStart.xCoarse].getPattern(e->song.orders.ord[selStart.xCoarse][e->getOrder()],true);
|
||||
switch (ev.key.keysym.sym) {
|
||||
case SDLK_UP:
|
||||
moveCursor(0,-1);
|
||||
break;
|
||||
case SDLK_DOWN:
|
||||
moveCursor(0,1);
|
||||
break;
|
||||
case SDLK_LEFT:
|
||||
moveCursor(-1,0);
|
||||
break;
|
||||
case SDLK_RIGHT:
|
||||
moveCursor(1,0);
|
||||
break;
|
||||
case SDLK_PAGEUP:
|
||||
moveCursor(0,-16);
|
||||
break;
|
||||
case SDLK_PAGEDOWN:
|
||||
moveCursor(0,16);
|
||||
break;
|
||||
case SDLK_DELETE:
|
||||
doDelete();
|
||||
break;
|
||||
default:
|
||||
if (selStart.xFine==0) { // note
|
||||
try {
|
||||
int num=12*curOctave+noteKeys.at(ev.key.keysym.sym);
|
||||
DivPattern* pat=e->song.pat[selStart.xCoarse].getPattern(e->song.orders.ord[selStart.xCoarse][e->getOrder()],true);
|
||||
|
||||
pat->data[selStart.y][0]=num%12;
|
||||
pat->data[selStart.y][1]=num/12;
|
||||
editAdvance();
|
||||
} catch (std::out_of_range& e) {
|
||||
}
|
||||
} else { // value
|
||||
try {
|
||||
int num=valueKeys.at(ev.key.keysym.sym);
|
||||
DivPattern* pat=e->song.pat[selStart.xCoarse].getPattern(e->song.orders.ord[selStart.xCoarse][e->getOrder()],true);
|
||||
if (pat->data[selStart.y][selStart.xFine+1]==-1) pat->data[selStart.y][selStart.xFine+1]=0;
|
||||
pat->data[selStart.y][selStart.xFine+1]=((pat->data[selStart.y][selStart.xFine+1]<<4)|num)&0xff;
|
||||
curNibble=!curNibble;
|
||||
if (!curNibble) editAdvance();
|
||||
} catch (std::out_of_range& e) {
|
||||
}
|
||||
pat->data[selStart.y][0]=num%12;
|
||||
pat->data[selStart.y][1]=num/12;
|
||||
editAdvance();
|
||||
} catch (std::out_of_range& e) {
|
||||
}
|
||||
} else { // value
|
||||
try {
|
||||
int num=valueKeys.at(ev.key.keysym.sym);
|
||||
DivPattern* pat=e->song.pat[selStart.xCoarse].getPattern(e->song.orders.ord[selStart.xCoarse][e->getOrder()],true);
|
||||
if (pat->data[selStart.y][selStart.xFine+1]==-1) pat->data[selStart.y][selStart.xFine+1]=0;
|
||||
pat->data[selStart.y][selStart.xFine+1]=((pat->data[selStart.y][selStart.xFine+1]<<4)|num)&0xff;
|
||||
if (selStart.xFine==1) { // instrument
|
||||
if (pat->data[selStart.y][selStart.xFine+1]>=(int)e->song.ins.size()) {
|
||||
pat->data[selStart.y][selStart.xFine+1]=(int)e->song.ins.size()-1;
|
||||
}
|
||||
if (e->song.ins.size()<16) {
|
||||
curNibble=false;
|
||||
editAdvance();
|
||||
} else {
|
||||
curNibble=!curNibble;
|
||||
if (!curNibble) editAdvance();
|
||||
}
|
||||
} else if (selStart.xFine==2) { // volume
|
||||
pat->data[selStart.y][selStart.xFine+1]&=e->getMaxVolumeChan(selStart.xCoarse);
|
||||
if (e->getMaxVolumeChan(selStart.xCoarse)<16) {
|
||||
curNibble=false;
|
||||
editAdvance();
|
||||
} else {
|
||||
curNibble=!curNibble;
|
||||
if (!curNibble) editAdvance();
|
||||
}
|
||||
} else {
|
||||
curNibble=!curNibble;
|
||||
if (!curNibble) editAdvance();
|
||||
}
|
||||
} catch (std::out_of_range& e) {
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -763,6 +870,57 @@ void FurnaceGUI::keyUp(SDL_Event& ev) {
|
|||
|
||||
}
|
||||
|
||||
int FurnaceGUI::load(String path) {
|
||||
if (!path.empty()) {
|
||||
logI("loading module...\n");
|
||||
FILE* f=fopen(path.c_str(),"rb");
|
||||
if (f==NULL) {
|
||||
perror("error");
|
||||
return 1;
|
||||
}
|
||||
if (fseek(f,0,SEEK_END)<0) {
|
||||
perror("size error");
|
||||
fclose(f);
|
||||
return 1;
|
||||
}
|
||||
ssize_t len=ftell(f);
|
||||
if (len==0x7fffffffffffffff) {
|
||||
perror("could not get file length");
|
||||
fclose(f);
|
||||
return 1;
|
||||
}
|
||||
if (len<1) {
|
||||
if (len==0) {
|
||||
printf("that file is empty!\n");
|
||||
} else {
|
||||
perror("tell error");
|
||||
}
|
||||
fclose(f);
|
||||
return 1;
|
||||
}
|
||||
unsigned char* file=new unsigned char[len];
|
||||
if (fseek(f,0,SEEK_SET)<0) {
|
||||
perror("size error");
|
||||
fclose(f);
|
||||
return 1;
|
||||
}
|
||||
if (fread(file,1,(size_t)len,f)!=(size_t)len) {
|
||||
perror("read error");
|
||||
fclose(f);
|
||||
return 1;
|
||||
}
|
||||
fclose(f);
|
||||
e->quitDispatch();
|
||||
if (!e->load((void*)file,(size_t)len)) {
|
||||
logE("could not open file!\n");
|
||||
return 1;
|
||||
}
|
||||
e->initDispatch();
|
||||
e->reset();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool FurnaceGUI::loop() {
|
||||
while (!quit) {
|
||||
SDL_Event ev;
|
||||
|
@ -829,7 +987,9 @@ bool FurnaceGUI::loop() {
|
|||
ImGui::BeginMainMenuBar();
|
||||
if (ImGui::BeginMenu("file")) {
|
||||
ImGui::MenuItem("new");
|
||||
ImGui::MenuItem("open...");
|
||||
if (ImGui::MenuItem("open...")) {
|
||||
ImGuiFileDialog::Instance()->OpenDialog("FileDialog","Open File","DefleMask module{.dmf},.*",workingDir);
|
||||
}
|
||||
ImGui::Separator();
|
||||
ImGui::MenuItem("save");
|
||||
ImGui::MenuItem("save as...");
|
||||
|
@ -857,6 +1017,34 @@ bool FurnaceGUI::loop() {
|
|||
drawInsEdit();
|
||||
drawPattern();
|
||||
|
||||
if (ImGuiFileDialog::Instance()->Display("FileDialog")) {
|
||||
if (ImGuiFileDialog::Instance()->IsOk()) {
|
||||
fileName=ImGuiFileDialog::Instance()->GetFilePathName();
|
||||
if (fileName!="") {
|
||||
if (isSaving) {
|
||||
if (fileName.size()<4 || fileName.rfind(".dmf")!=fileName.size()-4) {
|
||||
fileName+=".dmf";
|
||||
}
|
||||
}
|
||||
String copyOfName=fileName;
|
||||
if (isSaving) {
|
||||
printf("saving: %s\n",copyOfName.c_str());
|
||||
//SaveFile(copyOfName.c_str());
|
||||
isSaving=false;
|
||||
} else {
|
||||
load(copyOfName);
|
||||
}
|
||||
}
|
||||
}
|
||||
workingDir=ImGuiFileDialog::Instance()->GetCurrentPath();
|
||||
#ifdef _WIN32
|
||||
workingDir+='\\';
|
||||
#else
|
||||
workingDir+='/';
|
||||
#endif
|
||||
ImGuiFileDialog::Instance()->Close();
|
||||
}
|
||||
|
||||
SDL_SetRenderDrawColor(sdlRend,uiColors[GUI_COLOR_BACKGROUND].x*255,
|
||||
uiColors[GUI_COLOR_BACKGROUND].y*255,
|
||||
uiColors[GUI_COLOR_BACKGROUND].z*255,
|
||||
|
@ -872,6 +1060,17 @@ bool FurnaceGUI::loop() {
|
|||
bool FurnaceGUI::init() {
|
||||
float dpiScaleF;
|
||||
|
||||
char tempDir[4096];
|
||||
#ifdef _WIN32
|
||||
GetCurrentDirectory(4095,tempDir);
|
||||
workingDir=tempDir;
|
||||
workingDir+='\\';
|
||||
#else
|
||||
getcwd(tempDir,4095);
|
||||
workingDir=tempDir;
|
||||
workingDir+='/';
|
||||
#endif
|
||||
|
||||
sdlWin=SDL_CreateWindow("Furnace",SDL_WINDOWPOS_CENTERED,SDL_WINDOWPOS_CENTERED,scrW*dpiScale,scrH*dpiScale,SDL_WINDOW_RESIZABLE|SDL_WINDOW_ALLOW_HIGHDPI);
|
||||
if (sdlWin==NULL) {
|
||||
logE("could not open window!\n");
|
||||
|
@ -918,6 +1117,7 @@ bool FurnaceGUI::init() {
|
|||
FurnaceGUI::FurnaceGUI():
|
||||
e(NULL),
|
||||
quit(false),
|
||||
isSaving(false),
|
||||
scrW(1280),
|
||||
scrH(800),
|
||||
dpiScale(1),
|
||||
|
@ -964,7 +1164,7 @@ FurnaceGUI::FurnaceGUI():
|
|||
uiColors[GUI_COLOR_PATTERN_EFFECT_SYS_SECONDARY]=ImVec4(0.0f,1.0f,0.5f,1.0f);
|
||||
uiColors[GUI_COLOR_PATTERN_EFFECT_MISC]=ImVec4(0.3f,0.3f,1.0f,1.0f);
|
||||
|
||||
for (int i=0; i<63; i++) {
|
||||
for (int i=0; i<64; i++) {
|
||||
ImVec4 col1=uiColors[GUI_COLOR_PATTERN_VOLUME_MIN];
|
||||
ImVec4 col2=uiColors[GUI_COLOR_PATTERN_VOLUME_HALF];
|
||||
ImVec4 col3=uiColors[GUI_COLOR_PATTERN_VOLUME_MAX];
|
||||
|
|
|
@ -55,7 +55,9 @@ class FurnaceGUI {
|
|||
SDL_Window* sdlWin;
|
||||
SDL_Renderer* sdlRend;
|
||||
|
||||
bool quit;
|
||||
String workingDir, fileName;
|
||||
|
||||
bool quit, isSaving;
|
||||
|
||||
int scrW, scrH;
|
||||
|
||||
|
@ -102,11 +104,15 @@ class FurnaceGUI {
|
|||
void updateSelection(int xCoarse, int xFine, int y);
|
||||
void finishSelection();
|
||||
|
||||
void moveCursor(int x, int y);
|
||||
void editAdvance();
|
||||
void doDelete();
|
||||
|
||||
void keyDown(SDL_Event& ev);
|
||||
void keyUp(SDL_Event& ev);
|
||||
|
||||
int load(String path);
|
||||
|
||||
public:
|
||||
const char* noteName(short note, short octave);
|
||||
void bindEngine(DivEngine* eng);
|
||||
|
|
Loading…
Reference in a new issue