|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// TnzCore includes
|
|
Toshihiro Shimizu |
890ddd |
#include "tfilepath.h"
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// TnzLib includes
|
|
Toshihiro Shimizu |
890ddd |
#include "toonz/txshsimplelevel.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "toonz/preferences.h"
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#include "toonz/onionskinmask.h"
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//*****************************************************************************************
|
|
Toshihiro Shimizu |
890ddd |
// Macros
|
|
Toshihiro Shimizu |
890ddd |
//*****************************************************************************************
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#define MINFADE 0.35
|
|
Toshihiro Shimizu |
890ddd |
#define MAXFADE 0.95
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//*****************************************************************************************
|
|
Toshihiro Shimizu |
890ddd |
// Local namespace
|
|
Toshihiro Shimizu |
890ddd |
//*****************************************************************************************
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
namespace {
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
double inline getIncrement(int paperThickness) {
|
|
Shinya Kitaoka |
120a6e |
struct locals {
|
|
Shinya Kitaoka |
120a6e |
inline static void fillIncrements(double *values, int a, int b) {
|
|
Shinya Kitaoka |
120a6e |
double slope = (values[b] - values[a]) / (b - a);
|
|
Shinya Kitaoka |
120a6e |
for (int i = a + 1; i < b; ++i) values[i] = values[i - 1] + slope;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}; // locals
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
static double Incr[101] = {-1.0};
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (Incr[0] == -1.0) {
|
|
Shinya Kitaoka |
120a6e |
Incr[0] = 0.0;
|
|
Shinya Kitaoka |
120a6e |
Incr[10] = 0.05;
|
|
Shinya Kitaoka |
120a6e |
Incr[50] = 0.12;
|
|
Shinya Kitaoka |
120a6e |
Incr[90] = 0.3;
|
|
Shinya Kitaoka |
120a6e |
Incr[100] = MAXFADE - MINFADE;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
locals::fillIncrements(Incr, 0, 10);
|
|
Shinya Kitaoka |
120a6e |
locals::fillIncrements(Incr, 10, 50);
|
|
Shinya Kitaoka |
120a6e |
locals::fillIncrements(Incr, 50, 90);
|
|
Shinya Kitaoka |
120a6e |
locals::fillIncrements(Incr, 90, 100);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
return Incr[paperThickness];
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
} // namespace
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//***************************************************************************
|
|
Toshihiro Shimizu |
890ddd |
// OnionSkinMask implementation
|
|
Toshihiro Shimizu |
890ddd |
//***************************************************************************
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void OnionSkinMask::clear() {
|
|
Shinya Kitaoka |
120a6e |
m_fos.clear();
|
|
Shinya Kitaoka |
120a6e |
m_mos.clear();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
m_shiftTraceStatus = DISABLED;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
m_ghostAff[0] = TAffine();
|
|
Shinya Kitaoka |
120a6e |
m_ghostAff[1] = TAffine();
|
|
Shinya Kitaoka |
120a6e |
m_ghostCenter[0] = TPointD();
|
|
Shinya Kitaoka |
120a6e |
m_ghostCenter[1] = TPointD();
|
|
shun-iwasawa |
2b24e8 |
m_ghostFrame[0] = 0;
|
|
shun-iwasawa |
2b24e8 |
m_ghostFrame[1] = 0;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void OnionSkinMask::getAll(int currentRow, std::vector<int> &output) const {</int>
|
|
Shinya Kitaoka |
120a6e |
output.clear();
|
|
Shinya Kitaoka |
120a6e |
output.reserve(m_fos.size() + m_mos.size());
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
std::vector<int>::const_iterator fosIt, fosEnd(m_fos.end());</int>
|
|
Shinya Kitaoka |
120a6e |
std::vector<int>::const_iterator mosIt, mosEnd(m_mos.end());</int>
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
for (fosIt = m_fos.begin(), mosIt = m_mos.begin();
|
|
Shinya Kitaoka |
120a6e |
fosIt != fosEnd && mosIt != mosEnd;) {
|
|
Shinya Kitaoka |
120a6e |
int fos = *fosIt, mos = *mosIt + currentRow;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
if (fos < mos) {
|
|
Shinya Kitaoka |
120a6e |
if (fos != currentRow) output.push_back(fos);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
++fosIt;
|
|
Shinya Kitaoka |
120a6e |
} else {
|
|
Shinya Kitaoka |
120a6e |
if (mos != currentRow) output.push_back(mos);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
++mosIt;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
for (; fosIt != fosEnd; ++fosIt)
|
|
Shinya Kitaoka |
120a6e |
if (*fosIt != currentRow) output.push_back(*fosIt);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
for (; mosIt != mosEnd; ++mosIt) {
|
|
Shinya Kitaoka |
120a6e |
int mos = *mosIt + currentRow;
|
|
Shinya Kitaoka |
120a6e |
if (mos != currentRow) output.push_back(mos);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void OnionSkinMask::setMos(int drow, bool on) {
|
|
Shinya Kitaoka |
120a6e |
assert(drow != 0);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
typedef std::vector<int>::iterator Iter;</int>
|
|
Shinya Kitaoka |
120a6e |
std::pair<iter, iter=""> r = std::equal_range(m_mos.begin(), m_mos.end(), drow);</iter,>
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
if (on) {
|
|
Shinya Kitaoka |
120a6e |
if (r.first == r.second) m_mos.insert(r.first, drow);
|
|
Shinya Kitaoka |
120a6e |
} else {
|
|
Shinya Kitaoka |
120a6e |
if (r.first != r.second) m_mos.erase(r.first, r.second);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void OnionSkinMask::setFos(int row, bool on) {
|
|
Shinya Kitaoka |
120a6e |
typedef std::vector<int>::iterator Iter;</int>
|
|
Shinya Kitaoka |
120a6e |
std::pair<iter, iter=""> r = std::equal_range(m_fos.begin(), m_fos.end(), row);</iter,>
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (on) {
|
|
Shinya Kitaoka |
120a6e |
if (r.first == r.second) m_fos.insert(r.first, row);
|
|
Shinya Kitaoka |
120a6e |
} else {
|
|
Shinya Kitaoka |
120a6e |
if (r.first != r.second) m_fos.erase(r.first, r.second);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
bool OnionSkinMask::isFos(int row) const {
|
|
Shinya Kitaoka |
120a6e |
return std::binary_search(m_fos.begin(), m_fos.end(), row);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
bool OnionSkinMask::isMos(int drow) const {
|
|
Shinya Kitaoka |
120a6e |
return std::binary_search(m_mos.begin(), m_mos.end(), drow);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
bool OnionSkinMask::getMosRange(int &drow0, int &drow1) const {
|
|
Shinya Kitaoka |
120a6e |
if (m_mos.empty()) {
|
|
Shinya Kitaoka |
120a6e |
drow0 = 0, drow1 = -1;
|
|
Shinya Kitaoka |
120a6e |
return false;
|
|
Shinya Kitaoka |
120a6e |
} else {
|
|
Shinya Kitaoka |
120a6e |
drow0 = m_mos.front(), drow1 = m_mos.back();
|
|
Shinya Kitaoka |
120a6e |
return true;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
double OnionSkinMask::getOnionSkinFade(int rowsDistance) {
|
|
Shinya Kitaoka |
120a6e |
if (rowsDistance == 0) return 0.9;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
double fade =
|
|
Shinya Kitaoka |
120a6e |
MINFADE +
|
|
Shinya Kitaoka |
120a6e |
abs(rowsDistance) *
|
|
Shinya Kitaoka |
120a6e |
getIncrement(Preferences::instance()->getOnionPaperThickness());
|
|
Shinya Kitaoka |
120a6e |
return tcrop(fade, MINFADE, MAXFADE);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void OnionSkinMask::setShiftTraceGhostAff(int index, const TAffine &aff) {
|
|
Shinya Kitaoka |
120a6e |
assert(0 <= index && index < 2);
|
|
Shinya Kitaoka |
120a6e |
m_ghostAff[index] = aff;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void OnionSkinMask::setShiftTraceGhostCenter(int index, const TPointD ¢er) {
|
|
Shinya Kitaoka |
120a6e |
assert(0 <= index && index < 2);
|
|
Shinya Kitaoka |
120a6e |
m_ghostCenter[index] = center;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//***************************************************************************
|
|
Toshihiro Shimizu |
890ddd |
// OnionSkinMaskModifier implementation
|
|
Toshihiro Shimizu |
890ddd |
//***************************************************************************
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
OnionSkinMaskModifier::OnionSkinMaskModifier(OnionSkinMask mask, int currentRow)
|
|
Shinya Kitaoka |
120a6e |
: m_oldMask(mask)
|
|
Shinya Kitaoka |
120a6e |
, m_curMask(mask)
|
|
Shinya Kitaoka |
120a6e |
, m_firstRow(0)
|
|
Shinya Kitaoka |
120a6e |
, m_lastRow(0)
|
|
Shinya Kitaoka |
120a6e |
, m_curRow(currentRow)
|
|
Shinya Kitaoka |
120a6e |
, m_status(0) {}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void OnionSkinMaskModifier::click(int row, bool isFos) {
|
|
Shinya Kitaoka |
120a6e |
assert(m_status == 0);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
m_firstRow = m_lastRow = row;
|
|
Shinya Kitaoka |
120a6e |
if (isFos) {
|
|
Shinya Kitaoka |
120a6e |
assert(row != m_curRow);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (m_curMask.isEnabled() && m_curMask.isFos(row)) {
|
|
Shinya Kitaoka |
120a6e |
m_status = 2; // spegnere fos
|
|
Shinya Kitaoka |
120a6e |
m_curMask.setFos(row, false);
|
|
Shinya Kitaoka |
120a6e |
} else {
|
|
Shinya Kitaoka |
120a6e |
if (!m_curMask.isEnabled()) {
|
|
Shinya Kitaoka |
120a6e |
m_curMask.clear();
|
|
Shinya Kitaoka |
120a6e |
m_curMask.enable(true);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
m_curMask.setFos(row, true);
|
|
Shinya Kitaoka |
120a6e |
m_status = 3; // accendere fos
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
} else {
|
|
Shinya Kitaoka |
120a6e |
int drow = row - m_curRow;
|
|
Shinya Kitaoka |
120a6e |
if (drow != 0 && m_curMask.isEnabled() && m_curMask.isMos(drow)) {
|
|
Shinya Kitaoka |
120a6e |
m_status = 4; // spegnere mos
|
|
Shinya Kitaoka |
120a6e |
m_curMask.setMos(drow, false);
|
|
Shinya Kitaoka |
120a6e |
} else if (drow == 0) {
|
|
Shinya Kitaoka |
120a6e |
m_status = 8 + 4 + 1; // accendere mos; partito da 0
|
|
Shinya Kitaoka |
120a6e |
} else {
|
|
Shinya Kitaoka |
120a6e |
if (!m_curMask.isEnabled()) m_curMask.enable(true);
|
|
Shinya Kitaoka |
120a6e |
m_curMask.setMos(drow, true);
|
|
Shinya Kitaoka |
120a6e |
m_status = 4 + 1; // accendere mos;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void OnionSkinMaskModifier::drag(int row) {
|
|
Shinya Kitaoka |
120a6e |
if (m_status & 128) return;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
if (row == m_lastRow) return;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
m_status |= 64; // moved
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
int n = row - m_lastRow, d = 1;
|
|
Shinya Kitaoka |
120a6e |
if (n < 0) n = -n, d = -d;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
int oldr = m_lastRow, r = oldr + d;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
for (int i = 0; i < n; ++i, r += d) {
|
|
Shinya Kitaoka |
120a6e |
if (m_status & 4) {
|
|
Shinya Kitaoka |
120a6e |
if (!m_curMask.isEnabled()) {
|
|
Shinya Kitaoka |
120a6e |
m_curMask.clear();
|
|
Shinya Kitaoka |
120a6e |
m_curMask.enable(true);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
if (r != m_curRow) m_curMask.setMos(r - m_curRow, (m_status & 1) != 0);
|
|
Shinya Kitaoka |
120a6e |
} else
|
|
Shinya Kitaoka |
120a6e |
m_curMask.setFos(r, (m_status & 1) != 0);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
m_lastRow = row;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void OnionSkinMaskModifier::release(int row) {
|
|
Shinya Kitaoka |
120a6e |
if (m_status & 128) return;
|
|
Shinya Kitaoka |
120a6e |
if ((m_status & 64) == 0 // non si e' mosso
|
|
Shinya Kitaoka |
120a6e |
&& (m_status & 8) == 8 // e' partito da zero
|
|
Shinya Kitaoka |
120a6e |
&& row == m_curRow) {
|
|
Shinya Kitaoka |
120a6e |
if (!m_curMask.isEmpty() && m_curMask.isEnabled())
|
|
Shinya Kitaoka |
120a6e |
m_curMask.enable(false);
|
|
Shinya Kitaoka |
120a6e |
else {
|
|
Shinya Kitaoka |
120a6e |
m_curMask.enable(true);
|
|
Shinya Kitaoka |
120a6e |
if (m_curMask.isEmpty()) {
|
|
Shinya Kitaoka |
120a6e |
m_curMask.setMos(-1, true);
|
|
Shinya Kitaoka |
120a6e |
m_curMask.setMos(-2, true);
|
|
Shinya Kitaoka |
120a6e |
m_curMask.setMos(-3, true);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|