lots of changes
- GUI: ability to load files - GUI: arrow key navigation - fix sample volumes
This commit is contained in:
parent
29d7be032a
commit
52087edceb
|
@ -22,12 +22,12 @@ if (WIN32)
|
||||||
add_subdirectory(extern/zlib)
|
add_subdirectory(extern/zlib)
|
||||||
set(HAVE_SDL2 SDL2-static)
|
set(HAVE_SDL2 SDL2-static)
|
||||||
set(HAVE_Z zlibstatic)
|
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()
|
else()
|
||||||
if (BUILD_GUI)
|
if (BUILD_GUI)
|
||||||
set(SDL_SHARED ON)
|
set(SDL_SHARED ON)
|
||||||
add_subdirectory(extern/SDL)
|
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)
|
if (APPLE)
|
||||||
set(HAVE_SDL2 SDL2-static)
|
set(HAVE_SDL2 SDL2-static)
|
||||||
else()
|
else()
|
||||||
|
|
|
@ -117,5 +117,12 @@ class DivDispatch {
|
||||||
* @return the number of channels allocated.
|
* @return the number of channels allocated.
|
||||||
*/
|
*/
|
||||||
virtual int init(DivEngine* parent, int channels, int sugRate, bool pal);
|
virtual int init(DivEngine* parent, int channels, int sugRate, bool pal);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* quit the DivDispatch.
|
||||||
|
*/
|
||||||
|
virtual void quit();
|
||||||
|
|
||||||
|
virtual ~DivDispatch();
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1023,7 +1023,7 @@ void DivEngine::renderSamples() {
|
||||||
|
|
||||||
// step 1: render to PCM
|
// step 1: render to PCM
|
||||||
unsigned int k=0;
|
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]) {
|
for (double j=0; j<s->length; j+=samplePitches[s->pitch]) {
|
||||||
if (k>=s->rendLength) {
|
if (k>=s->rendLength) {
|
||||||
break;
|
break;
|
||||||
|
@ -1257,6 +1257,27 @@ void DivEngine::initDispatch() {
|
||||||
|
|
||||||
void DivEngine::quitDispatch() {
|
void DivEngine::quitDispatch() {
|
||||||
if (dispatch==NULL) return;
|
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) {
|
bool DivEngine::init(String outName) {
|
||||||
|
|
|
@ -90,7 +90,6 @@ class DivEngine {
|
||||||
void processRow(int i, bool afterDelay);
|
void processRow(int i, bool afterDelay);
|
||||||
void nextOrder();
|
void nextOrder();
|
||||||
void nextRow();
|
void nextRow();
|
||||||
void reset();
|
|
||||||
// returns true if end of song.
|
// returns true if end of song.
|
||||||
bool nextTick();
|
bool nextTick();
|
||||||
bool perSystemEffect(int ch, unsigned char effect, unsigned char effectVal);
|
bool perSystemEffect(int ch, unsigned char effect, unsigned char effectVal);
|
||||||
|
@ -113,6 +112,9 @@ class DivEngine {
|
||||||
// stop
|
// stop
|
||||||
void stop();
|
void stop();
|
||||||
|
|
||||||
|
// reset playback state
|
||||||
|
void reset();
|
||||||
|
|
||||||
// get sys channel count
|
// get sys channel count
|
||||||
int getChannelCount(DivSystem sys);
|
int getChannelCount(DivSystem sys);
|
||||||
|
|
||||||
|
|
|
@ -24,3 +24,9 @@ bool DivDispatch::keyOffAffectsArp(int ch) {
|
||||||
int DivDispatch::init(DivEngine* p, int channels, int sugRate, bool pal) {
|
int DivDispatch::init(DivEngine* p, int channels, int sugRate, bool pal) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DivDispatch::quit() {
|
||||||
|
}
|
||||||
|
|
||||||
|
DivDispatch::~DivDispatch() {
|
||||||
|
}
|
|
@ -377,3 +377,9 @@ int DivPlatformArcade::init(DivEngine* p, int channels, int sugRate, bool pal) {
|
||||||
|
|
||||||
return 13;
|
return 13;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DivPlatformArcade::quit() {
|
||||||
|
}
|
||||||
|
|
||||||
|
DivPlatformArcade::~DivPlatformArcade() {
|
||||||
|
}
|
|
@ -53,5 +53,7 @@ class DivPlatformArcade: public DivDispatch {
|
||||||
void tick();
|
void tick();
|
||||||
bool isStereo();
|
bool isStereo();
|
||||||
int init(DivEngine* parent, int channels, int sugRate, bool pal);
|
int init(DivEngine* parent, int channels, int sugRate, bool pal);
|
||||||
|
void quit();
|
||||||
|
~DivPlatformArcade();
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -314,3 +314,9 @@ int DivPlatformC64::init(DivEngine* p, int channels, int sugRate, bool pal) {
|
||||||
|
|
||||||
return 3;
|
return 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DivPlatformC64::quit() {
|
||||||
|
}
|
||||||
|
|
||||||
|
DivPlatformC64::~DivPlatformC64() {
|
||||||
|
}
|
|
@ -59,6 +59,8 @@ class DivPlatformC64: public DivDispatch {
|
||||||
void tick();
|
void tick();
|
||||||
int init(DivEngine* parent, int channels, int sugRate, bool pal);
|
int init(DivEngine* parent, int channels, int sugRate, bool pal);
|
||||||
void setChipModel(bool is6581);
|
void setChipModel(bool is6581);
|
||||||
|
void quit();
|
||||||
|
~DivPlatformC64();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -75,3 +75,9 @@ int DivPlatformDummy::init(DivEngine* p, int channels, int sugRate, bool pal) {
|
||||||
reset();
|
reset();
|
||||||
return channels;
|
return channels;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DivPlatformDummy::quit() {
|
||||||
|
}
|
||||||
|
|
||||||
|
DivPlatformDummy::~DivPlatformDummy() {
|
||||||
|
}
|
|
@ -20,4 +20,6 @@ class DivPlatformDummy: public DivDispatch {
|
||||||
void reset();
|
void reset();
|
||||||
void tick();
|
void tick();
|
||||||
int init(DivEngine* parent, int channels, int sugRate, bool pal);
|
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();
|
reset();
|
||||||
return 4;
|
return 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DivPlatformGB::quit() {
|
||||||
|
delete gb;
|
||||||
|
}
|
||||||
|
|
||||||
|
DivPlatformGB::~DivPlatformGB() {
|
||||||
|
}
|
|
@ -42,6 +42,8 @@ class DivPlatformGB: public DivDispatch {
|
||||||
void tick();
|
void tick();
|
||||||
bool isStereo();
|
bool isStereo();
|
||||||
int init(DivEngine* parent, int channels, int sugRate, bool pal);
|
int init(DivEngine* parent, int channels, int sugRate, bool pal);
|
||||||
|
void quit();
|
||||||
|
~DivPlatformGB();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -413,3 +413,10 @@ int DivPlatformGenesis::init(DivEngine* p, int channels, int sugRate, bool pal)
|
||||||
reset();
|
reset();
|
||||||
return 10;
|
return 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DivPlatformGenesis::quit() {
|
||||||
|
psg.quit();
|
||||||
|
}
|
||||||
|
|
||||||
|
DivPlatformGenesis::~DivPlatformGenesis() {
|
||||||
|
}
|
|
@ -56,5 +56,7 @@ class DivPlatformGenesis: public DivDispatch {
|
||||||
bool isStereo();
|
bool isStereo();
|
||||||
bool keyOffAffectsArp(int ch);
|
bool keyOffAffectsArp(int ch);
|
||||||
int init(DivEngine* parent, int channels, int sugRate, bool pal);
|
int init(DivEngine* parent, int channels, int sugRate, bool pal);
|
||||||
|
void quit();
|
||||||
|
~DivPlatformGenesis();
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -277,3 +277,10 @@ int DivPlatformGenesisExt::init(DivEngine* parent, int channels, int sugRate, bo
|
||||||
reset();
|
reset();
|
||||||
return 13;
|
return 13;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DivPlatformGenesisExt::quit() {
|
||||||
|
DivPlatformGenesis::quit();
|
||||||
|
}
|
||||||
|
|
||||||
|
DivPlatformGenesisExt::~DivPlatformGenesisExt() {
|
||||||
|
}
|
|
@ -20,4 +20,6 @@ class DivPlatformGenesisExt: public DivPlatformGenesis {
|
||||||
void tick();
|
void tick();
|
||||||
bool keyOffAffectsArp(int ch);
|
bool keyOffAffectsArp(int ch);
|
||||||
int init(DivEngine* parent, int channels, int sugRate, bool pal);
|
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();
|
reset();
|
||||||
return 5;
|
return 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DivPlatformNES::quit() {
|
||||||
|
}
|
||||||
|
|
||||||
|
DivPlatformNES::~DivPlatformNES() {
|
||||||
|
}
|
|
@ -48,6 +48,8 @@ class DivPlatformNES: public DivDispatch {
|
||||||
void tick();
|
void tick();
|
||||||
bool keyOffAffectsArp(int ch);
|
bool keyOffAffectsArp(int ch);
|
||||||
int init(DivEngine* parent, int channels, int sugRate, bool pal);
|
int init(DivEngine* parent, int channels, int sugRate, bool pal);
|
||||||
|
void quit();
|
||||||
|
~DivPlatformNES();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -304,3 +304,10 @@ int DivPlatformPCE::init(DivEngine* p, int channels, int sugRate, bool pal) {
|
||||||
reset();
|
reset();
|
||||||
return 6;
|
return 6;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DivPlatformPCE::quit() {
|
||||||
|
delete pce;
|
||||||
|
}
|
||||||
|
|
||||||
|
DivPlatformPCE::~DivPlatformPCE() {
|
||||||
|
}
|
|
@ -60,6 +60,8 @@ class DivPlatformPCE: public DivDispatch {
|
||||||
bool isStereo();
|
bool isStereo();
|
||||||
bool keyOffAffectsArp(int ch);
|
bool keyOffAffectsArp(int ch);
|
||||||
int init(DivEngine* parent, int channels, int sugRate, bool pal);
|
int init(DivEngine* parent, int channels, int sugRate, bool pal);
|
||||||
|
void quit();
|
||||||
|
~DivPlatformPCE();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -183,3 +183,10 @@ int DivPlatformSMS::init(DivEngine* p, int channels, int sugRate, bool pal) {
|
||||||
reset();
|
reset();
|
||||||
return 4;
|
return 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DivPlatformSMS::quit() {
|
||||||
|
delete sn;
|
||||||
|
}
|
||||||
|
|
||||||
|
DivPlatformSMS::~DivPlatformSMS() {
|
||||||
|
}
|
|
@ -38,6 +38,8 @@ class DivPlatformSMS: public DivDispatch {
|
||||||
void tick();
|
void tick();
|
||||||
bool keyOffAffectsArp(int ch);
|
bool keyOffAffectsArp(int ch);
|
||||||
int init(DivEngine* parent, int channels, int sugRate, bool pal);
|
int init(DivEngine* parent, int channels, int sugRate, bool pal);
|
||||||
|
void quit();
|
||||||
|
~DivPlatformSMS();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -529,3 +529,10 @@ int DivPlatformYM2610::init(DivEngine* p, int channels, int sugRate, bool pal) {
|
||||||
reset();
|
reset();
|
||||||
return 10;
|
return 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DivPlatformYM2610::quit() {
|
||||||
|
delete fm;
|
||||||
|
}
|
||||||
|
|
||||||
|
DivPlatformYM2610::~DivPlatformYM2610() {
|
||||||
|
}
|
|
@ -66,5 +66,7 @@ class DivPlatformYM2610: public DivDispatch {
|
||||||
bool isStereo();
|
bool isStereo();
|
||||||
bool keyOffAffectsArp(int ch);
|
bool keyOffAffectsArp(int ch);
|
||||||
int init(DivEngine* parent, int channels, int sugRate, bool pal);
|
int init(DivEngine* parent, int channels, int sugRate, bool pal);
|
||||||
|
void quit();
|
||||||
|
~DivPlatformYM2610();
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -256,3 +256,10 @@ int DivPlatformYM2610Ext::init(DivEngine* parent, int channels, int sugRate, boo
|
||||||
reset();
|
reset();
|
||||||
return 16;
|
return 16;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DivPlatformYM2610Ext::quit() {
|
||||||
|
DivPlatformYM2610::quit();
|
||||||
|
}
|
||||||
|
|
||||||
|
DivPlatformYM2610Ext::~DivPlatformYM2610Ext() {
|
||||||
|
}
|
|
@ -20,4 +20,6 @@ class DivPlatformYM2610Ext: public DivPlatformYM2610 {
|
||||||
void tick();
|
void tick();
|
||||||
bool keyOffAffectsArp(int ch);
|
bool keyOffAffectsArp(int ch);
|
||||||
int init(DivEngine* parent, int channels, int sugRate, bool pal);
|
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) {
|
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[0],0,size*sizeof(float));
|
||||||
memset(out[1],0,size*sizeof(float));
|
memset(out[1],0,size*sizeof(float));
|
||||||
return;
|
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;
|
totalProcessed=(1+runPos)*got.rate/dispatch->rate;
|
||||||
|
|
||||||
for (size_t i=0; i<runtotal; i++) {
|
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);
|
blip_read_samples(bb[1],bbOut[1],size,0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (out==NULL) return;
|
if (out==NULL) {
|
||||||
|
isBusy.unlock();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (dispatch->isStereo()) {
|
if (dispatch->isStereo()) {
|
||||||
for (size_t i=0; i<size; i++) {
|
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;
|
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 "gui.h"
|
||||||
#include "SDL_events.h"
|
#include "SDL_events.h"
|
||||||
|
#include "SDL_keycode.h"
|
||||||
#include "SDL_render.h"
|
#include "SDL_render.h"
|
||||||
#include "SDL_video.h"
|
#include "SDL_video.h"
|
||||||
#include "fonts.h"
|
#include "fonts.h"
|
||||||
#include "../ta-log.h"
|
#include "../ta-log.h"
|
||||||
#include "imgui.h"
|
#include "imgui.h"
|
||||||
#include "imgui_internal.h"
|
#include "imgui_internal.h"
|
||||||
|
#include "ImGuiFileDialog.h"
|
||||||
#include "misc/cpp/imgui_stdlib.h"
|
#include "misc/cpp/imgui_stdlib.h"
|
||||||
#include <cstdio>
|
|
||||||
#include <fmt/printf.h>
|
#include <fmt/printf.h>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
#include <windows.h>
|
||||||
|
#else
|
||||||
|
#include <unistd.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
const int _ZERO=0;
|
const int _ZERO=0;
|
||||||
const int _ONE=1;
|
const int _ONE=1;
|
||||||
const int _THREE=3;
|
const int _THREE=3;
|
||||||
|
@ -601,6 +608,7 @@ void FurnaceGUI::drawPattern() {
|
||||||
} else {
|
} else {
|
||||||
int volColor=(pat->data[i][3]*127)/chanVolMax;
|
int volColor=(pat->data[i][3]*127)/chanVolMax;
|
||||||
if (volColor>127) volColor=127;
|
if (volColor>127) volColor=127;
|
||||||
|
if (volColor<0) volColor=0;
|
||||||
sprintf(id,"%.2X##PV_%d_%d",pat->data[i][3],i,j);
|
sprintf(id,"%.2X##PV_%d_%d",pat->data[i][3],i,j);
|
||||||
ImGui::PushStyleColor(ImGuiCol_Text,volColors[volColor]);
|
ImGui::PushStyleColor(ImGuiCol_Text,volColors[volColor]);
|
||||||
}
|
}
|
||||||
|
@ -672,12 +680,7 @@ void FurnaceGUI::drawPattern() {
|
||||||
ImGui::PopStyleVar();
|
ImGui::PopStyleVar();
|
||||||
ImGui::PopFont();
|
ImGui::PopFont();
|
||||||
}
|
}
|
||||||
if (ImGui::IsWindowFocused()) {
|
if (ImGui::IsWindowFocused(ImGuiFocusedFlags_ChildWindows)) curWindow=GUI_WINDOW_PATTERN;
|
||||||
curWindow=GUI_WINDOW_PATTERN;
|
|
||||||
} else {
|
|
||||||
// TODO: what?!
|
|
||||||
curWindow=GUI_WINDOW_PATTERN;
|
|
||||||
}
|
|
||||||
ImGui::End();
|
ImGui::End();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -721,36 +724,140 @@ void FurnaceGUI::finishSelection() {
|
||||||
selecting=false;
|
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() {
|
void FurnaceGUI::editAdvance() {
|
||||||
|
finishSelection();
|
||||||
selStart.y+=editStep;
|
selStart.y+=editStep;
|
||||||
if (selStart.y>=e->song.patLen) selStart.y=e->song.patLen-1;
|
if (selStart.y>=e->song.patLen) selStart.y=e->song.patLen-1;
|
||||||
selEnd=selStart;
|
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) {
|
void FurnaceGUI::keyDown(SDL_Event& ev) {
|
||||||
printf("CUR WINDOW: %d\n",curWindow);
|
|
||||||
switch (curWindow) {
|
switch (curWindow) {
|
||||||
case GUI_WINDOW_PATTERN: {
|
case GUI_WINDOW_PATTERN: {
|
||||||
if (selStart.xFine==0) { // note
|
switch (ev.key.keysym.sym) {
|
||||||
try {
|
case SDLK_UP:
|
||||||
int num=12*curOctave+noteKeys.at(ev.key.keysym.sym);
|
moveCursor(0,-1);
|
||||||
DivPattern* pat=e->song.pat[selStart.xCoarse].getPattern(e->song.orders.ord[selStart.xCoarse][e->getOrder()],true);
|
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][0]=num%12;
|
||||||
pat->data[selStart.y][1]=num/12;
|
pat->data[selStart.y][1]=num/12;
|
||||||
editAdvance();
|
editAdvance();
|
||||||
} catch (std::out_of_range& e) {
|
} catch (std::out_of_range& e) {
|
||||||
}
|
}
|
||||||
} else { // value
|
} else { // value
|
||||||
try {
|
try {
|
||||||
int num=valueKeys.at(ev.key.keysym.sym);
|
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);
|
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;
|
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;
|
pat->data[selStart.y][selStart.xFine+1]=((pat->data[selStart.y][selStart.xFine+1]<<4)|num)&0xff;
|
||||||
curNibble=!curNibble;
|
if (selStart.xFine==1) { // instrument
|
||||||
if (!curNibble) editAdvance();
|
if (pat->data[selStart.y][selStart.xFine+1]>=(int)e->song.ins.size()) {
|
||||||
} catch (std::out_of_range& e) {
|
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;
|
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() {
|
bool FurnaceGUI::loop() {
|
||||||
while (!quit) {
|
while (!quit) {
|
||||||
SDL_Event ev;
|
SDL_Event ev;
|
||||||
|
@ -829,7 +987,9 @@ bool FurnaceGUI::loop() {
|
||||||
ImGui::BeginMainMenuBar();
|
ImGui::BeginMainMenuBar();
|
||||||
if (ImGui::BeginMenu("file")) {
|
if (ImGui::BeginMenu("file")) {
|
||||||
ImGui::MenuItem("new");
|
ImGui::MenuItem("new");
|
||||||
ImGui::MenuItem("open...");
|
if (ImGui::MenuItem("open...")) {
|
||||||
|
ImGuiFileDialog::Instance()->OpenDialog("FileDialog","Open File","DefleMask module{.dmf},.*",workingDir);
|
||||||
|
}
|
||||||
ImGui::Separator();
|
ImGui::Separator();
|
||||||
ImGui::MenuItem("save");
|
ImGui::MenuItem("save");
|
||||||
ImGui::MenuItem("save as...");
|
ImGui::MenuItem("save as...");
|
||||||
|
@ -857,6 +1017,34 @@ bool FurnaceGUI::loop() {
|
||||||
drawInsEdit();
|
drawInsEdit();
|
||||||
drawPattern();
|
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,
|
SDL_SetRenderDrawColor(sdlRend,uiColors[GUI_COLOR_BACKGROUND].x*255,
|
||||||
uiColors[GUI_COLOR_BACKGROUND].y*255,
|
uiColors[GUI_COLOR_BACKGROUND].y*255,
|
||||||
uiColors[GUI_COLOR_BACKGROUND].z*255,
|
uiColors[GUI_COLOR_BACKGROUND].z*255,
|
||||||
|
@ -872,6 +1060,17 @@ bool FurnaceGUI::loop() {
|
||||||
bool FurnaceGUI::init() {
|
bool FurnaceGUI::init() {
|
||||||
float dpiScaleF;
|
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);
|
sdlWin=SDL_CreateWindow("Furnace",SDL_WINDOWPOS_CENTERED,SDL_WINDOWPOS_CENTERED,scrW*dpiScale,scrH*dpiScale,SDL_WINDOW_RESIZABLE|SDL_WINDOW_ALLOW_HIGHDPI);
|
||||||
if (sdlWin==NULL) {
|
if (sdlWin==NULL) {
|
||||||
logE("could not open window!\n");
|
logE("could not open window!\n");
|
||||||
|
@ -918,6 +1117,7 @@ bool FurnaceGUI::init() {
|
||||||
FurnaceGUI::FurnaceGUI():
|
FurnaceGUI::FurnaceGUI():
|
||||||
e(NULL),
|
e(NULL),
|
||||||
quit(false),
|
quit(false),
|
||||||
|
isSaving(false),
|
||||||
scrW(1280),
|
scrW(1280),
|
||||||
scrH(800),
|
scrH(800),
|
||||||
dpiScale(1),
|
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_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);
|
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 col1=uiColors[GUI_COLOR_PATTERN_VOLUME_MIN];
|
||||||
ImVec4 col2=uiColors[GUI_COLOR_PATTERN_VOLUME_HALF];
|
ImVec4 col2=uiColors[GUI_COLOR_PATTERN_VOLUME_HALF];
|
||||||
ImVec4 col3=uiColors[GUI_COLOR_PATTERN_VOLUME_MAX];
|
ImVec4 col3=uiColors[GUI_COLOR_PATTERN_VOLUME_MAX];
|
||||||
|
|
|
@ -55,7 +55,9 @@ class FurnaceGUI {
|
||||||
SDL_Window* sdlWin;
|
SDL_Window* sdlWin;
|
||||||
SDL_Renderer* sdlRend;
|
SDL_Renderer* sdlRend;
|
||||||
|
|
||||||
bool quit;
|
String workingDir, fileName;
|
||||||
|
|
||||||
|
bool quit, isSaving;
|
||||||
|
|
||||||
int scrW, scrH;
|
int scrW, scrH;
|
||||||
|
|
||||||
|
@ -102,11 +104,15 @@ class FurnaceGUI {
|
||||||
void updateSelection(int xCoarse, int xFine, int y);
|
void updateSelection(int xCoarse, int xFine, int y);
|
||||||
void finishSelection();
|
void finishSelection();
|
||||||
|
|
||||||
|
void moveCursor(int x, int y);
|
||||||
void editAdvance();
|
void editAdvance();
|
||||||
|
void doDelete();
|
||||||
|
|
||||||
void keyDown(SDL_Event& ev);
|
void keyDown(SDL_Event& ev);
|
||||||
void keyUp(SDL_Event& ev);
|
void keyUp(SDL_Event& ev);
|
||||||
|
|
||||||
|
int load(String path);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
const char* noteName(short note, short octave);
|
const char* noteName(short note, short octave);
|
||||||
void bindEngine(DivEngine* eng);
|
void bindEngine(DivEngine* eng);
|
||||||
|
|
Loading…
Reference in a new issue