Merge branch 'master' of https://github.com/tildearrow/furnace into pv1000_xor

This commit is contained in:
cam900 2023-04-13 11:58:17 +09:00
commit a56d5aae9b
5 changed files with 268 additions and 38 deletions

View file

@ -1327,6 +1327,41 @@ void FurnaceGUI::keyDown(SDL_Event& ev) {
return; return;
} }
if (sampleMapWaitingInput) {
if (sampleMapColumn==1) {
// TODO: map?
if (ev.key.keysym.scancode==SDL_SCANCODE_DELETE) {
alterSampleMap(true,-1);
return;
}
try {
int key=noteKeys.at(ev.key.keysym.scancode);
int num=12*curOctave+key;
if (num<-60) num=-60; // C-(-5)
if (num>119) num=119; // B-9
alterSampleMap(true,num);
return;
} catch (std::out_of_range& e) {
}
} else {
// TODO: map?
if (ev.key.keysym.scancode==SDL_SCANCODE_DELETE) {
alterSampleMap(false,-1);
return;
}
try {
int num=valueKeys.at(ev.key.keysym.sym);
if (num<10) {
alterSampleMap(false,num);
return;
}
} catch (std::out_of_range& e) {
}
}
}
// PER-WINDOW KEYS // PER-WINDOW KEYS
switch (curWindow) { switch (curWindow) {
case GUI_WINDOW_PATTERN: case GUI_WINDOW_PATTERN:
@ -2905,7 +2940,7 @@ int FurnaceGUI::processEvent(SDL_Event* ev) {
} }
#endif #endif
if (ev->type==SDL_KEYDOWN) { if (ev->type==SDL_KEYDOWN) {
if (!ev->key.repeat && latchTarget==0 && !wantCaptureKeyboard && (ev->key.keysym.mod&(~(KMOD_NUM|KMOD_CAPS|KMOD_SCROLL)))==0) { if (!ev->key.repeat && latchTarget==0 && !wantCaptureKeyboard && !sampleMapWaitingInput && (ev->key.keysym.mod&(~(KMOD_NUM|KMOD_CAPS|KMOD_SCROLL)))==0) {
if (settings.notePreviewBehavior==0) return 1; if (settings.notePreviewBehavior==0) return 1;
switch (curWindow) { switch (curWindow) {
case GUI_WINDOW_SAMPLE_EDIT: case GUI_WINDOW_SAMPLE_EDIT:
@ -4913,6 +4948,8 @@ bool FurnaceGUI::loop() {
} }
if (displayNew) { if (displayNew) {
newSongQuery="";
newSongFirstFrame=true;
displayNew=false; displayNew=false;
ImGui::OpenPopup("New Song"); ImGui::OpenPopup("New Song");
} }
@ -5562,6 +5599,8 @@ bool FurnaceGUI::loop() {
} }
} }
sampleMapWaitingInput=(curWindow==GUI_WINDOW_INS_EDIT && sampleMapFocused);
curWindowThreadSafe=curWindow; curWindowThreadSafe=curWindow;
if (curWindow!=curWindowLast) { if (curWindow!=curWindowLast) {
@ -6472,8 +6511,12 @@ FurnaceGUI::FurnaceGUI():
samplePreviewOn(false), samplePreviewOn(false),
samplePreviewKey((SDL_Scancode)0), samplePreviewKey((SDL_Scancode)0),
samplePreviewNote(0), samplePreviewNote(0),
arpMacroScroll(-12), sampleMapSelStart(-1),
pitchMacroScroll(-80), sampleMapSelEnd(-1),
sampleMapDigit(0),
sampleMapColumn(0),
sampleMapFocused(false),
sampleMapWaitingInput(false),
macroDragStart(0,0), macroDragStart(0,0),
macroDragAreaSize(0,0), macroDragAreaSize(0,0),
macroDragCTarget(NULL), macroDragCTarget(NULL),

View file

@ -1565,6 +1565,7 @@ class FurnaceGUI {
double exportFadeOut; double exportFadeOut;
bool newSongFirstFrame;
bool editControlsOpen, ordersOpen, insListOpen, songInfoOpen, patternOpen, insEditOpen; bool editControlsOpen, ordersOpen, insListOpen, songInfoOpen, patternOpen, insEditOpen;
bool waveListOpen, waveEditOpen, sampleListOpen, sampleEditOpen, aboutOpen, settingsOpen; bool waveListOpen, waveEditOpen, sampleListOpen, sampleEditOpen, aboutOpen, settingsOpen;
bool mixerOpen, debugOpen, inspectorOpen, oscOpen, volMeterOpen, statsOpen, compatFlagsOpen; bool mixerOpen, debugOpen, inspectorOpen, oscOpen, volMeterOpen, statsOpen, compatFlagsOpen;
@ -1679,8 +1680,11 @@ class FurnaceGUI {
std::vector<TouchPoint> pressedPoints; std::vector<TouchPoint> pressedPoints;
std::vector<TouchPoint> releasedPoints; std::vector<TouchPoint> releasedPoints;
int arpMacroScroll; int sampleMapSelStart;
int pitchMacroScroll; int sampleMapSelEnd;
int sampleMapDigit;
int sampleMapColumn;
bool sampleMapFocused, sampleMapWaitingInput;
ImVec2 macroDragStart; ImVec2 macroDragStart;
ImVec2 macroDragAreaSize; ImVec2 macroDragAreaSize;
@ -1935,6 +1939,7 @@ class FurnaceGUI {
void drawMacroEdit(FurnaceGUIMacroDesc& i, int totalFit, float availableWidth, int index); void drawMacroEdit(FurnaceGUIMacroDesc& i, int totalFit, float availableWidth, int index);
void drawMacros(std::vector<FurnaceGUIMacroDesc>& macros, FurnaceGUIMacroEditState& state); void drawMacros(std::vector<FurnaceGUIMacroDesc>& macros, FurnaceGUIMacroEditState& state);
void alterSampleMap(bool isNote, int val);
void drawOrderButtons(); void drawOrderButtons();

View file

@ -2023,6 +2023,59 @@ void FurnaceGUI::drawMacros(std::vector<FurnaceGUIMacroDesc>& macros, FurnaceGUI
} }
} }
void FurnaceGUI::alterSampleMap(bool isNote, int val) {
if (curIns<0 || curIns>=(int)e->song.ins.size()) return;
DivInstrument* ins=e->song.ins[curIns];
int sampleMapMin=sampleMapSelStart;
int sampleMapMax=sampleMapSelEnd;
if (sampleMapMin>sampleMapMax) {
sampleMapMin^=sampleMapMax;
sampleMapMax^=sampleMapMin;
sampleMapMin^=sampleMapMax;
}
for (int i=sampleMapMin; i<=sampleMapMax; i++) {
if (i<0 || i>=120) continue;
if (sampleMapColumn==1 && isNote) {
ins->amiga.noteMap[i].freq=val;
} else if (sampleMapColumn==0 && !isNote) {
if (val<0) {
ins->amiga.noteMap[i].map=-1;
} else if (sampleMapDigit>0) {
ins->amiga.noteMap[i].map*=10;
ins->amiga.noteMap[i].map+=val;
} else {
ins->amiga.noteMap[i].map=val;
}
if (ins->amiga.noteMap[i].map>=(int)e->song.sample.size()) {
ins->amiga.noteMap[i].map=((int)e->song.sample.size())-1;
}
}
}
bool advance=false;
if (sampleMapColumn==1 && isNote) {
advance=true;
} else if (sampleMapColumn==0 && !isNote) {
int digits=1;
if (e->song.sample.size()>=10) digits=2;
if (e->song.sample.size()>=100) digits=3;
if (++sampleMapDigit>=digits) {
sampleMapDigit=0;
advance=true;
}
}
if (advance && sampleMapMin==sampleMapMax) {
sampleMapSelStart++;
if (sampleMapSelStart>119) sampleMapSelStart=119;
sampleMapSelEnd=sampleMapSelStart;
}
MARK_MODIFIED;
}
#define DRUM_FREQ(name,db,df,prop) \ #define DRUM_FREQ(name,db,df,prop) \
ImGui::TableNextRow(); \ ImGui::TableNextRow(); \
ImGui::TableNextColumn(); \ ImGui::TableNextColumn(); \
@ -4341,6 +4394,7 @@ void FurnaceGUI::drawInsEdit() {
ins->type==DIV_INS_GA20) { ins->type==DIV_INS_GA20) {
if (ImGui::BeginTabItem((ins->type==DIV_INS_SU)?"Sound Unit":"Sample")) { if (ImGui::BeginTabItem((ins->type==DIV_INS_SU)?"Sound Unit":"Sample")) {
String sName; String sName;
bool wannaOpenSMPopup=false;
if (ins->amiga.initSample<0 || ins->amiga.initSample>=e->song.sampleLen) { if (ins->amiga.initSample<0 || ins->amiga.initSample>=e->song.sampleLen) {
sName="none selected"; sName="none selected";
} else { } else {
@ -4405,71 +4459,191 @@ void FurnaceGUI::drawInsEdit() {
ImGui::BeginDisabled(ins->amiga.useWave); ImGui::BeginDisabled(ins->amiga.useWave);
P(ImGui::Checkbox("Use sample map",&ins->amiga.useNoteMap)); P(ImGui::Checkbox("Use sample map",&ins->amiga.useNoteMap));
if (ins->amiga.useNoteMap) { if (ins->amiga.useNoteMap) {
if (ImGui::BeginTable("NoteMap",3,ImGuiTableFlags_ScrollY|ImGuiTableFlags_Borders|ImGuiTableFlags_SizingStretchSame)) { if (ImGui::IsMouseClicked(ImGuiMouseButton_Left) && ImGui::IsWindowHovered(ImGuiHoveredFlags_ChildWindows)) sampleMapFocused=false;
if (curWindowLast!=GUI_WINDOW_INS_EDIT) sampleMapFocused=false;
if (!sampleMapFocused) sampleMapDigit=0;
if (ImGui::BeginTable("NoteMap",4,ImGuiTableFlags_ScrollY|ImGuiTableFlags_Borders|ImGuiTableFlags_SizingStretchSame)) {
ImGui::TableSetupColumn("c0",ImGuiTableColumnFlags_WidthFixed); ImGui::TableSetupColumn("c0",ImGuiTableColumnFlags_WidthFixed);
ImGui::TableSetupColumn("c1",ImGuiTableColumnFlags_WidthStretch); ImGui::TableSetupColumn("c1",ImGuiTableColumnFlags_WidthFixed);
ImGui::TableSetupColumn("c2",ImGuiTableColumnFlags_WidthStretch); ImGui::TableSetupColumn("c2",ImGuiTableColumnFlags_WidthFixed);
ImGui::TableSetupColumn("c3",ImGuiTableColumnFlags_WidthStretch);
ImGui::TableSetupScrollFreeze(0,1); ImGui::TableSetupScrollFreeze(0,1);
ImGui::TableNextRow(ImGuiTableRowFlags_Headers); ImGui::TableNextRow(ImGuiTableRowFlags_Headers);
ImGui::TableNextColumn(); ImGui::TableNextColumn();
ImGui::TableNextColumn(); ImGui::TableNextColumn();
ImGui::Text("Sample"); ImGui::Text("#");
ImGui::TableNextColumn(); ImGui::TableNextColumn();
ImGui::Text("Note"); ImGui::Text("note");
ImGui::TableNextColumn();
ImGui::Text("sample name");
int sampleMapMin=sampleMapSelStart;
int sampleMapMax=sampleMapSelEnd;
if (sampleMapMin>sampleMapMax) {
sampleMapMin^=sampleMapMax;
sampleMapMax^=sampleMapMin;
sampleMapMin^=sampleMapMax;
}
ImGui::PushStyleColor(ImGuiCol_Header,ImGui::GetColorU32(ImGuiCol_HeaderHovered));
ImGui::PushStyleColor(ImGuiCol_HeaderActive,ImGui::GetColorU32(ImGuiCol_HeaderHovered));
for (int i=0; i<120; i++) { for (int i=0; i<120; i++) {
DivInstrumentAmiga::SampleMap& sampleMap=ins->amiga.noteMap[i]; DivInstrumentAmiga::SampleMap& sampleMap=ins->amiga.noteMap[i];
ImGui::TableNextRow(); ImGui::TableNextRow();
ImGui::PushID(fmt::sprintf("NM_%d",i).c_str());
ImGui::TableNextColumn(); ImGui::TableNextColumn();
ImGui::TableSetBgColor(ImGuiTableBgTarget_CellBg,ImGui::GetColorU32(ImGuiCol_TableHeaderBg));
ImGui::Text("%s",noteNames[60+i]); ImGui::Text("%s",noteNames[60+i]);
ImGui::TableNextColumn(); ImGui::TableNextColumn();
if (sampleMap.map<0 || sampleMap.map>=e->song.sampleLen) { if (sampleMap.map<0 || sampleMap.map>=e->song.sampleLen) {
sName="-- empty --"; sName=fmt::sprintf("---##SM%d",i);
sampleMap.map=-1; sampleMap.map=-1;
} else { } else {
sName=e->song.sample[sampleMap.map]->name; sName=fmt::sprintf("%3d##SM%d",sampleMap.map,i);
} }
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); ImGui::PushFont(patFont);
if (ImGui::BeginCombo("##SM",sName.c_str())) { ImGui::SetNextItemWidth(ImGui::CalcTextSize("00000").x);
String id; ImGui::Selectable(sName.c_str(),(sampleMapWaitingInput && sampleMapColumn==0 && i>=sampleMapMin && i<=sampleMapMax));
if (ImGui::Selectable("-- empty --",sampleMap.map==-1)) { PARAMETER if (ImGui::IsItemClicked(ImGuiMouseButton_Left)) {
sampleMap.map=-1; sampleMapFocused=true;
sampleMapColumn=0;
sampleMapDigit=0;
sampleMapSelStart=i;
sampleMapSelEnd=i;
sampleMapMin=sampleMapSelStart;
sampleMapMax=sampleMapSelEnd;
if (sampleMapMin>sampleMapMax) {
sampleMapMin^=sampleMapMax;
sampleMapMax^=sampleMapMin;
sampleMapMin^=sampleMapMax;
} }
for (int j=0; j<e->song.sampleLen; j++) { ImGui::InhibitInertialScroll();
id=fmt::sprintf("%d: %s",j,e->song.sample[j]->name); }
if (ImGui::Selectable(id.c_str(),sampleMap.map==j)) { PARAMETER if (sampleMapFocused && ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByActiveItem) && ImGui::IsMouseDown(ImGuiMouseButton_Left)) {
sampleMap.map=j; sampleMapSelEnd=i;
}
if (ImGui::IsItemClicked(ImGuiMouseButton_Right)) {
if (sampleMapSelStart==sampleMapSelEnd) {
sampleMapFocused=true;
sampleMapColumn=0;
sampleMapDigit=0;
sampleMapSelStart=i;
sampleMapSelEnd=i;
sampleMapMin=sampleMapSelStart;
sampleMapMax=sampleMapSelEnd;
if (sampleMapMin>sampleMapMax) {
sampleMapMin^=sampleMapMax;
sampleMapMax^=sampleMapMin;
sampleMapMin^=sampleMapMax;
} }
} }
ImGui::EndCombo(); if (sampleMapFocused) {
wannaOpenSMPopup=true;
}
} }
ImGui::PopFont();
ImGui::TableNextColumn(); ImGui::TableNextColumn();
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); sName="???";
const char* nName="???";
if ((sampleMap.freq+60)>0 && (sampleMap.freq+60)<180) { if ((sampleMap.freq+60)>0 && (sampleMap.freq+60)<180) {
nName=noteNames[sampleMap.freq+60]; sName=noteNames[sampleMap.freq+60];
} }
if (ImGui::BeginCombo("##SN",nName)) { sName+=fmt::sprintf("##SN%d",i);
for (int j=0; j<180; j++) { ImGui::PushFont(patFont);
const char* nName2="???"; ImGui::SetNextItemWidth(ImGui::CalcTextSize("00000").x);
nName2=noteNames[j]; ImGui::Selectable(sName.c_str(),(sampleMapWaitingInput && sampleMapColumn==1 && i>=sampleMapMin && i<=sampleMapMax));
if (ImGui::Selectable(nName2,(sampleMap.freq+60)==j)) { if (ImGui::IsItemClicked(ImGuiMouseButton_Left)) {
sampleMap.freq=j-60; sampleMapFocused=true;
sampleMapColumn=1;
sampleMapDigit=0;
sampleMapSelStart=i;
sampleMapSelEnd=i;
sampleMapMin=sampleMapSelStart;
sampleMapMax=sampleMapSelEnd;
if (sampleMapMin>sampleMapMax) {
sampleMapMin^=sampleMapMax;
sampleMapMax^=sampleMapMin;
sampleMapMin^=sampleMapMax;
}
ImGui::InhibitInertialScroll();
}
if (sampleMapFocused && ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByActiveItem) && ImGui::IsMouseDown(ImGuiMouseButton_Left)) {
sampleMapSelEnd=i;
}
if (ImGui::IsItemClicked(ImGuiMouseButton_Right)) {
if (sampleMapSelStart==sampleMapSelEnd) {
sampleMapFocused=true;
sampleMapColumn=1;
sampleMapDigit=0;
sampleMapSelStart=i;
sampleMapSelEnd=i;
sampleMapMin=sampleMapSelStart;
sampleMapMax=sampleMapSelEnd;
if (sampleMapMin>sampleMapMax) {
sampleMapMin^=sampleMapMax;
sampleMapMax^=sampleMapMin;
sampleMapMin^=sampleMapMax;
} }
} }
ImGui::EndCombo(); if (sampleMapFocused) {
wannaOpenSMPopup=true;
}
} }
ImGui::PopFont();
ImGui::PopID(); ImGui::TableNextColumn();
if (sampleMap.map>=0 && sampleMap.map<e->song.sampleLen) {
ImGui::TextUnformatted(e->song.sample[sampleMap.map]->name.c_str());
}
} }
ImGui::PopStyleColor(2);
ImGui::EndTable(); ImGui::EndTable();
} }
} else {
sampleMapFocused=false;
} }
ImGui::EndDisabled(); ImGui::EndDisabled();
if (wannaOpenSMPopup) {
ImGui::OpenPopup("SampleMapUtils");
}
if (ImGui::BeginPopup("SampleMapUtils",ImGuiWindowFlags_NoMove|ImGuiWindowFlags_AlwaysAutoResize|ImGuiWindowFlags_NoTitleBar|ImGuiWindowFlags_NoSavedSettings)) {
if (sampleMapSelStart==sampleMapSelEnd && sampleMapSelStart>=0 && sampleMapSelStart<120) {
if (ImGui::MenuItem("set entire map to this note")) {
if (sampleMapSelStart>=0 && sampleMapSelStart<120) {
for (int i=0; i<120; i++) {
if (i==sampleMapSelStart) continue;
ins->amiga.noteMap[i].freq=ins->amiga.noteMap[sampleMapSelStart].freq;
}
}
}
if (ImGui::MenuItem("set entire map to this sample")) {
if (sampleMapSelStart>=0 && sampleMapSelStart<120) {
for (int i=0; i<120; i++) {
if (i==sampleMapSelStart) continue;
ins->amiga.noteMap[i].map=ins->amiga.noteMap[sampleMapSelStart].map;
}
}
}
}
if (ImGui::MenuItem("reset notes")) {
for (int i=0; i<120; i++) {
ins->amiga.noteMap[i].freq=i;
}
}
if (ImGui::MenuItem("clear map samples")) {
for (int i=0; i<120; i++) {
ins->amiga.noteMap[i].map=-1;
}
}
ImGui::EndPopup();
}
ImGui::EndTabItem(); ImGui::EndTabItem();
} else {
sampleMapFocused=false;
} }
} }
if (ins->type==DIV_INS_N163) if (ImGui::BeginTabItem(settings.c163Name.c_str())) { if (ins->type==DIV_INS_N163) if (ImGui::BeginTabItem(settings.c163Name.c_str())) {

View file

@ -34,6 +34,8 @@ void FurnaceGUI::drawNewSong() {
avail.y-=ImGui::GetFrameHeightWithSpacing(); avail.y-=ImGui::GetFrameHeightWithSpacing();
if (ImGui::BeginChild("sysPickerC",avail,false,ImGuiWindowFlags_NoScrollWithMouse|ImGuiWindowFlags_NoScrollbar)) { if (ImGui::BeginChild("sysPickerC",avail,false,ImGuiWindowFlags_NoScrollWithMouse|ImGuiWindowFlags_NoScrollbar)) {
if (newSongFirstFrame)
ImGui::SetKeyboardFocusHere();
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x);
if (ImGui::InputTextWithHint("##SysSearch","Search...",&newSongQuery)) { if (ImGui::InputTextWithHint("##SysSearch","Search...",&newSongQuery)) {
String lowerCase=newSongQuery; String lowerCase=newSongQuery;
@ -159,4 +161,6 @@ void FurnaceGUI::drawNewSong() {
updateWindowTitle(); updateWindowTitle();
ImGui::CloseCurrentPopup(); ImGui::CloseCurrentPopup();
} }
newSongFirstFrame=false;
} }

View file

@ -415,10 +415,14 @@ void FurnaceGUI::drawPiano() {
e->previewSample(curSample,note); e->previewSample(curSample,note);
break; break;
default: default:
e->synchronized([this,note]() { if (sampleMapWaitingInput) {
e->autoNoteOn(-1,curIns,note); alterSampleMap(true,note);
}); } else {
if (edit && curWindow!=GUI_WINDOW_INS_LIST && curWindow!=GUI_WINDOW_INS_EDIT) noteInput(note,0); e->synchronized([this,note]() {
e->autoNoteOn(-1,curIns,note);
});
if (edit && curWindow!=GUI_WINDOW_INS_LIST && curWindow!=GUI_WINDOW_INS_EDIT) noteInput(note,0);
}
break; break;
} }
} }