mirror of
https://github.com/aseprite/aseprite.git
synced 2025-03-01 01:13:40 +00:00
Add check box "Same in all tools" in the Dynamics options window (fix #4003)
Now each tool has independent 'dynamic options'. A global configuration for all tools is also possible via the 'Same in all tools' option. ALso this fix, solves a regression inserted in: 2cc15cda9e82611b3af7bb3cab07cf2fdc479b42 (bug inserted: stabilizer is always active)
This commit is contained in:
parent
bee6b98336
commit
572cdf2b0e
@ -1262,7 +1262,7 @@
|
||||
<param name="type" value="shading" />
|
||||
</item>
|
||||
<separator />
|
||||
<item command="SetSameInk" text="@.same_in_all_tools" group="ink_options" />
|
||||
<item command="SetSameInk" text="@general.same_in_all_tools" group="ink_options" />
|
||||
</menu>
|
||||
|
||||
</menus>
|
||||
|
@ -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>
|
||||
|
@ -976,6 +976,7 @@ END
|
||||
reset = Reset
|
||||
advanced_options = Advanced Options
|
||||
unknown = Unknown
|
||||
same_in_all_tools = Same in all Tools
|
||||
|
||||
[gif_options]
|
||||
title = GIF Options
|
||||
@ -1061,9 +1062,6 @@ copy_color = Copy Alpha+Color
|
||||
lock_alpha = Lock Alpha
|
||||
shading = Shading
|
||||
|
||||
[ink_popup_menu]
|
||||
same_in_all_tools = Same in all Tools
|
||||
|
||||
[jpeg_options]
|
||||
title = JPEG Options
|
||||
quality = Quality:
|
||||
|
@ -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>
|
||||
@ -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="@general.same_in_all_tools" />
|
||||
|
||||
</vbox>
|
||||
</gui>
|
||||
|
@ -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
|
||||
@ -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);
|
||||
|
@ -1152,37 +1152,7 @@ public:
|
||||
, 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() {
|
||||
@ -1192,6 +1162,28 @@ public:
|
||||
return;
|
||||
}
|
||||
|
||||
if (!m_popup.get())
|
||||
m_popup.reset(new DynamicsPopup(this));
|
||||
auto activeTool = App::instance()->activeTool();
|
||||
m_popup->loadDynamicsPref();
|
||||
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(),
|
||||
@ -1214,6 +1206,48 @@ public:
|
||||
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 {
|
||||
@ -1247,6 +1281,7 @@ private:
|
||||
ContextBar* m_ctxBar;
|
||||
mutable tools::DynamicsOptions m_dynamics;
|
||||
bool m_optionsGridVisibility = true;
|
||||
bool m_sameInAllTools = false;
|
||||
};
|
||||
|
||||
class ContextBar::FreehandAlgorithmField : public CheckBox {
|
||||
|
@ -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"
|
||||
@ -293,37 +295,39 @@ int DynamicsPopup::ditheringIndex() const {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void DynamicsPopup::loadDynamicPref(ToolPreferences* toolPref) {
|
||||
if (toolPref) {
|
||||
auto& dynaPref = toolPref->dynamics;
|
||||
m_dynamics->stabilizer()->setSelected(dynaPref.stabilizer());
|
||||
m_stabilizerFactorBackup = dynaPref.stabilizerFactor();
|
||||
m_dynamics->stabilizerFactor()->setValue(
|
||||
dynaPref.stabilizer() ? m_stabilizerFactorBackup : 0);
|
||||
m_dynamics->minSize()->setValue(dynaPref.minSize());
|
||||
m_dynamics->minAngle()->setValue(dynaPref.minAngle());
|
||||
m_pressureThreshold->minThreshold(dynaPref.minPressureThreshold());
|
||||
m_pressureThreshold->maxThreshold(dynaPref.maxPressureThreshold());
|
||||
m_velocityThreshold->minThreshold(dynaPref.minVelocityThreshold());
|
||||
m_velocityThreshold->maxThreshold(dynaPref.maxVelocityThreshold());
|
||||
m_fromTo = dynaPref.colorFromTo();
|
||||
void DynamicsPopup::loadDynamicsPref() {
|
||||
auto& dynaPref = Preferences::instance().tool(
|
||||
App::instance()->activeTool()).dynamics;
|
||||
m_dynamics->stabilizer()->setSelected(dynaPref.stabilizer());
|
||||
m_stabilizerFactorBackup = dynaPref.stabilizerFactor();
|
||||
m_dynamics->stabilizerFactor()->setValue(
|
||||
dynaPref.stabilizer() ? m_stabilizerFactorBackup : 0);
|
||||
m_dynamics->minSize()->setValue(dynaPref.minSize());
|
||||
m_dynamics->minAngle()->setValue(dynaPref.minAngle());
|
||||
m_pressureThreshold->minThreshold(dynaPref.minPressureThreshold());
|
||||
m_pressureThreshold->maxThreshold(dynaPref.maxPressureThreshold());
|
||||
m_velocityThreshold->minThreshold(dynaPref.minVelocityThreshold());
|
||||
m_velocityThreshold->maxThreshold(dynaPref.maxVelocityThreshold());
|
||||
m_fromTo = dynaPref.colorFromTo();
|
||||
|
||||
setCheck(SIZE_WITH_PRESSURE,
|
||||
dynaPref.size() == tools::DynamicSensor::Pressure);
|
||||
setCheck(SIZE_WITH_VELOCITY,
|
||||
dynaPref.size() == tools::DynamicSensor::Velocity);
|
||||
setCheck(ANGLE_WITH_PRESSURE,
|
||||
dynaPref.angle() == tools::DynamicSensor::Pressure);
|
||||
setCheck(ANGLE_WITH_VELOCITY,
|
||||
dynaPref.angle() == tools::DynamicSensor::Velocity);
|
||||
setCheck(GRADIENT_WITH_PRESSURE,
|
||||
dynaPref.gradient() == tools::DynamicSensor::Pressure);
|
||||
setCheck(GRADIENT_WITH_VELOCITY,
|
||||
dynaPref.gradient() == tools::DynamicSensor::Velocity);
|
||||
setCheck(SIZE_WITH_PRESSURE,
|
||||
dynaPref.size() == tools::DynamicSensor::Pressure);
|
||||
setCheck(SIZE_WITH_VELOCITY,
|
||||
dynaPref.size() == tools::DynamicSensor::Velocity);
|
||||
setCheck(ANGLE_WITH_PRESSURE,
|
||||
dynaPref.angle() == tools::DynamicSensor::Pressure);
|
||||
setCheck(ANGLE_WITH_VELOCITY,
|
||||
dynaPref.angle() == tools::DynamicSensor::Velocity);
|
||||
setCheck(GRADIENT_WITH_PRESSURE,
|
||||
dynaPref.gradient() == tools::DynamicSensor::Pressure);
|
||||
setCheck(GRADIENT_WITH_VELOCITY,
|
||||
dynaPref.gradient() == tools::DynamicSensor::Velocity);
|
||||
|
||||
if (m_ditheringSel)
|
||||
m_ditheringSel->setSelectedItemIndex(dynaPref.matrixIndex());
|
||||
}
|
||||
if (m_ditheringSel)
|
||||
m_ditheringSel->setSelectedItemIndex(dynaPref.matrixIndex());
|
||||
|
||||
m_dynamics->sameInAllTools()->setSelected(
|
||||
Preferences::instance().shared.shareDynamics());
|
||||
}
|
||||
|
||||
tools::DynamicsOptions DynamicsPopup::getDynamics() const
|
||||
@ -374,36 +378,12 @@ bool DynamicsPopup::isCheck(int i) const
|
||||
->icon() == theme->parts.dropPixelsOk());
|
||||
}
|
||||
|
||||
void DynamicsPopup::onValuesChange(ButtonSet::Item* item)
|
||||
// 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()
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
const bool hasPressure = (isCheck(SIZE_WITH_PRESSURE) ||
|
||||
isCheck(ANGLE_WITH_PRESSURE) ||
|
||||
isCheck(GRADIENT_WITH_PRESSURE));
|
||||
@ -459,6 +439,44 @@ void DynamicsPopup::onValuesChange(ButtonSet::Item* item)
|
||||
setHotRegion(m_hotRegion);
|
||||
}
|
||||
|
||||
bool DynamicsPopup::sharedSettings() const
|
||||
{
|
||||
return m_dynamics->sameInAllTools()->isSelected();
|
||||
}
|
||||
|
||||
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(
|
||||
|
@ -37,8 +37,10 @@ namespace app {
|
||||
|
||||
tools::DynamicsOptions getDynamics() const;
|
||||
void setOptionsGridVisibility(bool state);
|
||||
void loadDynamicPref(ToolPreferences* toolPref);
|
||||
void loadDynamicsPref();
|
||||
int ditheringIndex() const;
|
||||
void refreshVisibility();
|
||||
bool sharedSettings() const;
|
||||
|
||||
private:
|
||||
class ThresholdSlider;
|
||||
|
Loading…
x
Reference in New Issue
Block a user