Files
hfut-bishe/client/gui/params/ParamControls.cpp
2026-04-09 23:13:33 +08:00

132 lines
3.6 KiB
C++

#include "params/ParamControls.h"
#include <algorithm>
#include <cmath>
#include <QDoubleSpinBox>
#include <QHBoxLayout>
#include <QSlider>
namespace gui {
Float01ParamControl::Float01ParamControl(QWidget* parent)
: QWidget(parent) {
auto* row = new QHBoxLayout(this);
row->setContentsMargins(0, 0, 0, 0);
row->setSpacing(8);
m_slider = new QSlider(Qt::Horizontal, this);
m_slider->setRange(0, 1000);
m_slider->setSingleStep(1);
m_slider->setPageStep(10);
row->addWidget(m_slider, 1);
m_spin = new QDoubleSpinBox(this);
m_spin->setRange(0.0, 1.0);
m_spin->setDecimals(3);
m_spin->setSingleStep(0.01);
m_spin->setMinimumWidth(72);
row->addWidget(m_spin);
connect(m_slider, &QSlider::valueChanged, this, [this]() { syncFromSlider(); });
connect(m_spin, qOverload<double>(&QDoubleSpinBox::valueChanged), this, [this]() { syncFromSpin(); });
setValue01(0.5);
}
void Float01ParamControl::setEnabled(bool on) {
QWidget::setEnabled(on);
if (m_slider) m_slider->setEnabled(on);
if (m_spin) m_spin->setEnabled(on);
}
double Float01ParamControl::value01() const {
return m_spin ? m_spin->value() : 0.5;
}
void Float01ParamControl::setValue01(double v) {
const double clamped = std::clamp(v, 0.0, 1.0);
m_block = true;
if (m_spin) m_spin->setValue(clamped);
if (m_slider) m_slider->setValue(static_cast<int>(std::lround(clamped * 1000.0)));
m_block = false;
}
void Float01ParamControl::syncFromSlider() {
if (m_block || !m_slider || !m_spin) return;
m_block = true;
const double v = static_cast<double>(m_slider->value()) / 1000.0;
m_spin->setValue(v);
m_block = false;
emit valueChanged01(v);
}
void Float01ParamControl::syncFromSpin() {
if (m_block || !m_slider || !m_spin) return;
m_block = true;
const double v = m_spin->value();
m_slider->setValue(static_cast<int>(std::lround(v * 1000.0)));
m_block = false;
emit valueChanged01(v);
}
Vec2ParamControl::Vec2ParamControl(QWidget* parent)
: QWidget(parent) {
auto* row = new QHBoxLayout(this);
row->setContentsMargins(0, 0, 0, 0);
row->setSpacing(8);
m_x = new QDoubleSpinBox(this);
m_x->setRange(-1e9, 1e9);
m_x->setDecimals(2);
m_x->setSingleStep(1.0);
m_x->setMinimumWidth(72);
row->addWidget(m_x, 1);
m_y = new QDoubleSpinBox(this);
m_y->setRange(-1e9, 1e9);
m_y->setDecimals(2);
m_y->setSingleStep(1.0);
m_y->setMinimumWidth(72);
row->addWidget(m_y, 1);
connect(m_x, qOverload<double>(&QDoubleSpinBox::valueChanged), this, [this]() { emitIfChanged(); });
connect(m_y, qOverload<double>(&QDoubleSpinBox::valueChanged), this, [this]() { emitIfChanged(); });
setValue(0.0, 0.0);
}
void Vec2ParamControl::setEnabled(bool on) {
QWidget::setEnabled(on);
if (m_x) m_x->setEnabled(on);
if (m_y) m_y->setEnabled(on);
}
void Vec2ParamControl::setValue(double x, double y) {
m_block = true;
if (m_x) m_x->setValue(x);
if (m_y) m_y->setValue(y);
m_lastX = x;
m_lastY = y;
m_block = false;
}
double Vec2ParamControl::x() const { return m_x ? m_x->value() : 0.0; }
double Vec2ParamControl::y() const { return m_y ? m_y->value() : 0.0; }
void Vec2ParamControl::emitIfChanged() {
if (m_block || !m_x || !m_y) return;
const double nx = m_x->value();
const double ny = m_y->value();
auto nearEq = [](double a, double b) {
const double scale = std::max({1.0, std::abs(a), std::abs(b)});
return std::abs(a - b) <= 1e-4 * scale;
};
if (nearEq(nx, m_lastX) && nearEq(ny, m_lastY)) return;
m_lastX = nx;
m_lastY = ny;
emit valueChanged(nx, ny);
}
} // namespace gui