From a23c885ad63a2ef1cac24f2243dcc20ce7c6fa93 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ole-Andr=C3=A9=20Rodlie?= Date: Sun, 26 Jan 2025 22:16:17 +0100 Subject: [PATCH] Support expressions presets/bundle Support extending the default JS functions. Added 'clamp' as an example. --- src/app/GUI/Expressions/expressiondialog.cpp | 4 ++++ src/core/Expressions/expression.cpp | 11 +++++++-- src/core/Expressions/functions/clamp.conf | 1 + src/core/Expressions/functions/clamp.js | 3 +++ src/core/Private/esettings.h | 3 +++ src/core/appsupport.cpp | 25 ++++++++++++++++++++ src/core/appsupport.h | 1 + src/core/coreresources.qrc | 4 ++++ 8 files changed, 50 insertions(+), 2 deletions(-) create mode 100644 src/core/Expressions/functions/clamp.conf create mode 100644 src/core/Expressions/functions/clamp.js diff --git a/src/app/GUI/Expressions/expressiondialog.cpp b/src/app/GUI/Expressions/expressiondialog.cpp index 47d402d64..38d1984ac 100644 --- a/src/app/GUI/Expressions/expressiondialog.cpp +++ b/src/app/GUI/Expressions/expressiondialog.cpp @@ -280,6 +280,10 @@ void addBasicDefs(QsciAPIs* const target) { target->add("Math.tan(x)"); target->add("Math.tanh(x)"); target->add("Math.trunc(x)"); + + // load expressions bundle + const auto bundle = eSettings::instance().expressionsBundle; + for (const auto &fun : bundle) { target->add(fun.first); } } ExpressionDialog::ExpressionDialog(QrealAnimator* const target, diff --git a/src/core/Expressions/expression.cpp b/src/core/Expressions/expression.cpp index 05e68fc0c..53c5da5bc 100644 --- a/src/core/Expressions/expression.cpp +++ b/src/core/Expressions/expression.cpp @@ -26,6 +26,7 @@ #include "expression.h" #include "exceptions.h" +#include "Private/esettings.h" Expression::ResultTester Expression::sQrealAnimatorTester = [](const QJSValue& val) { @@ -60,8 +61,14 @@ void throwIfError(const QJSValue& value, const QString& name) { } void Expression::sAddDefinitionsTo(const QString& definitionsStr, - QJSEngine& e) { - const auto defRet = e.evaluate(definitionsStr); + QJSEngine& e) +{ + QString defs; + const auto bundle = eSettings::instance().expressionsBundle; + for (const auto &fun : bundle) { defs.append(fun.second); } + defs.append(definitionsStr); + + const auto defRet = e.evaluate(defs); throwIfError(defRet, "Definitions"); } diff --git a/src/core/Expressions/functions/clamp.conf b/src/core/Expressions/functions/clamp.conf new file mode 100644 index 000000000..48a0be9b9 --- /dev/null +++ b/src/core/Expressions/functions/clamp.conf @@ -0,0 +1 @@ +target="clamp(x, lower, upper)" diff --git a/src/core/Expressions/functions/clamp.js b/src/core/Expressions/functions/clamp.js new file mode 100644 index 000000000..cc5755fd0 --- /dev/null +++ b/src/core/Expressions/functions/clamp.js @@ -0,0 +1,3 @@ +function clamp(number, lower, upper) { + return Math.max(lower, Math.min(number, upper)); +} diff --git a/src/core/Private/esettings.h b/src/core/Private/esettings.h index 85d975697..581434f7a 100644 --- a/src/core/Private/esettings.h +++ b/src/core/Private/esettings.h @@ -159,6 +159,9 @@ class CORE_EXPORT eSettings : public QObject QList fCommandPalette; QList fCommandHistory; + // Expressions bundle + QList> expressionsBundle = AppSupport::getExpressionsBundle(); + signals: void settingsChanged(); diff --git a/src/core/appsupport.cpp b/src/core/appsupport.cpp index 18a21afc2..76c149fee 100644 --- a/src/core/appsupport.cpp +++ b/src/core/appsupport.cpp @@ -1120,3 +1120,28 @@ const QString AppSupport::filterId(const QString &input) { return QString(input).simplified().replace(" ", ""); } + +const QList > AppSupport::getExpressionsBundle() +{ + QStringList functions; + functions << "clamp"; + + QList > result; + for (const auto &fun : functions) { + const QString funConf = QString(":/expressions/%1.conf").arg(fun); + const QString funJs = QString(":/expressions/%1.js").arg(fun); + if (!QFile::exists(funConf) || !QFile::exists(funJs)) { continue; } + QPair expr; + QSettings conf(funConf, QSettings::IniFormat); + expr.first = conf.value("target").toString(); + QFile funFile(funJs); + if (funFile.open(QIODevice::Text | QIODevice::ReadOnly)) { + expr.second = funFile.readAll(); + funFile.close(); + } + if (expr.first.isEmpty() || expr.second.isEmpty()) { continue; } + qDebug() << "adding expression function" << expr.first; + result << expr; + } + return result; +} diff --git a/src/core/appsupport.h b/src/core/appsupport.h index de90ea3c0..c1fc86a0b 100644 --- a/src/core/appsupport.h +++ b/src/core/appsupport.h @@ -140,6 +140,7 @@ class CORE_EXPORT AppSupport : public QObject static const QList> getEasingPresets(); static void handlePortableFirstRun(); static const QString filterId(const QString &input); + static const QList> getExpressionsBundle(); }; #endif // APPSUPPORT_H diff --git a/src/core/coreresources.qrc b/src/core/coreresources.qrc index cdb9d4df0..53fa84dec 100755 --- a/src/core/coreresources.qrc +++ b/src/core/coreresources.qrc @@ -21,4 +21,8 @@ colorshaders/red.frag colorshaders/value.frag + + Expressions/functions/clamp.conf + Expressions/functions/clamp.js +