Merge branch 'master' into preset1
This commit is contained in:
commit
0c1a8bc001
7
TODO.md
7
TODO.md
|
@ -1,12 +1,13 @@
|
|||
# to-do for 0.6pre1
|
||||
|
||||
- rewrite the system name detection function anyway
|
||||
- add another FM editor layout
|
||||
- add ability to move selection by dragging
|
||||
- find and replace
|
||||
- implement Defle slide bug when using E1xy/E2xy and repeating origin note (requires format change)
|
||||
|
||||
# to-do for 0.6pre2 (as this requires new data structures)
|
||||
|
||||
- rewrite the system name detection function anyway
|
||||
- this involves the addition of a new "system" field in the song (which solves the problem)
|
||||
- songs made in older versions will go through old system name detection for compatibility
|
||||
- Game Boy envelope macro/sequence
|
||||
- volume commands should work on Game Boy
|
||||
- ability to customize `OFF`, `===` and `REL`
|
||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -1287,8 +1287,6 @@ namespace IGFD
|
|||
std::sort(prFileList.begin(), prFileList.end(),
|
||||
[](const std::shared_ptr<FileInfos>& a, const std::shared_ptr<FileInfos>& b) -> bool
|
||||
{
|
||||
if (a==NULL || b==NULL)
|
||||
return false;
|
||||
if (!a.use_count() || !b.use_count())
|
||||
return false;
|
||||
|
||||
|
@ -1760,7 +1758,7 @@ namespace IGFD
|
|||
struct stat statInfos = {};
|
||||
char timebuf[100];
|
||||
int result = stat(fpn.c_str(), &statInfos);
|
||||
if (!result)
|
||||
if (result!=-1)
|
||||
{
|
||||
if (vInfos->fileType != 'd')
|
||||
{
|
||||
|
@ -1781,7 +1779,11 @@ namespace IGFD
|
|||
{
|
||||
vInfos->fileModifDate = std::string(timebuf, len);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
vInfos->fileSize=0;
|
||||
vInfos->formatedFileSize = prFormatFileSize(vInfos->fileSize);
|
||||
vInfos->fileModifDate="???";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -21,6 +21,26 @@
|
|||
#include "../ta-log.h"
|
||||
#include "taAudio.h"
|
||||
|
||||
String sanitizePortName(const String& name) {
|
||||
#if defined(_WIN32)
|
||||
// remove port number
|
||||
size_t namePos=name.rfind(' ');
|
||||
if (namePos!=String::npos) {
|
||||
return name.substr(0,namePos);
|
||||
}
|
||||
return name;
|
||||
#elif defined(__linux__)
|
||||
// remove port location
|
||||
size_t namePos=name.rfind(' ');
|
||||
if (namePos!=String::npos) {
|
||||
return name.substr(0,namePos);
|
||||
}
|
||||
return name;
|
||||
#else
|
||||
return name;
|
||||
#endif
|
||||
}
|
||||
|
||||
// --- IN ---
|
||||
|
||||
bool TAMidiInRtMidi::gather() {
|
||||
|
@ -56,7 +76,7 @@ std::vector<String> TAMidiInRtMidi::listDevices() {
|
|||
unsigned int count=port->getPortCount();
|
||||
logD("got port count.");
|
||||
for (unsigned int i=0; i<count; i++) {
|
||||
String name=port->getPortName(i);
|
||||
String name=sanitizePortName(port->getPortName(i));
|
||||
if (name!="") ret.push_back(name);
|
||||
}
|
||||
} catch (RtMidiError& e) {
|
||||
|
@ -75,8 +95,12 @@ bool TAMidiInRtMidi::openDevice(String name) {
|
|||
try {
|
||||
bool portOpen=false;
|
||||
unsigned int count=port->getPortCount();
|
||||
logD("finding port %s...",name);
|
||||
for (unsigned int i=0; i<count; i++) {
|
||||
if (port->getPortName(i)==name) {
|
||||
String portName=sanitizePortName(port->getPortName(i));
|
||||
logV("- %d: %s",i,portName);
|
||||
if (portName==name) {
|
||||
logD("opening port %d...",i);
|
||||
port->openPort(i);
|
||||
portOpen=true;
|
||||
break;
|
||||
|
@ -184,8 +208,12 @@ bool TAMidiOutRtMidi::openDevice(String name) {
|
|||
try {
|
||||
bool portOpen=false;
|
||||
unsigned int count=port->getPortCount();
|
||||
logD("finding port %s...",name);
|
||||
for (unsigned int i=0; i<count; i++) {
|
||||
if (port->getPortName(i)==name) {
|
||||
String portName=sanitizePortName(port->getPortName(i));
|
||||
logV("- %d: %s",i,portName);
|
||||
if (portName==name) {
|
||||
logD("opening port %d...",i);
|
||||
port->openPort(i);
|
||||
portOpen=true;
|
||||
break;
|
||||
|
@ -222,7 +250,7 @@ std::vector<String> TAMidiOutRtMidi::listDevices() {
|
|||
try {
|
||||
unsigned int count=port->getPortCount();
|
||||
for (unsigned int i=0; i<count; i++) {
|
||||
String name=port->getPortName(i);
|
||||
String name=sanitizePortName(port->getPortName(i));
|
||||
if (name!="") ret.push_back(name);
|
||||
}
|
||||
} catch (RtMidiError& e) {
|
||||
|
@ -248,4 +276,4 @@ bool TAMidiOutRtMidi::quit() {
|
|||
port=NULL;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -83,7 +83,7 @@ struct DivChannelState {
|
|||
int note, oldNote, lastIns, pitch, portaSpeed, portaNote;
|
||||
int volume, volSpeed, cut, rowDelay, volMax;
|
||||
int delayOrder, delayRow, retrigSpeed, retrigTick;
|
||||
int vibratoDepth, vibratoRate, vibratoPos, vibratoDir, vibratoFine;
|
||||
int vibratoDepth, vibratoRate, vibratoPos, vibratoPosGiant, vibratoDir, vibratoFine;
|
||||
int tremoloDepth, tremoloRate, tremoloPos;
|
||||
unsigned char arp, arpStage, arpTicks, panL, panR;
|
||||
bool doNote, legato, portaStop, keyOn, keyOff, nowYouCanStop, stopOnOff;
|
||||
|
@ -112,6 +112,7 @@ struct DivChannelState {
|
|||
vibratoDepth(0),
|
||||
vibratoRate(0),
|
||||
vibratoPos(0),
|
||||
vibratoPosGiant(0),
|
||||
vibratoDir(0),
|
||||
vibratoFine(15),
|
||||
tremoloDepth(0),
|
||||
|
|
|
@ -306,7 +306,7 @@ void DivPlatformBubSysWSG::reset() {
|
|||
for (int i=0; i<2; i++) {
|
||||
chan[i]=DivPlatformBubSysWSG::Channel();
|
||||
chan[i].std.setEngine(parent);
|
||||
chan[i].ws.setEngine(parent);
|
||||
chan[i].ws.setEngine(parent,8);
|
||||
chan[i].ws.init(NULL,32,15,false);
|
||||
}
|
||||
if (dumpWrites) {
|
||||
|
|
|
@ -380,7 +380,7 @@ void DivPlatformMSM6258::setFlags(unsigned int flags) {
|
|||
chipClock=4000000;
|
||||
break;
|
||||
}
|
||||
rate=chipClock/128;
|
||||
rate=chipClock/256;
|
||||
for (int i=0; i<1; i++) {
|
||||
oscBuf[i]->rate=rate;
|
||||
}
|
||||
|
|
|
@ -682,6 +682,9 @@ void DivPlatformOPL::muteChannel(int ch, bool mute) {
|
|||
fm.channel[outChanMap[ch]].muted=mute;
|
||||
}
|
||||
int ops=(slots[3][ch]!=255 && chan[ch].state.ops==4 && oplType==3)?4:2;
|
||||
if (ch&1 && ch<12) {
|
||||
if (chan[ch-1].fourOp) return;
|
||||
}
|
||||
chan[ch].fourOp=(ops==4);
|
||||
update4OpMask=true;
|
||||
for (int i=0; i<ops; i++) {
|
||||
|
|
|
@ -332,7 +332,7 @@ void DivPlatformSCC::reset() {
|
|||
for (int i=0; i<5; i++) {
|
||||
chan[i]=DivPlatformSCC::Channel();
|
||||
chan[i].std.setEngine(parent);
|
||||
chan[i].ws.setEngine(parent);
|
||||
chan[i].ws.setEngine(parent,128);
|
||||
chan[i].ws.init(NULL,32,255,false);
|
||||
chan[i].vol=15;
|
||||
chan[i].outVol=15;
|
||||
|
|
|
@ -347,7 +347,7 @@ int DivPlatformSwan::dispatch(DivCommand c) {
|
|||
case DIV_CMD_VOLUME:
|
||||
if (chan[c.chan].vol!=c.value) {
|
||||
chan[c.chan].vol=c.value;
|
||||
if (!chan[c.chan].std.vol.had) {
|
||||
if (!chan[c.chan].std.vol.has) {
|
||||
calcAndWriteOutVol(c.chan,15);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -195,7 +195,7 @@ int DivPlatformVIC20::dispatch(DivCommand c) {
|
|||
case DIV_CMD_VOLUME:
|
||||
if (chan[c.chan].vol!=c.value) {
|
||||
chan[c.chan].vol=c.value;
|
||||
if (!chan[c.chan].std.vol.had) {
|
||||
if (!chan[c.chan].std.vol.has) {
|
||||
calcAndWriteOutVol(c.chan,15);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -988,6 +988,10 @@ bool DivEngine::nextTick(bool noAccum, bool inhibitLowLat) {
|
|||
if (chan[i].vibratoDepth>0) {
|
||||
chan[i].vibratoPos+=chan[i].vibratoRate;
|
||||
if (chan[i].vibratoPos>=64) chan[i].vibratoPos-=64;
|
||||
|
||||
chan[i].vibratoPosGiant+=chan[i].vibratoRate;
|
||||
if (chan[i].vibratoPos>=512) chan[i].vibratoPos-=512;
|
||||
|
||||
switch (chan[i].vibratoDir) {
|
||||
case 1: // up
|
||||
dispatchCmd(DivCommand(DIV_CMD_PITCH,i,chan[i].pitch+(MAX(0,(chan[i].vibratoDepth*vibTable[chan[i].vibratoPos]*chan[i].vibratoFine)>>4)/15)));
|
||||
|
|
|
@ -243,8 +243,13 @@ void DivWaveSynth::changeWave2(int num) {
|
|||
first=true;
|
||||
}
|
||||
|
||||
void DivWaveSynth::setEngine(DivEngine* engine) {
|
||||
void DivWaveSynth::setEngine(DivEngine* engine, int waveFloor) {
|
||||
e=engine;
|
||||
memset(wave1,waveFloor,256);
|
||||
memset(wave2,waveFloor,256);
|
||||
for (int i=0; i<256; i++) {
|
||||
output[i]=waveFloor;
|
||||
}
|
||||
}
|
||||
|
||||
void DivWaveSynth::init(DivInstrument* which, int w, int h, bool insChanged) {
|
||||
|
|
|
@ -70,7 +70,7 @@ class DivWaveSynth {
|
|||
* @param insChanged whether the instrument has changed.
|
||||
*/
|
||||
void init(DivInstrument* which, int width, int height, bool insChanged=false);
|
||||
void setEngine(DivEngine* engine);
|
||||
void setEngine(DivEngine* engine, int waveFloor=0);
|
||||
DivWaveSynth():
|
||||
e(NULL),
|
||||
pos(0),
|
||||
|
|
|
@ -66,6 +66,8 @@ void FurnaceGUI::prepareUndo(ActionType action) {
|
|||
e->curPat[i].getPattern(e->curOrders->ord[i][curOrder],false)->copyOn(oldPat[i]);
|
||||
}
|
||||
break;
|
||||
case GUI_UNDO_REPLACE: // this is handled by doReplace()
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -126,6 +128,8 @@ void FurnaceGUI::makeUndo(ActionType action) {
|
|||
doPush=true;
|
||||
}
|
||||
break;
|
||||
case GUI_UNDO_REPLACE: // this is handled by doReplace()
|
||||
break;
|
||||
}
|
||||
if (doPush) {
|
||||
MARK_MODIFIED;
|
||||
|
@ -943,6 +947,7 @@ void FurnaceGUI::doUndo() {
|
|||
case GUI_UNDO_PATTERN_FLIP:
|
||||
case GUI_UNDO_PATTERN_COLLAPSE:
|
||||
case GUI_UNDO_PATTERN_EXPAND:
|
||||
case GUI_UNDO_REPLACE:
|
||||
for (UndoPatternData& i: us.pat) {
|
||||
e->changeSongP(i.subSong);
|
||||
DivPattern* p=e->curPat[i.chan].getPattern(i.pat,true);
|
||||
|
@ -991,6 +996,7 @@ void FurnaceGUI::doRedo() {
|
|||
case GUI_UNDO_PATTERN_FLIP:
|
||||
case GUI_UNDO_PATTERN_COLLAPSE:
|
||||
case GUI_UNDO_PATTERN_EXPAND:
|
||||
case GUI_UNDO_REPLACE:
|
||||
for (UndoPatternData& i: us.pat) {
|
||||
e->changeSongP(i.subSong);
|
||||
DivPattern* p=e->curPat[i.chan].getPattern(i.pat,true);
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -4105,6 +4105,7 @@ bool FurnaceGUI::init() {
|
|||
|
||||
#ifndef __APPLE__
|
||||
if (settings.dpiScale<0.5f) {
|
||||
// TODO: replace with a function to actually detect the display scaling factor as it's unreliable.
|
||||
SDL_GetDisplayDPI(SDL_GetWindowDisplayIndex(sdlWin),&dpiScaleF,NULL,NULL);
|
||||
dpiScale=round(dpiScaleF/96.0f);
|
||||
if (dpiScale<1) dpiScale=1;
|
||||
|
@ -4431,6 +4432,26 @@ FurnaceGUI::FurnaceGUI():
|
|||
wavePreviewLen(32),
|
||||
wavePreviewHeight(255),
|
||||
wavePreviewInit(true),
|
||||
pgSys(0),
|
||||
pgAddr(0),
|
||||
pgVal(0),
|
||||
curQueryRangeX(false),
|
||||
curQueryBackwards(false),
|
||||
curQueryRangeXMin(0), curQueryRangeXMax(0),
|
||||
curQueryRangeY(0),
|
||||
curQueryEffectPos(0),
|
||||
queryReplaceEffectCount(0),
|
||||
queryReplaceEffectPos(0),
|
||||
queryReplaceNoteMode(0),
|
||||
queryReplaceInsMode(0),
|
||||
queryReplaceVolMode(0),
|
||||
queryReplaceNote(0),
|
||||
queryReplaceIns(0),
|
||||
queryReplaceVol(0),
|
||||
queryReplaceNoteDo(false),
|
||||
queryReplaceInsDo(false),
|
||||
queryReplaceVolDo(false),
|
||||
queryViewingResults(false),
|
||||
wavePreviewOn(false),
|
||||
wavePreviewKey((SDL_Scancode)0),
|
||||
wavePreviewNote(0),
|
||||
|
@ -4624,4 +4645,11 @@ FurnaceGUI::FurnaceGUI():
|
|||
|
||||
memset(pianoKeyHit,0,sizeof(float)*180);
|
||||
memset(pianoKeyPressed,0,sizeof(bool)*180);
|
||||
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -566,7 +566,8 @@ enum ActionType {
|
|||
GUI_UNDO_PATTERN_INVERT_VAL,
|
||||
GUI_UNDO_PATTERN_FLIP,
|
||||
GUI_UNDO_PATTERN_COLLAPSE,
|
||||
GUI_UNDO_PATTERN_EXPAND
|
||||
GUI_UNDO_PATTERN_EXPAND,
|
||||
GUI_UNDO_REPLACE
|
||||
};
|
||||
|
||||
struct UndoPatternData {
|
||||
|
@ -818,6 +819,7 @@ enum FurnaceGUIFindQueryModes {
|
|||
enum FurnaceGUIFindQueryReplaceModes {
|
||||
GUI_QUERY_REPLACE_SET=0,
|
||||
GUI_QUERY_REPLACE_ADD,
|
||||
GUI_QUERY_REPLACE_ADD_OVERFLOW,
|
||||
GUI_QUERY_REPLACE_CLEAR,
|
||||
|
||||
GUI_QUERY_REPLACE_MAX
|
||||
|
@ -855,6 +857,20 @@ struct FurnaceGUIFindQuery {
|
|||
}
|
||||
};
|
||||
|
||||
struct FurnaceGUIQueryResult {
|
||||
int subsong, order, x, y;
|
||||
FurnaceGUIQueryResult():
|
||||
subsong(0),
|
||||
order(0),
|
||||
x(0),
|
||||
y(0) {}
|
||||
FurnaceGUIQueryResult(int ss, int o, int xPos, int yPos):
|
||||
subsong(ss),
|
||||
order(o),
|
||||
x(xPos),
|
||||
y(yPos) {}
|
||||
};
|
||||
|
||||
class FurnaceGUI {
|
||||
DivEngine* e;
|
||||
|
||||
|
@ -1170,11 +1186,31 @@ class FurnaceGUI {
|
|||
int pgSys, pgAddr, pgVal;
|
||||
|
||||
std::vector<FurnaceGUIFindQuery> curQuery;
|
||||
bool curQueryRangeX, curQueryFromStart, curQueryBackwards;
|
||||
std::vector<FurnaceGUIQueryResult> curQueryResults;
|
||||
bool curQueryRangeX, curQueryBackwards;
|
||||
int curQueryRangeXMin, curQueryRangeXMax;
|
||||
int curQueryRangeY;
|
||||
int curQueryEffectPos;
|
||||
|
||||
int queryReplaceEffectCount;
|
||||
int queryReplaceEffectPos;
|
||||
int queryReplaceNoteMode;
|
||||
int queryReplaceInsMode;
|
||||
int queryReplaceVolMode;
|
||||
int queryReplaceEffectMode[8];
|
||||
int queryReplaceEffectValMode[8];
|
||||
int queryReplaceNote;
|
||||
int queryReplaceIns;
|
||||
int queryReplaceVol;
|
||||
int queryReplaceEffect[8];
|
||||
int queryReplaceEffectVal[8];
|
||||
bool queryReplaceNoteDo;
|
||||
bool queryReplaceInsDo;
|
||||
bool queryReplaceVolDo;
|
||||
bool queryReplaceEffectDo[8];
|
||||
bool queryReplaceEffectValDo[8];
|
||||
bool queryViewingResults;
|
||||
|
||||
struct ActiveNote {
|
||||
int chan;
|
||||
int note;
|
||||
|
@ -1456,6 +1492,8 @@ class FurnaceGUI {
|
|||
void doExpand(int multiplier);
|
||||
void doUndo();
|
||||
void doRedo();
|
||||
void doFind();
|
||||
void doReplace();
|
||||
void editOptions(bool topMenu);
|
||||
void noteInput(int num, int key, int vol=-1);
|
||||
void valueInput(int num, bool direct=false, int target=-1);
|
||||
|
@ -1502,6 +1540,8 @@ class FurnaceGUI {
|
|||
void addScroll(int amount);
|
||||
void setFileName(String name);
|
||||
void runBackupThread();
|
||||
void pushPartBlend();
|
||||
void popPartBlend();
|
||||
int processEvent(SDL_Event* ev);
|
||||
bool loop();
|
||||
bool finish();
|
||||
|
|
|
@ -1345,6 +1345,9 @@ void FurnaceGUI::drawMacros(std::vector<FurnaceGUIMacroDesc>& macros) {
|
|||
#define CENTER_VSLIDER \
|
||||
ImGui::SetCursorPosX(ImGui::GetCursorPosX()+0.5f*ImGui::GetContentRegionAvail().x-10.0f*dpiScale);
|
||||
|
||||
#define CENTER_TEXT_20(text) \
|
||||
ImGui::SetCursorPosX(ImGui::GetCursorPosX()+0.5*(20.0f*dpiScale-ImGui::CalcTextSize(text).x));
|
||||
|
||||
void FurnaceGUI::drawInsEdit() {
|
||||
if (nextWindow==GUI_WINDOW_INS_EDIT) {
|
||||
insEditOpen=true;
|
||||
|
@ -2016,7 +2019,452 @@ void FurnaceGUI::drawInsEdit() {
|
|||
|
||||
ImGui::EndTable();
|
||||
}
|
||||
} else {
|
||||
} else if (settings.fmLayout>=4 && settings.fmLayout<=6) { // alternate
|
||||
int columns=2;
|
||||
switch (settings.fmLayout) {
|
||||
case 4: // 2x2
|
||||
columns=2;
|
||||
break;
|
||||
case 5: // 1x4
|
||||
columns=1;
|
||||
break;
|
||||
case 6: // 4x1
|
||||
columns=opCount;
|
||||
break;
|
||||
}
|
||||
char tempID[1024];
|
||||
ImVec2 oldPadding=ImGui::GetStyle().CellPadding;
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_CellPadding,ImVec2(8.0f*dpiScale,4.0f*dpiScale));
|
||||
if (ImGui::BeginTable("KGE93BSIEO3NOWBDJZBA",columns,ImGuiTableFlags_SizingStretchSame|ImGuiTableFlags_BordersInner)) {
|
||||
for (int i=0; i<opCount; i++) {
|
||||
DivInstrumentFM::Operator& op=ins->fm.op[(opCount==4 && ins->type!=DIV_INS_OPL_DRUMS)?opOrder[i]:i];
|
||||
if ((settings.fmLayout!=6 && ((i+1)&1)) || i==0 || settings.fmLayout==5) ImGui::TableNextRow();
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::PushID(fmt::sprintf("op%d",i).c_str());
|
||||
|
||||
// push colors
|
||||
if (settings.separateFMColors) {
|
||||
bool mod=true;
|
||||
if (ins->type==DIV_INS_OPL_DRUMS) {
|
||||
mod=false;
|
||||
} else if (opCount==4) {
|
||||
if (ins->type==DIV_INS_OPL) {
|
||||
if (opIsOutputOPL[ins->fm.alg&3][i]) mod=false;
|
||||
} else {
|
||||
if (opIsOutput[ins->fm.alg&7][i]) mod=false;
|
||||
}
|
||||
} else {
|
||||
if (i==1 || (ins->type==DIV_INS_OPL && (ins->fm.alg&1))) mod=false;
|
||||
}
|
||||
if (mod) {
|
||||
pushAccentColors(
|
||||
uiColors[GUI_COLOR_FM_PRIMARY_MOD],
|
||||
uiColors[GUI_COLOR_FM_SECONDARY_MOD],
|
||||
uiColors[GUI_COLOR_FM_BORDER_MOD],
|
||||
uiColors[GUI_COLOR_FM_BORDER_SHADOW_MOD]
|
||||
);
|
||||
} else {
|
||||
pushAccentColors(
|
||||
uiColors[GUI_COLOR_FM_PRIMARY_CAR],
|
||||
uiColors[GUI_COLOR_FM_SECONDARY_CAR],
|
||||
uiColors[GUI_COLOR_FM_BORDER_CAR],
|
||||
uiColors[GUI_COLOR_FM_BORDER_SHADOW_CAR]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::Dummy(ImVec2(dpiScale,dpiScale));
|
||||
if (ins->type==DIV_INS_OPL_DRUMS) {
|
||||
snprintf(tempID,1024,"%s",oplDrumNames[i]);
|
||||
} else if (ins->type==DIV_INS_OPL && ins->fm.opllPreset==16) {
|
||||
if (i==1) {
|
||||
snprintf(tempID,1024,"Envelope 2 (kick only)");
|
||||
} else {
|
||||
snprintf(tempID,1024,"Envelope");
|
||||
}
|
||||
} else {
|
||||
snprintf(tempID,1024,"Operator %d",i+1);
|
||||
}
|
||||
CENTER_TEXT(tempID);
|
||||
ImGui::TextUnformatted(tempID);
|
||||
|
||||
float sliderHeight=200.0f*dpiScale;
|
||||
float waveWidth=140.0*dpiScale;
|
||||
float waveHeight=sliderHeight-ImGui::GetFrameHeightWithSpacing()*(ins->type==DIV_INS_OPLL?4.5f:5.5f);
|
||||
|
||||
int maxTl=127;
|
||||
if (ins->type==DIV_INS_OPLL) {
|
||||
if (i==1) {
|
||||
maxTl=15;
|
||||
} else {
|
||||
maxTl=63;
|
||||
}
|
||||
}
|
||||
if (ins->type==DIV_INS_OPL || ins->type==DIV_INS_OPL_DRUMS) {
|
||||
maxTl=63;
|
||||
}
|
||||
int maxArDr=(ins->type==DIV_INS_FM || ins->type==DIV_INS_OPZ)?31:15;
|
||||
|
||||
bool ssgOn=op.ssgEnv&8;
|
||||
bool ksrOn=op.ksr;
|
||||
bool vibOn=op.vib;
|
||||
bool egtOn=op.egt;
|
||||
bool susOn=op.sus; // yawn
|
||||
unsigned char ssgEnv=op.ssgEnv&7;
|
||||
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_CellPadding,oldPadding);
|
||||
if (ImGui::BeginTable("opParams",4,ImGuiTableFlags_BordersInnerV)) {
|
||||
ImGui::TableSetupColumn("c0",ImGuiTableColumnFlags_WidthFixed);
|
||||
ImGui::TableSetupColumn("c1",ImGuiTableColumnFlags_WidthFixed,waveWidth);
|
||||
ImGui::TableSetupColumn("c2",ImGuiTableColumnFlags_WidthStretch);
|
||||
ImGui::TableSetupColumn("c3",ImGuiTableColumnFlags_WidthFixed);
|
||||
|
||||
ImGui::TableNextRow();
|
||||
ImGui::TableNextColumn();
|
||||
float textY=ImGui::GetCursorPosY();
|
||||
CENTER_TEXT_20(FM_SHORT_NAME(FM_AR));
|
||||
ImGui::TextUnformatted(FM_SHORT_NAME(FM_AR));
|
||||
ImGui::TableNextColumn();
|
||||
if (ins->type==DIV_INS_FM) {
|
||||
ImGui::Text("SSG-EG");
|
||||
} else {
|
||||
ImGui::Text("Waveform");
|
||||
}
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::Text("Envelope");
|
||||
ImGui::TableNextColumn();
|
||||
CENTER_TEXT(FM_SHORT_NAME(FM_TL));
|
||||
ImGui::Text("TL");
|
||||
|
||||
// A/D/S/R
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
op.ar&=maxArDr;
|
||||
P(CWVSliderScalar("##AR",ImVec2(20.0f*dpiScale,sliderHeight),ImGuiDataType_U8,&op.ar,&maxArDr,&_ZERO));
|
||||
|
||||
ImGui::SameLine();
|
||||
op.dr&=maxArDr;
|
||||
float textX_DR=ImGui::GetCursorPosX();
|
||||
P(CWVSliderScalar("##DR",ImVec2(20.0f*dpiScale,sliderHeight),ImGuiDataType_U8,&op.dr,&maxArDr,&_ZERO));
|
||||
|
||||
float textX_SL=0.0f;
|
||||
if (settings.susPosition==0) {
|
||||
ImGui::SameLine();
|
||||
op.sl&=15;
|
||||
textX_SL=ImGui::GetCursorPosX();
|
||||
P(CWVSliderScalar("##SL",ImVec2(20.0f*dpiScale,sliderHeight),ImGuiDataType_U8,&op.sl,&_FIFTEEN,&_ZERO));
|
||||
}
|
||||
|
||||
float textX_D2R=0.0f;
|
||||
if (ins->type==DIV_INS_FM || ins->type==DIV_INS_OPZ) {
|
||||
ImGui::SameLine();
|
||||
op.d2r&=31;
|
||||
textX_D2R=ImGui::GetCursorPosX();
|
||||
P(CWVSliderScalar("##D2R",ImVec2(20.0f*dpiScale,sliderHeight),ImGuiDataType_U8,&op.d2r,&_THIRTY_ONE,&_ZERO));
|
||||
}
|
||||
|
||||
ImGui::SameLine();
|
||||
op.rr&=15;
|
||||
float textX_RR=ImGui::GetCursorPosX();
|
||||
P(CWVSliderScalar("##RR",ImVec2(20.0f*dpiScale,sliderHeight),ImGuiDataType_U8,&op.rr,&_FIFTEEN,&_ZERO));
|
||||
|
||||
if (settings.susPosition==1) {
|
||||
ImGui::SameLine();
|
||||
op.sl&=15;
|
||||
textX_SL=ImGui::GetCursorPosX();
|
||||
P(CWVSliderScalar("##SL",ImVec2(20.0f*dpiScale,sliderHeight),ImGuiDataType_U8,&op.sl,&_FIFTEEN,&_ZERO));
|
||||
}
|
||||
|
||||
ImVec2 prevCurPos=ImGui::GetCursorPos();
|
||||
|
||||
// labels
|
||||
ImGui::SetCursorPos(ImVec2(textX_DR,textY));
|
||||
CENTER_TEXT_20(FM_SHORT_NAME(FM_DR));
|
||||
ImGui::TextUnformatted(FM_SHORT_NAME(FM_DR));
|
||||
|
||||
ImGui::SetCursorPos(ImVec2(textX_SL,textY));
|
||||
CENTER_TEXT_20(FM_SHORT_NAME(FM_SL));
|
||||
ImGui::TextUnformatted(FM_SHORT_NAME(FM_SL));
|
||||
|
||||
ImGui::SetCursorPos(ImVec2(textX_RR,textY));
|
||||
CENTER_TEXT_20(FM_SHORT_NAME(FM_RR));
|
||||
ImGui::TextUnformatted(FM_SHORT_NAME(FM_RR));
|
||||
|
||||
if (ins->type==DIV_INS_FM || ins->type==DIV_INS_OPZ) {
|
||||
ImGui::SetCursorPos(ImVec2(textX_D2R,textY));
|
||||
CENTER_TEXT_20(FM_SHORT_NAME(FM_D2R));
|
||||
ImGui::TextUnformatted(FM_SHORT_NAME(FM_D2R));
|
||||
}
|
||||
|
||||
ImGui::SetCursorPos(prevCurPos);
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
switch (ins->type) {
|
||||
case DIV_INS_FM: {
|
||||
// SSG
|
||||
ImGui::BeginDisabled(!ssgOn);
|
||||
drawSSGEnv(op.ssgEnv&7,ImVec2(waveWidth,waveHeight));
|
||||
ImGui::EndDisabled();
|
||||
if (ImGui::Checkbox("##SSGOn",&ssgOn)) { PARAMETER
|
||||
op.ssgEnv=(op.ssgEnv&7)|(ssgOn<<3);
|
||||
}
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::SetTooltip("Only for OPN family chips");
|
||||
}
|
||||
|
||||
ImGui::SameLine();
|
||||
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x);
|
||||
if (CWSliderScalar("##SSG",ImGuiDataType_U8,&ssgEnv,&_ZERO,&_SEVEN,ssgEnvTypes[ssgEnv])) { PARAMETER
|
||||
op.ssgEnv=(op.ssgEnv&8)|(ssgEnv&7);
|
||||
}
|
||||
|
||||
// params
|
||||
ImGui::Separator();
|
||||
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x);
|
||||
snprintf(tempID,1024,"%s: %%d",FM_NAME(FM_MULT));
|
||||
P(CWSliderScalar("##MULT",ImGuiDataType_U8,&op.mult,&_ZERO,&_FIFTEEN,tempID)); rightClickable
|
||||
|
||||
int detune=(op.dt&7)-3;
|
||||
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x);
|
||||
snprintf(tempID,1024,"%s: %%d",FM_NAME(FM_DT));
|
||||
if (CWSliderInt("##DT",&detune,-3,4,tempID)) { PARAMETER
|
||||
op.dt=detune+3;
|
||||
} rightClickable
|
||||
|
||||
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x);
|
||||
snprintf(tempID,1024,"%s: %%d",FM_NAME(FM_DT2));
|
||||
P(CWSliderScalar("##DT2",ImGuiDataType_U8,&op.dt2,&_ZERO,&_THREE,tempID)); rightClickable
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::SetTooltip("Only on YM2151 (OPM)");
|
||||
}
|
||||
|
||||
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x);
|
||||
snprintf(tempID,1024,"%s: %%d",FM_NAME(FM_RS));
|
||||
P(CWSliderScalar("##RS",ImGuiDataType_U8,&op.rs,&_ZERO,&_THREE,tempID)); rightClickable
|
||||
|
||||
break;
|
||||
}
|
||||
case DIV_INS_OPLL:
|
||||
// waveform
|
||||
drawWaveform(i==0?(ins->fm.ams&1):(ins->fm.fms&1),ins->type==DIV_INS_OPZ,ImVec2(waveWidth,waveHeight));
|
||||
|
||||
// params
|
||||
ImGui::Separator();
|
||||
if (ImGui::BeginTable("FMParamsInner",2)) {
|
||||
ImGui::TableNextRow();
|
||||
ImGui::TableNextColumn();
|
||||
bool amOn=op.am;
|
||||
if (ImGui::Checkbox(FM_NAME(FM_AM),&amOn)) { PARAMETER
|
||||
op.am=amOn;
|
||||
}
|
||||
ImGui::TableNextColumn();
|
||||
if (ImGui::Checkbox(FM_NAME(FM_KSR),&ksrOn)) { PARAMETER
|
||||
op.ksr=ksrOn;
|
||||
}
|
||||
|
||||
ImGui::TableNextRow();
|
||||
ImGui::TableNextColumn();
|
||||
if (ImGui::Checkbox(FM_NAME(FM_VIB),&vibOn)) { PARAMETER
|
||||
op.vib=vibOn;
|
||||
}
|
||||
ImGui::TableNextColumn();
|
||||
if (ImGui::Checkbox(FM_NAME(FM_EGS),&ssgOn)) { PARAMETER
|
||||
op.ssgEnv=(op.ssgEnv&7)|(ssgOn<<3);
|
||||
}
|
||||
|
||||
ImGui::EndTable();
|
||||
}
|
||||
|
||||
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x);
|
||||
snprintf(tempID,1024,"%s: %%d",FM_NAME(FM_MULT));
|
||||
P(CWSliderScalar("##MULT",ImGuiDataType_U8,&op.mult,&_ZERO,&_FIFTEEN,tempID)); rightClickable
|
||||
|
||||
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x);
|
||||
snprintf(tempID,1024,"%s: %%d",FM_NAME(FM_KSL));
|
||||
P(CWSliderScalar("##KSL",ImGuiDataType_U8,&op.ksl,&_ZERO,&_THREE,tempID)); rightClickable
|
||||
|
||||
break;
|
||||
case DIV_INS_OPL:
|
||||
// waveform
|
||||
drawWaveform(op.ws&7,ins->type==DIV_INS_OPZ,ImVec2(waveWidth,waveHeight));
|
||||
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x);
|
||||
P(CWSliderScalar("##WS",ImGuiDataType_U8,&op.ws,&_ZERO,&_SEVEN,(ins->type==DIV_INS_OPZ)?opzWaveforms[op.ws&7]:(settings.oplStandardWaveNames?oplWaveformsStandard[op.ws&7]:oplWaveforms[op.ws&7]))); rightClickable
|
||||
if ((ins->type==DIV_INS_OPL || ins->type==DIV_INS_OPL_DRUMS) && ImGui::IsItemHovered()) {
|
||||
ImGui::SetTooltip("OPL2/3 only (last 4 waveforms are OPL3 only)");
|
||||
}
|
||||
|
||||
// params
|
||||
ImGui::Separator();
|
||||
if (ImGui::BeginTable("FMParamsInner",2)) {
|
||||
ImGui::TableNextRow();
|
||||
ImGui::TableNextColumn();
|
||||
bool amOn=op.am;
|
||||
if (ImGui::Checkbox(FM_NAME(FM_AM),&amOn)) { PARAMETER
|
||||
op.am=amOn;
|
||||
}
|
||||
ImGui::TableNextColumn();
|
||||
if (ImGui::Checkbox(FM_NAME(FM_KSR),&ksrOn)) { PARAMETER
|
||||
op.ksr=ksrOn;
|
||||
}
|
||||
|
||||
ImGui::TableNextRow();
|
||||
ImGui::TableNextColumn();
|
||||
if (ImGui::Checkbox(FM_NAME(FM_VIB),&vibOn)) { PARAMETER
|
||||
op.vib=vibOn;
|
||||
}
|
||||
ImGui::TableNextColumn();
|
||||
if (ImGui::Checkbox(FM_NAME(FM_SUS),&susOn)) { PARAMETER
|
||||
op.sus=susOn;
|
||||
}
|
||||
|
||||
ImGui::EndTable();
|
||||
}
|
||||
|
||||
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x);
|
||||
snprintf(tempID,1024,"%s: %%d",FM_NAME(FM_MULT));
|
||||
P(CWSliderScalar("##MULT",ImGuiDataType_U8,&op.mult,&_ZERO,&_FIFTEEN,tempID)); rightClickable
|
||||
|
||||
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x);
|
||||
snprintf(tempID,1024,"%s: %%d",FM_NAME(FM_KSL));
|
||||
P(CWSliderScalar("##KSL",ImGuiDataType_U8,&op.ksl,&_ZERO,&_THREE,tempID)); rightClickable
|
||||
|
||||
break;
|
||||
case DIV_INS_OPZ: {
|
||||
// waveform
|
||||
drawWaveform(op.ws&7,ins->type==DIV_INS_OPZ,ImVec2(waveWidth,waveHeight));
|
||||
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x);
|
||||
P(CWSliderScalar("##WS",ImGuiDataType_U8,&op.ws,&_ZERO,&_SEVEN,(ins->type==DIV_INS_OPZ)?opzWaveforms[op.ws&7]:(settings.oplStandardWaveNames?oplWaveformsStandard[op.ws&7]:oplWaveforms[op.ws&7]))); rightClickable
|
||||
if ((ins->type==DIV_INS_OPL || ins->type==DIV_INS_OPL_DRUMS) && ImGui::IsItemHovered()) {
|
||||
ImGui::SetTooltip("OPL2/3 only (last 4 waveforms are OPL3 only)");
|
||||
}
|
||||
|
||||
// params
|
||||
ImGui::Separator();
|
||||
if (egtOn) {
|
||||
int block=op.dt;
|
||||
int freqNum=(op.mult<<4)|(op.dvb&15);
|
||||
ImGui::Text("Block");
|
||||
ImGui::SameLine();
|
||||
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x);
|
||||
ImVec2 cursorAlign=ImGui::GetCursorPos();
|
||||
if (ImGui::InputInt("##Block",&block,1,1)) {
|
||||
if (block<0) block=0;
|
||||
if (block>7) block=7;
|
||||
op.dt=block;
|
||||
}
|
||||
|
||||
ImGui::Text("Freq");
|
||||
ImGui::SameLine();
|
||||
ImGui::SetCursorPos(ImVec2(cursorAlign.x,ImGui::GetCursorPosY()));
|
||||
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x);
|
||||
if (ImGui::InputInt("##FreqNum",&freqNum,1,16)) {
|
||||
if (freqNum<0) freqNum=0;
|
||||
if (freqNum>255) freqNum=255;
|
||||
op.mult=freqNum>>4;
|
||||
op.dvb=freqNum&15;
|
||||
}
|
||||
} else {
|
||||
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x);
|
||||
snprintf(tempID,1024,"%s: %%d",FM_NAME(FM_MULT));
|
||||
P(CWSliderScalar("##MULT",ImGuiDataType_U8,&op.mult,&_ZERO,&_FIFTEEN,tempID)); rightClickable
|
||||
|
||||
int detune=(op.dt&7)-3;
|
||||
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x);
|
||||
snprintf(tempID,1024,"%s: %%d",FM_NAME(FM_DT));
|
||||
if (CWSliderInt("##DT",&detune,-3,4,tempID)) { PARAMETER
|
||||
op.dt=detune+3;
|
||||
} rightClickable
|
||||
}
|
||||
|
||||
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x);
|
||||
snprintf(tempID,1024,"%s: %%d",FM_NAME(FM_DT2));
|
||||
P(CWSliderScalar("##DT2",ImGuiDataType_U8,&op.dt2,&_ZERO,&_THREE,tempID)); rightClickable
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::SetTooltip("Only on YM2151 (OPM)");
|
||||
}
|
||||
|
||||
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x);
|
||||
snprintf(tempID,1024,"%s: %%d",FM_NAME(FM_RS));
|
||||
P(CWSliderScalar("##RS",ImGuiDataType_U8,&op.rs,&_ZERO,&_THREE,tempID)); rightClickable
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
float envHeight=sliderHeight;//-ImGui::GetStyle().ItemSpacing.y*2.0f;
|
||||
if (ins->type==DIV_INS_OPZ) {
|
||||
envHeight-=ImGui::GetFrameHeightWithSpacing()*2.0f;
|
||||
}
|
||||
drawFMEnv(op.tl&maxTl,op.ar&maxArDr,op.dr&maxArDr,(ins->type==DIV_INS_OPL || ins->type==DIV_INS_OPL_DRUMS || ins->type==DIV_INS_OPLL)?((op.rr&15)*2):op.d2r&31,op.rr&15,op.sl&15,op.sus,op.ssgEnv&8,ins->fm.alg,maxTl,maxArDr,ImVec2(ImGui::GetContentRegionAvail().x,envHeight),ins->type);
|
||||
|
||||
if (ins->type==DIV_INS_OPZ) {
|
||||
ImGui::Separator();
|
||||
if (ImGui::BeginTable("FMParamsInnerOPZ",2)) {
|
||||
ImGui::TableNextRow();
|
||||
ImGui::TableNextColumn();
|
||||
if (!egtOn) {
|
||||
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x);
|
||||
snprintf(tempID,1024,"%s: %%d",FM_NAME(FM_FINE));
|
||||
P(CWSliderScalar("##FINE",ImGuiDataType_U8,&op.dvb,&_ZERO,&_FIFTEEN,tempID)); rightClickable
|
||||
}
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
bool amOn=op.am;
|
||||
if (ImGui::Checkbox(FM_NAME(FM_AM),&amOn)) { PARAMETER
|
||||
op.am=amOn;
|
||||
}
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Checkbox("Fixed",&egtOn)) { PARAMETER
|
||||
op.egt=egtOn;
|
||||
}
|
||||
|
||||
ImGui::TableNextRow();
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x);
|
||||
snprintf(tempID,1024,"%s: %%d",FM_NAME(FM_EGSHIFT));
|
||||
P(CWSliderScalar("##EGShift",ImGuiDataType_U8,&op.ksl,&_ZERO,&_THREE,tempID)); rightClickable
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x);
|
||||
snprintf(tempID,1024,"%s: %%d",FM_NAME(FM_REV));
|
||||
P(CWSliderScalar("##REV",ImGuiDataType_U8,&op.dam,&_ZERO,&_SEVEN,tempID)); rightClickable
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
|
||||
ImGui::EndTable();
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
op.tl&=maxTl;
|
||||
P(CWVSliderScalar("##TL",ImVec2(ImGui::GetFrameHeight(),sliderHeight-(ins->type==DIV_INS_FM?(ImGui::GetFrameHeightWithSpacing()+ImGui::CalcTextSize(FM_SHORT_NAME(FM_AM)).y+ImGui::GetStyle().ItemSpacing.y):0.0f)),ImGuiDataType_U8,&op.tl,&maxTl,&_ZERO));
|
||||
|
||||
if (ins->type==DIV_INS_FM) {
|
||||
CENTER_TEXT(FM_SHORT_NAME(FM_AM));
|
||||
ImGui::TextUnformatted(FM_SHORT_NAME(FM_AM));
|
||||
bool amOn=op.am;
|
||||
if (ImGui::Checkbox("##AM",&amOn)) { PARAMETER
|
||||
op.am=amOn;
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::EndTable();
|
||||
}
|
||||
ImGui::PopStyleVar();
|
||||
|
||||
if (settings.separateFMColors) {
|
||||
popAccentColors();
|
||||
}
|
||||
|
||||
ImGui::PopID();
|
||||
}
|
||||
ImGui::EndTable();
|
||||
}
|
||||
ImGui::PopStyleVar();
|
||||
} else { // classic
|
||||
int columns=2;
|
||||
switch (settings.fmLayout) {
|
||||
case 1: // 2x2
|
||||
|
|
|
@ -25,6 +25,7 @@ const int _THREE=3;
|
|||
const int _SEVEN=7;
|
||||
const int _TEN=10;
|
||||
const int _FIFTEEN=15;
|
||||
const int _SIXTEEN=16;
|
||||
const int _THIRTY_ONE=31;
|
||||
const int _SIXTY_FOUR=64;
|
||||
const int _ONE_HUNDRED=100;
|
||||
|
|
|
@ -27,6 +27,7 @@ extern const int _THREE;
|
|||
extern const int _SEVEN;
|
||||
extern const int _TEN;
|
||||
extern const int _FIFTEEN;
|
||||
extern const int _SIXTEEN;
|
||||
extern const int _THIRTY_ONE;
|
||||
extern const int _SIXTY_FOUR;
|
||||
extern const int _ONE_HUNDRED;
|
||||
|
|
|
@ -17,7 +17,6 @@
|
|||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include <imgui.h>
|
||||
#define _USE_MATH_DEFINES
|
||||
#include "gui.h"
|
||||
#include "../ta-log.h"
|
||||
|
@ -31,6 +30,30 @@ inline float randRange(float min, float max) {
|
|||
return min+((float)rand()/(float)RAND_MAX)*(max-min);
|
||||
}
|
||||
|
||||
void _pushPartBlend(const ImDrawList* drawList, const ImDrawCmd* cmd) {
|
||||
if (cmd!=NULL) {
|
||||
if (cmd->UserCallbackData!=NULL) {
|
||||
((FurnaceGUI*)cmd->UserCallbackData)->pushPartBlend();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void _popPartBlend(const ImDrawList* drawList, const ImDrawCmd* cmd) {
|
||||
if (cmd!=NULL) {
|
||||
if (cmd->UserCallbackData!=NULL) {
|
||||
((FurnaceGUI*)cmd->UserCallbackData)->popPartBlend();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FurnaceGUI::pushPartBlend() {
|
||||
SDL_SetRenderDrawBlendMode(sdlRend,SDL_BLENDMODE_ADD);
|
||||
}
|
||||
|
||||
void FurnaceGUI::popPartBlend() {
|
||||
SDL_SetRenderDrawBlendMode(sdlRend,SDL_BLENDMODE_BLEND);
|
||||
}
|
||||
|
||||
// draw a pattern row
|
||||
inline void FurnaceGUI::patternRow(int i, bool isPlaying, float lineHeight, int chans, int ord, const DivPattern** patCache, bool inhibitSel) {
|
||||
static char id[32];
|
||||
|
@ -692,11 +715,14 @@ void FurnaceGUI::drawPattern() {
|
|||
ImU32* color=noteGrad;
|
||||
|
||||
switch (i.cmd) {
|
||||
case DIV_CMD_NOTE_ON:
|
||||
case DIV_CMD_NOTE_ON: {
|
||||
float strength=CLAMP(i.value,0,119);
|
||||
partIcon=ICON_FA_ASTERISK;
|
||||
life=96.0f;
|
||||
life=80.0f+((i.value==DIV_NOTE_NULL)?0.0f:(strength*0.3f));
|
||||
lifeSpeed=3.0f;
|
||||
num=6+(strength/16);
|
||||
break;
|
||||
}
|
||||
case DIV_CMD_LEGATO:
|
||||
partIcon=ICON_FA_COG;
|
||||
color=insGrad;
|
||||
|
@ -794,7 +820,7 @@ void FurnaceGUI::drawPattern() {
|
|||
|
||||
float frameTime=ImGui::GetIO().DeltaTime*60.0f;
|
||||
|
||||
// note slides
|
||||
// note slides and vibrato
|
||||
ImVec2 arrowPoints[7];
|
||||
if (e->isPlaying()) for (int i=0; i<chans; i++) {
|
||||
if (!e->curSubSong->chanShow[i]) continue;
|
||||
|
@ -849,11 +875,30 @@ void FurnaceGUI::drawPattern() {
|
|||
}
|
||||
}
|
||||
}
|
||||
if (ch->vibratoDepth>0) {
|
||||
ImVec4 col=uiColors[GUI_COLOR_PATTERN_EFFECT_PITCH];
|
||||
col.w*=0.2;
|
||||
float width=patChanX[i+1]-patChanX[i];
|
||||
|
||||
particles.push_back(Particle(
|
||||
pitchGrad,
|
||||
ICON_FA_GLASS,
|
||||
off.x+patChanX[i]+(width*0.5+0.5*sin(M_PI*(float)ch->vibratoPosGiant/64.0f)*width)-scrollX,
|
||||
off.y+(ImGui::GetWindowHeight()*0.5f)+randRange(0,patFont->FontSize),
|
||||
randRange(-4.0f,4.0f),
|
||||
2.0f*(3.0f+(rand()%5)+ch->vibratoRate),
|
||||
0.4f,
|
||||
1.0f,
|
||||
128.0f,
|
||||
4.0f
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
// particle simulation
|
||||
ImDrawList* fdl=ImGui::GetForegroundDrawList();
|
||||
if (!particles.empty()) WAKE_UP;
|
||||
fdl->AddCallback(_pushPartBlend,this);
|
||||
for (size_t i=0; i<particles.size(); i++) {
|
||||
Particle& part=particles[i];
|
||||
if (part.update(frameTime)) {
|
||||
|
@ -870,6 +915,7 @@ void FurnaceGUI::drawPattern() {
|
|||
i--;
|
||||
}
|
||||
}
|
||||
fdl->AddCallback(_popPartBlend,this);
|
||||
}
|
||||
|
||||
ImGui::PopStyleColor(3);
|
||||
|
|
|
@ -1117,6 +1117,15 @@ void FurnaceGUI::drawSettings() {
|
|||
if (ImGui::RadioButton("Compact (4x1)##fml3",settings.fmLayout==3)) {
|
||||
settings.fmLayout=3;
|
||||
}
|
||||
if (ImGui::RadioButton("Alternate (2x2)##fml4",settings.fmLayout==4)) {
|
||||
settings.fmLayout=4;
|
||||
}
|
||||
if (ImGui::RadioButton("Alternate (1x4)##fml5",settings.fmLayout==5)) {
|
||||
settings.fmLayout=5;
|
||||
}
|
||||
if (ImGui::RadioButton("Alternate (4x1)##fml5",settings.fmLayout==6)) {
|
||||
settings.fmLayout=6;
|
||||
}
|
||||
|
||||
ImGui::Text("Position of Sustain in FM editor:");
|
||||
if (ImGui::RadioButton("Between Decay and Sustain Rate##susp0",settings.susPosition==0)) {
|
||||
|
@ -2077,7 +2086,7 @@ void FurnaceGUI::syncSettings() {
|
|||
clampSetting(settings.roundedMenus,0,1);
|
||||
clampSetting(settings.loadJapanese,0,1);
|
||||
clampSetting(settings.loadChinese,0,1);
|
||||
clampSetting(settings.fmLayout,0,3);
|
||||
clampSetting(settings.fmLayout,0,6);
|
||||
clampSetting(settings.susPosition,0,1);
|
||||
clampSetting(settings.effectCursorDir,0,2);
|
||||
clampSetting(settings.cursorPastePos,0,1);
|
||||
|
|
13
src/main.cpp
13
src/main.cpp
|
@ -30,6 +30,7 @@
|
|||
#ifdef _WIN32
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
#include <combaseapi.h>
|
||||
#include <shellapi.h>
|
||||
#else
|
||||
#include <unistd.h>
|
||||
|
@ -244,6 +245,12 @@ void initParams() {
|
|||
// TODO: add crash log
|
||||
int main(int argc, char** argv) {
|
||||
initLog();
|
||||
#ifdef _WIN32
|
||||
HRESULT coResult=CoInitializeEx(NULL,COINIT_MULTITHREADED);
|
||||
if (coResult!=S_OK) {
|
||||
logE("CoInitializeEx failed!");
|
||||
}
|
||||
#endif
|
||||
#if !(defined(__APPLE__) || defined(_WIN32) || defined(ANDROID))
|
||||
// workaround for Wayland HiDPI issue
|
||||
if (getenv("SDL_VIDEODRIVER")==NULL) {
|
||||
|
@ -447,6 +454,12 @@ int main(int argc, char** argv) {
|
|||
|
||||
logI("stopping engine.");
|
||||
e.quit();
|
||||
|
||||
#ifdef _WIN32
|
||||
if (coResult==S_OK || coResult==S_FALSE) {
|
||||
CoUninitialize();
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue