Merge branch 'tildearrow:master' into sysmgrtooltip_syschaninfo

This commit is contained in:
Eknous 2024-03-21 11:09:16 +04:00 committed by GitHub
commit fb29626f5d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
11 changed files with 2424 additions and 2240 deletions

View file

@ -2,7 +2,7 @@
some of the effect numbers are taken from ProTracker / FastTracker 2.
however, effects are continuous, which means you only need to type it once and then stop it with an effect value of `00` or no effect value at all.
however, effects are continuous (unless specified), which means you only need to type it once and then stop it with an effect value of `00` or no effect value at all.
## volume

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -1468,7 +1468,7 @@ void DivSample::render(unsigned int formatMask) {
delta[0]=0;
delta[1]=0;
void* codec=adpcm_create_context(1,4,NOISE_SHAPING_OFF,delta);
void* codec=adpcm_create_context(1,1,NOISE_SHAPING_OFF,delta);
if (codec==NULL) {
logE("oh no IMA encoder could not be created!");
} else {

View file

@ -635,6 +635,73 @@ void FurnaceGUI::updateWindowTitle() {
}
}
void FurnaceGUI::autoDetectSystemIter(std::vector<FurnaceGUISysDef>& category, bool& isMatch, std::map<DivSystem,int>& defCountMap, std::map<DivSystem,DivConfig>& defConfMap, std::map<DivSystem,int>& sysCountMap, std::map<DivSystem,DivConfig>& sysConfMap) {
for (FurnaceGUISysDef& j: category) {
if (!j.orig.empty()) {
defCountMap.clear();
defConfMap.clear();
for (FurnaceGUISysDefChip& k: j.orig) {
auto it=defCountMap.find(k.sys);
if (it==defCountMap.cend()) {
defCountMap[k.sys]=1;
} else {
it->second++;
}
DivConfig dc;
dc.loadFromMemory(k.flags);
defConfMap[k.sys]=dc;
}
if (defCountMap.size()==sysCountMap.size()) {
isMatch=true;
/*logV("trying on defCountMap: %s",j.name);
for (std::pair<DivSystem,int> k: defCountMap) {
logV("- %s: %d",e->getSystemName(k.first),k.second);
}*/
for (std::pair<DivSystem,int> k: defCountMap) {
auto countI=sysCountMap.find(k.first);
if (countI==sysCountMap.cend()) {
isMatch=false;
break;
} else if (countI->second!=k.second) {
isMatch=false;
break;
}
auto confI=sysConfMap.find(k.first);
if (confI==sysConfMap.cend()) {
isMatch=false;
break;
}
DivConfig& sysDC=confI->second;
auto defConfI=defConfMap.find(k.first);
if (defConfI==defConfMap.cend()) {
isMatch=false;
break;
}
for (std::pair<String,String> l: defConfI->second.configMap()) {
if (!sysDC.has(l.first)) {
isMatch=false;
break;
}
if (sysDC.getString(l.first,"")!=l.second) {
isMatch=false;
break;
}
}
if (!isMatch) break;
}
if (isMatch) {
logV("match found!");
e->song.systemName=j.name;
break;
}
}
}
if (!j.subDefs.empty()) autoDetectSystemIter(j.subDefs,isMatch,defCountMap,defConfMap,sysCountMap,sysConfMap);
if (isMatch) break;
}
}
void FurnaceGUI::autoDetectSystem() {
std::map<DivSystem,int> sysCountMap;
std::map<DivSystem,DivConfig> sysConfMap;
@ -657,65 +724,7 @@ void FurnaceGUI::autoDetectSystem() {
std::map<DivSystem,int> defCountMap;
std::map<DivSystem,DivConfig> defConfMap;
for (FurnaceGUISysCategory& i: sysCategories) {
for (FurnaceGUISysDef& j: i.systems) {
defCountMap.clear();
defConfMap.clear();
for (FurnaceGUISysDefChip& k: j.orig) {
auto it=defCountMap.find(k.sys);
if (it==defCountMap.cend()) {
defCountMap[k.sys]=1;
} else {
it->second++;
}
DivConfig dc;
dc.loadFromMemory(k.flags);
defConfMap[k.sys]=dc;
}
if (defCountMap.size()!=sysCountMap.size()) continue;
isMatch=true;
/*logV("trying on defCountMap: %s",j.name);
for (std::pair<DivSystem,int> k: defCountMap) {
logV("- %s: %d",e->getSystemName(k.first),k.second);
}*/
for (std::pair<DivSystem,int> k: defCountMap) {
auto countI=sysCountMap.find(k.first);
if (countI==sysCountMap.cend()) {
isMatch=false;
break;
} else if (countI->second!=k.second) {
isMatch=false;
break;
}
auto confI=sysConfMap.find(k.first);
if (confI==sysConfMap.cend()) {
isMatch=false;
break;
}
DivConfig& sysDC=confI->second;
auto defConfI=defConfMap.find(k.first);
if (defConfI==defConfMap.cend()) {
isMatch=false;
break;
}
for (std::pair<String,String> l: defConfI->second.configMap()) {
if (!sysDC.has(l.first)) {
isMatch=false;
break;
}
if (sysDC.getString(l.first,"")!=l.second) {
isMatch=false;
break;
}
}
if (!isMatch) break;
}
if (isMatch) {
logV("match found!");
e->song.systemName=j.name;
break;
}
}
autoDetectSystemIter(i.systems,isMatch,defCountMap,defConfMap,sysCountMap,sysConfMap);
if (isMatch) break;
}

View file

@ -1814,6 +1814,7 @@ class FurnaceGUI {
int basicColors;
int playbackTime;
int shaderOsc;
int cursorWheelStep;
unsigned int maxUndoSteps;
String mainFontPath;
String headFontPath;
@ -2018,6 +2019,7 @@ class FurnaceGUI {
basicColors(1),
playbackTime(1),
shaderOsc(1),
cursorWheelStep(0),
maxUndoSteps(100),
mainFontPath(""),
headFontPath(""),
@ -2511,6 +2513,7 @@ class FurnaceGUI {
void updateWindowTitle();
void autoDetectSystem();
void autoDetectSystemIter(std::vector<FurnaceGUISysDef>& category, bool& isMatch, std::map<DivSystem,int>& defCountMap, std::map<DivSystem,DivConfig>& defConfMap, std::map<DivSystem,int>& sysCountMap, std::map<DivSystem,DivConfig>& sysConfMap);
void prepareLayout();
ImVec4 channelColor(int ch);
ImVec4 channelTextColor(int ch);
@ -2549,6 +2552,8 @@ class FurnaceGUI {
void waveListItem(int index, float* wavePreview, int dir, int asset);
void sampleListItem(int index, int dir, int asset);
void drawSysDefs(std::vector<FurnaceGUISysDef>& category, bool& accepted, std::vector<int>& sysDefStack);
void toggleMobileUI(bool enable, bool force=false);
void pushToggleColors(bool status);
@ -2712,6 +2717,9 @@ class FurnaceGUI {
void initTutorial();
void activateTutorial(FurnaceGUITutorials which);
bool loadUserPresets(bool redundancy=true);
bool saveUserPresets(bool redundancy=true);
void encodeMMLStr(String& target, int* macro, int macroLen, int macroLoop, int macroRel, bool hex=false, bool bit30=false);
void decodeMMLStr(String& source, int* macro, unsigned char& macroLen, unsigned char& macroLoop, int macroMin, int macroMax, unsigned char& macroRel, bool bit30=false);
void decodeMMLStrW(String& source, int* macro, int& macroLen, int macroMin, int macroMax, bool hex=false);

View file

@ -22,8 +22,80 @@
#include <fmt/printf.h>
#include <algorithm>
String sysDefID;
void FurnaceGUI::drawSysDefs(std::vector<FurnaceGUISysDef>& category, bool& accepted, std::vector<int>& sysDefStack) {
int index=0;
String sysDefIDLeader="##NS";
for (int i: sysDefStack) {
sysDefIDLeader+=fmt::sprintf("/%d",i);
}
for (FurnaceGUISysDef& i: category) {
bool treeNode=false;
bool isHovered=false;
ImGui::TableNextRow();
ImGui::TableNextColumn();
if (!i.subDefs.empty()) {
if (i.orig.empty()) {
sysDefID=fmt::sprintf("%s%s/%dS",i.name,sysDefIDLeader,index);
} else {
sysDefID=fmt::sprintf("%s/%dS",sysDefIDLeader,index);
}
treeNode=ImGui::TreeNodeEx(sysDefID.c_str(),i.orig.empty()?ImGuiTreeNodeFlags_SpanAvailWidth:0);
ImGui::SameLine();
}
if (!i.orig.empty()) {
sysDefID=fmt::sprintf("%s%s/%d",i.name,sysDefIDLeader,index);
if (ImGui::Selectable(sysDefID.c_str(),false,ImGuiSelectableFlags_DontClosePopups)) {
nextDesc=i.definition;
nextDescName=i.name;
accepted=true;
}
if (ImGui::IsItemHovered()) isHovered=true;
} else if (i.subDefs.empty()) {
ImGui::TextUnformatted(i.name);
if (ImGui::IsItemHovered()) isHovered=true;
}
if (treeNode) {
sysDefStack.push_back(index);
drawSysDefs(i.subDefs,accepted,sysDefStack);
sysDefStack.erase(sysDefStack.end()-1);
ImGui::TreePop();
}
if (isHovered) {
if (ImGui::BeginTooltip()) {
std::map<DivSystem,int> chipCounts;
std::vector<DivSystem> chips;
for (FurnaceGUISysDefChip chip: i.orig) {
if (chipCounts.find(chip.sys)==chipCounts.end()) {
chipCounts[chip.sys]=1;
chips.push_back(chip.sys);
} else {
chipCounts[chip.sys]+=1;
}
}
for (size_t chipIndex=0; chipIndex<chips.size(); chipIndex++) {
DivSystem chip=chips[chipIndex];
const DivSysDef* sysDef=e->getSystemDef(chip);
ImGui::PushTextWrapPos(MIN(scrW*dpiScale,400.0f*dpiScale));
ImGui::Text("%s (x%d): ",sysDef->name,chipCounts[chip]);
ImGui::Text("%s",sysDef->description);
ImGui::PopTextWrapPos();
if (chipIndex+1<chips.size()) {
ImGui::Separator();
}
}
ImGui::EndTooltip();
}
}
index++;
}
}
void FurnaceGUI::drawNewSong() {
bool accepted=false;
std::vector<int> sysDefStack;
ImGui::PushFont(bigFont);
ImGui::SetCursorPosX((ImGui::GetContentRegionAvail().x-ImGui::CalcTextSize("Choose a System!").x)*0.5);
@ -97,6 +169,7 @@ void FurnaceGUI::drawNewSong() {
if (ImGui::IsItemHovered()) {
ImGui::SetTooltip("%s",i.description);
}
if (strcmp(i.name,"User")==0) ImGui::Separator();
index++;
}
}
@ -105,43 +178,19 @@ void FurnaceGUI::drawNewSong() {
ImGui::TableNextColumn();
if (ImGui::BeginTable("Systems",1,ImGuiTableFlags_BordersInnerV|ImGuiTableFlags_ScrollY)) {
std::vector<FurnaceGUISysDef>& category=(newSongQuery.empty())?(sysCategories[newSongCategory].systems):(newSongSearchResults);
for (FurnaceGUISysDef& i: category) {
if (category.empty()) {
ImGui::TableNextRow();
ImGui::TableNextColumn();
if (ImGui::Selectable(i.name,false,ImGuiSelectableFlags_DontClosePopups)) {
nextDesc=i.definition;
nextDescName=i.name;
accepted=true;
}
if (ImGui::IsItemHovered()) {
if (ImGui::BeginTooltip()) {
std::map<DivSystem,int> chipCounts;
std::vector<DivSystem> chips;
for (FurnaceGUISysDefChip chip: i.orig) {
if (chipCounts.find(chip.sys)==chipCounts.end()) {
chipCounts[chip.sys]=1;
chips.push_back(chip.sys);
} else {
chipCounts[chip.sys]+=1;
}
}
for (size_t chipIndex=0; chipIndex<chips.size(); chipIndex++) {
DivSystem chip=chips[chipIndex];
const DivSysDef* sysDef=e->getSystemDef(chip);
ImGui::PushTextWrapPos(MIN(scrW*dpiScale,400.0f*dpiScale));
ImGui::Text("%s (x%d): ",sysDef->name,chipCounts[chip]);
ImGui::Text("%s",sysDef->description);
ImGui::PopTextWrapPos();
if (chipIndex+1<chips.size()) {
ImGui::Separator();
}
}
ImGui::EndTooltip();
}
if (newSongQuery.empty()) {
ImGui::Text("no systems here yet!");
} else {
ImGui::Text("no results");
}
} else {
sysDefStack.push_back(newSongQuery.empty()?newSongCategory:-1);
drawSysDefs(category,accepted,sysDefStack);
sysDefStack.erase(sysDefStack.end()-1);
}
ImGui::EndTable();
}

View file

@ -469,7 +469,10 @@ void FurnaceGUI::drawPattern() {
nextAddScroll=0.0f;
}
ImDrawList* tdl=NULL;
if (ImGui::BeginTable("PatternView",displayChans+2,ImGuiTableFlags_BordersInnerV|ImGuiTableFlags_ScrollX|ImGuiTableFlags_ScrollY|ImGuiTableFlags_NoPadInnerX|ImGuiTableFlags_NoBordersInFrozenArea|((settings.cursorFollowsWheel || wheelCalmDown)?ImGuiTableFlags_NoScrollWithMouse:0))) {
if (chans<1) {
ImGui::Text("there aren't any channels to show.");
} else if (ImGui::BeginTable("PatternView",displayChans+2,ImGuiTableFlags_BordersInnerV|ImGuiTableFlags_ScrollX|ImGuiTableFlags_ScrollY|ImGuiTableFlags_NoPadInnerX|ImGuiTableFlags_NoBordersInFrozenArea|((settings.cursorFollowsWheel || wheelCalmDown)?ImGuiTableFlags_NoScrollWithMouse:0))) {
ImGui::TableSetupColumn("pos",ImGuiTableColumnFlags_WidthFixed);
char chanID[2048];
float lineHeight=(ImGui::GetTextLineHeight()+2*dpiScale);
@ -1176,7 +1179,13 @@ void FurnaceGUI::drawPattern() {
// cursor follows wheel
if (settings.cursorFollowsWheel && (!e->isPlaying() || !followPattern) && ImGui::IsWindowHovered(ImGuiHoveredFlags_ChildWindows)) {
if (wheelX!=0 || wheelY!=0) {
moveCursor(wheelX,(settings.cursorFollowsWheel==2)?wheelY:-wheelY,false);
int xAmount=wheelX;
int yAmount=(settings.cursorFollowsWheel==2)?wheelY:-wheelY;
if (settings.cursorWheelStep==1) {
xAmount*=MAX(1,editStep);
yAmount*=MAX(1,editStep);
}
moveCursor(xAmount,yAmount,false);
}
}

File diff suppressed because it is too large Load diff

View file

@ -2423,6 +2423,18 @@ void FurnaceGUI::drawSettings() {
}
ImGui::Unindent();
if (settings.cursorFollowsWheel) {
ImGui::Text("How many steps to move with each scroll wheel step?");
if (ImGui::RadioButton("One##cws0",settings.cursorWheelStep==0)) {
settings.cursorWheelStep=0;
settingsChanged=true;
}
if (ImGui::RadioButton("Edit Step##cws1",settings.cursorWheelStep==1)) {
settings.cursorWheelStep=1;
settingsChanged=true;
}
}
// SUBSECTION ASSETS
CONFIG_SUBSECTION("Assets");
@ -3992,6 +4004,7 @@ void FurnaceGUI::readConfig(DivConfig& conf, FurnaceGUISettingGroups groups) {
settings.insertBehavior=conf.getInt("insertBehavior",1);
settings.pullDeleteRow=conf.getInt("pullDeleteRow",1);
settings.cursorFollowsWheel=conf.getInt("cursorFollowsWheel",0);
settings.cursorWheelStep=conf.getInt("cursorWheelStep",0);
settings.removeInsOff=conf.getInt("removeInsOff",0);
settings.removeVolOff=conf.getInt("removeVolOff",0);
settings.insTypeMenu=conf.getInt("insTypeMenu",1);
@ -4323,6 +4336,7 @@ void FurnaceGUI::readConfig(DivConfig& conf, FurnaceGUISettingGroups groups) {
clampSetting(settings.playbackTime,0,1);
clampSetting(settings.shaderOsc,0,1);
clampSetting(settings.oscLineSize,0.25f,16.0f);
clampSetting(settings.cursorWheelStep,0,1);
if (settings.exportLoops<0.0) settings.exportLoops=0.0;
if (settings.exportFadeOut<0.0) settings.exportFadeOut=0.0;
@ -4462,6 +4476,7 @@ void FurnaceGUI::writeConfig(DivConfig& conf, FurnaceGUISettingGroups groups) {
conf.set("insertBehavior",settings.insertBehavior);
conf.set("pullDeleteRow",settings.pullDeleteRow);
conf.set("cursorFollowsWheel",settings.cursorFollowsWheel);
conf.set("cursorWheelStep",settings.cursorWheelStep);
conf.set("removeInsOff",settings.removeInsOff);
conf.set("removeVolOff",settings.removeVolOff);
conf.set("insTypeMenu",settings.insTypeMenu);