lay down basic imgui wrappers/helpers

This commit is contained in:
SimoZ64
2025-04-28 21:22:27 +02:00
parent 3f14a99ea0
commit f57e15f4de
8 changed files with 178 additions and 74 deletions

View File

@@ -1,44 +1,44 @@
#include <AudioSettings.hpp> #include <AudioSettings.hpp>
AudioSettings::AudioSettings(nlohmann::json &settings) : QWidget(nullptr), settings(settings) { AudioSettings::AudioSettings(nlohmann::json &settings) : settings(settings) {
lockChannels->setChecked(JSONGetField<bool>(settings, "audio", "lock")); lockChannels.setChecked(JSONGetField<bool>(settings, "audio", "lock"));
volumeL->setValue(JSONGetField<float>(settings, "audio", "volumeL") * 100); volumeL.setValue(JSONGetField<float>(settings, "audio", "volumeL") * 100);
volumeR->setValue(JSONGetField<float>(settings, "audio", "volumeR") * 100); volumeR.setValue(JSONGetField<float>(settings, "audio", "volumeR") * 100);
volumeL->setRange(0, 100);
volumeR->setRange(0, 100);
connect(lockChannels.get(), &QCheckBox::stateChanged, this, [&]() {
JSONSetField(settings, "audio", "lock", lockChannels->isChecked());
if (lockChannels->isChecked()) {
volumeR->setValue(volumeL->value());
}
emit modified();
});
connect(volumeL.get(), &QSlider::valueChanged, this, [&]() {
JSONSetField(settings, "audio", "volumeL", float(volumeL->value()) / 100.f);
if (lockChannels->isChecked()) {
volumeR->setValue(volumeL->value());
JSONSetField(settings, "audio", "volumeR", float(volumeL->value()) / 100.f);
}
emit modified();
});
connect(volumeR.get(), &QSlider::valueChanged, this, [&]() {
if (!lockChannels->isChecked()) {
JSONSetField(settings, "audio", "volumeR", float(volumeR->value()) / 100.f);
}
emit modified();
});
mainLayout->addWidget(labelLock.get());
mainLayout->addWidget(lockChannels.get());
volLayout->addWidget(labelL.get());
volLayout->addWidget(volumeL.get());
volLayout->addWidget(labelR.get());
volLayout->addWidget(volumeR.get());
mainLayout->addLayout(volLayout.get());
mainLayout->addStretch();
setLayout(mainLayout.get());
} }
bool AudioSettings::render() {
if(lockChannels.render()) {
auto isChecked = lockChannels.isChecked();
JSONSetField(settings, "audio", "lock", isChecked);
if (isChecked) {
volumeR.setValue(volumeL.getValue());
}
modified = true;
}
ImGui::SameLine();
if(volumeL.render()) {
float valueL = volumeL.getValue();
JSONSetField(settings, "audio", "volumeL", float(valueL) / 100.f);
if (lockChannels.isChecked()) {
volumeR.setValue(valueL);
JSONSetField(settings, "audio", "volumeR", float(valueL) / 100.f);
}
modified = true;
}
ImGui::SameLine();
if(volumeR.render()) {
if (!lockChannels.isChecked()) {
JSONSetField(settings, "audio", "volumeR", float(volumeR.getValue()) / 100.f);
}
modified = true;
}
return modified;
}

View File

@@ -1,17 +1,17 @@
#pragma once #pragma once
#include <JSONUtils.hpp> #include <JSONUtils.hpp>
#include <ImGuiImpl/Checkbox.hpp>
#include <ImGuiImpl/Slider.hpp>
class AudioSettings final { class AudioSettings final {
//std::unique_ptr<QCheckBox> lockChannels = std::make_unique<QCheckBox>(); gui::Checkbox lockChannels{"Lock channels:", false};
//std::unique_ptr<QLabel> labelLock = std::make_unique<QLabel>("Lock channels:"); bool modified = false;
//std::unique_ptr<QLabel> labelL = std::make_unique<QLabel>("Volume L");
//std::unique_ptr<QLabel> labelR = std::make_unique<QLabel>("Volume R");
//std::unique_ptr<QVBoxLayout> mainLayout = std::make_unique<QVBoxLayout>();
//std::unique_ptr<QHBoxLayout> volLayout = std::make_unique<QHBoxLayout>();
//Q_OBJECT
public: public:
//std::unique_ptr<QSlider> volumeL = std::make_unique<QSlider>(Qt::Horizontal), gui::SliderFloat volumeL{"Volume L", 0.f, 100.f, 0.f};
// volumeR = std::make_unique<QSlider>(Qt::Horizontal); gui::SliderFloat volumeR{"Volume R", 0.f, 100.f, 0.f};
explicit AudioSettings(nlohmann::json &); explicit AudioSettings(nlohmann::json &);
bool render();
void setModified(bool v) { modified = v; }
bool getModified() { return modified; }
nlohmann::json &settings; nlohmann::json &settings;
}; };

View File

@@ -2,30 +2,22 @@
#include <JSONUtils.hpp> #include <JSONUtils.hpp>
#include <log.hpp> #include <log.hpp>
CPUSettings::CPUSettings(nlohmann::json &settings) : QWidget(nullptr), settings(settings) { CPUSettings::CPUSettings(nlohmann::json &settings) : settings(settings) {
cpuTypes->addItems({
"Interpreter" //, "Dynamic Recompiler"
});
if (JSONGetField<std::string>(settings, "cpu", "type") == "jit") { if (JSONGetField<std::string>(settings, "cpu", "type") == "jit") {
cpuTypes->setCurrentIndex(1); cpuTypes.setCurrentIndex(1);
} else { } else {
cpuTypes->setCurrentIndex(0); cpuTypes.setCurrentIndex(0);
} }
}
connect(cpuTypes.get(), &QComboBox::currentIndexChanged, this, [&]() { bool CPUSettings::render() {
if (cpuTypes->currentIndex() == 0) { if(cpuTypes.render()) {
if(cpuTypes.getCurrentIndex() == 0) {
JSONSetField(settings, "cpu", "type", "interpreter"); JSONSetField(settings, "cpu", "type", "interpreter");
//} else if (cpuTypes->currentIndex() == 1) {
// JSONSetField(settings, "cpu", "type", "jit");
} else { } else {
Util::panic("Impossible CPU type!"); Util::panic("JIT is unfinished and currently not supported!");
} }
emit modified(); modified = true;
}); }
mainLayout->addWidget(label.get());
mainLayout->addWidget(cpuTypes.get());
mainLayout->addStretch();
setLayout(mainLayout.get());
} }

View File

@@ -1,12 +1,13 @@
#pragma once #pragma once
#include <JSONUtils.hpp> #include <JSONUtils.hpp>
#include <ImGuiImpl/Combobox.hpp>
class CPUSettings final { class CPUSettings final {
//std::unique_ptr<QComboBox> cpuTypes = std::make_unique<QComboBox>(); gui::Combobox cpuTypes{"CPU type:", {"Interpreter" //, "Dynamic Recompiler"
//std::unique_ptr<QLabel> label = std::make_unique<QLabel>("CPU type:"); }};
//std::unique_ptr<QVBoxLayout> mainLayout = std::make_unique<QVBoxLayout>(); bool modified = false;
//Q_OBJECT
public: public:
bool render();
explicit CPUSettings(nlohmann::json &); explicit CPUSettings(nlohmann::json &);
nlohmann::json &settings; nlohmann::json &settings;
}; };

View File

@@ -1,6 +1,7 @@
#include <Debugger.hpp> #include <Debugger.hpp>
Debugger::Debugger() : QWidget(nullptr) { Debugger::Debugger() {
/*
disassembly->setWindowTitle("Disassembly"); disassembly->setWindowTitle("Disassembly");
disassembly->setFeatures(QDockWidget::DockWidgetFloatable | QDockWidget::DockWidgetMovable); disassembly->setFeatures(QDockWidget::DockWidgetFloatable | QDockWidget::DockWidgetMovable);
codeView->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); codeView->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
@@ -18,4 +19,5 @@ Debugger::Debugger() : QWidget(nullptr) {
setLayout(verLayout.get()); setLayout(verLayout.get());
// connect(codeView.get(), &QTreeView::activated, this, ); // connect(codeView.get(), &QTreeView::activated, this, );
*/
} }

View File

@@ -1,6 +1,16 @@
#pragma once #pragma once
#include <imgui.h> #include <imgui.h>
#include <string>
namespace gui { namespace gui {
struct Checkbox {
Checkbox(const std::string& label, bool def = false) : val(def), label(label) {}
void setChecked(bool v) { val = v; }
bool render() { return ImGui::Checkbox(label.c_str(), &val); }
bool isChecked() { return val; }
private:
bool val = false;
std::string label = "";
};
} }

View File

@@ -0,0 +1,46 @@
#pragma once
#include <imgui.h>
#include <string>
#include <vector>
namespace gui {
struct Combobox {
Combobox(std::string label, const std::vector<std::string>& items, std::string preview = "") : label(label), items(items), preview(preview) {}
bool render() {
const char* _preview = "";
if(preview != "") {
_preview = preview.c_str();
} else {
_preview = items[current_index].c_str();
}
bool changed = false;
if (ImGui::BeginCombo(label.c_str(), _preview)) {
for (int n = 0; n < items.size(); n++) {
const bool is_selected = ((current_index) == n);
if (ImGui::Selectable(items[n].c_str(), is_selected))
{
current_index = n;
changed = true;
}
// Set the initial focus when opening the combo (scrolling + keyboard navigation focus)
if (is_selected)
ImGui::SetItemDefaultFocus();
}
ImGui::EndCombo();
}
return changed;
}
void setCurrentIndex(int v) { current_index = v; }
int getCurrentIndex() { return current_index; }
private:
const std::vector<std::string>& items;
std::string label, preview;
int current_index = 0;
};
}

View File

@@ -0,0 +1,53 @@
#pragma once
#include <imgui.h>
#include <string>
namespace gui {
template <typename T>
struct Slider {
Slider(const std::string& label, T min = 0, T max = 0, T default = 0)
: val(default), label(label), min(min), max(max) { }
void setValue(T v) { val = v; }
bool render() {
return ImGui::SliderScalarN(label.c_str(), type_to_imgui(), (void*)&val, 1, (void*)&min, (void*)&max);
}
T getValue() { return val; }
private:
constexpr ImGuiDataType_ type_to_imgui() {
if constexpr(std::is_same_v<T, char>) {
return ImGuiDataType_S8;
} else if constexpr(std::is_same_v<T, unsigned char>) {
return ImGuiDataType_U8;
} else if constexpr(std::is_same_v<T, short>) {
return ImGuiDataType_S16;
} else if constexpr(std::is_same_v<T, unsigned short>) {
return ImGuiDataType_U16;
} else if constexpr(std::is_same_v<T, int>) {
return ImGuiDataType_S32;
} else if constexpr(std::is_same_v<T, unsigned int>) {
return ImGuiDataType_U32;
} else if constexpr(std::is_same_v<T, long long>) {
return ImGuiDataType_S64;
} else if constexpr(std::is_same_v<T, unsigned long long>) {
return ImGuiDataType_U64;
} else if constexpr(std::is_same_v<T, float>) {
return ImGuiDataType_Float;
} else if constexpr(std::is_same_v<T, double>) {
return ImGuiDataType_Double;
} else if constexpr(std::is_same_v<T, bool>) {
return ImGuiDataType_Bool;
} else if constexpr(std::is_same_v<T, char*>) {
return ImGuiDataType_String;
} else {
return ImGuiDataType_COUNT;
}
}
T val{}, min{}, max{};
std::string label = "";
};
using SliderFloat = Slider<float>;
using SliderInt = Slider<int>;
}