From 98b2121e3eb55034b76710091f8b3f747f7c0b35 Mon Sep 17 00:00:00 2001 From: parker Date: Tue, 12 Aug 2025 03:00:23 +0100 Subject: [PATCH] feat: add bool switch --- CMakeLists.txt | 1 + src/Engine/Operator/Context.cpp | 33 +++++++++++ src/Engine/Operator/Context.h | 2 + src/Engine/Types.h | 3 +- src/Gui/Parameters/BoolSwitchParm.cpp | 82 +++++++++++++++++++++++++++ src/Gui/Parameters/BoolSwitchParm.h | 45 +++++++++++++++ src/Gui/Parameters/FormParm.cpp | 22 +++++++ src/Gui/Parameters/FormParm.h | 1 + src/OpDefs/GopGrid.cpp | 14 +++-- src/OpDefs/GopSineWave.cpp | 34 ++++++++--- 10 files changed, 222 insertions(+), 15 deletions(-) create mode 100644 src/Gui/Parameters/BoolSwitchParm.cpp create mode 100644 src/Gui/Parameters/BoolSwitchParm.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 758295c..374f6ae 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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 ) diff --git a/src/Engine/Operator/Context.cpp b/src/Engine/Operator/Context.cpp index 9ce76b1..cd94dfb 100644 --- a/src/Engine/Operator/Context.cpp +++ b/src/Engine/Operator/Context.cpp @@ -1,6 +1,7 @@ #include "Engine/Operator/Context.h" #include "Engine/Network/NetworkManager.h" #include "Engine/Parameter/Parameter.h" +#include "Engine/Types.h" #include #include #include @@ -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 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 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 { diff --git a/src/Engine/Operator/Context.h b/src/Engine/Operator/Context.h index c5f2a9a..5e048fe 100644 --- a/src/Engine/Operator/Context.h +++ b/src/Engine/Operator/Context.h @@ -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_; diff --git a/src/Engine/Types.h b/src/Engine/Types.h index 0b2fcb6..7e93b73 100644 --- a/src/Engine/Types.h +++ b/src/Engine/Types.h @@ -41,8 +41,9 @@ namespace enzo { LIST_TERMINATOR, STRING, - XYZ, FLOAT, + BOOL, + XYZ, INT, TOGGLE }; diff --git a/src/Gui/Parameters/BoolSwitchParm.cpp b/src/Gui/Parameters/BoolSwitchParm.cpp new file mode 100644 index 0000000..5d91882 --- /dev/null +++ b/src/Gui/Parameters/BoolSwitchParm.cpp @@ -0,0 +1,82 @@ +#include "Gui/Parameters/BoolSwitchParm.h" +#include +#include +#include +#include + +enzo::ui::BoolSwitchParm::BoolSwitchParm(std::weak_ptr 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); +} + diff --git a/src/Gui/Parameters/BoolSwitchParm.h b/src/Gui/Parameters/BoolSwitchParm.h new file mode 100644 index 0000000..e55c3f2 --- /dev/null +++ b/src/Gui/Parameters/BoolSwitchParm.h @@ -0,0 +1,45 @@ +#pragma once + +#include "Engine/Parameter/Parameter.h" +#include "Engine/Types.h" +#include +#include +#include +#include +#include + +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 parameter, QWidget *parent = nullptr); +private: + std::weak_ptr 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); +}; +} diff --git a/src/Gui/Parameters/FormParm.cpp b/src/Gui/Parameters/FormParm.cpp index 5378316..f328c35 100644 --- a/src/Gui/Parameters/FormParm.cpp +++ b/src/Gui/Parameters/FormParm.cpp @@ -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 #include @@ -41,6 +42,14 @@ enzo::ui::FormParm::FormParm(std::weak_ptr 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) { diff --git a/src/Gui/Parameters/FormParm.h b/src/Gui/Parameters/FormParm.h index 5cf489a..50264a0 100644 --- a/src/Gui/Parameters/FormParm.h +++ b/src/Gui/Parameters/FormParm.h @@ -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); diff --git a/src/OpDefs/GopGrid.cpp b/src/OpDefs/GopGrid.cpp index 4147b6e..a25612b 100644 --- a/src/OpDefs/GopGrid.cpp +++ b/src/OpDefs/GopGrid.cpp @@ -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(columns-1, 1); + const bt::floatT rowDivisor = std::max(rows-1, 1); // add points for(int i=0;i(i)/(columns-1)*width-centerOffsetX; - const bt::floatT z = static_cast(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 }; diff --git a/src/OpDefs/GopSineWave.cpp b/src/OpDefs/GopSineWave.cpp index 60cdcc8..695c68e 100644 --- a/src/OpDefs/GopSineWave.cpp +++ b/src/OpDefs/GopSineWave.cpp @@ -25,14 +25,30 @@ void GopSineWave::cookOp(enzo::op::Context context) const ga::Offset pointCount = geo.getNumPoints(); const bt::floatT frequency = context.evalFloatParm("frequency"); - tbb::parallel_for(tbb::blocked_range(0, pointCount), [&geo, frequency](tbb::blocked_range range){ - for(ga::Offset i=range.begin(); i!=range.end(); ++i) - { - bt::Vector3 pos = geo.getPointPos(i); - pos += bt::Vector3(0, sin(pos.x()*frequency), 0); - geo.setPointPos(i, pos); - } - }); + 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(0, pointCount), [&geo, frequency, center](tbb::blocked_range 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(0, pointCount), [&geo, frequency] (tbb::blocked_range range){ + for(ga::Offset i=range.begin(); i!=range.end(); ++i) + { + bt::Vector3 pos = geo.getPointPos(i); + pos += bt::Vector3(0, sin(pos.x()*frequency), 0); + 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 };