Skip to content

Commit

Permalink
Add check box "Same in all tools" in the Dynamics options window (fix a…
Browse files Browse the repository at this point in the history
…seprite#4003)

Now each tool has independent 'dynamic options'. A global configuration
for all tools is also possible via the 'Same in all tools' option.
  • Loading branch information
Gasparoken committed Aug 17, 2023
1 parent 115e20d commit fad4f3b
Show file tree
Hide file tree
Showing 7 changed files with 132 additions and 68 deletions.
2 changes: 2 additions & 0 deletions data/pref.xml
Original file line number Diff line number Diff line change
Expand Up @@ -317,6 +317,7 @@
<option id="discard_brush" type="bool" default="false" />
</section>
<section id="shared">
<option id="share_dynamics" type="bool" default="false" />
<option id="share_ink" type="bool" default="false" />
<option id="ink" type="app::tools::InkType" default="app::tools::InkType::DEFAULT" />
</section>
Expand Down Expand Up @@ -473,6 +474,7 @@
<option id="max_pressure_threshold" type="double" default="0.9" />
<option id="min_velocity_threshold" type="double" default="0.1" />
<option id="max_velocity_threshold" type="double" default="0.9" />
<option id="same_in_all_tools" type="bool" default="false" />
</section>
</tool>

Expand Down
1 change: 1 addition & 0 deletions data/strings/en.ini
Original file line number Diff line number Diff line change
Expand Up @@ -777,6 +777,7 @@ merged_layers = Duplicate merged layers only
[dynamics]
stabilizer = Stabilizer
stabilizer_tooltip = Stabilizer radius to avoid shaky lines
same_in_all_tools = Same in all Tools
pressure = Pressure
pressure_tooltip = Control parameters through the pen pressure sensor
velocity = Velocity
Expand Down
4 changes: 3 additions & 1 deletion data/widgets/dynamics.xml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<!-- Aseprite -->
<!-- Copyright (C) 2020-2022 Igara Studio S.A. -->
<!-- Copyright (C) 2020-2023 Igara Studio S.A. -->
<gui>
<vbox id="dynamics">
<hbox>
Expand Down Expand Up @@ -57,6 +57,8 @@
<label id="velocity_label" text="@.velocity" style="mini_label" />
<hbox id="velocity_placeholder" cell_align="horizontal" />
</grid>
<separator horizontal="true" cell_hspan="2" />
<check id="same_in_all_tools" text="@.same_in_all_tools" />

</vbox>
</gui>
4 changes: 2 additions & 2 deletions src/app/tools/tool_loop_manager.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// Aseprite
// Copyright (C) 2019-2022 Igara Studio S.A.
// Copyright (C) 2019-2023 Igara Studio S.A.
// Copyright (C) 2001-2018 David Capello
//
// This program is distributed under the terms of
Expand Down Expand Up @@ -169,7 +169,7 @@ bool ToolLoopManager::releaseButton(const Pointer& pointer)
void ToolLoopManager::movement(Pointer pointer)
{
// Filter points with the stabilizer
if (m_dynamics.stabilizerFactor > 0) {
if (m_dynamics.stabilizer && m_dynamics.stabilizerFactor > 0) {
const double f = m_dynamics.stabilizerFactor;
const gfx::Point delta = (pointer.point() - m_stabilizerCenter);
const double distance = std::sqrt(delta.x*delta.x + delta.y*delta.y);
Expand Down
96 changes: 65 additions & 31 deletions src/app/ui/context_bar.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1152,37 +1152,7 @@ class ContextBar::DynamicsField : public ButtonSet
, m_ctxBar(ctxBar) {
addItem(SkinTheme::get(this)->parts.dynamics(), "dynamics_field");

// TODO: it would be better to initialize 'm_popup' at the time you
// need to display the dynamic options in the 'switchPopup()'
// function.
// However, initialization during construction of the DynamicField
// is an easy way to get the current dithering matrix given the
// index of the selected item of the "dithering matrix" comboBox.
m_popup.reset(new DynamicsPopup(this));
m_popup->loadDynamicPref(
&Preferences::instance().tool(App::instance()->activeTool()));
m_popup->setOptionsGridVisibility(m_optionsGridVisibility);
m_dynamics = m_popup->getDynamics();
m_popup->Close.connect(
[this](CloseEvent&){
deselectItems();
m_dynamics = m_popup->getDynamics();
auto& dynaPref = Preferences::instance().tool(
App::instance()->activeTool()).dynamics;
dynaPref.stabilizer(m_dynamics.stabilizer);
dynaPref.stabilizerFactor(m_dynamics.stabilizerFactor);
dynaPref.size(m_dynamics.size);
dynaPref.angle(m_dynamics.angle);
dynaPref.gradient(m_dynamics.gradient);
dynaPref.minSize.setValue(m_dynamics.minSize);
dynaPref.minAngle.setValue(m_dynamics.minAngle);
dynaPref.minPressureThreshold(m_dynamics.minPressureThreshold);
dynaPref.minVelocityThreshold(m_dynamics.minVelocityThreshold);
dynaPref.maxPressureThreshold(m_dynamics.maxPressureThreshold);
dynaPref.maxVelocityThreshold(m_dynamics.maxVelocityThreshold);
dynaPref.colorFromTo(m_dynamics.colorFromTo);
dynaPref.matrixIndex(m_popup->ditheringIndex());
});
loadDynamicsPref();
}

void switchPopup() {
Expand All @@ -1192,6 +1162,27 @@ class ContextBar::DynamicsField : public ButtonSet
return;
}

m_popup.reset(new DynamicsPopup(this));
auto activeTool = App::instance()->activeTool();
m_popup->loadDynamicsPref(&Preferences::instance());
m_dynamics = m_popup->getDynamics();
m_sameInAllTools = m_popup->sharedSettings();
m_popup->Close.connect(
[this](CloseEvent&) {
deselectItems();
auto activeTool = App::instance()->activeTool();
m_dynamics = m_popup->getDynamics();
m_sameInAllTools = m_popup->sharedSettings();
if (m_sameInAllTools) {
for (Tool* tool : *App::instance()->toolBox())
saveDynamicsPref(tool);
}
else
saveDynamicsPref(activeTool);
});

m_popup->refreshVisibility();

const gfx::Rect bounds = this->bounds();
m_popup->remapWindow();
fit_bounds(display(), m_popup.get(),
Expand All @@ -1214,6 +1205,48 @@ class ContextBar::DynamicsField : public ButtonSet
m_popup->setOptionsGridVisibility(state);
}

void saveDynamicsPref(Tool* tool) {
auto& dynaPref = Preferences::instance().tool(tool).dynamics;
dynaPref.stabilizer(m_dynamics.stabilizer);
dynaPref.stabilizerFactor(m_dynamics.stabilizerFactor);
dynaPref.size(m_dynamics.size);
dynaPref.angle(m_dynamics.angle);
dynaPref.gradient(m_dynamics.gradient);
dynaPref.minSize.setValue(m_dynamics.minSize);
dynaPref.minAngle.setValue(m_dynamics.minAngle);
dynaPref.minPressureThreshold(m_dynamics.minPressureThreshold);
dynaPref.minVelocityThreshold(m_dynamics.minVelocityThreshold);
dynaPref.maxPressureThreshold(m_dynamics.maxPressureThreshold);
dynaPref.maxVelocityThreshold(m_dynamics.maxVelocityThreshold);
dynaPref.colorFromTo(m_dynamics.colorFromTo);
dynaPref.matrixIndex(m_popup->ditheringIndex());
Preferences::instance().shared.shareDynamics(m_sameInAllTools);
}

void loadDynamicsPref() {
auto& dynaPref = Preferences::instance()
.tool(App::instance()->activeTool()).dynamics;
m_dynamics.stabilizer = dynaPref.stabilizer();
m_dynamics.stabilizerFactor = dynaPref.stabilizerFactor();
m_dynamics.size = dynaPref.size();
m_dynamics.angle = dynaPref.angle();
m_dynamics.gradient = dynaPref.gradient();
m_dynamics.minSize = dynaPref.minSize();
m_dynamics.minAngle = dynaPref.minAngle();
m_dynamics.minPressureThreshold = dynaPref.minPressureThreshold();
m_dynamics.minVelocityThreshold = dynaPref.minVelocityThreshold();
m_dynamics.maxPressureThreshold = dynaPref.maxPressureThreshold();
m_dynamics.maxVelocityThreshold = dynaPref.maxVelocityThreshold();
m_dynamics.colorFromTo = dynaPref.colorFromTo();

DitheringSelector matrixSel(DitheringSelector::SelectMatrix);
matrixSel.setSelectedItemIndex(dynaPref.matrixIndex());
render::DitheringMatrix matrix(matrixSel.ditheringMatrix());
m_dynamics.ditheringMatrix = matrix;

m_sameInAllTools = Preferences::instance().shared.shareDynamics();
}

private:
// DynamicsPopup::Delegate impl
doc::BrushRef getActiveBrush() override {
Expand Down Expand Up @@ -1247,6 +1280,7 @@ class ContextBar::DynamicsField : public ButtonSet
ContextBar* m_ctxBar;
mutable tools::DynamicsOptions m_dynamics;
bool m_optionsGridVisibility = true;
bool m_sameInAllTools = false;
};

class ContextBar::FreehandAlgorithmField : public CheckBox {
Expand Down
88 changes: 55 additions & 33 deletions src/app/ui/dynamics_popup.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@

#include "app/ui/dynamics_popup.h"

#include "app/app.h"
#include "app/tools/tool_box.h"
#include "app/ui/dithering_selector.h"
#include "app/ui/skin/skin_theme.h"
#include "os/font.h"
Expand Down Expand Up @@ -293,9 +295,9 @@ int DynamicsPopup::ditheringIndex() const {
return 0;
}

void DynamicsPopup::loadDynamicPref(ToolPreferences* toolPref) {
if (toolPref) {
auto& dynaPref = toolPref->dynamics;
void DynamicsPopup::loadDynamicsPref(Preferences* pref) {
if (pref) {
auto& dynaPref = pref->tool(App::instance()->activeTool()).dynamics;
m_dynamics->stabilizer()->setSelected(dynaPref.stabilizer());
m_stabilizerFactorBackup = dynaPref.stabilizerFactor();
m_dynamics->stabilizerFactor()->setValue(
Expand Down Expand Up @@ -323,6 +325,8 @@ void DynamicsPopup::loadDynamicPref(ToolPreferences* toolPref) {

if (m_ditheringSel)
m_ditheringSel->setSelectedItemIndex(dynaPref.matrixIndex());

m_dynamics->sameInAllTools()->setSelected(pref->shared.shareDynamics());
}
}

Expand Down Expand Up @@ -374,36 +378,11 @@ bool DynamicsPopup::isCheck(int i) const
->icon() == theme->parts.dropPixelsOk());
}

void DynamicsPopup::onValuesChange(ButtonSet::Item* item)
{
auto theme = SkinTheme::get(this);
const skin::SkinPartPtr& ok = theme->parts.dropPixelsOk();
const int i = (item ? m_dynamics->values()->getItemIndex(item): -1);

// Switch item off
if (item && item->icon().get() == ok.get()) {
item->setIcon(nullptr);
}
else {
switch (i) {
case SIZE_WITH_PRESSURE:
case SIZE_WITH_VELOCITY:
setCheck(SIZE_WITH_PRESSURE, i == SIZE_WITH_PRESSURE);
setCheck(SIZE_WITH_VELOCITY, i == SIZE_WITH_VELOCITY);
break;
case ANGLE_WITH_PRESSURE:
case ANGLE_WITH_VELOCITY:
setCheck(ANGLE_WITH_PRESSURE, i == ANGLE_WITH_PRESSURE);
setCheck(ANGLE_WITH_VELOCITY, i == ANGLE_WITH_VELOCITY);
break;
case GRADIENT_WITH_PRESSURE:
case GRADIENT_WITH_VELOCITY:
setCheck(GRADIENT_WITH_PRESSURE, i == GRADIENT_WITH_PRESSURE);
setCheck(GRADIENT_WITH_VELOCITY, i == GRADIENT_WITH_VELOCITY);
break;
}
}

// Update Pressure/Velocity/Gradient popup's variables visibility
// according ButtonSet checks.
// Used after a value change (onValuesChange) and when the popup is
// displayed (on ContextBar::DynamicsField::switchPopup()).
void DynamicsPopup::refreshVisibility() {
const bool hasPressure = (isCheck(SIZE_WITH_PRESSURE) ||
isCheck(ANGLE_WITH_PRESSURE) ||
isCheck(GRADIENT_WITH_PRESSURE));
Expand Down Expand Up @@ -459,6 +438,49 @@ void DynamicsPopup::onValuesChange(ButtonSet::Item* item)
setHotRegion(m_hotRegion);
}

bool DynamicsPopup::sharedSettings() const
{
return m_dynamics->sameInAllTools()->isSelected();
}

void DynamicsPopup::sharedSettings(bool state)
{
m_dynamics->sameInAllTools()->setSelected(state);
}

void DynamicsPopup::onValuesChange(ButtonSet::Item* item)
{
auto theme = SkinTheme::get(this);
const skin::SkinPartPtr& ok = theme->parts.dropPixelsOk();
const int i = (item ? m_dynamics->values()->getItemIndex(item): -1);

// Switch item off
if (item && item->icon().get() == ok.get()) {
item->setIcon(nullptr);
}
else {
switch (i) {
case SIZE_WITH_PRESSURE:
case SIZE_WITH_VELOCITY:
setCheck(SIZE_WITH_PRESSURE, i == SIZE_WITH_PRESSURE);
setCheck(SIZE_WITH_VELOCITY, i == SIZE_WITH_VELOCITY);
break;
case ANGLE_WITH_PRESSURE:
case ANGLE_WITH_VELOCITY:
setCheck(ANGLE_WITH_PRESSURE, i == ANGLE_WITH_PRESSURE);
setCheck(ANGLE_WITH_VELOCITY, i == ANGLE_WITH_VELOCITY);
break;
case GRADIENT_WITH_PRESSURE:
case GRADIENT_WITH_VELOCITY:
setCheck(GRADIENT_WITH_PRESSURE, i == GRADIENT_WITH_PRESSURE);
setCheck(GRADIENT_WITH_VELOCITY, i == GRADIENT_WITH_VELOCITY);
break;
}
}

refreshVisibility();
}

void DynamicsPopup::updateFromToText()
{
m_dynamics->gradientFromTo()->setText(
Expand Down
5 changes: 4 additions & 1 deletion src/app/ui/dynamics_popup.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,11 @@ namespace app {

tools::DynamicsOptions getDynamics() const;
void setOptionsGridVisibility(bool state);
void loadDynamicPref(ToolPreferences* toolPref);
void loadDynamicsPref(Preferences* pref);
int ditheringIndex() const;
void refreshVisibility();
bool sharedSettings() const;
void sharedSettings(bool state);

private:
class ThresholdSlider;
Expand Down

0 comments on commit fad4f3b

Please sign in to comment.