Add javascript variable inputs: Float, Int, Check, Color, Select

master
Jeremy Hu 2019-07-26 10:50:32 +09:30
parent cc51fdafe0
commit af792a9bdc
12 changed files with 569 additions and 37 deletions

View File

@ -404,6 +404,9 @@ HEADERS += src/updateschecker.h
SOURCES += src/updatescheckwidget.cpp
HEADERS += src/updatescheckwidget.h
SOURCES += src/intnumberwidget.cpp
HEADERS += src/intnumberwidget.h
SOURCES += src/main.cpp
HEADERS += src/version.h

View File

@ -3346,16 +3346,20 @@ void Document::updateScript(const QString &script)
void Document::updateVariable(const QString &name, const std::map<QString, QString> &value)
{
bool needRunScript = false;
auto variable = m_cachedVariables.find(name);
if (variable == m_cachedVariables.end()) {
qDebug() << "Update a nonexist variable:" << name << "value:" << value;
m_cachedVariables[name] = value;
needRunScript = true;
} else if (variable->second != value) {
variable->second = value;
} else {
return;
}
if (variable->second == value)
return;
variable->second = value;
m_mergedVariables[name] = value;
emit mergedVaraiblesChanged();
if (needRunScript)
runScript();
}
void Document::updateVariableValue(const QString &name, const QString &value)
@ -3368,22 +3372,36 @@ void Document::updateVariableValue(const QString &name, const QString &value)
auto &variableValue = variable->second["value"];
if (variableValue == value)
return;
qDebug() << "Update variable:" << name << "from:" << variableValue << "to:" << value;
variableValue = value;
m_mergedVariables[name] = variable->second;
runScript();
}
void Document::updateDefaultVariables(const std::map<QString, std::map<QString, QString>> &defaultVariables)
bool Document::updateDefaultVariables(const std::map<QString, std::map<QString, QString>> &defaultVariables)
{
bool updated = false;
for (const auto &it: defaultVariables) {
if (m_mergedVariables.find(it.first) != m_mergedVariables.end())
continue;
auto findMergedVariable = m_mergedVariables.find(it.first);
if (findMergedVariable != m_mergedVariables.end()) {
bool hasChangedAttribute = false;
for (const auto &attribute: it.second) {
if (attribute.first == "value")
continue;
const auto &findMatch = findMergedVariable->second.find(attribute.first);
if (findMatch != findMergedVariable->second.end()) {
if (findMatch->second == attribute.second)
continue;
}
hasChangedAttribute = true;
}
if (!hasChangedAttribute)
continue;
}
updated = true;
auto findCached = m_cachedVariables.find(it.first);
if (findCached != m_cachedVariables.end()) {
m_mergedVariables[it.first] = findCached->second;
m_mergedVariables[it.first] = it.second;
m_mergedVariables[it.first]["value"] = valueOfKeyInMapOrEmpty(findCached->second, "value");
} else {
m_mergedVariables[it.first] = it.second;
m_cachedVariables[it.first] = it.second;
@ -3402,6 +3420,7 @@ void Document::updateDefaultVariables(const std::map<QString, std::map<QString,
if (updated) {
emit mergedVaraiblesChanged();
}
return updated;
}
void Document::runScript()
@ -3420,7 +3439,9 @@ void Document::runScript()
m_scriptRunner = new ScriptRunner();
m_scriptRunner->moveToThread(thread);
m_scriptRunner->setScript(new QString(m_script));
m_scriptRunner->setVariables(new std::map<QString, std::map<QString, QString>>(m_mergedVariables));
m_scriptRunner->setVariables(new std::map<QString, std::map<QString, QString>>(
m_mergedVariables.empty() ? m_cachedVariables : m_mergedVariables
));
connect(thread, &QThread::started, m_scriptRunner, &ScriptRunner::process);
connect(m_scriptRunner, &ScriptRunner::finished, this, &Document::scriptResultReady);
connect(m_scriptRunner, &ScriptRunner::finished, thread, &QThread::quit);
@ -3435,6 +3456,7 @@ void Document::scriptResultReady()
std::map<QString, std::map<QString, QString>> *defaultVariables = m_scriptRunner->takeDefaultVariables();
bool errorChanged = false;
bool consoleLogChanged = false;
bool mergedVariablesChanged = false;
const QString &scriptError = m_scriptRunner->scriptError();
if (m_scriptError != scriptError) {
@ -3455,7 +3477,7 @@ void Document::scriptResultReady()
}
if (nullptr != defaultVariables) {
updateDefaultVariables(*defaultVariables);
mergedVariablesChanged = updateDefaultVariables(*defaultVariables);
delete defaultVariables;
}
@ -3470,7 +3492,7 @@ void Document::scriptResultReady()
qDebug() << "Script run done";
if (m_isScriptResultObsolete) {
if (m_isScriptResultObsolete || mergedVariablesChanged) {
runScript();
}
}

View File

@ -658,7 +658,6 @@ public slots:
void applyPreferenceFlatShadingChange();
void initScript(const QString &script);
void updateScript(const QString &script);
void updateDefaultVariables(const std::map<QString, std::map<QString, QString>> &defaultVariables);
void runScript();
void scriptResultReady();
void updateVariable(const QString &name, const std::map<QString, QString> &value);
@ -680,6 +679,7 @@ private:
void removeRigResults();
void updateLinkedPart(QUuid oldPartId, QUuid newPartId);
//void addToolToMesh(MeshLoader *mesh);
bool updateDefaultVariables(const std::map<QString, std::map<QString, QString>> &defaultVariables);
private: // need initialize
bool m_isResultMeshObsolete;
MeshGenerator *m_meshGenerator;

74
src/intnumberwidget.cpp Normal file
View File

@ -0,0 +1,74 @@
#include <QtWidgets>
#include <QHBoxLayout>
#include <QVBoxLayout>
#include "theme.h"
#include "intnumberwidget.h"
IntNumberWidget::IntNumberWidget(QWidget *parent, bool singleLine) :
QWidget(parent)
{
m_slider = new QSlider(Qt::Horizontal, this);
m_slider->setRange(0, 100);
m_slider->setFixedWidth(120);
m_label = new QLabel(this);
m_label->setAlignment(Qt::AlignLeft);
connect(m_slider, &QAbstractSlider::valueChanged, [=](int value) {
updateValueLabel(value);
emit valueChanged(value);
});
QBoxLayout *layout = nullptr;
if (singleLine) {
layout = new QHBoxLayout(this);
layout->setMargin(2);
layout->addWidget(m_slider);
layout->addWidget(m_label);
} else {
layout = new QVBoxLayout(this);
layout->setMargin(2);
layout->addWidget(m_label);
layout->addWidget(m_slider);
}
}
void IntNumberWidget::updateValueLabel(int value)
{
QString valueString = QString::number(value);
if (m_itemName.isEmpty())
m_label->setText(valueString);
else
m_label->setText(m_itemName + ": " + valueString);
}
void IntNumberWidget::setItemName(const QString &name)
{
m_itemName = name;
updateValueLabel(value());
}
void IntNumberWidget::setRange(int min, int max)
{
m_slider->setRange(min, max);
}
void IntNumberWidget::increaseValue()
{
m_slider->triggerAction(QSlider::SliderPageStepAdd);
}
void IntNumberWidget::descreaseValue()
{
m_slider->triggerAction(QSlider::SliderPageStepSub);
}
int IntNumberWidget::value() const
{
return m_slider->value();
}
void IntNumberWidget::setValue(int value)
{
m_slider->setValue(value);
}

34
src/intnumberwidget.h Normal file
View File

@ -0,0 +1,34 @@
#ifndef DUST3D_INT_NUMBER_WIDGET_H
#define DUST3D_INT_NUMBER_WIDGET_H
#include <QToolButton>
QT_FORWARD_DECLARE_CLASS(QLabel)
QT_FORWARD_DECLARE_CLASS(QSlider)
class IntNumberWidget : public QWidget
{
Q_OBJECT
public:
explicit IntNumberWidget(QWidget *parent = nullptr, bool singleLine=true);
void setRange(int min, int max);
int value() const;
void setItemName(const QString &name);
public slots:
void increaseValue();
void descreaseValue();
void setValue(int value);
signals:
void valueChanged(int value);
private:
void updateValueLabel(int value);
private:
QLabel *m_label = nullptr;
QSlider *m_slider = nullptr;
QString m_itemName;
};
#endif

View File

@ -2,6 +2,7 @@
#include <QElapsedTimer>
#include <QUuid>
#include "scriptrunner.h"
#include "util.h"
JSClassID ScriptRunner::js_partClassId = 0;
JSClassID ScriptRunner::js_componentClassId = 0;
@ -206,16 +207,82 @@ static JSValue js_createNode(JSContext *context, JSValueConst thisValue,
return node;
}
static JSValue js_createVariable(JSContext *context, JSValueConst thisValue,
static JSValue js_createFloatInput(JSContext *context, JSValueConst thisValue,
int argc, JSValueConst *argv)
{
ScriptRunner *runner = (ScriptRunner *)JS_GetContextOpaque(context);
if (argc < 4) {
runner->consoleLog() += "Incomplete parameters, expect: name, defaultValue, minValue, maxValue\r\n";
return JS_EXCEPTION;
}
double mergedValue = 0.0;
const char *name = nullptr;
double defaultValue = 0.0;
double minValue = 0.0;
double maxValue = 0.0;
name = JS_ToCString(context, argv[0]);
if (!name)
goto fail;
JS_ToFloat64(context, &defaultValue, argv[1]);
JS_ToFloat64(context, &minValue, argv[2]);
JS_ToFloat64(context, &maxValue, argv[3]);
mergedValue = runner->createFloatInput(name, defaultValue, minValue, maxValue);
JS_FreeCString(context, name);
return JS_NewFloat64(context, mergedValue);
fail:
JS_FreeCString(context, name);
return JS_EXCEPTION;
}
static JSValue js_createIntInput(JSContext *context, JSValueConst thisValue,
int argc, JSValueConst *argv)
{
ScriptRunner *runner = (ScriptRunner *)JS_GetContextOpaque(context);
if (argc < 4) {
runner->consoleLog() += "Incomplete parameters, expect: name, defaultValue, minValue, maxValue\r\n";
return JS_EXCEPTION;
}
int64_t mergedValue = 0.0;
const char *name = nullptr;
int64_t defaultValue = 0;
int64_t minValue = 0;
int64_t maxValue = 0;
name = JS_ToCString(context, argv[0]);
if (!name)
goto fail;
JS_ToInt64(context, &defaultValue, argv[1]);
JS_ToInt64(context, &minValue, argv[2]);
JS_ToInt64(context, &maxValue, argv[3]);
mergedValue = runner->createIntInput(name, defaultValue, minValue, maxValue);
JS_FreeCString(context, name);
return JS_NewInt64(context, mergedValue);
fail:
JS_FreeCString(context, name);
return JS_EXCEPTION;
}
static JSValue js_createColorInput(JSContext *context, JSValueConst thisValue,
int argc, JSValueConst *argv)
{
ScriptRunner *runner = (ScriptRunner *)JS_GetContextOpaque(context);
if (argc < 2) {
runner->consoleLog() += "Incomplete parameters, expect: name, value\r\n";
runner->consoleLog() += "Incomplete parameters, expect: name, defaultValue\r\n";
return JS_EXCEPTION;
}
QString mergedValue;
QColor mergeValue;
const char *name = nullptr;
const char *defaultValue = nullptr;
@ -227,11 +294,12 @@ static JSValue js_createVariable(JSContext *context, JSValueConst thisValue,
if (!defaultValue)
goto fail;
mergedValue = runner->createVariable(name, defaultValue);
mergeValue = runner->createColorInput(name, defaultValue);
JS_FreeCString(context, name);
JS_FreeCString(context, defaultValue);
return JS_NewFloat64(context, mergedValue.toDouble());
return JS_NewString(context, mergeValue.name().toUtf8().constData());
fail:
JS_FreeCString(context, name);
@ -239,6 +307,98 @@ fail:
return JS_EXCEPTION;
}
static JSValue js_createCheckInput(JSContext *context, JSValueConst thisValue,
int argc, JSValueConst *argv)
{
ScriptRunner *runner = (ScriptRunner *)JS_GetContextOpaque(context);
if (argc < 2) {
runner->consoleLog() += "Incomplete parameters, expect: name, defaultValue\r\n";
return JS_EXCEPTION;
}
bool mergedValue = false;
const char *name = nullptr;
const char *value = nullptr;
bool defaultValue = false;
name = JS_ToCString(context, argv[0]);
if (!name)
goto fail;
value = JS_ToCString(context, argv[1]);
if (!value)
goto fail;
defaultValue = isTrueValueString(value);
mergedValue = runner->createCheckInput(name, defaultValue);
JS_FreeCString(context, name);
JS_FreeCString(context, value);
return JS_NewInt64(context, mergedValue);
fail:
JS_FreeCString(context, name);
JS_FreeCString(context, value);
return JS_EXCEPTION;
}
static JSValue js_createSelectInput(JSContext *context, JSValueConst thisValue,
int argc, JSValueConst *argv)
{
ScriptRunner *runner = (ScriptRunner *)JS_GetContextOpaque(context);
if (argc < 3) {
runner->consoleLog() += "Incomplete parameters, expect: name, defaultValue, options\r\n";
return JS_EXCEPTION;
}
const char *name = nullptr;
int32_t defaultValue = 0;
int32_t mergedValue = 0;
JSValue *arrayItems = nullptr;
uint32_t arrayLength = 0;
QStringList options;
name = JS_ToCString(context, argv[0]);
if (!name)
goto fail;
JS_ToInt32(context, &defaultValue, argv[1]);
if (true != JS_IsArray(context, argv[2])) {
runner->consoleLog() += "Expect array as the third parameter\r\n";
goto fail;
}
if (!js_get_fast_array(context, argv[2], &arrayItems, &arrayLength)) {
runner->consoleLog() += "Read third parameter as array failed\r\n";
goto fail;
}
for (uint32_t i = 0; i < arrayLength; ++i) {
const char *optionValue = JS_ToCString(context, arrayItems[i]);
if (nullptr != optionValue) {
options.append(optionValue);
JS_FreeCString(context, optionValue);
} else {
options.append("");
}
}
mergedValue = runner->createSelectInput(name, defaultValue, options);
if (mergedValue < 0)
mergedValue = 0;
else if (mergedValue >= options.size())
mergedValue = options.size() - 1;
JS_FreeCString(context, name);
return JS_NewInt32(context, mergedValue);
fail:
JS_FreeCString(context, name);
return JS_EXCEPTION;
}
ScriptRunner::ScriptRunner()
{
}
@ -375,7 +535,7 @@ void ScriptRunner::run()
JS_SetContextOpaque(context, this);
if (nullptr != m_script &&
!m_script->isEmpty()) {
!m_script->trimmed().isEmpty()) {
auto buffer = m_script->toUtf8();
JSValue globalObject = JS_GetGlobalObject(context);
@ -391,8 +551,20 @@ void ScriptRunner::run()
document, "createNode",
JS_NewCFunction(context, js_createNode, "createNode", 1));
JS_SetPropertyStr(context,
document, "createVariable",
JS_NewCFunction(context, js_createVariable, "createVariable", 2));
document, "createFloatInput",
JS_NewCFunction(context, js_createFloatInput, "createFloatInput", 4));
JS_SetPropertyStr(context,
document, "createIntInput",
JS_NewCFunction(context, js_createIntInput, "createIntInput", 4));
JS_SetPropertyStr(context,
document, "createColorInput",
JS_NewCFunction(context, js_createColorInput, "createColorInput", 2));
JS_SetPropertyStr(context,
document, "createCheckInput",
JS_NewCFunction(context, js_createCheckInput, "createCheckInput", 2));
JS_SetPropertyStr(context,
document, "createSelectInput",
JS_NewCFunction(context, js_createSelectInput, "createSelectInput", 3));
JS_SetPropertyStr(context,
document, "connect",
JS_NewCFunction(context, js_connect, "connect", 2));
@ -552,13 +724,13 @@ void ScriptRunner::generateSnapshot()
}
}
QString ScriptRunner::createVariable(const QString &name, const QString &defaultValue)
QString ScriptRunner::createInput(const QString &name, const std::map<QString, QString> &attributes)
{
if (nullptr != m_defaultVariables) {
if (m_defaultVariables->find(name) != m_defaultVariables->end()) {
m_scriptError += "Repeated variable name found: \"" + name + "\"\r\n";
}
(*m_defaultVariables)[name]["value"] = defaultValue;
(*m_defaultVariables)[name] = attributes;
}
if (nullptr != m_variables) {
auto findVariable = m_variables->find(name);
@ -568,7 +740,73 @@ QString ScriptRunner::createVariable(const QString &name, const QString &default
return findValue->second;
}
}
return defaultValue;
auto findValue = attributes.find("value");
if (findValue != attributes.end())
return findValue->second;
return QString();
}
float ScriptRunner::createFloatInput(const QString &name, float defaultValue, float minValue, float maxValue)
{
std::map<QString, QString> attributes;
attributes["input"] = "Float";
attributes["value"] = QString::number(defaultValue);
attributes["defaultValue"] = attributes["value"];
attributes["minValue"] = QString::number(minValue);
attributes["maxValue"] = QString::number(maxValue);
auto inputValue = createInput(name, attributes);
return inputValue.toFloat();
}
int ScriptRunner::createIntInput(const QString &name, int defaultValue, int minValue, int maxValue)
{
std::map<QString, QString> attributes;
attributes["input"] = "Int";
attributes["value"] = QString::number(defaultValue);
attributes["defaultValue"] = attributes["value"];
attributes["minValue"] = QString::number(minValue);
attributes["maxValue"] = QString::number(maxValue);
auto inputValue = createInput(name, attributes);
return inputValue.toInt();
}
QColor ScriptRunner::createColorInput(const QString &name, const QColor &defaultValue)
{
std::map<QString, QString> attributes;
attributes["input"] = "Color";
attributes["value"] = defaultValue.name();
attributes["defaultValue"] = attributes["value"];
auto inputValue = createInput(name, attributes);
return QColor(inputValue);
}
bool ScriptRunner::createCheckInput(const QString &name, bool checked)
{
std::map<QString, QString> attributes;
attributes["input"] = "Check";
attributes["value"] = checked ? "true" : "false";
attributes["defaultValue"] = attributes["value"];
auto inputValue = createInput(name, attributes);
return isTrueValueString(inputValue);
}
int ScriptRunner::createSelectInput(const QString &name, int defaultSelectedIndex, const QStringList &options)
{
std::map<QString, QString> attributes;
attributes["input"] = "Select";
attributes["value"] = QString::number(defaultSelectedIndex);
attributes["defaultValue"] = attributes["value"];
attributes["length"] = QString::number(options.size());
for (int i = 0; i < options.size(); ++i) {
attributes["option" + QString::number(i)] = options[i];
}
auto inputValue = createInput(name, attributes);
int selectedIndex = inputValue.toInt();
if (selectedIndex >= options.size()) {
m_scriptError += QString("Selected index of select input \"%1\" is been reset to 0 because of out of range\r\n").arg(name);
selectedIndex = 0;
}
return selectedIndex;
}
void ScriptRunner::process()

View File

@ -2,6 +2,8 @@
#define DUST3D_SCRIPT_RUNNER_H
#include <QObject>
#include <QUuid>
#include <QColor>
#include <QStringList>
#include "snapshot.h"
extern "C" {
#include "quickjs.h"
@ -63,7 +65,6 @@ public:
std::map<QString, std::map<QString, QString>> *takeDefaultVariables();
const QString &scriptError();
static void mergeVaraibles(std::map<QString, std::map<QString, QString>> *target, const std::map<QString, std::map<QString, QString>> &source);
QString createVariable(const QString &name, const QString &defaultValue);
DocumentPart *createPart(DocumentComponent *component);
DocumentComponent *createComponent(DocumentComponent *parentComponent);
DocumentNode *createNode(DocumentPart *part);
@ -71,6 +72,12 @@ public:
QString attribute(DocumentElement *element, const QString &name);
void connect(DocumentNode *firstNode, DocumentNode *secondNode);
QString &consoleLog();
QString createInput(const QString &name, const std::map<QString, QString> &attributes);
float createFloatInput(const QString &name, float defaultValue, float minValue, float maxValue);
int createIntInput(const QString &name, int defaultValue, int minValue, int maxValue);
QColor createColorInput(const QString &name, const QColor &defaultValue);
bool createCheckInput(const QString &name, bool checked);
int createSelectInput(const QString &name, int defaultSelectedIndex, const QStringList &options);
signals:
void finished();
public slots:

View File

@ -1,9 +1,15 @@
#include <QDoubleSpinBox>
#include <QFormLayout>
#include <QDebug>
#include <QCheckBox>
#include <QComboBox>
#include <QLabel>
#include <QColorDialog>
#include "scriptvariableswidget.h"
#include "util.h"
#include "theme.h"
#include "floatnumberwidget.h"
#include "intnumberwidget.h"
ScriptVariablesWidget::ScriptVariablesWidget(const Document *document,
QWidget *parent) :
@ -23,14 +29,157 @@ void ScriptVariablesWidget::reload()
QFormLayout *formLayout = new QFormLayout;
for (const auto &variable: m_document->variables()) {
auto name = variable.first;
auto value = valueOfKeyInMapOrEmpty(variable.second, "value").toFloat();
qDebug() << "Script variable, name:" << name << "value:" << value;
QDoubleSpinBox *inputBox = new QDoubleSpinBox;
inputBox->setValue(value);
connect(inputBox, static_cast<void (QDoubleSpinBox::*)(double)>(&QDoubleSpinBox::valueChanged), this, [=](double toValue) {
emit updateVariableValue(name, QString::number(toValue));
});
formLayout->addRow(name, inputBox);
auto input = valueOfKeyInMapOrEmpty(variable.second, "input");
if ("Float" == input) {
auto minValue = valueOfKeyInMapOrEmpty(variable.second, "minValue").toFloat();
auto maxValue = valueOfKeyInMapOrEmpty(variable.second, "maxValue").toFloat();
auto value = valueOfKeyInMapOrEmpty(variable.second, "value").toFloat();
auto defaultValue = valueOfKeyInMapOrEmpty(variable.second, "defaultValue").toFloat();
FloatNumberWidget *floatWidget = new FloatNumberWidget;
floatWidget->setItemName(name);
floatWidget->setRange(minValue, maxValue);
floatWidget->setValue(value);
connect(floatWidget, &FloatNumberWidget::valueChanged, [=](float toValue) {
emit updateVariableValue(name, QString::number(toValue));
});
QPushButton *floatEraser = new QPushButton(QChar(fa::eraser));
Theme::initAwesomeToolButton(floatEraser);
connect(floatEraser, &QPushButton::clicked, [=]() {
floatWidget->setValue(defaultValue);
});
QHBoxLayout *floatLayout = new QHBoxLayout;
floatLayout->addWidget(floatEraser);
floatLayout->addWidget(floatWidget);
formLayout->addRow(floatLayout);
} else if ("Int" == input) {
auto minValue = valueOfKeyInMapOrEmpty(variable.second, "minValue").toInt();
auto maxValue = valueOfKeyInMapOrEmpty(variable.second, "maxValue").toInt();
auto value = valueOfKeyInMapOrEmpty(variable.second, "value").toInt();
auto defaultValue = valueOfKeyInMapOrEmpty(variable.second, "defaultValue").toInt();
IntNumberWidget *intWidget = new IntNumberWidget;
intWidget->setItemName(name);
intWidget->setRange(minValue, maxValue);
intWidget->setValue(value);
connect(intWidget, &IntNumberWidget::valueChanged, [=](int toValue) {
emit updateVariableValue(name, QString::number(toValue));
});
QPushButton *intEraser = new QPushButton(QChar(fa::eraser));
Theme::initAwesomeToolButton(intEraser);
connect(intEraser, &QPushButton::clicked, [=]() {
intWidget->setValue(defaultValue);
});
QHBoxLayout *intLayout = new QHBoxLayout;
intLayout->addWidget(intEraser);
intLayout->addWidget(intWidget);
formLayout->addRow(intLayout);
} else if ("Check" == input) {
auto value = isTrueValueString(valueOfKeyInMapOrEmpty(variable.second, "value"));
auto defaultValue = isTrueValueString(valueOfKeyInMapOrEmpty(variable.second, "defaultValue"));
QCheckBox *checkBox = new QCheckBox;
checkBox->setText(name);
checkBox->setChecked(value);
connect(checkBox, &QCheckBox::stateChanged, [=](int) {
emit updateVariableValue(name, checkBox->isChecked() ? "true" : "false");
});
QPushButton *checkEraser = new QPushButton(QChar(fa::eraser));
Theme::initAwesomeToolButton(checkEraser);
connect(checkEraser, &QPushButton::clicked, [=]() {
checkBox->setChecked(defaultValue);
});
QHBoxLayout *checkLayout = new QHBoxLayout;
checkLayout->addWidget(checkEraser);
checkLayout->addWidget(checkBox);
formLayout->addRow(checkLayout);
} else if ("Select" == input) {
auto value = valueOfKeyInMapOrEmpty(variable.second, "value").toInt();
auto defaultValue = valueOfKeyInMapOrEmpty(variable.second, "defaultValue").toInt();
auto length = valueOfKeyInMapOrEmpty(variable.second, "length").toInt();
QComboBox *selectBox = new QComboBox;
selectBox->setEditable(false);
selectBox->setSizeAdjustPolicy(QComboBox::AdjustToContents);
for (auto i = 0; i < length; ++i) {
selectBox->addItem(valueOfKeyInMapOrEmpty(variable.second, "option" + QString::number(i)));
}
selectBox->setCurrentIndex(value);
connect(selectBox, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), [=](int index) {
emit updateVariableValue(name, QString::number(index));
});
QPushButton *selectEraser = new QPushButton(QChar(fa::eraser));
Theme::initAwesomeToolButton(selectEraser);
connect(selectEraser, &QPushButton::clicked, [=]() {
selectBox->setCurrentIndex(defaultValue);
});
QLabel *selectLabel = new QLabel;
selectLabel->setText(name);
QHBoxLayout *selectLayout = new QHBoxLayout;
selectLayout->addWidget(selectEraser);
selectLayout->addWidget(selectBox);
selectLayout->addWidget(selectLabel);
formLayout->addRow(selectLayout);
} else if ("Color" == input) {
auto value = valueOfKeyInMapOrEmpty(variable.second, "value");
auto defaultValue = valueOfKeyInMapOrEmpty(variable.second, "defaultValue");
QPushButton *colorEraser = new QPushButton(QChar(fa::eraser));
Theme::initAwesomeToolButton(colorEraser);
QPushButton *pickButton = new QPushButton();
Theme::initAwesomeToolButtonWithoutFont(pickButton);
auto updatePickButtonColor = [=](const QColor &color) {
QPalette palette = pickButton->palette();
palette.setColor(QPalette::Window, color);
palette.setColor(QPalette::Button, color);
pickButton->setPalette(palette);
};
updatePickButtonColor(QColor(value));
connect(colorEraser, &QPushButton::clicked, [=]() {
emit updateVariableValue(name, defaultValue);
});
connect(pickButton, &QPushButton::clicked, [=]() {
QColor color = QColorDialog::getColor(value, this);
if (color.isValid()) {
updatePickButtonColor(color.name());
emit updateVariableValue(name, color.name());
}
});
QLabel *selectLabel = new QLabel;
selectLabel->setText(name);
QHBoxLayout *colorLayout = new QHBoxLayout;
colorLayout->addWidget(colorEraser);
colorLayout->addWidget(pickButton);
colorLayout->addWidget(selectLabel);
colorLayout->addStretch();
formLayout->addRow(colorLayout);
}
}
widget->setLayout(formLayout);

View File

@ -42,6 +42,7 @@ ScriptWidget::ScriptWidget(const Document *document, QWidget *parent) :
splitter->addWidget(scriptEditWidget);
splitter->addWidget(m_consoleEdit);
splitter->addWidget(scriptVariablesWidget);
splitter->setStretchFactor(2, 1);
QVBoxLayout *mainLayout = new QVBoxLayout;
mainLayout->addWidget(splitter);

View File

@ -13632,7 +13632,7 @@ static JSValue JS_GetIterator2(JSContext *ctx, JSValueConst obj,
return enum_obj;
}
static JSValue JS_GetIterator(JSContext *ctx, JSValueConst obj, BOOL is_async)
JSValue JS_GetIterator(JSContext *ctx, JSValueConst obj, BOOL is_async)
{
JSValue method, ret, sync_iter;
@ -13707,7 +13707,7 @@ static JSValue JS_IteratorNext2(JSContext *ctx, JSValueConst enum_obj,
return JS_EXCEPTION;
}
static JSValue JS_IteratorNext(JSContext *ctx, JSValueConst enum_obj,
JSValue JS_IteratorNext(JSContext *ctx, JSValueConst enum_obj,
JSValueConst method,
int argc, JSValueConst *argv, BOOL *pdone)
{
@ -13898,7 +13898,7 @@ static JSValue js_create_array_iterator(JSContext *ctx, JSValueConst this_val,
int argc, JSValueConst *argv, int magic);
/* Access an Array's internal JSValue array if available */
static BOOL js_get_fast_array(JSContext *ctx, JSValueConst obj,
int js_get_fast_array(JSContext *ctx, JSValueConst obj,
JSValue **arrpp, uint32_t *countp)
{
/* Try and handle fast arrays explicitly */

View File

@ -894,4 +894,8 @@ int JS_SetModuleExportList(JSContext *ctx, JSModuleDef *m,
#undef js_unlikely
#undef js_force_inline
// https://www.freelists.org/post/quickjs-devel/how-to-iterator-over-a-JSValue-object,1
int js_get_fast_array(JSContext *ctx, JSValueConst obj,
JSValue **arrpp, uint32_t *countp);
#endif /* QUICKJS_H */

View File

@ -32,7 +32,7 @@ bool ChartPacker::tryPack(float textureSize)
std::vector<maxRectsSize> rects;
int width = textureSize * m_floatToIntFactor;
int height = width;
if (m_tryNum > 3) {
if (m_tryNum > 50) {
qDebug() << "Try the " << m_tryNum << "nth times pack with factor:" << m_textureSizeFactor << " size:" << width << "x" << height;
}
for (const auto &chartSize: m_chartSizes) {