feat: add bool switch

This commit is contained in:
parker
2025-08-12 03:00:23 +01:00
parent 63ce4c7694
commit 98b2121e3e
10 changed files with 222 additions and 15 deletions

View File

@@ -55,6 +55,7 @@ set(GUI_SOURCES
src/Gui/ParametersPanel/ParametersPanel.cpp
src/Gui/Parameters/FloatSliderParm.cpp
src/Gui/Parameters/IntSliderParm.cpp
src/Gui/Parameters/BoolSwitchParm.cpp
src/Gui/Parameters/FormParm.cpp
src/Gui/Parameters/StringParm.cpp
)

View File

@@ -1,6 +1,7 @@
#include "Engine/Operator/Context.h"
#include "Engine/Network/NetworkManager.h"
#include "Engine/Parameter/Parameter.h"
#include "Engine/Types.h"
#include <iostream>
#include <memory>
#include <stdexcept>
@@ -51,6 +52,38 @@ enzo::bt::floatT enzo::op::Context::evalFloatParm(const char* parmName, const un
}
}
// TODO: cache value
enzo::bt::intT enzo::op::Context::evalIntParm(const char* parmName, const unsigned int index) const
{
enzo::nt::GeometryOperator& selfOp = networkManager_.getGeoOperator(opId_);
std::weak_ptr<prm::Parameter> parameter = selfOp.getParameter(parmName);
if(auto sharedParm = parameter.lock())
{
return sharedParm->evalInt(index);
}
else
{
throw std::runtime_error("Parameter weak ptr invalid");
}
}
// TODO: cache value
enzo::bt::boolT enzo::op::Context::evalBoolParm(const char* parmName, const unsigned int index) const
{
enzo::nt::GeometryOperator& selfOp = networkManager_.getGeoOperator(opId_);
std::weak_ptr<prm::Parameter> parameter = selfOp.getParameter(parmName);
if(auto sharedParm = parameter.lock())
{
return sharedParm->evalInt(index);
}
else
{
throw std::runtime_error("Parameter weak ptr invalid");
}
}
// TODO: cache value
enzo::bt::String enzo::op::Context::evalStringParm(const char* parmName, const unsigned int index) const
{

View File

@@ -16,6 +16,8 @@ public:
Context(enzo::nt::OpId opId, enzo::nt::NetworkManager& networkManager);
enzo::geo::Geometry cloneInputGeo(unsigned int inputIndex);
bt::floatT evalFloatParm(const char* parmName, const unsigned int index=0) const;
bt::intT evalIntParm(const char* parmName, const unsigned int index=0) const;
bt::boolT evalBoolParm(const char* parmName, const unsigned int index=0) const;
bt::String evalStringParm(const char* parmName, const unsigned int index=0) const;
private:
enzo::nt::OpId opId_;

View File

@@ -41,8 +41,9 @@ namespace enzo
{
LIST_TERMINATOR,
STRING,
XYZ,
FLOAT,
BOOL,
XYZ,
INT,
TOGGLE
};

View File

@@ -0,0 +1,82 @@
#include "Gui/Parameters/BoolSwitchParm.h"
#include <qnamespace.h>
#include <qpushbutton.h>
#include <QPainter>
#include <QParallelAnimationGroup>
enzo::ui::BoolSwitchParm::BoolSwitchParm(std::weak_ptr<enzo::prm::Parameter> parameter, QWidget *parent)
: QPushButton(parent), parameter_{parameter}
{
setFixedWidth(40);
parameter_ = parameter;
setCheckable(true);
setProperty("class", "BoolSwitchParm");
setStyleSheet(R"(
.BoolSwitchParm
{
border-radius: 8px;
border: 1px solid #383838;
}
)");
if(auto parameterShared = parameter_.lock())
{
bool toggled = parameterShared->evalInt();
setChecked(toggled);
switchXEnd_=width() - 20 - 4;
switchColor_= toggled ? switchColorOn_ : switchColorOff_;
switchX_= toggled ? switchXEnd_ : 0;
}
connect(this, &QPushButton::toggled, this, &BoolSwitchParm::onToggle);
}
void enzo::ui::BoolSwitchParm::onToggle(bool checked)
{
animateSwitch(checked);
setValue(checked);
}
void enzo::ui::BoolSwitchParm::paintEvent(QPaintEvent* event)
{
QPushButton::paintEvent(event); // paint bg
QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing, true);
QRect bgRect = rect();
painter.setPen(Qt::NoPen);
painter.setBrush(switchColor_);
constexpr int borderRadius = 7;
constexpr int margin = 2;
painter.drawRoundedRect(QRectF(bgRect.left()+margin+switchX_, bgRect.top()+margin, 20, bgRect.height()-margin*2), borderRadius, borderRadius);
}
void enzo::ui::BoolSwitchParm::setValue(bt::intT value)
{
setChecked(value);
valueChanged(value);
}
void enzo::ui::BoolSwitchParm::animateSwitch(bool checked)
{
auto posAnim = new QPropertyAnimation(this, "switchX");
posAnim->setDuration(200);
posAnim->setEasingCurve(QEasingCurve::InOutQuad);
posAnim->setStartValue(switchX_);
posAnim->setEndValue(checked ? switchXEnd_ : 0);
auto colorAnim = new QPropertyAnimation(this, "switchColor");
colorAnim->setDuration(200);
colorAnim->setEasingCurve(QEasingCurve::InOutQuad);
colorAnim->setStartValue(switchColor_);
colorAnim->setEndValue(checked ? switchColorOn_ : switchColorOff_);
auto group = new QParallelAnimationGroup(this);
group->addAnimation(posAnim);
group->addAnimation(colorAnim);
group->start(QAbstractAnimation::DeleteWhenStopped);
}

View File

@@ -0,0 +1,45 @@
#pragma once
#include "Engine/Parameter/Parameter.h"
#include "Engine/Types.h"
#include <memory>
#include <QWidget>
#include <qpushbutton.h>
#include <QPropertyAnimation>
#include <icecream.hpp>
namespace enzo::ui
{
class BoolSwitchParm
: public QPushButton
{
Q_OBJECT
Q_PROPERTY(qreal switchX READ switchX WRITE setSwitchX)
Q_PROPERTY(QColor switchColor READ switchColor WRITE setSwitchColor)
public:
BoolSwitchParm(std::weak_ptr<enzo::prm::Parameter> parameter, QWidget *parent = nullptr);
private:
std::weak_ptr<enzo::prm::Parameter> parameter_;
qreal switchX_=0;
qreal switchXEnd_;
QColor switchColorOff_=QColor("#383838");
QColor switchColorOn_=QColor("#B3B3B3");
QColor switchColor_;
void setValue(bt::intT);
void onToggle(bool checked);
qreal switchX() const { return switchX_; }
void setSwitchX(qreal x) { switchX_ = x; update(); }
QColor switchColor() const { return switchColor_; }
void setSwitchColor(const QColor &c) { switchColor_ = c; update(); }
protected:
void paintEvent(QPaintEvent *) override;
private Q_SLOTS:
void animateSwitch(bool checked);
Q_SIGNALS:
void valueChanged(bt::intT value);
};
}

View File

@@ -2,6 +2,7 @@
#include "Gui/Parameters/IntSliderParm.h"
#include "Engine/Types.h"
#include "Gui/Parameters/FloatSliderParm.h"
#include "Gui/Parameters/BoolSwitchParm.h"
#include "Gui/Parameters/StringParm.h"
#include <qboxlayout.h>
#include <QLabel>
@@ -41,6 +42,14 @@ enzo::ui::FormParm::FormParm(std::weak_ptr<prm::Parameter> parameter)
connect(slider, &IntSliderParm::valueChanged, this, [this](bt::intT value){this->changeValue(value, 0);});
break;
}
case prm::Type::BOOL:
{
BoolSwitchParm* switchParm = new BoolSwitchParm(parameter_);
mainLayout_->addWidget(switchParm);
mainLayout_->addStretch();
connect(switchParm, &BoolSwitchParm::valueChanged, this, [this](bt::intT value){this->changeValue(value, 0);});
break;
}
case prm::Type::XYZ:
{
const unsigned int vectorSize = sharedParameter->getVectorSize();
@@ -96,6 +105,19 @@ void enzo::ui::FormParm::setLeftPadding(int padding)
}
void enzo::ui::FormParm::changeValue(enzo::bt::intT value, unsigned int index)
{
if(auto sharedParameter=parameter_.lock())
{
sharedParameter->setInt(value, index);
}
else
{
std::cout << "ERROR: parameter no longer exists\n";
}
}
void enzo::ui::FormParm::changeValue(enzo::bt::floatT value, unsigned int index)
{

View File

@@ -18,6 +18,7 @@ public:
void setLeftPadding(int padding);
protected Q_SLOTS:
void changeValue(bt::intT value, unsigned int index=0);
void changeValue(bt::floatT value, unsigned int index=0);
void changeValue(bt::String value, unsigned int index=0);

View File

@@ -24,8 +24,8 @@ void GopGrid::cookOp(enzo::op::Context context)
bt::floatT width = context.evalFloatParm("size", 0);
bt::floatT height = context.evalFloatParm("size", 1);
const bt::intT columns = context.evalFloatParm("columns");
const bt::intT rows = context.evalFloatParm("rows");
const bt::intT columns = context.evalIntParm("columns");
const bt::intT rows = context.evalIntParm("rows");
if(columns<=0 || rows<=0)
{
setOutputGeometry(0, geo);
@@ -35,13 +35,15 @@ void GopGrid::cookOp(enzo::op::Context context)
const bt::floatT centerOffsetX = width/2.0;
const bt::floatT centerOffsetY = height/2.0;
const bt::floatT columnDivisor = std::max<bt::floatT>(columns-1, 1);
const bt::floatT rowDivisor = std::max<bt::floatT>(rows-1, 1);
// add points
for(int i=0;i<columns;i++)
{
for(int j=0;j<rows;++j)
{
const bt::floatT x = static_cast<bt::floatT>(i)/(columns-1)*width-centerOffsetX;
const bt::floatT z = static_cast<bt::floatT>(j)/(rows-1)*height-centerOffsetY;
const bt::floatT x = i/columnDivisor*width-centerOffsetX;
const bt::floatT z = j/rowDivisor*height-centerOffsetY;
geo.addPoint(bt::Vector3(x, 0, z));
}
}
@@ -80,14 +82,14 @@ enzo::prm::Template GopGrid::parameterList[] =
enzo::prm::Name("rows", "Rows"),
enzo::prm::Default(10),
1,
enzo::prm::Range(0, enzo::prm::RangeFlag::LOCKED, 100, enzo::prm::RangeFlag::UNLOCKED)
enzo::prm::Range(1, enzo::prm::RangeFlag::LOCKED, 100, enzo::prm::RangeFlag::UNLOCKED)
),
enzo::prm::Template(
enzo::prm::Type::INT,
enzo::prm::Name("columns", "Columns"),
enzo::prm::Default(10),
1,
enzo::prm::Range(0, enzo::prm::RangeFlag::LOCKED, 100, enzo::prm::RangeFlag::UNLOCKED)
enzo::prm::Range(1, enzo::prm::RangeFlag::LOCKED, 100, enzo::prm::RangeFlag::UNLOCKED)
),
enzo::prm::Terminator
};

View File

@@ -25,6 +25,21 @@ void GopSineWave::cookOp(enzo::op::Context context)
const ga::Offset pointCount = geo.getNumPoints();
const bt::floatT frequency = context.evalFloatParm("frequency");
const bool radial = context.evalBoolParm("radial");
if(radial)
{
const bt::Vector3 center(context.evalFloatParm("center", 0), context.evalFloatParm("center", 1), context.evalFloatParm("center", 2));
tbb::parallel_for(tbb::blocked_range<ga::Offset>(0, pointCount), [&geo, frequency, center](tbb::blocked_range<ga::Offset> range){
for(ga::Offset i=range.begin(); i!=range.end(); ++i)
{
bt::Vector3 pos = geo.getPointPos(i);
pos += bt::Vector3(0, sin((pos-center).norm()*frequency), 0);
geo.setPointPos(i, pos);
}
});
}
else
{
tbb::parallel_for(tbb::blocked_range<ga::Offset>(0, pointCount), [&geo, frequency] (tbb::blocked_range<ga::Offset> range){
for(ga::Offset i=range.begin(); i!=range.end(); ++i)
{
@@ -33,6 +48,7 @@ void GopSineWave::cookOp(enzo::op::Context context)
geo.setPointPos(i, pos);
}
});
}
setOutputGeometry(0, geo);
}
@@ -41,6 +57,8 @@ void GopSineWave::cookOp(enzo::op::Context context)
enzo::prm::Template GopSineWave::parameterList[] =
{
enzo::prm::Template(enzo::prm::Type::BOOL, enzo::prm::Name("radial", "Radial Mode")),
enzo::prm::Template(enzo::prm::Type::XYZ, enzo::prm::Name("center", "Center"), 3),
enzo::prm::Template(enzo::prm::Type::FLOAT, enzo::prm::Name("frequency", "Frequency"), enzo::prm::Default(1), 1),
enzo::prm::Terminator
};