Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions Meta/include/meta/metadata/keys.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,18 @@ namespace meta::keys::ui
inline constexpr char category[] = "ui.category";
inline constexpr char closed[] = "ui.closed";
inline constexpr char data_provider[] = "ui.data_provider";

/** @brief Highest value the rail spans, when that is lower than the real max.
*
* A rail has to end somewhere comfortable to drag across, but the parameter
* behind it may legitimately accept far more. Spatial Frequency is the case
* that prompted this: 0 to 64 is the useful range to aim at, yet a user who
* knows they want 512 should be able to type it.
*
* Absent, the rail spans to constraints::max and typing is bounded by the same
* value, which is the behaviour every attribute had before this key existed.
*/
inline constexpr char drag_max[] = "ui.drag_max";
inline constexpr char format[] = "ui.format";
inline constexpr char label[] = "ui.label";
inline constexpr char label_false[] = "ui.label_false";
Expand Down
33 changes: 20 additions & 13 deletions MetaUI/qt/include/meta_qt/designs/industrial/editor_style.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,35 +33,43 @@ inline void style_editor(QWidget *host, const Theme &theme)
"#IndustrialEditor QLabel { color: %1; background: transparent; }"
"#IndustrialEditor QPushButton, #IndustrialEditor QToolButton, "
"#IndustrialEditor QComboBox {"
" color: %1; background: %2; border: 1px solid %3; border-radius: 5px; "
" color: %1; background: %2; border: 1px solid %3; border-radius: "
"5px; "
"padding: 3px 7px; }"
"#IndustrialEditor QPushButton:hover, #IndustrialEditor QToolButton:hover { "
"#IndustrialEditor QPushButton:hover, #IndustrialEditor "
"QToolButton:hover { "
"border-color: %4; }"
"#IndustrialEditor QPushButton:checked { background: %4; color: %1; }"
"#IndustrialEditor QPushButton:disabled, #IndustrialEditor "
"QToolButton:disabled { color: %5; background: transparent; border-color: %3; }"
"#IndustrialEditor QScrollArea { border: none; background: transparent; }"
"#IndustrialEditor QScrollBar:vertical { width: 8px; background: transparent; }"
"QToolButton:disabled { color: %5; background: transparent; "
"border-color: %3; }"
"#IndustrialEditor QScrollArea { border: none; background: "
"transparent; }"
"#IndustrialEditor QScrollBar:vertical { width: 8px; background: "
"transparent; }"
"#IndustrialEditor QScrollBar::handle:vertical { background: %3; "
"border-radius: 3px; min-height: 24px; }"
"#IndustrialEditor QScrollBar::add-line:vertical, #IndustrialEditor "
"QScrollBar::sub-line:vertical { height: 0px; }"
"#IndustrialEditor QScrollBar::add-page:vertical, #IndustrialEditor "
"QScrollBar::sub-page:vertical { background: transparent; }"
"#IndustrialEditor QComboBox::drop-down { border: none; width: 20px; }"
"#IndustrialEditor QComboBox::drop-down { border: none; width: 20px; "
"}"
"#IndustrialEditor QToolButton::menu-indicator { image: none; }"
"#IndustrialEditor QPushButton[preset_name] { padding: 2px; border: 2px solid "
"#IndustrialEditor QPushButton[preset_name] { padding: 2px; border: "
"2px solid "
"transparent; border-radius: 5px; background: transparent; }"
"#IndustrialEditor QPushButton[preset_name]:hover { border-color: %5; }"
"#IndustrialEditor QPushButton[preset_name]:checked { border-color: %4; "
"#IndustrialEditor QPushButton[preset_name]:hover { border-color: "
"%5; }"
"#IndustrialEditor QPushButton[preset_name]:checked { border-color: "
"%4; "
"background: transparent; }")
.arg(theme.ink_primary.name(),
theme.field.name(),
theme.field_border.name(),
theme.accent.name(),
theme.ink_dim.name()));
if (host->layout())
host->layout()->setSpacing(8);
if (host->layout()) host->layout()->setSpacing(8);
for (auto *child : host->findChildren<QWidget *>())
{
child->setProperty("industrialEditor", true);
Expand All @@ -79,8 +87,7 @@ inline void style_editor(QWidget *host, const Theme &theme)
}
for (auto *button : host->findChildren<QAbstractButton *>())
{
if (button->property("preset_name").isValid())
continue;
if (button->property("preset_name").isValid()) continue;
button->setFont(ui_font(12));
button->setFixedHeight(28);
button->setCursor(Qt::PointingHandCursor);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@ class LinkedSliders : public Control<glm::vec2>
{
Q_OBJECT
public:
LinkedSliders(Attribute<glm::vec2> &, const RowContext &, QWidget * = nullptr);
LinkedSliders(Attribute<glm::vec2> &,
const RowContext &,
QWidget * = nullptr);
static bool can_render(const Attribute<glm::vec2> &) { return true; }
glm::vec2 get() const override { return value_; }
void set(const glm::vec2 &) override;
Expand Down
4 changes: 3 additions & 1 deletion MetaUI/qt/include/meta_qt/designs/industrial/text_row.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,9 @@ class TextRow : public Control<std::string>
Q_OBJECT

public:
TextRow(Attribute<std::string> &attr, const RowContext &ctx, QWidget *parent = nullptr);
TextRow(Attribute<std::string> &attr,
const RowContext &ctx,
QWidget *parent = nullptr);

/// Any string attribute. There is no metadata this row cannot honour.
static bool can_render(const Attribute<std::string> &attr);
Expand Down
9 changes: 4 additions & 5 deletions MetaUI/qt/include/meta_qt/ui/number_format.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,13 @@ namespace meta::qt
inline QString display_float(float value, int decimals = 2)
{
const double magnitude = std::abs(double(value));
if (!std::isfinite(value))
return QString::number(value);
if (!std::isfinite(value)) return QString::number(value);
decimals = std::clamp(decimals, 0, 8);
if (magnitude == 0 || magnitude >= std::pow(10., -decimals))
return QString::number(value == 0 ? 0 : value, 'f', decimals);
if (magnitude < 1e-10)
return QString::number(value, 'g', 6);
const int precision = std::min(12, int(std::ceil(-std::log10(magnitude))) + 5);
if (magnitude < 1e-10) return QString::number(value, 'g', 6);
const int precision = std::min(12,
int(std::ceil(-std::log10(magnitude))) + 5);
QString text = QString::number(value, 'f', precision);
while (text.endsWith('0') && text.size() - text.indexOf('.') - 1 > decimals)
text.chop(1);
Expand Down
2 changes: 1 addition & 1 deletion MetaUI/qt/include/meta_qt/widgets/array_canvas.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ class ArrayCanvas : public QWidget

QSize sizeHint() const override;
QSize minimumSizeHint() const override { return QSize(120, 120); }
int heightForWidth(int width) const override { return width; }
int heightForWidth(int width) const override { return width; }

void set_field_data(const std::vector<float> &data);
const std::vector<float> &get_field_data() const;
Expand Down
26 changes: 13 additions & 13 deletions MetaUI/qt/include/meta_qt/widgets/points_canvas.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,17 +53,17 @@ class PointsCanvas : public QWidget
bool closed = false,
QWidget *parent = nullptr);

void clear_all();
void clear_all();
QSize sizeHint() const override { return QSize(320, 320); }
QSize minimumSizeHint() const override { return QSize(120, 120); }
int heightForWidth(int width) const override { return width; }
void randomize(int count);
void load_csv(const QString &path); // x,y,z per line (z clamped to [0,1])
void set_points(const std::vector<glm::vec3> &new_points);
void set_background_image(const std::vector<uint8_t> &pixels,
int w,
int h,
int channels);
int heightForWidth(int width) const override { return width; }
void randomize(int count);
void load_csv(const QString &path); // x,y,z per line (z clamped to [0,1])
void set_points(const std::vector<glm::vec3> &new_points);
void set_background_image(const std::vector<uint8_t> &pixels,
int w,
int h,
int channels);

Q_SIGNALS:
void points_changed();
Expand Down Expand Up @@ -93,11 +93,11 @@ class PointsCanvas : public QWidget
std::vector<glm::vec3> &points_;
float min_x_, max_x_, min_y_, max_y_, z_step_;

int hovered_idx_ = -1;
int hovered_idx_ = -1;
QString order_input_;
int drag_idx_ = -1;
bool moved_during_drag_ = false;
int hovered_segment_ = -1;
int drag_idx_ = -1;
bool moved_during_drag_ = false;
int hovered_segment_ = -1;

Mode mode_;
bool closed_;
Expand Down
11 changes: 8 additions & 3 deletions MetaUI/qt/include/meta_qt/widgets/range_bar.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@

#include <vector>

#include "meta_qt/ui/theme.hpp"
#include <QWidget>
#include <glm/glm.hpp>
#include "meta_qt/ui/theme.hpp"

namespace meta::qt
{
Expand All @@ -34,7 +34,12 @@ class RangeBar : public QWidget
QWidget *parent = nullptr);

void set_value(glm::vec2 v);
void set_theme(const Theme &theme) { theme_ = theme; industrial_ = true; update(); }
void set_theme(const Theme &theme)
{
theme_ = theme;
industrial_ = true;
update();
}
void set_histogram(const std::vector<float> &x, const std::vector<float> &y);

Q_SIGNALS:
Expand All @@ -50,7 +55,7 @@ class RangeBar : public QWidget

private:
Theme theme_;
bool industrial_ = false;
bool industrial_ = false;
enum class Handle
{
None,
Expand Down
46 changes: 35 additions & 11 deletions MetaUI/qt/src/designs/industrial/industrial.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -90,39 +90,63 @@ void register_design()
// construction yields a complete panel rather than a handful of rows. Drop
// this line and the unported widget types simply render nothing.
stock::register_design();
const RowFactory editor = [](AbstractAttribute &attr, const RowContext &ctx,
QWidget *parent) -> MetaWidget *
const RowFactory editor = [](AbstractAttribute &attr,
const RowContext &ctx,
QWidget *parent) -> MetaWidget *
{
auto *widget = DesignRegistry::instance().render(&attr, stock::kDesignName, ctx, parent);
auto *widget = DesignRegistry::instance().render(&attr,
stock::kDesignName,
ctx,
parent);
if (!widget) return nullptr;
#ifdef META_ENABLE_ARRAY_TYPES
if (auto *canvas = widget->findChild<ArrayCanvas *>())
{
auto *layout = qobject_cast<QVBoxLayout *>(widget->layout());
layout->insertWidget(0, new QLabel(QString::fromStdString(meta::common::label(static_cast<Attribute<meta::Array> &>(attr))), widget));
auto *hint = new QLabel(QObject::tr("Drag to paint · Right-drag to erase · Scroll to resize"), widget);
layout->insertWidget(
0,
new QLabel(QString::fromStdString(meta::common::label(
static_cast<Attribute<meta::Array> &>(attr))),
widget));
auto *hint = new QLabel(
QObject::tr("Drag to paint · Right-drag to erase · Scroll to resize"),
widget);
hint->setWordWrap(true);
layout->addWidget(hint);
canvas->setProperty("industrialEditor", true);
}
#endif
style_editor(widget, ctx.theme ? *ctx.theme : DesignRegistry::instance().theme(kDesignName));
for (auto *range : widget->findChildren<RangeBar *>()) {
range->set_theme(ctx.theme ? *ctx.theme : DesignRegistry::instance().theme(kDesignName));
style_editor(widget,
ctx.theme ? *ctx.theme
: DesignRegistry::instance().theme(kDesignName));
for (auto *range : widget->findChildren<RangeBar *>())
{
range->set_theme(ctx.theme
? *ctx.theme
: DesignRegistry::instance().theme(kDesignName));
range->setFixedHeight(60);
}
return widget;
};
#ifdef META_ENABLE_GLM_TYPES
registry.add(kDesignName, typeid(glm::vec2), "RangeBar", editor);
registry.add(kDesignName, typeid(std::vector<glm::vec3>), "PathEditor", editor);
registry.add(kDesignName, typeid(std::vector<glm::vec3>), "PointsEditor", editor);
registry.add(kDesignName,
typeid(std::vector<glm::vec3>),
"PathEditor",
editor);
registry.add(kDesignName,
typeid(std::vector<glm::vec3>),
"PointsEditor",
editor);
#endif
#ifdef META_ENABLE_ARRAY_TYPES
registry.add(kDesignName, typeid(meta::Array), kAnyWidgetType, editor);
#endif
#ifdef META_ENABLE_COLOR_GRADIENT_TYPES
registry.add(kDesignName, typeid(meta::ColorGradient), kAnyWidgetType, editor);
registry.add(kDesignName,
typeid(meta::ColorGradient),
kAnyWidgetType,
editor);
#endif
registry.set_fallback(kDesignName, stock::kDesignName);
}
Expand Down
15 changes: 14 additions & 1 deletion MetaUI/qt/src/designs/industrial/int_slider.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,20 @@ IntSlider::IntSlider(Attribute<int> &attr,
max_ = std::numeric_limits<int>::max();
}

input_max_ = max_ == 64 ? std::numeric_limits<int>::max() : max_;
// The rail may deliberately stop short of what the parameter accepts. Where
// it does, dragging is held to the rail while typing goes to the real
// maximum. Declared per attribute rather than inferred: this used to trigger
// on max == 64 exactly, which caught unrelated parameters whose 64 is a hard
// cap, Islands and n_vertices among them, and let a user type any number
// into them.
input_max_ = max_;
if (const int declared = meta::common::try_get<int>(attr,
meta::keys::ui::drag_max,
0);
declared > min_ && declared < max_)
{
max_ = declared; // the rail ends here; input_max_ keeps the real limit
}
value_ = std::clamp(attr.value(), min_, input_max_);
norm_ = unbounded_ ? kRestNorm : to_norm(value_);

Expand Down
Loading
Loading