Add paint brush pressure sensitivity

This commit is contained in:
manongjohn 2021-06-01 21:36:13 -04:00
parent c6dc84e015
commit 2d59a69622

View file

@ -46,7 +46,10 @@ using namespace ToolUtils;
TEnv::StringVar PaintBrushColorType("InknpaintPaintBrushColorType", "Areas"); TEnv::StringVar PaintBrushColorType("InknpaintPaintBrushColorType", "Areas");
TEnv::IntVar PaintBrushSelective("InknpaintPaintBrushSelective", 0); TEnv::IntVar PaintBrushSelective("InknpaintPaintBrushSelective", 0);
TEnv::DoubleVar PaintBrushSize("InknpaintPaintBrushSize", 10); TEnv::DoubleVar PaintBrushSizeMax("InknpaintPaintBrushSizeMax", 10);
TEnv::DoubleVar PaintBrushSizeMin("InknpaintPaintBrushSizeMin", 10);
TEnv::IntVar PaintBrushPressureSensitivity("InknpaintBrushPressureSensitivity",
1);
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -237,6 +240,16 @@ void drawEmptyCircle(int thick, const TPointD &mousePos, bool isPencil,
} }
} }
//-------------------------------------------------------------------------------------------------------
double computeThickness(double pressure, const TDoublePairProperty &property) {
double t = pressure * pressure * pressure;
double thick0 = property.getValue().first;
double thick1 = property.getValue().second;
if (thick1 < 0.0001) thick0 = thick1 = 0.0;
return (thick0 + (thick1 - thick0) * t) * 0.5;
}
} // namespace } // namespace
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -248,14 +261,13 @@ class PaintBrushTool final : public TTool {
bool m_firstTime; bool m_firstTime;
double m_pointSize, m_distance2;
bool m_selecting; bool m_selecting;
TTileSaverCM32 *m_tileSaver; TTileSaverCM32 *m_tileSaver;
TPointD m_mousePos; TPointD m_mousePos;
TIntProperty m_toolSize; TDoublePairProperty m_rasThickness;
TBoolProperty m_pressure;
TBoolProperty m_onlyEmptyAreas; TBoolProperty m_onlyEmptyAreas;
TEnumProperty m_colorType; TEnumProperty m_colorType;
TPropertyGroup m_prop; TPropertyGroup m_prop;
@ -266,6 +278,8 @@ class PaintBrushTool final : public TTool {
--*/ --*/
TFrameId m_workingFrameId; TFrameId m_workingFrameId;
double m_minThick, m_maxThick;
public: public:
PaintBrushTool(); PaintBrushTool();
@ -297,7 +311,7 @@ public:
/*--- /*---
* onDeactivateにもMouseReleaseと同じ終了処理を行う * onDeactivateにもMouseReleaseと同じ終了処理を行う
* ---*/ * ---*/
void finishBrush(); void finishBrush(double pressureValue);
/*--- Brush、PaintBrush、EraserToolがPencilModeのときにTrueを返す。 /*--- Brush、PaintBrush、EraserToolがPencilModeのときにTrueを返す。
   PaintBrushはピクセルのStyleIndexを入れ替えるツールのため    PaintBrushはピクセルのStyleIndexを入れ替えるツールのため
  PencilMode ---*/   PencilMode ---*/
@ -315,17 +329,17 @@ PaintBrushTool paintBrushTool;
PaintBrushTool::PaintBrushTool() PaintBrushTool::PaintBrushTool()
: TTool("T_PaintBrush") : TTool("T_PaintBrush")
, m_rasterTrack(0) , m_rasterTrack(0)
, m_pointSize(-1)
, m_selecting(false) , m_selecting(false)
, m_tileSaver(0) , m_tileSaver(0)
, m_cursor(ToolCursor::EraserCursor) , m_cursor(ToolCursor::EraserCursor)
// sostituire i nomi con quelli del current, tipo W_ToolOptions... // sostituire i nomi con quelli del current, tipo W_ToolOptions...
, m_toolSize("Size:", 1, 1000, 10, false) // W_ToolOptions_BrushToolSize , m_rasThickness("Size:", 1, 1000, 10, 5)
, m_colorType("Mode:") // W_ToolOptions_InkOrPaint , m_colorType("Mode:") // W_ToolOptions_InkOrPaint
, m_onlyEmptyAreas("Selective", false) // W_ToolOptions_Selective , m_onlyEmptyAreas("Selective", false) // W_ToolOptions_Selective
, m_firstTime(true) , m_firstTime(true)
, m_pressure("Pressure", true)
, m_workingFrameId(TFrameId()) { , m_workingFrameId(TFrameId()) {
m_toolSize.setNonLinearSlider(); m_rasThickness.setNonLinearSlider();
m_colorType.addValue(LINES); m_colorType.addValue(LINES);
m_colorType.addValue(AREAS); m_colorType.addValue(AREAS);
@ -333,18 +347,20 @@ PaintBrushTool::PaintBrushTool()
bind(TTool::ToonzImage); bind(TTool::ToonzImage);
m_prop.bind(m_toolSize); m_prop.bind(m_rasThickness);
m_prop.bind(m_colorType); m_prop.bind(m_colorType);
m_prop.bind(m_onlyEmptyAreas); m_prop.bind(m_onlyEmptyAreas);
m_prop.bind(m_pressure);
m_onlyEmptyAreas.setId("Selective"); m_onlyEmptyAreas.setId("Selective");
m_colorType.setId("Mode"); m_colorType.setId("Mode");
m_pressure.setId("PressureSensitivity");
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void PaintBrushTool::updateTranslation() { void PaintBrushTool::updateTranslation() {
m_toolSize.setQStringName(tr("Size:")); m_rasThickness.setQStringName(tr("Size:"));
m_colorType.setQStringName(tr("Mode:")); m_colorType.setQStringName(tr("Mode:"));
m_colorType.setItemUIName(LINES, tr("Lines")); m_colorType.setItemUIName(LINES, tr("Lines"));
@ -352,6 +368,8 @@ void PaintBrushTool::updateTranslation() {
m_colorType.setItemUIName(ALL, tr("Lines & Areas")); m_colorType.setItemUIName(ALL, tr("Lines & Areas"));
m_onlyEmptyAreas.setQStringName(tr("Selective", NULL)); m_onlyEmptyAreas.setQStringName(tr("Selective", NULL));
m_pressure.setQStringName(tr("Pressure"));
} }
//------------------------------------------------------------------------------------------------------- //-------------------------------------------------------------------------------------------------------
@ -386,9 +404,6 @@ void PaintBrushTool::fixMousePos(TPointD pos, bool precise) {
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void PaintBrushTool::draw() { void PaintBrushTool::draw() {
/*-- MouseLeave時にBrushTipが描かれるのを防止する --*/
if (m_pointSize == -1) return;
// If toggled off, don't draw brush outline // If toggled off, don't draw brush outline
if (!Preferences::instance()->isCursorOutlineEnabled()) return; if (!Preferences::instance()->isCursorOutlineEnabled()) return;
@ -405,8 +420,10 @@ void PaintBrushTool::draw() {
else else
glColor3d(1.0, 0.0, 0.0); glColor3d(1.0, 0.0, 0.0);
drawEmptyCircle(m_toolSize.getValue(), m_mousePos, true, lx % 2 == 0, drawEmptyCircle(tround(m_rasThickness.getValue().second), m_mousePos, true,
ly % 2 == 0); lx % 2 == 0, ly % 2 == 0);
drawEmptyCircle(tround(m_rasThickness.getValue().first), m_mousePos, true,
lx % 2 == 0, ly % 2 == 0);
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -416,30 +433,19 @@ const UINT pointCount = 20;
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
bool PaintBrushTool::onPropertyChanged(std::string propertyName) { bool PaintBrushTool::onPropertyChanged(std::string propertyName) {
PaintBrushColorType = ::to_string(m_colorType.getValue());
PaintBrushSelective = (int)(m_onlyEmptyAreas.getValue());
PaintBrushSizeMin = m_rasThickness.getValue().first;
PaintBrushSizeMax = m_rasThickness.getValue().second;
PaintBrushPressureSensitivity = m_pressure.getValue();
/*-- Size ---*/ /*-- Size ---*/
if (propertyName == m_toolSize.getName()) { if (propertyName == m_rasThickness.getName()) {
PaintBrushSize = m_toolSize.getValue(); m_minThick = m_rasThickness.getValue().first;
double x = m_toolSize.getValue(); m_maxThick = m_rasThickness.getValue().second;
double minRange = 1;
double maxRange = 100;
double minSize = 0.01;
double maxSize = 100;
m_pointSize =
(x - minRange) / (maxRange - minRange) * (maxSize - minSize) + minSize;
invalidate();
} }
// Selective
else if (propertyName == m_onlyEmptyAreas.getName()) {
PaintBrushSelective = (int)(m_onlyEmptyAreas.getValue());
}
// Areas, Lines etc. // Areas, Lines etc.
else if (propertyName == m_colorType.getName()) { else if (propertyName == m_colorType.getName()) {
PaintBrushColorType = ::to_string(m_colorType.getValue());
/*--- ColorModelのCursor更新のためにSIGNALを出す ---*/ /*--- ColorModelのCursor更新のためにSIGNALを出す ---*/
TTool::getApplication()->getCurrentTool()->notifyToolChanged(); TTool::getApplication()->getCurrentTool()->notifyToolChanged();
} }
@ -460,7 +466,15 @@ void PaintBrushTool::leftButtonDown(const TPointD &pos, const TMouseEvent &e) {
if (TToonzImageP ti = image) { if (TToonzImageP ti = image) {
TRasterCM32P ras = ti->getRaster(); TRasterCM32P ras = ti->getRaster();
if (ras) { if (ras) {
int thickness = m_toolSize.getValue(); double maxThick = m_rasThickness.getValue().second;
double thickness =
(m_pressure.getValue())
? computeThickness(e.m_pressure, m_rasThickness) * 2
: maxThick;
if (m_pressure.getValue() && e.m_pressure == 1.0)
thickness = m_rasThickness.getValue().first;
int styleId = TTool::getApplication()->getCurrentLevelStyleIndex(); int styleId = TTool::getApplication()->getCurrentLevelStyleIndex();
TTileSetCM32 *tileSet = new TTileSetCM32(ras->getSize()); TTileSetCM32 *tileSet = new TTileSetCM32(ras->getSize());
m_tileSaver = new TTileSaverCM32(ras, tileSet); m_tileSaver = new TTileSaverCM32(ras, tileSet);
@ -488,7 +502,12 @@ void PaintBrushTool::leftButtonDrag(const TPointD &pos, const TMouseEvent &e) {
leftButtonDragから呼ばれることがありm_rasterTrackが無い可能性がある leftButtonDragから呼ばれることがありm_rasterTrackが無い可能性がある
 ---*/  ---*/
if (m_rasterTrack) { if (m_rasterTrack) {
int thickness = m_toolSize.getValue(); double maxThick = m_rasThickness.getValue().second;
double thickness =
(m_pressure.getValue())
? computeThickness(e.m_pressure, m_rasThickness) * 2
: maxThick;
m_rasterTrack->add(TThickPoint( m_rasterTrack->add(TThickPoint(
m_mousePos + convert(ri->getRaster()->getCenter()), thickness)); m_mousePos + convert(ri->getRaster()->getCenter()), thickness));
m_tileSaver->save(m_rasterTrack->getLastRect()); m_tileSaver->save(m_rasterTrack->getLastRect());
@ -500,12 +519,14 @@ void PaintBrushTool::leftButtonDrag(const TPointD &pos, const TMouseEvent &e) {
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void PaintBrushTool::leftButtonUp(const TPointD &pos, const TMouseEvent &) { void PaintBrushTool::leftButtonUp(const TPointD &pos, const TMouseEvent &e) {
if (!m_selecting) return; if (!m_selecting) return;
fixMousePos(pos); fixMousePos(pos);
finishBrush(); double pressure = m_pressure.getValue() && e.isTablet() ? e.m_pressure : 0.5;
finishBrush(pressure);
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -521,19 +542,14 @@ void PaintBrushTool::onEnter() {
if (m_firstTime) { if (m_firstTime) {
m_onlyEmptyAreas.setValue(PaintBrushSelective ? 1 : 0); m_onlyEmptyAreas.setValue(PaintBrushSelective ? 1 : 0);
m_colorType.setValue(::to_wstring(PaintBrushColorType.getValue())); m_colorType.setValue(::to_wstring(PaintBrushColorType.getValue()));
m_toolSize.setValue(PaintBrushSize); m_rasThickness.setValue(
TDoublePairProperty::Value(PaintBrushSizeMin, PaintBrushSizeMax));
m_pressure.setValue(PaintBrushPressureSensitivity ? 1 : 0);
m_firstTime = false; m_firstTime = false;
} }
double x = m_toolSize.getValue();
double minRange = 1; m_minThick = m_rasThickness.getValue().first;
double maxRange = 100; m_maxThick = m_rasThickness.getValue().second;
double minSize = 0.01;
double maxSize = 100;
m_pointSize =
(x - minRange) / (maxRange - minRange) * (maxSize - minSize) + minSize;
if ((TToonzImageP)getImage(false)) if ((TToonzImageP)getImage(false))
m_cursor = ToolCursor::PenCursor; m_cursor = ToolCursor::PenCursor;
@ -543,7 +559,10 @@ void PaintBrushTool::onEnter() {
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void PaintBrushTool::onLeave() { m_pointSize = -1; } void PaintBrushTool::onLeave() {
m_minThick = 0;
m_maxThick = 0;
}
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -553,17 +572,25 @@ void PaintBrushTool::onActivate() { onEnter(); }
void PaintBrushTool::onDeactivate() { void PaintBrushTool::onDeactivate() {
/*--マウスドラッグ中(m_selecting=true)にツールが切り替わったときに描画の終了処理を行う---*/ /*--マウスドラッグ中(m_selecting=true)にツールが切り替わったときに描画の終了処理を行う---*/
if (m_selecting) finishBrush(); if (m_selecting) finishBrush(1);
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
/*! /*!
* onDeactivateでもMouseReleaseと同じ終了処理を行う * onDeactivateでもMouseReleaseと同じ終了処理を行う
*/ */
void PaintBrushTool::finishBrush() { void PaintBrushTool::finishBrush(double pressureValue) {
if (TToonzImageP ti = (TToonzImageP)getImage(true)) { if (TToonzImageP ti = (TToonzImageP)getImage(true)) {
if (m_rasterTrack) { if (m_rasterTrack) {
int thickness = m_toolSize.getValue(); double maxThick = m_rasThickness.getValue().second;
double thickness =
(m_pressure.getValue())
? computeThickness(pressureValue, m_rasThickness) * 2
: maxThick;
if (m_pressure.getValue() && pressureValue == 1.0)
thickness = m_rasThickness.getValue().first;
m_rasterTrack->add(TThickPoint( m_rasterTrack->add(TThickPoint(
m_mousePos + convert(ti->getRaster()->getCenter()), thickness)); m_mousePos + convert(ti->getRaster()->getCenter()), thickness));
m_tileSaver->save(m_rasterTrack->getLastRect()); m_tileSaver->save(m_rasterTrack->getLastRect());