Outer Glow, brush Smoothing and the rest of Compositor 1.2.0
This commit is contained in:
1 parent
2cd0d1b86d
commit
374ba8ec73
32 files changed
+624
-47
No files matched your search
@@ -52,6 +52,11 @@ BrushControls::BrushControls(EditorSession &session, QWidget *parent)
|
||||
[this](int value) { changeBrush(m_session, [value](BrushSettings &brush) { brush.opacity = value / 1000.0; }); })),
|
||||
m_opacity(new SelectionAmountField(session, 1, 100, [this] { return m_session.brushSettings().opacity * 100; },
|
||||
[this](double percent) { changeBrush(m_session, [percent](BrushSettings &brush) { brush.opacity = percent / 100; }); }, this)),
|
||||
m_smoothingLabel(label(QStringLiteral("Smoothing"), this)),
|
||||
m_smoothingSlider(slider(QStringLiteral("brushSmoothingSlider"), 0, 1000,
|
||||
[this](int value) { changeBrush(m_session, [value](BrushSettings &brush) { brush.smoothing = value / 10.0; }); })),
|
||||
m_smoothing(new SelectionAmountField(session, 0, 100, [this] { return m_session.brushSettings().smoothing; },
|
||||
[this](double value) { changeBrush(m_session, [value](BrushSettings &brush) { brush.smoothing = value; }); }, this)),
|
||||
m_paintLabel(label(QStringLiteral("Paint"), this)), m_maskPaint(new QComboBox(this)), m_colourLabel(label(QStringLiteral("Color"), this)),
|
||||
m_colour(new SwatchButton([&session] { return session.foregroundColor(); }, 4, 1, 1, this)),
|
||||
m_cloneNote(label(QStringLiteral("Alt-click to set the source"), this)), m_mask(label(QStringLiteral("Mask"), this))
|
||||
@@ -73,6 +78,9 @@ BrushControls::BrushControls(EditorSession &session, QWidget *parent)
|
||||
m_opacity->setObjectName(QStringLiteral("brushOpacity"));
|
||||
m_opacity->setFixedWidth(42);
|
||||
m_opacity->setToolTip(QStringLiteral("Press 1–9 for 10–90%, 0 for 100%"));
|
||||
m_smoothing->setObjectName(QStringLiteral("brushSmoothing"));
|
||||
m_smoothing->setFixedWidth(42);
|
||||
m_smoothing->setToolTip(QStringLiteral("The brush trails the pointer on a string this long, so a shaky hand still draws a smooth line"));
|
||||
m_maskPaint->setObjectName(QStringLiteral("maskPaint"));
|
||||
m_maskPaint->setFixedWidth(180);
|
||||
m_maskPaint->addItem(QStringLiteral("Black · Hide"), false);
|
||||
@@ -95,7 +103,7 @@ BrushControls::BrushControls(EditorSession &session, QWidget *parent)
|
||||
widgets.insert(widgets.end(), {m_aligned, m_thisLayer, m_allLayers});
|
||||
widgets.insert(widgets.end(), {label(QStringLiteral("Size"), this), m_size, label(QStringLiteral("px"), this), label(QStringLiteral("Hardness"), this),
|
||||
m_hardnessSlider, m_hardness, label(QStringLiteral("%"), this), m_opacityLabel, m_opacitySlider, m_opacity,
|
||||
label(QStringLiteral("%"), this), m_paintLabel, m_maskPaint, m_colourLabel, m_colour});
|
||||
label(QStringLiteral("%"), this), m_smoothingLabel, m_smoothingSlider, m_smoothing, m_paintLabel, m_maskPaint, m_colourLabel, m_colour});
|
||||
for (QWidget *widget : widgets)
|
||||
row->insertWidget(row->count() - 1, widget);
|
||||
row->addWidget(m_cloneNote);
|
||||
@@ -156,10 +164,14 @@ void BrushControls::synchronize()
|
||||
m_size->sync(int(std::lround(brush.diameter)));
|
||||
m_hardness->sync(int(std::lround(brush.hardness * 100)));
|
||||
m_opacity->sync(int(std::lround(brush.opacity * 100)));
|
||||
for (QWidget *widget : std::initializer_list<QWidget *>{m_smoothingLabel, m_smoothingSlider, m_smoothing})
|
||||
widget->setVisible(tool == NavigationTool::brush);
|
||||
m_smoothing->sync(int(std::lround(brush.smoothing)));
|
||||
// The sliders show the session's numbers without writing back.
|
||||
const QSignalBlocker hardness(m_hardnessSlider), opacity(m_opacitySlider);
|
||||
const QSignalBlocker hardness(m_hardnessSlider), opacity(m_opacitySlider), smoothing(m_smoothingSlider);
|
||||
m_hardnessSlider->setValue(int(std::lround(brush.hardness * 1000)));
|
||||
m_opacitySlider->setValue(int(std::lround(brush.opacity * 1000)));
|
||||
m_smoothingSlider->setValue(int(std::lround(brush.smoothing * 10)));
|
||||
const bool mask = m_session.isMaskSelected();
|
||||
m_paintLabel->setVisible(mask);
|
||||
m_maskPaint->setVisible(mask);
|
||||
|
||||
@@ -44,6 +44,10 @@ private:
|
||||
QLabel *const m_opacityLabel;
|
||||
QSlider *const m_opacitySlider;
|
||||
SelectionAmountField *const m_opacity;
|
||||
// Paint and Erase only; other tools have their own feel.
|
||||
QLabel *const m_smoothingLabel;
|
||||
QSlider *const m_smoothingSlider;
|
||||
SelectionAmountField *const m_smoothing;
|
||||
QLabel *const m_paintLabel;
|
||||
QComboBox *const m_maskPaint;
|
||||
// The foreground colour, the rail swatch's own picker.
|
||||
|
||||
@@ -1,10 +1,20 @@
|
||||
#include "UI/CompositorMenus.h"
|
||||
#include "Logging.h"
|
||||
#include "UI/KeyboardShortcuts.h"
|
||||
#include "UI/NativeLayerList.h"
|
||||
#include <QApplication>
|
||||
#include <QMenu>
|
||||
|
||||
namespace {
|
||||
// The layer list holding the keys, as Swift's table.
|
||||
NativeLayerList *focusedList()
|
||||
{
|
||||
for (QWidget *widget = QApplication::focusWidget(); widget; widget = widget->parentWidget())
|
||||
if (auto *list = qobject_cast<NativeLayerList *>(widget))
|
||||
return list;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// An entry's name: Hue/Saturation is newHueSaturationAdjustment.
|
||||
QString adjustmentName(AdjustmentKind kind)
|
||||
{
|
||||
@@ -157,12 +167,14 @@ CompositorMenus::CompositorMenus(ProjectWorkspace &workspace, QMenuBar &bar, QWi
|
||||
add(view, QStringLiteral("clearGuides"), QStringLiteral("Clear Guides"), QKeySequence(), [this] { session().clearGuides(); });
|
||||
|
||||
QMenu *select = bar.addMenu(QStringLiteral("&Select"));
|
||||
// Text fields keep their own Select All.
|
||||
// The focus takes Select All first, as Swift's responder chain.
|
||||
add(select, QStringLiteral("selectAll"), QStringLiteral("All"), QKeySequence(Qt::CTRL | Qt::Key_A), [this] {
|
||||
if (m_field)
|
||||
m_field->selectAll();
|
||||
else if (InlineTextEditor *text = typedText())
|
||||
text->selectAll();
|
||||
else if (NativeLayerList *list = focusedList())
|
||||
list->selectAllRows();
|
||||
else
|
||||
session().selectAll();
|
||||
});
|
||||
@@ -332,7 +344,6 @@ void CompositorMenus::synchronize()
|
||||
action(QStringLiteral("transformControls"))->setChecked(s.showsTransformControls());
|
||||
action(QStringLiteral("transformControls"))->setEnabled(s.tool() == NavigationTool::move && s.document().has_value());
|
||||
const bool selected = s.selection().has_value();
|
||||
action(QStringLiteral("selectAll"))->setEnabled(drawn);
|
||||
action(QStringLiteral("deselect"))->setEnabled(selected && s.canEditSelection());
|
||||
action(QStringLiteral("inverse"))->setEnabled(selected && s.canEditSelection());
|
||||
action(QStringLiteral("layerPixels"))->setEnabled(active && active->asset && s.canEditSelection());
|
||||
|
||||
@@ -85,6 +85,13 @@ EffectsSheet::EffectsSheet(EditorSession &session, LayerEffectKind kind, QWidget
|
||||
slider(QStringLiteral("Blur"), [](const LayerEffects &e) { return e.innerShadow ? std::optional(e.innerShadow->blur) : std::nullopt; },
|
||||
[](LayerEffects &e, double value) { e.innerShadow->blur = value; }, 0, 100, QStringLiteral("px"), 500);
|
||||
break;
|
||||
case LayerEffectKind::outerGlow:
|
||||
header(QStringLiteral("Outer Glow"), false);
|
||||
slider(QStringLiteral("Size"), [](const LayerEffects &e) { return e.outerGlow ? std::optional(e.outerGlow->size) : std::nullopt; },
|
||||
[](LayerEffects &e, double value) { e.outerGlow->size = value; }, 0, 100, QStringLiteral("px"), 500);
|
||||
slider(QStringLiteral("Opacity"), [](const LayerEffects &e) { return percent(e.outerGlow); },
|
||||
[](LayerEffects &e, double value) { e.outerGlow->opacity = value / 100; }, 0, 100, QStringLiteral("%"));
|
||||
break;
|
||||
}
|
||||
auto *cancel = new QPushButton(QStringLiteral("Cancel"), this);
|
||||
cancel->setObjectName(QStringLiteral("effectsCancel"));
|
||||
|
||||
@@ -255,3 +255,13 @@ void NativeLayerList::changeEvent(QEvent *event)
|
||||
if (event->type() == QEvent::PaletteChange)
|
||||
QMetaObject::invokeMethod(this, &NativeLayerList::update, Qt::QueuedConnection);
|
||||
}
|
||||
|
||||
void NativeLayerList::selectAllRows()
|
||||
{
|
||||
if (m_rows.empty())
|
||||
return;
|
||||
QSet<QUuid> ids;
|
||||
for (const ImageLayer &row : m_rows)
|
||||
ids.insert(row.id);
|
||||
m_session.selectLayers(ids, m_rows.front().id);
|
||||
}
|
||||
@@ -212,6 +212,8 @@ public:
|
||||
QString dragToken() const { return m_dragToken; }
|
||||
|
||||
EditorSession &session() const { return m_session; }
|
||||
// The table's Select All: every row, the top one primary.
|
||||
void selectAllRows();
|
||||
void update();
|
||||
std::vector<LayerCell *> cells() const { return m_cells; }
|
||||
// The row under a point of this list, or -1.
|
||||
|
||||
Reference in new issue
Block a user