Merge pull request #567 from manongjohn/ot_patches_20210126

OpenToonz changes thru 2/11/2021
This commit is contained in:
manongjohn 2021-02-11 10:13:09 -05:00 committed by GitHub
commit 5a5bfa8679
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
100 changed files with 3636 additions and 905 deletions

View file

@ -3,13 +3,3 @@ brew update
# Remove symlink to bin/2to3 in order for latest python to install
rm -f '/usr/local/bin/2to3'
brew install boost qt clang-format glew lz4 lzo libmypaint jpeg-turbo nasm yasm aom dav1d fontconfig freetype gnutls lame libass libbluray libsoxr libvorbis libvpx opencore-amr openh264 openjpeg opus rav1e sdl2 snappy speex tesseract theora webp xvid xz
# delete older qt versions and make sure to have only the latest
brew cleanup qt
# temp workaround to brew installed glew cmake info overriding glew lib detection
# which causes compiling issues later
if [ -L /usr/local/lib/cmake/glew ]
then
echo "Symbolic link '/usr/local/lib/cmake/glew' detected. Removing to avoid glew lib detection issue!"
ls -l /usr/local/lib/cmake/glew
rm /usr/local/lib/cmake/glew
fi

View file

@ -6,13 +6,3 @@ brew install clang-format
# from Homebrew 1.6.0 the old formula for obtaining Qt5.9.2 becomes invalid.
# so we start to use the latest version of Qt. (#1910)
brew install qt
# delete older qt versions and make sure to have only the latest
brew cleanup qt
# temp workaround to brew installed glew cmake info overriding glew lib detection
# which causes compiling issues later
if [ -L /usr/local/lib/cmake/glew ]
then
echo "Symbolic link '/usr/local/lib/cmake/glew' detected. Removing to avoid glew lib detection issue!"
ls -l /usr/local/lib/cmake/glew
rm /usr/local/lib/cmake/glew
fi

View file

@ -1316,9 +1316,16 @@
<item>"STD_iwa_GlareFx" "Glare Iwa" </item>
<item>"STD_iwa_GlareFx.renderMode" "Render Mode" </item>
<item>"STD_iwa_GlareFx.irisMode" "Iris Shape" </item>
<item>"STD_iwa_GlareFx.irisScale" "Iris Scale" </item>
<item>"STD_iwa_GlareFx.irisGearEdgeCount" "Edges" </item>
<item>"STD_iwa_GlareFx.irisRandomSeed" "Random Seed" </item>
<item>"STD_iwa_GlareFx.irisSymmetry" "Symmetry" </item>
<item>"STD_iwa_GlareFx.irisAppearance" "Appearance" </item>
<item>"STD_iwa_GlareFx.intensity" "Intensity" </item>
<item>"STD_iwa_GlareFx.size" "Filter Size" </item>
<item>"STD_iwa_GlareFx.rotation" "Filter Rotation" </item>
<item>"STD_iwa_GlareFx.aberration" "Chromatic Aberration" </item>
<item>"STD_iwa_GlareFx.noise_factor" "Noise Factor" </item>
<item>"STD_iwa_GlareFx.noise_size" "Noise Size" </item>
<item>"STD_iwa_GlareFx.noise_octave" "Noise Octave" </item>

View file

@ -1496,9 +1496,6 @@ QStatusBar #StatusBarLabel {
/* -----------------------------------------------------------------------------
Style Editor
----------------------------------------------------------------------------- */
#StyleEditor #TabBarContainer {
margin-left: -5px;
}
#StyleEditor #bottomWidget {
border-top: 1 solid #111111;
padding: 3 2 8 3;
@ -2365,9 +2362,13 @@ SpreadsheetViewer {
qproperty-KeyFrameColor: #995d1d;
qproperty-KeyFrameBorderColor: #db9041;
qproperty-SelectedKeyFrameColor: #a2835b;
qproperty-IgnoredKeyFrameColor: #ac2a39;
qproperty-SelectedIgnoredKeyFrameColor: #b25872;
qproperty-InBetweenColor: #666250;
qproperty-InBetweenBorderColor: #b0aa91;
qproperty-SelectedInBetweenColor: #717970;
qproperty-IgnoredInBetweenColor: #8a695e;
qproperty-SelectedIgnoredInBetweenColor: #93807d;
qproperty-SelectedEmptyColor: rgba(90, 100, 106, 0.5);
qproperty-SelectedSceneRangeEmptyColor: rgba(90, 100, 106, 0.5);
qproperty-TextColor: #e6e6e6;

View file

@ -1496,9 +1496,6 @@ QStatusBar #StatusBarLabel {
/* -----------------------------------------------------------------------------
Style Editor
----------------------------------------------------------------------------- */
#StyleEditor #TabBarContainer {
margin-left: -5px;
}
#StyleEditor #bottomWidget {
border-top: 1 solid #060606;
padding: 3 2 8 3;
@ -2365,9 +2362,13 @@ SpreadsheetViewer {
qproperty-KeyFrameColor: #995d1d;
qproperty-KeyFrameBorderColor: #db9041;
qproperty-SelectedKeyFrameColor: #a2835b;
qproperty-IgnoredKeyFrameColor: #ac2a39;
qproperty-SelectedIgnoredKeyFrameColor: #b25872;
qproperty-InBetweenColor: #666250;
qproperty-InBetweenBorderColor: #b0aa91;
qproperty-SelectedInBetweenColor: #717970;
qproperty-IgnoredInBetweenColor: #8a695e;
qproperty-SelectedIgnoredInBetweenColor: #93807d;
qproperty-SelectedEmptyColor: rgba(83, 93, 100, 0.5);
qproperty-SelectedSceneRangeEmptyColor: rgba(83, 93, 100, 0.5);
qproperty-TextColor: #e6e6e6;

View file

@ -1496,9 +1496,6 @@ QStatusBar #StatusBarLabel {
/* -----------------------------------------------------------------------------
Style Editor
----------------------------------------------------------------------------- */
#StyleEditor #TabBarContainer {
margin-left: -5px;
}
#StyleEditor #bottomWidget {
border-top: 1 solid #a8a8a8;
padding: 3 2 8 3;
@ -2365,9 +2362,13 @@ SpreadsheetViewer {
qproperty-KeyFrameColor: #edaa64;
qproperty-KeyFrameBorderColor: #bb6a16;
qproperty-SelectedKeyFrameColor: #c9a278;
qproperty-IgnoredKeyFrameColor: #cb5765;
qproperty-SelectedIgnoredKeyFrameColor: #eb96ad;
qproperty-InBetweenColor: #e2dbcc;
qproperty-InBetweenBorderColor: #ac9f82;
qproperty-SelectedInBetweenColor: #c2c4c0;
qproperty-IgnoredInBetweenColor: #c29c92;
qproperty-SelectedIgnoredInBetweenColor: #ab9898;
qproperty-SelectedEmptyColor: rgba(146, 153, 158, 0.5);
qproperty-SelectedSceneRangeEmptyColor: rgba(146, 153, 158, 0.5);
qproperty-TextColor: #000;

View file

@ -1496,9 +1496,6 @@ QStatusBar #StatusBarLabel {
/* -----------------------------------------------------------------------------
Style Editor
----------------------------------------------------------------------------- */
#StyleEditor #TabBarContainer {
margin-left: -5px;
}
#StyleEditor #bottomWidget {
border-top: 1 solid #2c2c2c;
padding: 3 2 8 3;
@ -2365,9 +2362,13 @@ SpreadsheetViewer {
qproperty-KeyFrameColor: #995d1d;
qproperty-KeyFrameBorderColor: #db9041;
qproperty-SelectedKeyFrameColor: #a2835b;
qproperty-IgnoredKeyFrameColor: #ac2a39;
qproperty-SelectedIgnoredKeyFrameColor: #b25872;
qproperty-InBetweenColor: #666250;
qproperty-InBetweenBorderColor: #b0aa91;
qproperty-SelectedInBetweenColor: #717970;
qproperty-IgnoredInBetweenColor: #8a695e;
qproperty-SelectedIgnoredInBetweenColor: #93807d;
qproperty-SelectedEmptyColor: rgba(103, 113, 119, 0.5);
qproperty-SelectedSceneRangeEmptyColor: rgba(103, 113, 119, 0.5);
qproperty-TextColor: #e6e6e6;

View file

@ -556,9 +556,13 @@
@function-KeyFrame-color: darken(desaturate(spin(@keyframe-total-color, 0.0000), 0.7570), 8.4314);
@function-KeyFrameBorder-color: lighten(@function-KeyFrame-color, 20);
@function-SelectedKeyFrame-color: mix(shade(@function-KeyFrame-color, -40), @cellHighlightTintColor, 60);
@function-IgnoredKeyFrame-color: rgb(172,42,57);
@function-SelectedIgnoredKeyFrame-color: mix(shade(@function-IgnoredKeyFrame-color, -40), @cellHighlightTintColor, 60);
@function-Inbetween-color: darken(desaturate(spin(@keyframe-inbetween-color, 0.4423), 4.8071), 7.2549);
@function-InbetweenBorder-color: lighten(@keyframe-inbetween-color, 20);
@function-SelectedInbetween-color: mix(shade(@function-Inbetween-color, @cellHighlightLightness), @cellHighlightTintColor, @cellHighlightTintAmount);
@function-IgnoredInbetween-color: rgb(138,105,94);
@function-SelectedIgnoredInbetween-color: mix(shade(@function-IgnoredInbetween-color, @cellHighlightLightness), @cellHighlightTintColor, @cellHighlightTintAmount);
// Expression Field
@function-ExpressionFieldBG-color: lighten(@bg, 61.9608);

View file

@ -3,9 +3,6 @@
----------------------------------------------------------------------------- */
#StyleEditor {
& #TabBarContainer {
margin-left: -5px;
}
& #bottomWidget {
border-top: 1 solid @accent;
padding: 3 2 8 3;

View file

@ -280,9 +280,13 @@ SpreadsheetViewer {
qproperty-KeyFrameColor: @function-KeyFrame-color;
qproperty-KeyFrameBorderColor: @function-KeyFrameBorder-color;
qproperty-SelectedKeyFrameColor: @function-SelectedKeyFrame-color;
qproperty-IgnoredKeyFrameColor: @function-IgnoredKeyFrame-color;
qproperty-SelectedIgnoredKeyFrameColor: @function-SelectedIgnoredKeyFrame-color;
qproperty-InBetweenColor: @function-Inbetween-color;
qproperty-InBetweenBorderColor: @function-InbetweenBorder-color;
qproperty-SelectedInBetweenColor: @function-SelectedInbetween-color;
qproperty-IgnoredInBetweenColor: @function-IgnoredInbetween-color;
qproperty-SelectedIgnoredInBetweenColor: @function-SelectedIgnoredInbetween-color;
qproperty-SelectedEmptyColor: @xsheet-SelectedEmptyCell-color; // paired
qproperty-SelectedSceneRangeEmptyColor: @function-SelectedSceneRangeEmpty-color;
qproperty-TextColor: @xsheet-text-color; // paired

View file

@ -5,6 +5,8 @@
// -----------------------------------------------------------------------------
// This inherits from NEUTRAL theme, when updating NEUTRAL make sure to check
// changes against LIGHT.
//
// NOTE: Compile Neutral.less before this.
// -----------------------------------------------------------------------------
// Override
@ -234,7 +236,10 @@
@function-panel-bg-color: @schematic-viewer-bg-color;
@function-panel-OtherCurves-color: rgb(218, 218, 218);
@function-panel-Text-color: @text-color;
@function-panel-Sub-color: #fff;
@function-panel-Selected-color: #ffe033;
@function-IgnoredKeyFrame-color: rgb(203,87,101);
@function-IgnoredInbetween-color: rgb(194,156,146);
@function-SelectedKeyFrame-color: mix(shade(@function-KeyFrame-color, @cellHighlightLightness), @cellHighlightTintColor, @cellHighlightTintAmount);

View file

@ -1496,9 +1496,6 @@ QStatusBar #StatusBarLabel {
/* -----------------------------------------------------------------------------
Style Editor
----------------------------------------------------------------------------- */
#StyleEditor #TabBarContainer {
margin-left: -5px;
}
#StyleEditor #bottomWidget {
border-top: 1 solid #5a5a5a;
padding: 3 2 8 3;
@ -2365,9 +2362,13 @@ SpreadsheetViewer {
qproperty-KeyFrameColor: #c4833e;
qproperty-KeyFrameBorderColor: #64421f;
qproperty-SelectedKeyFrameColor: #deae7b;
qproperty-IgnoredKeyFrameColor: #ac2a39;
qproperty-SelectedIgnoredKeyFrameColor: #b25872;
qproperty-InBetweenColor: #b4b09e;
qproperty-InBetweenBorderColor: #6e6c64;
qproperty-SelectedInBetweenColor: #c7c7bb;
qproperty-IgnoredInBetweenColor: #8a695e;
qproperty-SelectedIgnoredInBetweenColor: #93807d;
qproperty-SelectedEmptyColor: rgba(155, 159, 162, 0.5);
qproperty-SelectedSceneRangeEmptyColor: rgba(155, 159, 162, 0.5);
qproperty-TextColor: #000;

View file

@ -1,9 +1,24 @@
<fxlayout help_command="iexplore" help_file="BokehIwa.html">
<page name="Glare Iwa">
<control>renderMode</control>
<control>irisMode</control>
<vbox modeSensitive="irisMode" mode="1,2,3,4">
<separator/>
<control>irisScale</control>
<control>irisSymmetry</control>
<control>irisAppearance</control>
</vbox>
<vbox modeSensitive="irisMode" mode="4">
<control>irisGearEdgeCount</control>
<control>irisRandomSeed</control>
</vbox>
<vbox modeSensitive="irisMode" mode="1,2,3,4">
<separator/>
</vbox>
<control>intensity</control>
<control>size</control>
<control>rotation</control>
<control>aberration</control>
<control>noise_factor</control>
<control>noise_size</control>
<control>noise_octave</control>

View file

@ -1,10 +1,10 @@
<fxlayout help_file="MotionBlurIwa.html">
<page name="Motion Blur Iwa">
<vbox>
<hbox>
<control>motionObjectType</control>
<vbox modeSensitive="motionObjectType" mode="1,2,4">
<control>motionObjectIndex</control>
</hbox>
</vbox>
<control>shutterStart</control>
<control>startValue</control>
<control>startCurve</control>

View file

@ -0,0 +1,62 @@
<palette name="1611507682_28145">
<version>
71 0
</version>
<styles>
<style>
"|-1611507682_28145-0"color_0 3 255 255 255 0
</style>
<style>
"|-1611507682_28145-1"color_1 3 0 0 0 255
</style>
<style>
"|-1611507682_28145-2"color_2 3 255 255 255 255
</style>
<style>
_1 "|-1611507682_28145-3"color_3 3 255 0 0 255
</style>
<style>
_1 "|-1611507682_28145-4"color_4 3 0 255 0 255
</style>
<style>
_1 "|-1611507682_28145-5"color_5 3 0 0 255 255
</style>
<style>
"|-1611507682_28145-6"color_6 3 255 128 255 255
</style>
<style>
"|-1611507682_28145-7"color_7 3 128 255 192 255
</style>
<style>
"|-1611507682_28145-8"color_8 3 255 255 0 255
</style>
<style>
"|-1611507682_28145-9"color_9 3 128 128 255 255
</style>
<style>
"|-1611507682_28145-10"color_10 3 255 128 0 255
</style>
<style>
"|-1611507682_28145-11"color_11 3 0 192 255 255
</style>
<style>
"|-1611507682_28145-12"color_12 3 128 255 255 255
</style>
<style>
"|-1611507682_28145-13"color_13 3 255 128 128 255
</style>
</styles>
<stylepages>
<page>
<name>
colors
</name>
<indices>
0 1 2 3 4 5 6 7 8 9 10 11 12 13
</indices>
</page>
</stylepages>
<shortcuts>
9 0 1 2 3 4 5 6 7 8
</shortcuts>
</palette>

View file

@ -395,7 +395,11 @@ elseif(BUILD_ENV_APPLE)
if(GLEW-NOTFOUND)
pkg_check_modules(GLEW REQUIRED glew)
endif()
set(GLEW_LIB ${GLEW_LIBRARIES})
if (TARGET GLEW::GLEW)
set(GLEW_LIB GLEW::GLEW)
else()
set(GLEW_LIB ${GLEW_LIBRARIES})
endif()
pkg_check_modules(LZ4_LIB REQUIRED liblz4)

View file

@ -26,7 +26,8 @@ public:
m_errorPos; //!< Position of the error in the expression's text
bool m_isValid, //!< Whether the expression is valid
m_hasBeenParsed; //!< Whether the expression has already been parsed
m_hasBeenParsed, //!< Whether the expression has already been parsed
m_hasReference;
public:
Imp()
@ -35,7 +36,8 @@ public:
, m_calculator(0)
, m_errorPos(0, -1)
, m_isValid(false)
, m_hasBeenParsed(true) {}
, m_hasBeenParsed(true)
, m_hasReference(false) {}
~Imp() { delete m_calculator; }
};
@ -60,6 +62,7 @@ TExpression::TExpression(const TExpression &src) : m_imp(new Imp()) {
m_imp->m_error = src.m_imp->m_error;
m_imp->m_errorPos = src.m_imp->m_errorPos;
m_imp->m_hasBeenParsed = false;
m_imp->m_hasReference = src.m_imp->m_hasReference;
}
//--------------------------------------------------------------------------
@ -85,11 +88,12 @@ const TSyntax::Grammar *TExpression::getGrammar() const {
//--------------------------------------------------------------------------
void TExpression::setText(std::string text) {
if (m_imp->m_text != text) {
if (m_imp->m_text != text || m_imp->m_hasReference) {
m_imp->m_text = text;
delete m_imp->m_calculator;
m_imp->m_calculator = 0;
m_imp->m_isValid = false;
m_imp->m_hasReference = false;
m_imp->m_hasBeenParsed = false;
m_imp->m_error = "";
m_imp->m_errorPos = std::make_pair(0, -1);
@ -142,8 +146,9 @@ void TExpression::parse() {
delete m_imp->m_calculator;
m_imp->m_calculator = 0;
m_imp->m_errorPos = std::make_pair(0, -1);
m_imp->m_error = std::string();
m_imp->m_errorPos = std::make_pair(0, -1);
m_imp->m_error = std::string();
m_imp->m_hasReference = false;
if (!m_imp->m_grammar) {
m_imp->m_error = "No grammar defined";
@ -156,7 +161,8 @@ void TExpression::parse() {
if (m_imp->m_calculator)
m_imp->m_calculator->setOwnerParameter(m_imp->m_param);
m_imp->m_isValid = parser.isValid();
m_imp->m_isValid = parser.isValid();
m_imp->m_hasReference = parser.hasReference();
if (!m_imp->m_isValid) {
m_imp->m_error = parser.getError();

View file

@ -66,13 +66,15 @@ public:
std::vector<SyntaxToken> m_syntaxTokens;
Grammar::Position m_position;
// Pattern *m_lastPattern;
bool m_hasReference;
Imp(const Grammar *grammar)
: m_grammar(grammar)
, m_errorString("")
, m_isValid(false)
, m_calculator(0)
, m_position(Grammar::ExpressionStart) {}
, m_position(Grammar::ExpressionStart)
, m_hasReference(false) {}
~Imp() {
clearPointerContainer(m_nodeStack);
delete m_calculator;
@ -235,14 +237,24 @@ bool Parser::Imp::parseExpression(bool checkOnly) {
Calculator *Parser::parse(std::string text) {
m_imp->m_tokenizer.setBuffer(text);
clearPointerContainer(m_imp->m_nodeStack);
m_imp->m_errorString = "";
m_imp->m_isValid = false;
m_imp->m_calculator = new Calculator();
bool ret = m_imp->parseExpression(false);
m_imp->m_errorString = "";
m_imp->m_isValid = false;
m_imp->m_hasReference = false;
m_imp->m_calculator = new Calculator();
bool ret = m_imp->parseExpression(false);
if (ret && !m_imp->m_nodeStack.empty()) {
m_imp->m_calculator->setRootNode(m_imp->m_nodeStack.back());
for (auto node : m_imp->m_nodeStack) {
if (node->hasReference()) {
m_imp->m_hasReference = true;
break;
}
}
m_imp->m_nodeStack.pop_back();
m_imp->m_isValid = true;
} else {
delete m_imp->m_calculator;
m_imp->m_calculator = 0;
@ -306,6 +318,10 @@ bool Parser::isValid() const { return m_imp->m_isValid; }
//-------------------------------------------------------------------
bool Parser::hasReference() const { return m_imp->m_hasReference; }
//-------------------------------------------------------------------
std::string Parser::getText() const { return m_imp->m_tokenizer.getBuffer(); }
//-------------------------------------------------------------------

View file

@ -37,9 +37,10 @@ public:
}
int getUndoCount() const { return (int)m_undos.size(); }
void setLast() {
for (UINT i = 1; i < m_undos.size(); i++)
m_undos[i]->m_isLastInBlock = false;
m_undos[0]->m_isLastInBlock = true;
for (UINT i = 0; i < m_undos.size(); i++) {
m_undos[i]->m_isLastInBlock = (i == 0);
m_undos[i]->m_isLastInRedoBlock = (i == m_undos.size() - 1);
}
}
void undo() const override {
@ -65,7 +66,8 @@ public:
//}
void onAdd() override {}
void add(TUndo *undo) {
undo->m_isLastInBlock = true;
undo->m_isLastInBlock = true;
undo->m_isLastInRedoBlock = true;
m_undos.push_back(undo);
}
@ -97,7 +99,7 @@ public:
return m_undos.back()->getHistoryType();
}
};
}
} // namespace
typedef std::deque<TUndo *> UndoList;
typedef UndoList::iterator UndoListIterator;
@ -186,9 +188,8 @@ void TUndoManager::TUndoManagerImp::doAdd(TUndo *undo) {
int i, memorySize = 0, count = m_undoList.size();
for (i = 0; i < count; i++) memorySize += m_undoList[i]->getSize();
while (
count > 100 ||
(count != 0 && memorySize + undo->getSize() > m_undoMemorySize)) // 20MB
while (count > 100 || (count != 0 && memorySize + undo->getSize() >
m_undoMemorySize)) // 20MB
{
--count;
TUndo *undo = m_undoList.front();
@ -197,7 +198,8 @@ void TUndoManager::TUndoManagerImp::doAdd(TUndo *undo) {
delete undo;
}
undo->m_isLastInBlock = true;
undo->m_isLastInBlock = true;
undo->m_isLastInRedoBlock = true;
m_undoList.push_back(undo);
m_current = m_undoList.end();
}

View file

@ -701,6 +701,9 @@ void TFx::setNewIdentifier() { m_imp->m_id = ++m_imp->m_nextId; }
//--------------------------------------------------
void TFx::loadData(TIStream &is) {
// default version of fx is 1
setFxVersion(1);
std::string tagName;
VersionNumber tnzVersion = is.getVersion();
// Prevent to load "params" tag under "super" tag on saving macro fx.
@ -818,6 +821,10 @@ void TFx::loadData(TIStream &is) {
is >> groupName;
groupNames.append(groupName);
}
} else if (tagName == "fxVersion") {
int version = 1;
is >> version;
setFxVersion(version);
} else {
throw TException("Unknown tag!");
}
@ -907,6 +914,7 @@ void TFx::saveData(TOStream &os) {
for (i = 0; i < groupNameStack.size(); i++) os << groupNameStack[i];
os.closeChild();
}
if (getFxVersion() != 1) os.child("fxVersion") << getFxVersion();
}
//--------------------------------------------------
@ -992,6 +1000,14 @@ TFx *TFx::getLinkedFx() const {
return m_imp->m_next->m_fx;
}
//--------------------------------------------------
void TFx::setFxVersion(int v) { m_imp->m_attributes.setFxVersion(v); }
//--------------------------------------------------
int TFx::getFxVersion() const { return m_imp->m_attributes.getFxVersion(); }
//===================================================
//
// TFxTimeRegion

View file

@ -468,13 +468,11 @@ void TSystem::readDirectory_DirItems(QStringList &dst, const TFilePath &path) {
#ifdef _WIN32
// equivalent to sorting with QDir::LocaleAware
struct strCompare {
bool operator()(const QString &s1, const QString &s2) const {
return QString::localeAwareCompare(s1, s2) < 0;
}
auto const strCompare = [](const QString &s1, const QString &s2) {
return QString::localeAwareCompare(s1, s2) < 0;
};
std::set<QString, strCompare> entries;
std::set<QString, decltype(strCompare)> entries(strCompare);
WIN32_FIND_DATA find_dir_data;
QString dir_search_path = dir.absolutePath() + "\\*";

View file

@ -902,7 +902,7 @@ void TifWriter::open(FILE *file, const TImageInfo &info) {
std::wstring compressionType =
((TEnumProperty *)(m_properties->getProperty("Compression Type")))
->getValue();
if (compressionType == TNZ_INFO_COMPRESS_LZW)
if (compressionType == TNZ_INFO_COMPRESS_LZW || compressionType == TNZ_INFO_COMPRESS_LZW_LEG)
TIFFSetField(m_tiff, TIFFTAG_COMPRESSION, COMPRESSION_LZW);
else if (compressionType == TNZ_INFO_COMPRESS_PACKBITS)
TIFFSetField(m_tiff, TIFFTAG_COMPRESSION, COMPRESSION_PACKBITS);

View file

@ -14,7 +14,8 @@
#define TNZ_INFO_COMPRESS_CCITTRLE L"CCITT modified Huffman Run-length encoding"
#define TNZ_INFO_COMPRESS_CCITTFAX3 L"CCITT Group 3 fax encoding"
#define TNZ_INFO_COMPRESS_CCITTFAX4 L"CCITT Group 4 fax encoding"
#define TNZ_INFO_COMPRESS_LZW L"Lempel-Ziv & Welch encoding"
#define TNZ_INFO_COMPRESS_LZW L"Lempel-Ziv and Welch encoding"
#define TNZ_INFO_COMPRESS_LZW_LEG L"Lempel-Ziv & Welch encoding"
#define TNZ_INFO_COMPRESS_PACKBITS L"Macintosh Run-length encoding"
#define TNZ_INFO_COMPRESS_THUNDERSCAN L"ThunderScan Run-length encoding"
#define TNZ_INFO_COMPRESS_RLE L"Run-length compression"

View file

@ -53,10 +53,6 @@ public:
PlasticDeformer();
~PlasticDeformer();
friend void swap(PlasticDeformer &a, PlasticDeformer &b) {
std::swap(a.m_imp, b.m_imp);
}
/*!
Returns whether the last compilation procedure succeeded, or it either failed
or was never invoked after the last initialize() call.

View file

@ -503,6 +503,9 @@ public:
// parameter is loaded. Do nothing by default.
virtual void onObsoleteParamLoaded(const std::string &paramName) {}
void setFxVersion(int);
int getFxVersion() const;
public:
// Id-related functions

View file

@ -33,6 +33,8 @@ class DVAPI TFxAttributes {
/*-- MotionBlurなどのFxのために、オブジェクトの軌跡のデータを取得する --*/
QList<TPointD> m_motionPoints;
// to maintain backward compatibility in the fx
int m_fxVersion;
public:
TFxAttributes();
@ -62,6 +64,8 @@ public:
m_motionPoints = motionPoints;
}
QList<TPointD> getMotionPoints() { return m_motionPoints; }
void setFxVersion(int version) { m_fxVersion = version; }
int getFxVersion() const { return m_fxVersion; };
// Group management

View file

@ -31,7 +31,7 @@ class TUnit;
namespace TSyntax {
class Token;
class Calculator;
}
} // namespace TSyntax
//==============================================
@ -63,6 +63,8 @@ public:
virtual void accept(CalculatorNodeVisitor &visitor) = 0;
virtual bool hasReference() const { return false; }
private:
// Non-copyable
CalculatorNode(const CalculatorNode &);

View file

@ -57,14 +57,15 @@ public:
/*-- (StylePickerTool内で)LineとAreaを切り替えてPickできる。mode: 0=Area,
* 1=Line, 2=Line&Areas(default) --*/
int pickStyleId(const TPointD &point, double radius2 = 1, int mode = 2) const;
int pickStyleId(const TPointD &point, double radius, double scale2,
int mode = 2) const;
/*--- Toonz Raster LevelのToneを拾う。 ---*/
int pickTone(const TPointD &pos) const;
// per pli come sopra, ma ritorna il maincolor
// per tzp e fullcolor ritorna il colore effettivo del pixel
TPixel32 pickColor(const TPointD &point, double radius2 = 1) const;
TPixel32 pickColor(const TPointD &point, double radius, double scale2) const;
TPixel32 pickAverageColor(const TRectD &rect) const;
// ritorna il colore medio presente nell'area della finestra corrente openGL

View file

@ -466,8 +466,9 @@ return true if the method execution can have changed the current tool
const TAffine &getMatrix() const { return m_matrix; }
void setMatrix(const TAffine &matrix) { m_matrix = matrix; }
TAffine getCurrentColumnMatrix()
TAffine getCurrentColumnMatrix(int frame = -1)
const; //!< Returns the current column matrix transformation.
//! if frame = -1 then it uses the current frame
//! \sa TXsheet::getPlacement.
TAffine getCurrentColumnParentMatrix()
@ -480,9 +481,10 @@ return true if the method execution can have changed the current tool
Returns the matrix transformation of the stage object with column
index equal to \p index
and frame as the current frame.
\sa TXsheet::getPlacement.
if frame = -1 then it uses the current frame
\sa TXsheet::getPlacement.
*/
TAffine getColumnMatrix(int index) const;
TAffine getColumnMatrix(int index, int frame = -1) const;
/*!
Updates the current matrix transformation with the actual column matrix

View file

@ -0,0 +1,57 @@
#pragma once
#ifndef EXPRESSIONREFERENCEMONITOR_H
#define EXPRESSIONREFERENCEMONITOR_H
#undef DVAPI
#undef DVVAR
#ifdef TOONZLIB_EXPORTS
#define DVAPI DV_EXPORT_API
#define DVVAR DV_EXPORT_VAR
#else
#define DVAPI DV_IMPORT_API
#define DVVAR DV_IMPORT_VAR
#endif
#include <QMap>
#include <QSet>
#include <QString>
class TDoubleParam;
class DVAPI ExpressionReferenceMonitorInfo {
// name of the parameter
QString m_name = "";
// true if the parameter is not monitored
bool m_ignored = false;
// column indices to which the parameter refers.
// note that the columns refered by the "cell" syntax will be
// registered in this container, but not in the paramRefMap.
QSet<int> m_colRefMap;
// parameters to which the parameter refers
QSet<TDoubleParam*> m_paramRefMap;
public:
QString& name() { return m_name; }
bool& ignored() { return m_ignored; }
QSet<int>& colRefMap() { return m_colRefMap; }
QSet<TDoubleParam*>& paramRefMap() { return m_paramRefMap; }
};
class DVAPI ExpressionReferenceMonitor {
QMap<TDoubleParam*, ExpressionReferenceMonitorInfo> m_info;
public:
ExpressionReferenceMonitor() {}
QMap<TDoubleParam*, ExpressionReferenceMonitorInfo>& info() { return m_info; }
void clearAll() { m_info.clear(); }
ExpressionReferenceMonitor* clone() {
ExpressionReferenceMonitor* ret = new ExpressionReferenceMonitor();
ret->info() = m_info;
return ret;
}
};
#endif

View file

@ -397,6 +397,9 @@ public:
// Animation tab
int getKeyframeType() const { return getIntValue(keyframeType); }
int getAnimationStep() const { return getIntValue(animationStep); }
bool isModifyExpressionOnMovingReferencesEnabled() const {
return getBoolValue(modifyExpressionOnMovingReferences);
}
// Preview tab
void getBlankValues(int &bCount, TPixel32 &bColor) const {

View file

@ -131,6 +131,7 @@ enum PreferencesItemId {
// Animation
keyframeType,
animationStep,
modifyExpressionOnMovingReferences,
//----------
// Preview

View file

@ -302,14 +302,16 @@ class DVAPI Picker final : public Visitor {
TPointD m_point;
TAffine m_viewAff;
double m_minDist2;
int m_devPixRatio;
int m_currentColumnIndex = -1;
public:
Picker(const TAffine &viewAff, const TPointD &p,
const ImagePainter::VisualSettings &vs);
const ImagePainter::VisualSettings &vs, int devPixRatio = 1);
void setDistance(double d);
// minimum distance to pick thin vector strokes.
void setMinimumDistance(double d);
void onImage(const Stage::Player &data) override;
void onRasterImage(TRasterImage *ri, const Stage::Player &data) override{};

View file

@ -13,6 +13,7 @@
// TnzLib includes
#include "toonz/txshcolumn.h"
#include "toonz/txshlevel.h"
#include "toonz/txsheetcolumnchange.h"
#include "cellposition.h"
@ -50,6 +51,8 @@ class TXshSoundColumn;
class TXshNoteSet;
class TFrameId;
class Orientation;
class TXsheetColumnChangeObserver;
class ExpressionReferenceMonitor;
//=============================================================================
@ -159,6 +162,8 @@ private:
int m_cameraColumnIndex;
TXshColumn *m_cameraColumn;
TXsheetColumnChangeObserver *m_observer;
DECLARE_CLASS_CODE
public:
@ -236,15 +241,15 @@ public:
*/
void removeCells(int row, int col, int rowCount = 1);
/*! If column identified by index \b \e col is not empty, is a \b TXshCellColumn and is not
locked, clear \b \e rowCount cells starting from \b \e row and it recalls TXshCellColumn::clearCells().
Clears cells and it shifts remaining cells. Xsheet's frame count is updated.
\sa removeCells(), insertCells()
*/ void
clearCells(int row, int col, int rowCount = 1);
/*! If column identified by index \b \e col is not empty, is a \b
TXshCellColumn and is not locked, clear \b \e rowCount cells starting from
\b \e row and it recalls TXshCellColumn::clearCells(). Clears cells and it
shifts remaining cells. Xsheet's frame count is updated. \sa removeCells(),
insertCells()
*/ void clearCells(int row, int col, int rowCount = 1);
/*! Clears xsheet. It sets to default values all xsheet elements contained in
* struct \b TXsheetImp.
*/
*/
void clearAll();
/*! Returns cell range of column identified by index \b \e col and set \b \e
r0 and \b \e r1 respectively to first and last not empty cell, it then
@ -432,7 +437,7 @@ frame duplication.
/*! Exposes level \b \e xl in xsheet starting from cell identified by \b \e
row and \b \e col.
Returns the number of the inserted cells.
*/
*/
int exposeLevel(int row, int col, TXshLevel *xl, bool overwrite = false);
// cutomized exposseLevel used from LoadLevel command
@ -461,7 +466,7 @@ frame duplication.
*/
void saveData(TOStream &os) override;
/*! Inserts an empty column in \b \e index calling \b insertColumn().
*/
*/
void insertColumn(int index,
TXshColumn::ColumnType type = TXshColumn::eLevelType);
/*! Insert \b \e column in column \b \e index. Insert column in the column
@ -497,10 +502,10 @@ in TXsheetImp.
calls
\b TColumnSetT::getColumnCount().
\sa getColumn() and getMaxFrame().
*/
*/
int getColumnCount() const;
/*! Returns first not empty column index in xsheet.
*/
*/
int getFirstFreeColumnIndex() const;
TSoundTrack *makeSound(SoundProperties *properties, int col = -1);
@ -570,6 +575,14 @@ in TXsheetImp.
void setCameraColumnLocked(bool locked) { m_cameraColumn->lock(locked); }
bool isCameraColumnLocked() { return m_cameraColumn->isLocked(); }
ExpressionReferenceMonitor *getExpRefMonitor() const;
void setObserver(TXsheetColumnChangeObserver *observer);
void notify(const TXsheetColumnChange &change);
void notifyFxAdded(const std::vector<TFx *> &fxs);
void notifyStageObjectAdded(const TStageObjectId id);
bool isReferenceManagementIgnored(TDoubleParam *);
protected:
bool checkCircularReferences(TXsheet *childCandidate);

View file

@ -0,0 +1,56 @@
#pragma once
#ifndef TXSHEETCOLUMNCHANGE_INCLUDED
#define TXSHEETCOLUMNCHANGE_INCLUDED
// TnzCore includes
#include "tcommon.h"
// TnzLib includes
#include "tstageobjectid.h"
#undef DVAPI
#undef DVVAR
#ifdef TOONZLIB_EXPORTS
#define DVAPI DV_EXPORT_API
#define DVVAR DV_EXPORT_VAR
#else
#define DVAPI DV_IMPORT_API
#define DVVAR DV_IMPORT_VAR
#endif
class TFx;
class TDoubleParam;
//===========================================================
//*****************************************************************************************
// TXsheetColumnChange declaration
//*****************************************************************************************
class DVAPI TXsheetColumnChange {
public:
enum OperationType { Insert, Remove, Move } m_type;
int m_index1, m_index2;
public:
TXsheetColumnChange(OperationType type, int index1, int index2 = -1)
: m_type(type), m_index1(index1), m_index2(index2) {}
};
//*****************************************************************************************
// TXsheetColumnChangeObserver definition
//*****************************************************************************************
class DVAPI TXsheetColumnChangeObserver {
public:
virtual void onChange(const TXsheetColumnChange &) = 0;
// Call when adding fxs in which expression references may be included.
// This can be happen when undoing removing fxs operation.
virtual void onFxAdded(const std::vector<TFx *> &) = 0;
// Call when adding stage objects in which expression references may be
// included. This can be happen when undoing removing objects operation.
virtual void onStageObjectAdded(const TStageObjectId) = 0;
virtual bool isIgnored(TDoubleParam *) = 0;
};
#endif // TPARAMCHANGE_INCLUDED

View file

@ -4,6 +4,7 @@
#define XSHEETEXPR_INCLUDED
#include "tgrammar.h"
#include <QSet>
#undef DVAPI
#undef DVVAR
@ -24,5 +25,7 @@ class TExpression;
DVAPI TSyntax::Grammar *createXsheetGrammar(TXsheet *xsh);
DVAPI bool dependsOn(TExpression &expr, TDoubleParam *possiblyDependentParam);
DVAPI bool dependsOn(TDoubleParam *param, TDoubleParam *possiblyDependentParam);
DVAPI void referenceParams(TExpression &expr, QSet<int> &columnIndices,
QSet<TDoubleParam *> &params);
#endif // XSHEETEXPR_INCLUDED

View file

@ -40,7 +40,7 @@ class DoubleLineEdit;
class IntLineEdit;
class MeasuredDoubleLineEdit;
class CheckBox;
}
} // namespace DVGui
//---------------------------------------------------------------
@ -124,8 +124,8 @@ public:
// camera => widget fields (i.e. initialize widget)
void setFields(const TCamera *camera);
// widget fields => camera
void getFields(TCamera *camera);
// widget fields => camera return true if the value is actually changed
bool getFields(TCamera *camera);
QSize sizeHint() const override { return minimumSize(); }

View file

@ -34,6 +34,7 @@ class TXsheet;
class TParamContainer;
class TFxHandle;
class TObjectHandle;
class TXsheetHandle;
class FunctionTreeView;
class FunctionViewer;
@ -70,7 +71,7 @@ class FunctionViewer;
TnzExt library).
*/
class FunctionTreeModel final : public TreeModel, public TParamObserver {
class DVAPI FunctionTreeModel final : public TreeModel, public TParamObserver {
Q_OBJECT
public:
@ -85,6 +86,7 @@ to
virtual bool isActive() const = 0;
virtual bool isAnimated() const = 0;
virtual bool isIgnored() const = 0;
};
//----------------------------------------------------------------------------------
@ -104,6 +106,7 @@ to
bool isActive() const override;
bool isAnimated() const override;
bool isIgnored() const override;
virtual QString getShortName() const { return m_name; }
virtual QString getLongName() const { return m_name; }
@ -153,9 +156,9 @@ color, which
//----------------------------------------------------------------------------------
//! The model item representing a channel (i.e. a real-valued function).
class Channel final : public ParamWrapper,
public Item,
public TParamObserver {
class DVAPI Channel final : public ParamWrapper,
public Item,
public TParamObserver {
FunctionTreeModel *m_model; //!< (\p not \p owned) Reference to the model
ChannelGroup
*m_group; //!< (\p not \p owned) Reference to the enclosing group
@ -189,6 +192,7 @@ color, which
void setIsActive(bool active);
bool isAnimated() const override;
bool isIgnored() const override;
bool isCurrent() const;
void setIsCurrent(bool current);
@ -313,7 +317,7 @@ public:
//=============================================================================
class FxChannelGroup final : public FunctionTreeModel::ChannelGroup {
class DVAPI FxChannelGroup final : public FunctionTreeModel::ChannelGroup{
public:
TFx *m_fx;
@ -337,7 +341,8 @@ public:
//=============================================================================
class StageObjectChannelGroup final : public FunctionTreeModel::ChannelGroup {
class DVAPI StageObjectChannelGroup final
: public FunctionTreeModel::ChannelGroup {
public:
TStageObject *m_stageObject; //!< (not owned) Referenced stage object
FunctionTreeModel::ChannelGroup
@ -381,6 +386,8 @@ class FunctionTreeView final : public TreeView {
QColor m_textColor; // text color (black)
Q_PROPERTY(QColor TextColor READ getTextColor WRITE setTextColor)
TXsheetHandle *m_xshHandle;
public:
FunctionTreeView(FunctionViewer *parent);
@ -392,6 +399,9 @@ public:
QColor getTextColor() const { return m_textColor; }
FunctionViewer *getViewer() { return m_viewer; }
void setXsheetHandle(TXsheetHandle *xshHandle) { m_xshHandle = xshHandle; }
TXsheetHandle *getXsheetHandle() { return m_xshHandle; }
protected:
void onClick(TreeModel::Item *item, const QPoint &itemPos,
QMouseEvent *e) override;

View file

@ -121,6 +121,7 @@ public:
bool columnsOrGraphHasFocus();
void setSceneHandle(TSceneHandle *sceneHandle);
TSceneHandle *getSceneHandle() const { return m_sceneHandle; }
TXsheetHandle *getXsheetHandle() const { return m_xshHandle; }
// SaveLoadQSettings
virtual void save(QSettings &settings) const override;

View file

@ -155,6 +155,7 @@ private:
signals:
void doCollapse(const QList<TFxP> &);
void doExplodeChild(const QList<TFxP> &);
void doDelete();
};
#endif

View file

@ -54,6 +54,8 @@ class QToolButton;
class QAction;
class QTouchEvent;
class QGestureEvent;
class FxSelection;
class StageObjectSelection;
//====================================================
namespace {
@ -566,6 +568,9 @@ signals:
void doExplodeChild(QList<TStageObjectId>);
void editObject();
void doDeleteFxs(const FxSelection *);
void doDeleteStageObjects(const StageObjectSelection *);
protected slots:
void onSceneChanged();
@ -577,6 +582,9 @@ protected slots:
void zoomModeEnabled();
void handModeEnabled();
void deleteFxs();
void deleteStageObjects();
private:
SchematicSceneViewer *m_viewer;
StageSchematicScene *m_stageScene;

View file

@ -253,10 +253,14 @@ class DVAPI SpreadsheetViewer : public QDialog {
QColor m_keyFrameColor; // (219,139,54)
QColor m_keyFrameBorderColor; // (82,51,20)
QColor m_selectedKeyFrameColor; // (237,197,155)
QColor m_ignoredKeyFrameColor;
QColor m_selectedIgnoredKeyFrameColor;
// key frame inbetween
QColor m_inBetweenColor; // (194,194,176)
QColor m_inBetweenBorderColor; // (72,72,65)
QColor m_selectedInBetweenColor; // (225,225,216)
QColor m_ignoredInBetweenColor;
QColor m_selectedIgnoredInBetweenColor;
// empty cell
QColor m_selectedEmptyColor; // (190,190,190)
// empty cell in the scene range
@ -266,12 +270,22 @@ class DVAPI SpreadsheetViewer : public QDialog {
setKeyFrameBorderColor)
Q_PROPERTY(QColor SelectedKeyFrameColor READ getSelectedKeyFrameColor WRITE
setSelectedKeyFrameColor)
Q_PROPERTY(QColor IgnoredKeyFrameColor READ getIgnoredKeyFrameColor WRITE
setIgnoredKeyFrameColor)
Q_PROPERTY(
QColor SelectedIgnoredKeyFrameColor READ getSelectedIgnoredKeyFrameColor
WRITE setSelectedIgnoredKeyFrameColor)
Q_PROPERTY(
QColor InBetweenColor READ getInBetweenColor WRITE setInBetweenColor)
Q_PROPERTY(QColor InBetweenBorderColor READ getInBetweenBorderColor WRITE
setInBetweenBorderColor)
Q_PROPERTY(QColor SelectedInBetweenColor READ getSelectedInBetweenColor WRITE
setSelectedInBetweenColor)
Q_PROPERTY(QColor IgnoredInBetweenColor READ getIgnoredInBetweenColor WRITE
setIgnoredInBetweenColor)
Q_PROPERTY(
QColor SelectedIgnoredInBetweenColor READ getSelectedIgnoredInBetweenColor
WRITE setSelectedIgnoredInBetweenColor)
Q_PROPERTY(QColor SelectedEmptyColor READ getSelectedEmptyColor WRITE
setSelectedEmptyColor)
Q_PROPERTY(
@ -352,6 +366,18 @@ public:
m_selectedKeyFrameColor = color;
}
QColor getSelectedKeyFrameColor() const { return m_selectedKeyFrameColor; }
void setIgnoredKeyFrameColor(const QColor &color) {
m_ignoredKeyFrameColor = color;
}
QColor getIgnoredKeyFrameColor() const { return m_ignoredKeyFrameColor; }
void setSelectedIgnoredKeyFrameColor(const QColor &color) {
m_selectedIgnoredKeyFrameColor = color;
}
QColor getSelectedIgnoredKeyFrameColor() const {
return m_selectedIgnoredKeyFrameColor;
}
void setInBetweenColor(const QColor &color) { m_inBetweenColor = color; }
QColor getInBetweenColor() const { return m_inBetweenColor; }
void setInBetweenBorderColor(const QColor &color) {
@ -362,6 +388,18 @@ public:
m_selectedInBetweenColor = color;
}
QColor getSelectedInBetweenColor() const { return m_selectedInBetweenColor; }
void setIgnoredInBetweenColor(const QColor &color) {
m_ignoredInBetweenColor = color;
}
QColor getIgnoredInBetweenColor() const { return m_ignoredInBetweenColor; }
void setSelectedIgnoredInBetweenColor(const QColor &color) {
m_selectedIgnoredInBetweenColor = color;
}
QColor getSelectedIgnoredInBetweenColor() const {
return m_selectedIgnoredInBetweenColor;
}
void setSelectedEmptyColor(const QColor &color) {
m_selectedEmptyColor = color;
}

View file

@ -19,6 +19,7 @@
// Qt includes
#include <QList>
#include <QMap>
#undef DVAPI
#undef DVVAR
@ -128,6 +129,12 @@ public:
std::vector<TStageObjectId> restoreObjects(
std::set<int> &columnIndices, std::list<int> &restoredSplinIds,
TXsheet *xsheet, int fxFlags, const TPointD &pos = TConst::nowhere) const;
std::vector<TStageObjectId> restoreObjects(
std::set<int> &columnIndices, std::list<int> &restoredSplinIds,
TXsheet *xsheet, int fxFlags,
QMap<TStageObjectId, TStageObjectId> &idTable,
QMap<TFx *, TFx *> &fxTable, const TPointD &pos = TConst::nowhere) const;
};
#endif // STAGEOBJECT_DATA_H

View file

@ -137,6 +137,8 @@ public:
SchematicViewer *getSchematicViewer() { return m_viewer; }
StageObjectSelection *getStageSelection() const { return m_selection; }
private:
StageSchematicNode *addStageSchematicNode(TStageObject *pegbar);
StageSchematicGroupNode *addStageGroupNode(QList<TStageObject *> objs);

View file

@ -40,6 +40,9 @@ public:
//! return true if the last parsed string was correct
bool isValid() const;
//! return true if the last parsed string was correct
bool hasReference() const;
//! return the last parsed string
std::string getText() const;

View file

@ -28,7 +28,10 @@
class DVAPI TUndo {
public:
// To be called in the last of the block when undo
bool m_isLastInBlock;
// To be called in the last of the block when redo
bool m_isLastInRedoBlock;
public:
TUndo() {}

View file

@ -12,11 +12,15 @@
#include "iwa_xyz.h"
#include "iwa_simplexnoise.h"
#include <random>
#include <QPair>
#include <QVector>
#include <QReadWriteLock>
#include <QMutexLocker>
#include <QMap>
#include <QImage>
#include <QPainter>
namespace {
// FFT coordinate -> Normal corrdinate
@ -38,25 +42,55 @@ inline int getCoord(int i, int j, int lx, int ly) {
Iwa_GlareFx::Iwa_GlareFx()
: m_renderMode(new TIntEnumParam(RendeMode_FilterPreview, "Filter Preview"))
, m_irisMode(new TIntEnumParam(Iris_InputImage, "Input Image"))
, m_irisScale(0.2)
, m_irisGearEdgeCount(10)
, m_irisRandomSeed(0)
, m_irisSymmetry(1.0)
, m_irisAppearance(new TIntEnumParam())
, m_intensity(0.0)
, m_size(100.0)
, m_rotation(0.0)
, m_aberration(1.0)
, m_noise_factor(0.0)
, m_noise_size(0.5)
, m_noise_octave(new TIntEnumParam(1, "1"))
, m_noise_evolution(0.0)
, m_noise_offset(TPointD(0, 0)) {
// Version 1 : lights had been constantly summed in all wavelength
// Version 2 : intensities are weighted proportional to 1/(rambda^2)
setFxVersion(2);
// Bind the common parameters
addInputPort("Source", m_source);
addInputPort("Iris", m_iris);
bindParam(this, "renderMode", m_renderMode);
m_renderMode->addItem(RendeMode_Render, "Render");
m_renderMode->addItem(RenderMode_Iris, "Iris");
bindParam(this, "irisMode", m_irisMode);
m_irisMode->addItem(Iris_Square, "4 Streaks");
m_irisMode->addItem(Iris_Hexagon, "6 Streaks");
m_irisMode->addItem(Iris_Octagon, "8 Streaks");
m_irisMode->addItem(Iris_GearShape, "Multiple Streaks");
bindParam(this, "irisScale", m_irisScale);
bindParam(this, "irisGearEdgeCount", m_irisGearEdgeCount);
bindParam(this, "irisRandomSeed", m_irisRandomSeed);
bindParam(this, "irisSymmetry", m_irisSymmetry);
bindParam(this, "irisAppearance", m_irisAppearance);
m_irisAppearance->addItem(Appearance_ThinLine, "Thin Line");
m_irisAppearance->addItem(Appearance_MediumLine, "Medium Line");
m_irisAppearance->addItem(Appearance_ThickLine, "Thick Line");
m_irisAppearance->addItem(Appearance_Fill, "Filled");
m_irisAppearance->setValue(Appearance_MediumLine);
bindParam(this, "intensity", m_intensity, false);
bindParam(this, "size", m_size, false);
m_size->setMeasureName("fxLength");
bindParam(this, "rotation", m_rotation, false);
bindParam(this, "aberration", m_aberration, false);
bindParam(this, "noise_factor", m_noise_factor, false);
bindParam(this, "noise_size", m_noise_size, false);
@ -69,9 +103,15 @@ Iwa_GlareFx::Iwa_GlareFx()
m_noise_offset->getX()->setMeasureName("fxLength");
m_noise_offset->getY()->setMeasureName("fxLength");
m_irisScale->setValueRange(0.1, 0.8);
m_irisGearEdgeCount->setValueRange(3, 50);
m_irisSymmetry->setValueRange(0.1, 1.0);
m_irisRandomSeed->setValueRange(0, (std::numeric_limits<int>::max)());
m_intensity->setValueRange(-5.0, 5.0);
m_size->setValueRange(10.0, 500.0);
m_size->setValueRange(10.0, 1500.0);
m_rotation->setValueRange(-1800, 1800);
m_aberration->setValueRange(-2.0, 2.0);
m_noise_factor->setValueRange(0.0, 1.0);
m_noise_size->setValueRange(0.01, 3.0);
}
@ -91,12 +131,149 @@ double Iwa_GlareFx::getSizePixelAmount(const double val, const TAffine affine) {
/*--- return the length of the vector ---*/
return sqrt(vect.x * vect.x + vect.y * vect.y);
}
//--------------------------------------------------------------
void Iwa_GlareFx::drawPresetIris(TRaster32P irisRas, double irisSize,
const double frame) {
QImage img(irisRas->getLx(), irisRas->getLy(),
QImage::Format_ARGB32_Premultiplied);
img.fill(Qt::black);
QPainter painter(&img);
painter.setRenderHint(QPainter::Antialiasing, true);
painter.translate(
QPointF((float)irisRas->getLx() / 2.0, (float)irisRas->getLy() / 2.0));
painter.scale(irisSize, irisSize);
// shrink a bit
painter.scale(0.9, 0.9);
QPen pen(Qt::white);
double lineWidthRatio;
int appearance = m_irisAppearance->getValue();
if (appearance == Appearance_Fill) {
painter.setPen(Qt::NoPen);
painter.setBrush(Qt::white);
} else {
assert(appearance >= 0 && appearance <= 2);
pen.setCapStyle(Qt::RoundCap);
pen.setJoinStyle(Qt::MiterJoin);
double ratio[3] = {0.05, 0.1, 0.2};
lineWidthRatio = ratio[appearance];
pen.setWidthF(lineWidthRatio);
painter.setPen(pen);
painter.setBrush(Qt::NoBrush);
}
double symmetry = m_irisSymmetry->getValue(frame);
switch (m_irisMode->getValue()) {
case Iris_Square:
painter.scale(1.0, symmetry);
painter.drawRect(QRectF(-1.0, -1.0, 2.0, 2.0));
break;
case Iris_Hexagon: {
QPointF p(1.0 - 0.5 * symmetry, symmetry * std::sqrt(3) * 0.5);
const QPointF points[6] = {-p, QPointF(-1.0, 0.0), QPointF(-p.x(), p.y()),
p, QPointF(1.0, 0.0), QPointF(p.x(), -p.y())};
if (appearance != Appearance_Fill) {
if (symmetry < 1.0) {
painter.drawPolyline(points, 3);
painter.drawPolyline(&points[3], 3);
}
pen.setWidthF(lineWidthRatio * symmetry);
painter.setPen(pen);
}
painter.drawPolygon(points, 6);
if (appearance != Appearance_Fill && symmetry < 1.0) {
pen.setColor(Qt::black);
painter.setPen(pen);
painter.setBrush(Qt::NoBrush);
painter.drawRect(
QRectF(-1.2, -p.y() - symmetry, 2.4, (p.y() + symmetry) * 2.0));
}
} break;
case Iris_Octagon: {
double u = (2 + std::sqrt(2) * (1 - symmetry)) / (2 * std::sqrt(2) + 2);
double v = (2 + std::sqrt(2) * (1 + symmetry)) / (2 * std::sqrt(2) + 2);
const QPointF points[8] = {QPointF(u, v), QPointF(v, u), QPointF(v, -u),
QPointF(u, -v), QPointF(-u, -v), QPointF(-v, -u),
QPointF(-v, u), QPointF(-u, v)};
if (appearance != Appearance_Fill) {
if (symmetry < 1.0) {
painter.drawLine(points[0], points[1]);
painter.drawLine(points[2], points[3]);
painter.drawLine(points[4], points[5]);
painter.drawLine(points[6], points[7]);
}
pen.setWidthF(lineWidthRatio * symmetry);
painter.setPen(pen);
}
painter.drawPolygon(points, 8);
if (appearance != Appearance_Fill && symmetry < 1.0) {
pen.setColor(Qt::black);
painter.setPen(pen);
painter.setBrush(Qt::NoBrush);
painter.drawRect(QRectF(-v - symmetry, -v - symmetry,
(v + symmetry) * 2.0, (v + symmetry) * 2.0));
}
} break;
case Iris_GearShape: {
int edgeCount = (int)std::round(m_irisGearEdgeCount->getValue(frame));
QPointF* points = new QPointF[edgeCount * 2];
QList<double> thickness;
double angleUnit = M_PI / (double)edgeCount;
std::mt19937_64 mt;
mt.seed(m_irisRandomSeed->getValue());
std::uniform_real_distribution<> random_plusminus1(-1.0, 1.0);
std::uniform_real_distribution<> random_thickness(symmetry * lineWidthRatio,
lineWidthRatio);
for (int e = 0; e < edgeCount; e++) {
double baseAngle = angleUnit * e * 2.0;
double theta =
baseAngle + random_plusminus1(mt) * angleUnit * (1.0 - symmetry);
points[e * 2] = QPointF(std::cos(theta), std::sin(theta));
thickness.append(random_thickness(mt));
baseAngle += angleUnit;
theta = baseAngle + random_plusminus1(mt) * angleUnit * (1.0 - symmetry);
points[e * 2 + 1] = QPointF(0.5 * std::cos(theta), 0.5 * std::sin(theta));
thickness.append(random_thickness(mt));
}
if (appearance != Appearance_Fill) {
for (int v = 0; v < edgeCount * 2; v++) {
int next_v = (v == edgeCount * 2 - 1) ? 0 : v + 1;
pen.setWidthF(thickness.at(v));
painter.setPen(pen);
painter.drawLine(points[v], points[next_v]);
}
} else {
painter.drawPolygon(points, edgeCount * 2);
}
delete[] points;
} break;
default:
break;
}
for (int j = 0; j < img.height(); j++) {
TPixel32* pix = irisRas->pixels(j);
QRgb* img_p = (QRgb*)img.scanLine(img.height() - j - 1);
for (int i = 0; i < img.width(); i++, img_p++, pix++) {
pix->r = (unsigned char)(qRed(*img_p));
pix->g = (unsigned char)(qGreen(*img_p));
pix->b = (unsigned char)(qBlue(*img_p));
pix->m = (unsigned char)(qAlpha(*img_p));
}
}
}
//--------------------------------------------------------------
void Iwa_GlareFx::doCompute(TTile& tile, double frame,
const TRenderSettings& settings) {
int irisMode = m_irisMode->getValue();
// If the iris is not connected, then do nothing
if (!m_iris.isConnected()) {
if (irisMode == Iris_InputImage && !m_iris.isConnected()) {
tile.getRaster()->clear();
return;
}
@ -110,16 +287,35 @@ void Iwa_GlareFx::doCompute(TTile& tile, double frame,
// Get the original size of Iris image
TRectD irisBBox;
m_iris->getBBox(frame, irisBBox, settings);
// Compute the iris tile.
TTile irisTile;
m_iris->allocateAndCompute(
irisTile, irisBBox.getP00(),
TDimension(static_cast<int>(irisBBox.getLx() + 0.5),
static_cast<int>(irisBBox.getLy() + 0.5)),
tile.getRaster(), frame, settings);
TRasterP irisRas;
double size = getSizePixelAmount(m_size->getValue(frame), settings.m_affine);
if (irisMode == Iris_InputImage) {
m_iris->getBBox(frame, irisBBox, settings);
// Compute the iris tile.
m_iris->allocateAndCompute(
irisTile, irisBBox.getP00(),
TDimension(static_cast<int>(irisBBox.getLx() + 0.5),
static_cast<int>(irisBBox.getLy() + 0.5)),
tile.getRaster(), frame, settings);
irisRas = irisTile.getRaster();
} else {
// obtain iris bbox based on the glare pattern size
double irisSize = size * m_irisScale->getValue(frame);
irisBBox = TRectD(-irisSize, -irisSize, irisSize, irisSize);
int dimIrisRas = int(std::ceil(irisSize) * 2.0);
irisRas = TRaster32P(dimIrisRas, dimIrisRas);
drawPresetIris(irisRas, irisSize, frame);
}
if (renderMode == RenderMode_Iris) {
TTranslation aff(
(double)(tile.getRaster()->getLx() - irisRas->getLx()) * 0.5,
(double)(tile.getRaster()->getLy() - irisRas->getLy()) * 0.5);
TRop::quickPut(tile.getRaster(), irisRas, aff);
return;
}
int dimIris = int(std::ceil(size) * 2.0);
dimIris = kiss_fft_next_fast_size(dimIris);
while ((tile.getRaster()->getSize().lx - dimIris) % 2 != 0)
@ -140,7 +336,8 @@ void Iwa_GlareFx::doCompute(TTile& tile, double frame,
kissfft_comp_iris_before_ras->lock();
kissfft_comp_iris_before =
(kiss_fft_cpx*)kissfft_comp_iris_before_ras->getRawData();
convertIris(kissfft_comp_iris_before, dimIris, irisBBox, irisTile);
convertIris(kissfft_comp_iris_before, dimIris, irisBBox, irisRas);
// Create the FFT plan for the iris image.
kiss_fftnd_cfg iris_kissfft_plan;
@ -349,10 +546,20 @@ void Iwa_GlareFx::powerSpectrum2GlarePattern(
glare_xyz_ras->clear();
double irisRadius = double(dimIris / 2);
double aberration = m_aberration->getValue(frame);
// old version had summed each wavelength constantly.
// it was not physically-collect but keep it in order to maintain backward
// compatibility.
bool isOldVersion = getFxVersion() < 2;
// accumurate xyz values for each optical wavelength
for (int ram = 0; ram < 34; ram++) {
double rambda = 0.38 + 0.01 * (double)ram;
double scale = 0.55 / rambda;
// double scale = 0.55 / rambda;
double scale = std::pow(0.55 / rambda, aberration);
double intensity_scale =
(isOldVersion) ? 1.0 : std::pow(0.55 / rambda, 2.0 * aberration);
scale *= irisResizeFactor;
for (int j = 0; j < dimIris; j++) {
double j_scaled = (double(j) - irisRadius) * scale + irisRadius;
@ -369,7 +576,8 @@ void Iwa_GlareFx::powerSpectrum2GlarePattern(
else if (i_scaled > double(dimIris - 1))
break;
double gl = lerpGlarePtn(i_scaled, j_scaled, glarePattern_p);
double gl =
lerpGlarePtn(i_scaled, j_scaled, glarePattern_p) * intensity_scale;
g_xyz_p->x += gl * cie_d65[ram] * xyz[ram * 3 + 0];
g_xyz_p->y += gl * cie_d65[ram] * xyz[ram * 3 + 1];
g_xyz_p->z += gl * cie_d65[ram] * xyz[ram * 3 + 2];
@ -634,7 +842,7 @@ bool Iwa_GlareFx::canHandle(const TRenderSettings& info, double frame) {
// Enlarge the iris to the output size.
void Iwa_GlareFx::convertIris(kiss_fft_cpx* kissfft_comp_iris_before,
const int& dimIris, const TRectD& irisBBox,
const TTile& irisTile) {
const TRasterP irisRaster) {
// the original size of iris image
double2 irisOrgSize = {irisBBox.getLx(), irisBBox.getLy()};
@ -655,10 +863,10 @@ void Iwa_GlareFx::convertIris(kiss_fft_cpx* kissfft_comp_iris_before,
if (dimIris % 2 == 1) affOffset += TPointD(0.5, 0.5);
aff = TTranslation(resizedIris->getCenterD() + affOffset);
aff *= TTranslation(-(irisTile.getRaster()->getCenterD() + affOffset));
aff *= TTranslation(-(irisRaster->getCenterD() + affOffset));
// resample the iris
TRop::resample(resizedIris, irisTile.getRaster(), aff);
TRop::resample(resizedIris, irisRaster, aff);
// accumulated value
float irisValAmount = 0.0;

View file

@ -35,12 +35,21 @@ class Iwa_GlareFx : public TStandardRasterFx {
protected:
TRasterFxPort m_source;
TRasterFxPort m_iris;
// rendering mode (filter preview / render)
// rendering mode (filter preview / render / iris)
TIntEnumParamP m_renderMode;
TIntEnumParamP m_irisMode;
TDoubleParamP m_irisScale;
TDoubleParamP m_irisGearEdgeCount;
TIntParamP m_irisRandomSeed;
TDoubleParamP m_irisSymmetry;
TIntEnumParamP m_irisAppearance;
TDoubleParamP m_intensity;
TDoubleParamP m_size;
TDoubleParamP m_rotation;
TDoubleParamP m_aberration;
TDoubleParamP m_noise_factor;
TDoubleParamP m_noise_size;
@ -48,15 +57,32 @@ protected:
TDoubleParamP m_noise_evolution;
TPointParamP m_noise_offset;
enum { RendeMode_FilterPreview = 0, RendeMode_Render };
enum { RendeMode_FilterPreview = 0, RendeMode_Render, RenderMode_Iris };
enum {
Iris_InputImage = 0,
Iris_Square,
Iris_Hexagon,
Iris_Octagon,
Iris_GearShape
};
enum {
Appearance_ThinLine,
Appearance_MediumLine,
Appearance_ThickLine,
Appearance_Fill,
};
double getSizePixelAmount(const double val, const TAffine affine);
void drawPresetIris(TRaster32P irisRas, double irisSize, const double frame);
// Resize / flip the iris image according to the size ratio.
// Normalize the brightness of the iris image.
// Enlarge the iris to the output size.
void convertIris(kiss_fft_cpx *kissfft_comp_iris_before, const int &dimIris,
const TRectD &irisBBox, const TTile &irisTile);
const TRectD &irisBBox, const TRasterP irisRaster);
void powerSpectrum2GlarePattern(const double frame, const TAffine affine,
kiss_fft_cpx *spectrum, double3 *glare,

View file

@ -32,7 +32,7 @@ public:
, m_shutterEnd(0.05)
, m_traceResolution(4)
, m_motionObjectType(new TIntEnumParam(OBJTYPE_OWN, "Own Motion"))
, m_motionObjectIndex(0) {
, m_motionObjectIndex(1) {
m_shutterStart->setValueRange(0.0, 1.0);
m_shutterEnd->setValueRange(0.0, 1.0);
m_traceResolution->setValueRange(1, 20);

View file

@ -13,7 +13,8 @@ TFxAttributes::TFxAttributes()
, m_isOpened(false)
, m_speed()
, m_groupSelector(-1)
, m_passiveCacheDataIdx(-1) {}
, m_passiveCacheDataIdx(-1)
, m_fxVersion(1) {}
//----------------------------------------------------------------------

View file

@ -576,8 +576,7 @@ void ControlPointEditorTool::leftButtonDown(const TPointD &pos,
if (m_autoSelectDrawing.getValue()) {
// Non sono in nessun gadget
std::vector<int> columnIndexes;
getViewer()->posToColumnIndexes(e.m_pos, columnIndexes,
getPixelSize() * 5, false);
getViewer()->posToColumnIndexes(e.m_pos, columnIndexes, 5.0, false);
getNearestStrokeColumnIndexes(columnIndexes, pos);
if (!columnIndexes.empty()) {
int currentColumnIndex = app->getCurrentColumn()->getColumnIndex();

View file

@ -1059,8 +1059,7 @@ void EditTool::onEditAllLeftButtonDown(TPointD &pos, const TMouseEvent &e) {
if (selectedDevice < 0 && m_autoSelect.getValue() != L"None") {
pos = getMatrix() * pos;
int columnIndex =
getViewer()->posToColumnIndex(e.m_pos, 5 * getPixelSize(), false);
int columnIndex = getViewer()->posToColumnIndex(e.m_pos, 5.0, false);
if (columnIndex >= 0) {
TStageObjectId id = TStageObjectId::ColumnId(columnIndex);
int currentColumnIndex = getColumnIndex();

View file

@ -1812,6 +1812,8 @@ void AreaFillTool::onEnter() {
// getApplication()->editImage();
}
bool descending(int i, int j) { return (i > j); }
} // namespace
//=============================================================================
@ -2457,14 +2459,30 @@ void FillTool::draw() {
//-----------------------------------------------------------------------------
int FillTool::pick(const TImageP &image, const TPointD &pos) {
int FillTool::pick(const TImageP &image, const TPointD &pos, const int frame) {
TToonzImageP ti = image;
TVectorImageP vi = image;
if (!ti && !vi) return 0;
StylePicker picker(image);
double pixelSize2 = getPixelSize() * getPixelSize();
return picker.pickStyleId(pos, pixelSize2);
double scale2 = 1.0;
if (vi) {
TAffine aff = getViewer()->getViewMatrix() * getCurrentColumnMatrix(frame);
scale2 = aff.det();
}
TPointD pickPos = pos;
// in case that the column is animated in scene-editing mode
if (frame > 0) {
TPointD dpiScale = getViewer()->getDpiScale();
pickPos.x *= dpiScale.x;
pickPos.y *= dpiScale.y;
TPointD worldPos = getCurrentColumnMatrix() * pickPos;
pickPos = getCurrentColumnMatrix(frame).inv() * worldPos;
pickPos.x /= dpiScale.x;
pickPos.y /= dpiScale.y;
}
// thin stroke can be picked with 10 pixel range
return picker.pickStyleId(pickPos, 10.0, scale2);
}
//-----------------------------------------------------------------------------
@ -2481,32 +2499,53 @@ int FillTool::pickOnionColor(const TPointD &pos) {
if (!sl) return 0;
std::vector<int> rows;
osMask.getAll(sl->guessIndex(fid), rows);
// level editing case
if (app->getCurrentFrame()->isEditingLevel()) {
osMask.getAll(sl->guessIndex(fid), rows);
int i, j;
for (i = 0; i < (int)rows.size(); i++)
if (sl->index2fid(rows[i]) > fid) break;
int i, j;
for (i = 0; i < (int)rows.size(); i++)
if (sl->index2fid(rows[i]) > fid) break;
int onionStyleId = 0;
for (j = i - 1; j >= 0; j--) {
TFrameId onionFid = sl->index2fid(rows[j]);
if (onionFid != fid &&
((onionStyleId =
pick(m_level->getFrame(onionFid, ImageManager::none, 1), pos)) >
0)) // subsabling must be 1, otherwise onionfill does not work
break;
}
if (onionStyleId == 0)
for (j = i; j < (int)rows.size(); j++) {
int onionStyleId = 0;
for (j = i - 1; j >= 0; j--) {
TFrameId onionFid = sl->index2fid(rows[j]);
if (onionFid != fid &&
((onionStyleId =
pick(m_level->getFrame(onionFid, ImageManager::none, 1), pos)) >
0)) // subsabling must be 1, otherwise onionfill does not work
0)) // subsampling must be 1, otherwise onionfill does not work
break;
}
return onionStyleId;
if (onionStyleId == 0)
for (j = i; j < (int)rows.size(); j++) {
TFrameId onionFid = sl->index2fid(rows[j]);
if (onionFid != fid &&
((onionStyleId = pick(
m_level->getFrame(onionFid, ImageManager::none, 1), pos)) >
0)) // subsampling must be 1, otherwise onionfill does not work
break;
}
return onionStyleId;
} else { // scene editing case
TXsheet *xsh = app->getCurrentXsheet()->getXsheet();
int colId = app->getCurrentColumn()->getColumnIndex();
int row = app->getCurrentFrame()->getFrame();
osMask.getAll(row, rows);
std::vector<int>::iterator it = rows.begin();
while (it != rows.end() && *it < row) it++;
std::sort(rows.begin(), it, descending);
int onionStyleId = 0;
for (int i = 0; i < (int)rows.size(); i++) {
if (rows[i] == row) continue;
TXshCell cell = xsh->getCell(rows[i], colId);
TXshLevel *xl = cell.m_level.getPointer();
if (!xl || xl->getSimpleLevel() != sl) continue;
TFrameId onionFid = cell.getFrameId();
onionStyleId = pick(m_level->getFrame(onionFid, ImageManager::none, 1),
pos, rows[i]);
if (onionStyleId > 0) break;
}
return onionStyleId;
}
}
//-----------------------------------------------------------------------------

View file

@ -76,7 +76,7 @@ public:
void onActivate();
void onEnter();
};
}
} // namespace
class FillTool final : public QObject, public TTool {
// Q_DECLARE_TR_FUNCTIONS(FillTool)
Q_OBJECT
@ -135,7 +135,8 @@ public:
void onImageChanged() override;
void draw() override;
int pick(const TImageP &image, const TPointD &pos);
// if frame = -1 it uses current frame
int pick(const TImageP &image, const TPointD &pos, const int frame = -1);
int pickOnionColor(const TPointD &pos);
void onEnter() override;

View file

@ -450,8 +450,7 @@ void ShiftTraceTool::leftButtonDown(const TPointD &pos, const TMouseEvent &e) {
m_gadget = RotateGadget;
}
int row = getViewer()->posToRow(e.m_pos, getPixelSize() * getPixelSize(),
false, true);
int row = getViewer()->posToRow(e.m_pos, 5.0, false, true);
if (row >= 0) {
int index = -1;
TApplication *app = TTool::getApplication();

View file

@ -180,7 +180,7 @@ DragPositionTool::DragPositionTool(SkeletonTool *tool)
void DragPositionTool::leftButtonDown(const TPointD &pos, const TMouseEvent &) {
start();
m_firstPos = pos;
m_firstPos = pos;
m_firstDrag = true;
}
@ -190,9 +190,9 @@ void DragPositionTool::leftButtonDrag(const TPointD &pos,
const TMouseEvent &e) {
TPointD delta = pos - m_firstPos;
if (m_firstDrag && (delta.x > 2.0 || delta.y > 2.0)) {
m_firstPos = pos;
delta = TPointD(0.0, 0.0);
m_firstDrag = false;
m_firstPos = pos;
delta = TPointD(0.0, 0.0);
m_firstDrag = false;
}
if (e.isShiftPressed()) {
if (fabs(delta.x) > fabs(delta.y))
@ -300,10 +300,10 @@ void ParentChangeTool::leftButtonDown(const TPointD &pos,
// registro alcune informazioni relative a colId:
// placement, bbox, centro, hooks, name, ecc.
Element element;
element.m_columnIndex = col;
TImageP img = cell.getImage(false);
element.m_columnIndex = col;
TImageP img = cell.getImage(false);
if (img) element.m_bbox = img->getBBox();
element.m_aff = xsh->getPlacement(colId, currentFrame);
element.m_aff = xsh->getPlacement(colId, currentFrame);
Peer peer;
peer.m_columnIndex = col;
peer.m_handle = 0;
@ -352,7 +352,7 @@ void ParentChangeTool::leftButtonDrag(const TPointD &pos,
if (m_snapped) return;
getTool()->setParentProbe(getTool()->getCurrentColumnParentMatrix() * pos);
m_index = m_viewer->posToColumnIndex(e.m_pos, m_pixelSize * 5, false);
m_index = m_viewer->posToColumnIndex(e.m_pos, 5.0, false);
m_lastPos = m_viewer->winToWorld(e.m_pos);
@ -425,16 +425,13 @@ void ParentChangeTool::draw() { getTool()->drawHooks(); }
//
//------------------------------------------------------------
// This needs some clarification.
namespace {
class Graph {
// local variables defined below are:
// Nodes m_nodes;
// std::map<int, int> m_leaves;
public:
typedef std::set<int> Links;
typedef Links::const_iterator LinkIter;
@ -455,7 +452,7 @@ public:
// check if a node is found in m_nodes
bool isNode(int id) const { return m_nodes.count(id) > 0; }
int getNodeCount() const { return (int)m_nodes.size(); }
void link(int a, int b) {
@ -468,7 +465,7 @@ public:
NodeIter it = m_nodes.find(a);
return it == m_nodes.end() ? false : it->second.count(b);
}
const Links &getLinks(int id) const {
static const Links empty;
NodeIter it = m_nodes.find(id);
@ -501,7 +498,7 @@ public:
LeaveIter it = m_leaves.find(id);
return it == m_leaves.end() ? 0 : it->second;
}
void setLeaveType(int id, int type) { m_leaves[id] = type; }
@ -509,7 +506,7 @@ public:
void remove(int id) {
NodeIter it = m_nodes.find(id);
if (it != m_nodes.end()) {
// iterate over the links
// iterate over the links
for (LinkIter j = it->second.begin(); j != it->second.end(); ++j)
m_nodes[*j].erase(id);
m_nodes.erase(it->first);
@ -536,15 +533,15 @@ bool hasPinned(const Skeleton::Bone *bone, const Skeleton::Bone *prevBone) {
if (bone->getParent() && bone->getParent() != prevBone &&
hasPinned(bone->getParent(), bone)) {
return true;
return true;
}
for (int i = 0; i < bone->getChildCount(); i++) {
if (bone->getChild(i) != prevBone) {
if (hasPinned(bone->getChild(i), bone)) {
return true;
}
if (bone->getChild(i) != prevBone) {
if (hasPinned(bone->getChild(i), bone)) {
return true;
}
}
}
return false;
@ -556,9 +553,9 @@ bool hasPinned(const Skeleton::Bone *bone, const Skeleton::Bone *prevBone) {
bool addToActiveChain(Graph &tree, const Skeleton::Bone *bone,
const Skeleton::Bone *prevBone) {
if (!bone) return false;
// The handle is what you grabbed
bool isHandle = prevBone == 0;
bool isHandle = prevBone == 0;
bool isChild = prevBone != 0 && prevBone == bone->getParent();
bool isParent = prevBone != 0 && prevBone->getParent() == bone;
@ -571,19 +568,19 @@ bool addToActiveChain(Graph &tree, const Skeleton::Bone *bone,
// Go up the chain from what you grabbed and add bones
if (!isChild && isFree) {
if (bone->getParent()) {
propagate |= addToActiveChain(tree, bone->getParent(), bone);
}
if (bone->getParent()) {
propagate |= addToActiveChain(tree, bone->getParent(), bone);
}
}
std::vector<int> children;
// Once you reach the top parent, add the other children
if (isHandle || isFree) {
for (int i = 0; i < bone->getChildCount(); i++) {
if (bone->getChild(i) != prevBone) {
propagate |= addToActiveChain(tree, bone->getChild(i), bone);
}
for (int i = 0; i < bone->getChildCount(); i++) {
if (bone->getChild(i) != prevBone) {
propagate |= addToActiveChain(tree, bone->getChild(i), bone);
}
}
}
bool insert = false;
@ -856,8 +853,9 @@ void IKTool::initEngine(const TPointD &pos) {
Skeleton::Bone *next = m_skeleton->getBoneByColumnIndex(*it++);
for (; it != links.end(); ++it)
stack.push_back(std::make_pair(*it, prev));
if (links.size() > 1 || (prev && next && (prev->getParent() == bone &&
next->getParent() == bone))) {
if (links.size() > 1 ||
(prev && next &&
(prev->getParent() == bone && next->getParent() == bone))) {
bone = next;
} else {
m_joints.push_back(Joint(bone, prev, sign));
@ -918,11 +916,12 @@ void IKTool::computeIHateIK() {
int n = (int)objs.size();
int frame = TTool::getApplication()->getCurrentFrame()->getFrame();
m_foot = m_firstFoot = 0;
m_frameOnNewPin = false;
m_frameOnNewPin = false;
// this just finds the first pin
int i;
for (i = 0; i < n && !objs[i]->getPinnedRangeSet()->isPinned(frame); i++) {}
for (i = 0; i < n && !objs[i]->getPinnedRangeSet()->isPinned(frame); i++) {
}
if (i == n) return;
// this makes m_foot to be the current pin
@ -940,7 +939,8 @@ void IKTool::computeIHateIK() {
// the frame is the start of a new pinned frame, find the previous pin
for (;;) {
for (i = 0; i < n && !objs[i]->getPinnedRangeSet()->isPinned(firstFrame);
i++) {}
i++) {
}
if (i == n) break;
m_firstFoot = objs[i];

View file

@ -383,8 +383,7 @@ void SkeletonTool::leftButtonDown(const TPointD &ppos, const TMouseEvent &e) {
if (m_device < 0) {
// No gadget clicked. Select the column
std::vector<int> columnIndexes;
getViewer()->posToColumnIndexes(e.m_pos, columnIndexes, getPixelSize() * getPixelSize(),
false);
getViewer()->posToColumnIndexes(e.m_pos, columnIndexes, 5.0, false);
if (!columnIndexes.empty()) {
int columnIndex;
columnIndex = columnIndexes.back();
@ -1056,8 +1055,7 @@ void SkeletonTool::drawHooks() {
// otherColumn = "picked" column not connected
TPointD parentProbePos = getViewer()->worldToPos(m_parentProbe);
std::vector<int> indexes;
getViewer()->posToColumnIndexes(parentProbePos, indexes,
getPixelSize() * 10, false);
getViewer()->posToColumnIndexes(parentProbePos, indexes, 10.0, false);
for (int i = (int)indexes.size() - 1; i >= 0; i--) {
if (connectedColumns.count(indexes[i]) == 0) {
otherColumn = indexes[i];

View file

@ -11,6 +11,7 @@
#include "toonz/dpiscale.h"
#include "tpixelutils.h"
#include "tregion.h"
#include "toonzqt/gutil.h"
#include <QRect>
@ -44,7 +45,7 @@ TPoint StylePicker::getRasterPoint(const TPointD &p) const {
//---------------------------------------------------------
/*-- (StylePickerTool内で)LineとAreaを切り替えてPickできる。mode: 0=Area,
* 1=Line, 2=Line&Areas(default) --*/
int StylePicker::pickStyleId(const TPointD &pos, double radius2,
int StylePicker::pickStyleId(const TPointD &pos, double radius, double scale2,
int mode) const {
int styleId = 0;
if (TToonzImageP ti = m_image) {
@ -78,11 +79,6 @@ int StylePicker::pickStyleId(const TPointD &pos, double radius2,
// prima cerca lo stile della regione piu' vicina
TRegion *r = vi->getRegion(pos);
if (r) styleId = r->getStyle();
// poi cerca quello della stroke, ma se prima aveva trovato una regione,
// richiede che
// il click sia proprio sopra la stroke, altrimenti cerca la stroke piu'
// vicina (max circa 10 pixel)
const double maxDist2 = (styleId == 0) ? 100.0 * radius2 : 0;
bool strokeFound;
double dist2, w, thick;
UINT index;
@ -90,9 +86,16 @@ int StylePicker::pickStyleId(const TPointD &pos, double radius2,
// la thickness, cioe' la min distance dalla outline e non dalla centerLine
strokeFound = vi->getNearestStroke(pos, w, index, dist2);
if (strokeFound) {
int devPixRatio = getDevPixRatio();
dist2 *= scale2;
TStroke *stroke = vi->getStroke(index);
thick = stroke->getThickPoint(w).thick;
if (dist2 - thick * thick < maxDist2) {
double len2 = thick * thick * scale2;
const double minDist2 =
(styleId == 0) ? radius * radius * (double)(devPixRatio * devPixRatio)
: 0;
double checkDist = std::max(minDist2, len2);
if (dist2 < checkDist) {
assert(stroke);
styleId = stroke->getStyle();
}
@ -118,7 +121,8 @@ int StylePicker::pickTone(const TPointD &pos) const {
//---------------------------------------------------------
TPixel32 StylePicker::pickColor(const TPointD &pos, double radius2) const {
TPixel32 StylePicker::pickColor(const TPointD &pos, double radius,
double scale2) const {
TToonzImageP ti = m_image;
TRasterImageP ri = m_image;
TVectorImageP vi = m_image;
@ -141,14 +145,14 @@ TPixel32 StylePicker::pickColor(const TPointD &pos, double radius2) const {
} else if (vi) {
const TPalette *palette = m_palette.getPointer();
if (!palette) return TPixel32::Transparent;
int styleId = pickStyleId(pos, radius2);
int styleId = pickStyleId(pos, radius, scale2);
if (0 <= styleId && styleId < palette->getStyleCount())
return palette->getStyle(styleId)->getAverageColor();
} else if (ti) {
const TPalette *palette = m_palette.getPointer();
if (!palette) return TPixel32::Transparent;
int paintId = pickStyleId(pos, radius2, 0);
int inkId = pickStyleId(pos, radius2, 1);
int paintId = pickStyleId(pos, radius, scale2, 0);
int inkId = pickStyleId(pos, radius, scale2, 1);
int tone = pickTone(pos);
TPixel32 ink, paint;
if (0 <= inkId && inkId < palette->getStyleCount())

View file

@ -9,6 +9,7 @@
// TnzQt includes
#include "toonzqt/tselectionhandle.h"
#include "toonzqt/styleselection.h"
#include "toonzqt/gutil.h"
// TnzLib includes
#include "toonz/txshsimplelevel.h"
@ -86,13 +87,13 @@ void StylePickerTool::pick(const TPointD &pos, const TMouseEvent &e,
---*/
if (Preferences::instance()->isMultiLayerStylePickerEnabled() &&
getApplication()->getCurrentFrame()->isEditingScene()) {
int superPickedColumnId = getViewer()->posToColumnIndex(
e.m_pos, getPixelSize() * getPixelSize(), false);
double pickRange = 10.0;
int superPickedColumnId =
getViewer()->posToColumnIndex(e.m_pos, pickRange, false);
if (superPickedColumnId >= 0 /*-- 何かColumnに当たった場合 --*/
&&
getApplication()->getCurrentColumn()->getColumnIndex() !=
superPickedColumnId) /*-- かつ、Current Columnでない場合 --*/
&& getApplication()->getCurrentColumn()->getColumnIndex() !=
superPickedColumnId) /*-- かつ、Current Columnでない場合 --*/
{
/*-- そのColumnからPickを試みる --*/
int currentFrame = getApplication()->getCurrentFrame()->getFrame();
@ -112,13 +113,16 @@ void StylePickerTool::pick(const TPointD &pos, const TMouseEvent &e,
tmpMousePosition.x /= tmpDpiScale.x;
tmpMousePosition.y /= tmpDpiScale.y;
TAffine aff =
getViewer()->getViewMatrix() * getColumnMatrix(superPickedColumnId);
double scale2 = aff.det();
StylePicker superPicker(pickedImage);
int picked_subsampling =
picked_level->getImageSubsampling(pickedCell.getFrameId());
int superPicked_StyleId = superPicker.pickStyleId(
TScale(1.0 / picked_subsampling) * tmpMousePosition +
TPointD(-0.5, -0.5),
getPixelSize() * getPixelSize(), modeValue);
pickRange, scale2, modeValue);
/*-- 何かStyleが拾えて、Transparentでない場合 --*/
if (superPicked_StyleId > 0) {
/*-- Levelの移動 --*/
@ -152,25 +156,26 @@ void StylePickerTool::pick(const TPointD &pos, const TMouseEvent &e,
/*-- 画面外をpickしても拾えないようにする --*/
if (!m_viewer->getGeometry().contains(pos)) return;
TAffine aff = getViewer()->getViewMatrix() * getCurrentColumnMatrix();
double scale2 = aff.det();
int subsampling = level->getImageSubsampling(getCurrentFid());
StylePicker picker(image);
int styleId =
picker.pickStyleId(TScale(1.0 / subsampling) * pos + TPointD(-0.5, -0.5),
getPixelSize() * getPixelSize(), modeValue);
10.0, scale2, modeValue);
if (styleId < 0) return;
if (modeValue == 1) // LINES
{
/*-- pickLineモードのとき、取得Styleが0の場合はカレントStyleを変えない。
* --*/
* --*/
if (styleId == 0) return;
/*--
* pickLineモードのときPurePaintの部分をクリックしてもカレントStyleを変えない
* --*/
if (ti &&
picker.pickTone(TScale(1.0 / subsampling) * pos +
TPointD(-0.5, -0.5)) == 255)
* pickLineモードのときPurePaintの部分をクリックしてもカレントStyleを変えない
* --*/
if (ti && picker.pickTone(TScale(1.0 / subsampling) * pos +
TPointD(-0.5, -0.5)) == 255)
return;
}
@ -207,13 +212,13 @@ void StylePickerTool::mouseMove(const TPointD &pos, const TMouseEvent &e) {
return;
}
TAffine aff = getViewer()->getViewMatrix() * getCurrentColumnMatrix();
double scale2 = aff.det();
int subsampling = level->getImageSubsampling(getCurrentFid());
StylePicker picker(image);
TPointD pickPos(TScale(1.0 / subsampling) * pos + TPointD(-0.5, -0.5));
int inkStyleId =
picker.pickStyleId(pickPos, getPixelSize() * getPixelSize(), 1);
int paintStyleId =
picker.pickStyleId(pickPos, getPixelSize() * getPixelSize(), 0);
int inkStyleId = picker.pickStyleId(pickPos, 10.0, scale2, 1);
int paintStyleId = picker.pickStyleId(pickPos, 10.0, scale2, 0);
int tone = picker.pickTone(pickPos);
controller->notifyStylePassivePicked(inkStyleId, paintStyleId, tone);
}

View file

@ -721,8 +721,9 @@ TFrameId TTool::getCurrentFid() const {
//-----------------------------------------------------------------------------
TAffine TTool::getCurrentColumnMatrix() const {
return getColumnMatrix(m_application->getCurrentColumn()->getColumnIndex());
TAffine TTool::getCurrentColumnMatrix(int frame) const {
return getColumnMatrix(m_application->getCurrentColumn()->getColumnIndex(),
frame);
}
//-----------------------------------------------------------------------------
@ -759,12 +760,12 @@ TAffine TTool::getCurrentObjectParentMatrix() const {
//-----------------------------------------------------------------------------
TAffine TTool::getColumnMatrix(int columnIndex) const {
TAffine TTool::getColumnMatrix(int columnIndex, int frame) const {
if (!m_application) return TAffine();
TFrameHandle *fh = m_application->getCurrentFrame();
if (fh->isEditingLevel()) return TAffine();
int frame = fh->getFrame();
if (frame < 0) frame = fh->getFrame();
TXsheet *xsh = m_application->getCurrentXsheet()->getXsheet();
TStageObjectId columnObjId =
(columnIndex >= 0)

View file

@ -120,6 +120,7 @@ set(MOC_HEADERS
xshrowviewer.h
quicktoolbar.h
xdtsimportpopup.h
expressionreferencemanager.h
motionpathpanel.h
graphwidget.h
../stopmotion/stopmotion.h
@ -345,6 +346,7 @@ set(SOURCES
separatecolorspopup.cpp
xdtsio.cpp
xdtsimportpopup.cpp
expressionreferencemanager.cpp
# Tracker file
dummyprocessor.cpp
metnum.cpp

View file

@ -224,11 +224,12 @@ void CameraSettingsPopup::updateWindowTitle() {
void CameraSettingsPopup::onChanged() {
TCamera *camera = getCamera();
if (!camera) return;
m_cameraSettingsWidget->getFields(camera);
TApp::instance()->getCurrentScene()->notifySceneChanged();
TApp::instance()->getCurrentXsheet()->notifyXsheetChanged();
if (m_cameraSettingsWidget->getFields(camera)) {
TApp::instance()->getCurrentScene()->notifySceneChanged();
TApp::instance()->getCurrentXsheet()->notifyXsheetChanged();
emit changed();
emit changed();
}
}
void CameraSettingsPopup::onNameChanged() {

View file

@ -6,6 +6,7 @@
#include "menubarcommandids.h"
#include "columnselection.h"
#include "tapp.h"
#include "expressionreferencemanager.h"
// TnzQt includes
#include "toonzqt/tselectionhandle.h"
@ -37,6 +38,7 @@
#include "toonz/tstageobjectspline.h"
#include "toonz/fxcommand.h"
#include "toonz/preferences.h"
#include "toonz/tstageobjectid.h"
// TnzBase includes
#include "tfx.h"
@ -51,6 +53,7 @@
// Qt includes
#include <QApplication>
#include <QClipboard>
#include <QSet>
#include <memory>
@ -773,8 +776,9 @@ static void copyColumns_internal(const std::set<int> &indices) {
TXsheet *xsh = TApp::instance()->getCurrentXsheet()->getXsheet();
data->storeColumns(indices, xsh, StageObjectsData::eDoClone |
StageObjectsData::eResetFxDagPositions);
data->storeColumns(
indices, xsh,
StageObjectsData::eDoClone | StageObjectsData::eResetFxDagPositions);
data->storeColumnFxs(
indices, xsh,
StageObjectsData::eDoClone | StageObjectsData::eResetFxDagPositions);
@ -962,8 +966,8 @@ void ColumnCmd::resequence(int index) {
assert(!cell.isEmpty());
TXshChildLevel *xl = cell.m_level->getChildLevel();
assert(xl);
TXsheet *childXsh = xl->getXsheet();
int frameCount = childXsh->getFrameCount();
TXsheet *childXsh = xl->getXsheet();
int frameCount = childXsh->getFrameCount();
if (frameCount < 1) frameCount = 1;
TUndoManager::manager()->add(new ResequenceUndo(index, frameCount));
@ -1001,7 +1005,7 @@ public:
void redo() const override {
TXsheet *xsh = TApp::instance()->getCurrentXsheet()->getXsheet();
xsh->insertColumn(m_columnIndex);
int frameCount = m_childLevel->getXsheet()->getFrameCount();
int frameCount = m_childLevel->getXsheet()->getFrameCount();
if (frameCount < 1) frameCount = 1;
for (int r = 0; r < frameCount; r++)
xsh->setCell(r, m_columnIndex,
@ -1196,6 +1200,160 @@ void ColumnCmd::clearCells(int index) {
TApp::instance()->getCurrentScene()->setDirtyFlag(true);
}
//=============================================================================
// checkExpressionReferences
//=============================================================================
// - If onlyColumns is true, it means that only columns with specified indices
// will be removed.
// - If onlyColumns is false, it means that the relevant pegbars will be removed
// as well (when collapsing collumns).
// - Note that relevant Fxs will be removed / collapsed regardless of
// onlyColumns.
// - When checkInvert is true, check references both side from the main xsheet
// and the child xsheet when collapsing columns.
bool ColumnCmd::checkExpressionReferences(const std::set<int> &indices,
bool onlyColumns, bool checkInvert) {
if (!Preferences::instance()->isModifyExpressionOnMovingReferencesEnabled())
return true;
TApp *app = TApp::instance();
TXsheet *xsh = app->getCurrentXsheet()->getXsheet();
// check if fxs will be deleted
QSet<int> colIdsToBeDeleted;
QSet<TFx *> fxsToBeDeleted;
// store column fxs to be deleted
std::set<TFx *> leaves;
for (auto index : indices) {
if (index < 0) continue;
TXshColumn *column = xsh->getColumn(index);
if (!column) continue;
colIdsToBeDeleted.insert(index);
TFx *fx = column->getFx();
if (fx) {
leaves.insert(fx);
TZeraryColumnFx *zcfx = dynamic_cast<TZeraryColumnFx *>(fx);
if (zcfx) fxsToBeDeleted.insert(zcfx->getZeraryFx());
}
}
// store relevant fxs which will be deleted along with the columns
TFxSet *fxSet = xsh->getFxDag()->getInternalFxs();
for (int i = 0; i < fxSet->getFxCount(); i++) {
TFx *fx = fxSet->getFx(i);
if (canRemoveFx(leaves, fx)) fxsToBeDeleted.insert(fx);
}
// store object ids which will be duplicated in the child xsheet on collapse
QList<TStageObjectId> objIdsToBeDuplicated;
if (checkInvert && !onlyColumns) {
for (auto index : indices) {
TStageObjectId id =
xsh->getStageObjectParent(TStageObjectId::ColumnId(index));
// store pegbars/cameras connected to the columns
while (id.isPegbar() || id.isCamera()) {
if (!objIdsToBeDuplicated.contains(id)) objIdsToBeDuplicated.append(id);
id = xsh->getStageObjectParent(id);
}
}
}
return ExpressionReferenceManager::instance()->checkReferenceDeletion(
colIdsToBeDeleted, fxsToBeDeleted, objIdsToBeDuplicated, checkInvert);
}
//-----------------------------------------------------------------------------
bool ColumnCmd::checkExpressionReferences(const std::set<int> &indices,
const std::set<TFx *> &fxs,
bool onlyColumns, bool checkInvert) {
if (!Preferences::instance()->isModifyExpressionOnMovingReferencesEnabled())
return true;
TApp *app = TApp::instance();
TXsheet *xsh = app->getCurrentXsheet()->getXsheet();
// check if fxs will be deleted
QSet<int> colIdsToBeDeleted;
QSet<TFx *> fxsToBeDeleted;
for (auto index : indices) {
if (index < 0) continue;
TXshColumn *column = xsh->getColumn(index);
if (!column) continue;
colIdsToBeDeleted.insert(index);
TFx *fx = column->getFx();
if (fx) {
TZeraryColumnFx *zcfx = dynamic_cast<TZeraryColumnFx *>(fx);
if (zcfx) fxsToBeDeleted.insert(zcfx->getZeraryFx());
}
}
TFxSet *fxSet = xsh->getFxDag()->getInternalFxs();
for (auto fx : fxs) fxsToBeDeleted.insert(fx);
// store object ids which will be duplicated in the child xsheet on collapse
QList<TStageObjectId> objIdsToBeDuplicated;
if (checkInvert && !onlyColumns) {
for (auto index : indices) {
TStageObjectId id =
xsh->getStageObjectParent(TStageObjectId::ColumnId(index));
// store pegbars/cameras connected to the columns
while (id.isPegbar() || id.isCamera()) {
if (!objIdsToBeDuplicated.contains(id)) objIdsToBeDuplicated.append(id);
id = xsh->getStageObjectParent(id);
}
}
}
return ExpressionReferenceManager::instance()->checkReferenceDeletion(
colIdsToBeDeleted, fxsToBeDeleted, objIdsToBeDuplicated, checkInvert);
}
//-----------------------------------------------------------------------------
bool ColumnCmd::checkExpressionReferences(
const QList<TStageObjectId> &objects) {
if (!Preferences::instance()->isModifyExpressionOnMovingReferencesEnabled())
return true;
TApp *app = TApp::instance();
TXsheet *xsh = app->getCurrentXsheet()->getXsheet();
QSet<int> colIdsToBeDeleted;
QSet<TFx *> fxsToBeDeleted;
QList<TStageObjectId> objIdsToBeDuplicated;
// store column fxs to be deleted
std::set<TFx *> leaves;
for (auto objId : objects) {
if (objId.isColumn()) {
int index = objId.getIndex();
if (index < 0) continue;
TXshColumn *column = xsh->getColumn(index);
if (!column) continue;
colIdsToBeDeleted.insert(index);
TFx *fx = column->getFx();
if (fx) {
leaves.insert(fx);
TZeraryColumnFx *zcfx = dynamic_cast<TZeraryColumnFx *>(fx);
if (zcfx) fxsToBeDeleted.insert(zcfx->getZeraryFx());
}
} else
objIdsToBeDuplicated.append(objId);
}
// store relevant fxs which will be deleted along with the columns
TFxSet *fxSet = xsh->getFxDag()->getInternalFxs();
for (int i = 0; i < fxSet->getFxCount(); i++) {
TFx *fx = fxSet->getFx(i);
if (canRemoveFx(leaves, fx)) fxsToBeDeleted.insert(fx);
}
return ExpressionReferenceManager::instance()->checkReferenceDeletion(
colIdsToBeDeleted, fxsToBeDeleted, objIdsToBeDuplicated, true);
}
//=============================================================================
namespace {
@ -1294,7 +1452,7 @@ public:
else
column->setCamstandVisible(!column->isCamstandVisible());
if (column->getSoundColumn()) sound_changed = true;
viewer_changed = true;
viewer_changed = true;
}
/*TAB
if(cmd & (CMD_ENABLE_PREVIEW|CMD_DISABLE_PREVIEW|CMD_TOGGLE_PREVIEW))

View file

@ -4,8 +4,12 @@
#define COLUMN_COMMAND_INCLUDED
#include <set>
#include <QList>
#include "toonz/tstageobjectid.h"
class StageObjectsData;
class TFx;
namespace ColumnCmd {
@ -35,6 +39,21 @@ void clearCells(int index);
//! Adds an undo object for converting layer to vector.
void addConvertToVectorUndo(std::set<int> &newColumnIndices);
} // namespace
// "checkInvert" flag is ON when collapsing columns.
// expression references need to be checked in both way,
// the columns to be collapsed and other columns to be kept in the parent
// xsheet.
bool checkExpressionReferences(const std::set<int> &indices,
bool onlyColumns = true,
bool checkInvert = false);
bool checkExpressionReferences(const std::set<int> &indices,
const std::set<TFx *> &fxs,
bool onlyColumns = true,
bool checkInvert = false);
// checkInvert is always true for collapsing in stage schematic
bool checkExpressionReferences(const QList<TStageObjectId> &objects);
} // namespace ColumnCmd
#endif

View file

@ -95,6 +95,8 @@ void TColumnSelection::pasteColumns() {
//-----------------------------------------------------------------------------
void TColumnSelection::deleteColumns() {
if (!ColumnCmd::checkExpressionReferences(m_indices)) return;
ColumnCmd::deleteColumns(m_indices, false, false);
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,89 @@
#pragma once
#ifndef EXPRESSIONREFERENCEMANAGER_H
#define EXPRESSIONREFERENCEMANAGER_H
#include "tparamchange.h"
#include "toonzqt/treemodel.h"
#include "toonzqt/functiontreeviewer.h"
#include "toonz/txsheetcolumnchange.h"
#include "toonz/tstageobjectid.h"
#include "toonz/expressionreferencemonitor.h"
#include <QObject>
#include <QMap>
#include <QSet>
#include <QList>
class TDoubleParam;
class TFx;
class ExpressionReferenceManager : public QObject,
public TXsheetColumnChangeObserver,
public TParamObserver { // singleton
Q_OBJECT
FunctionTreeModel* m_model;
// block to run onChange() due to keyframe change caused by itself
bool m_blockParamChange;
ExpressionReferenceMonitor* currentMonitor();
QMap<TDoubleParam*, ExpressionReferenceMonitorInfo>& info(
TXsheet* xsh = nullptr);
ExpressionReferenceMonitorInfo& touchInfo(TDoubleParam* param,
TXsheet* xsh = nullptr);
ExpressionReferenceManager();
void checkRef(TreeModel::Item* item, TXsheet* xsh = nullptr);
FunctionTreeModel::Channel* findChannel(TDoubleParam* param,
TreeModel::Item* item);
void gatherParams(TreeModel::Item* item, QList<TDoubleParam*>&);
bool refreshParamsRef(TDoubleParam* curve, TXsheet* xsh = nullptr);
void replaceExpressionTexts(
TDoubleParam* curve, const std::map<std::string, std::string> replaceMap,
TXsheet* xsh = nullptr);
bool doCheckReferenceDeletion(
const QSet<int>& columnIdsToBeDeleted, const QSet<TFx*>& fxsToBeDeleted,
const QList<TStageObjectId>& objectIdsToBeDeleted,
const QList<TStageObjectId>& objIdsToBeDuplicated,
bool checkInvert = false);
public:
static ExpressionReferenceManager* instance();
void onChange(const TXsheetColumnChange&) override;
void onFxAdded(const std::vector<TFx*>&) override;
void onStageObjectAdded(const TStageObjectId) override;
bool isIgnored(TDoubleParam*) override;
void onChange(const TParamChange&) override;
void init();
bool checkReferenceDeletion(const QSet<int>& columnIdsToBeDeleted,
const QSet<TFx*>& fxsToBeDeleted,
const QList<TStageObjectId>& objIdsToBeDuplicated,
bool checkInvert);
bool checkReferenceDeletion(
const QList<TStageObjectId>& objectIdsToBeDeleted);
bool checkExplode(TXsheet* childXsh, int index, bool removeColumn,
bool columnsOnly);
void transferReference(TXsheet* fromXsh, TXsheet* toXsh,
const QMap<TStageObjectId, TStageObjectId>& idTable,
const QMap<TFx*, TFx*>& fxTable);
bool askIfParamIsIgnoredOnSave(bool saveSubXsheet);
protected slots:
void onSceneSwitched();
void onXsheetSwitched();
void onXsheetChanged();
void onPreferenceChanged(const QString& prefName);
};
#endif

View file

@ -239,10 +239,15 @@ void TFilmstripSelection::copyFrames() {
void TFilmstripSelection::cutFrames() {
TXshSimpleLevel *sl = TApp::instance()->getCurrentLevel()->getSimpleLevel();
if (sl) {
int firstSelectedIndex = sl->fid2index(*m_selectedFrames.begin());
assert(firstSelectedIndex >= 0);
FilmstripCmd::cut(sl, m_selectedFrames);
selectNone();
TApp::instance()->getCurrentFrame()->setFid(sl->getFirstFid());
select(sl->getFirstFid());
TFrameId fId = (firstSelectedIndex == 0)
? sl->getFirstFid()
: sl->getFrameId(firstSelectedIndex - 1);
TApp::instance()->getCurrentFrame()->setFid(fId);
select(fId);
}
}

View file

@ -954,9 +954,11 @@ void ImageViewer::pickColor(QMouseEvent *event, bool putValueToStyleEditor) {
TPointD(0.5 * imgRect.getLx() + pos.x, 0.5 * imgRect.getLy() + pos.y);
TPixel32 pix;
if (m_lutCalibrator && m_lutCalibrator->isValid())
pix = picker.pickColor(pos + TPointD(-0.5, -0.5));
else
if (m_lutCalibrator && m_lutCalibrator->isValid()) {
// for specifiying pixel range on picking vector
double scale2 = getViewAff().det();
pix = picker.pickColor(pos + TPointD(-0.5, -0.5), 10.0, scale2);
} else
pix = picker.pickColor(area);
if (!img->raster() || imgRect.contains(imagePos)) {

View file

@ -20,6 +20,7 @@
#include "versioncontrol.h"
#include "cachefxcommand.h"
#include "xdtsio.h"
#include "expressionreferencemanager.h"
// TnzTools includes
#include "tools/toolhandle.h"
@ -1370,6 +1371,13 @@ bool IoCmd::saveScene(const TFilePath &path, int flags) {
.arg(toQString(scenePath.getParentDir())));
return false;
}
// notify user if the scene will be saved including any "broken" expression
// reference
if (!ExpressionReferenceManager::instance()->askIfParamIsIgnoredOnSave(
saveSubxsheet))
return false;
if (!overwrite && TFileStatus(scenePath).doesExist()) {
QString question;
question = QObject::tr(
@ -3025,7 +3033,7 @@ public:
if (sl && sl->getPath().getType() == "pli")
sl->save(palettePath, TFilePath(), true);
else if (sl->getType() & FULLCOLOR_TYPE)
else if (sl && sl->getType() & FULLCOLOR_TYPE)
FullColorPalette::instance()->savePalette(scene);
else
StudioPalette::instance()->save(palettePath, palette);

View file

@ -8,6 +8,7 @@
#include "previewfxmanager.h"
#include "cleanupsettingspopup.h"
#include "filebrowsermodel.h"
#include "expressionreferencemanager.h"
// TnzTools includes
#include "tools/tool.h"
@ -467,11 +468,7 @@ int main(int argc, char *argv[]) {
fmt.setStencil(true);
QGLFormat::setDefaultFormat(fmt);
// seems this function should be called at all systems
// perhaps in some GLUT-implementations initalization is mere formality
#if defined(LINUX) || defined(_WIN32)
glutInit(&argc, argv);
#endif
splash.showMessage(offsetStr + "Initializing environment...",
Qt::AlignRight | Qt::AlignBottom, Qt::black);
@ -710,6 +707,8 @@ int main(int argc, char *argv[]) {
QSettings settings(toQString(fp), QSettings::IniFormat);
w.restoreGeometry(settings.value("MainWindowGeometry").toByteArray());
ExpressionReferenceManager::instance()->init();
#ifndef MACOSX
// Workaround for the maximized window case: Qt delivers two resize events,
// one in the normal geometry, before

File diff suppressed because it is too large Load diff

View file

@ -7,9 +7,12 @@
#include "toonz/sceneproperties.h"
#include <QLabel>
// forward declaration
class ToonzScene;
class QComboBox;
class QScrollArea;
class QListWidgetItem;
namespace DVGui {
class FileField;
@ -17,7 +20,7 @@ class LineEdit;
class IntLineEdit;
class CheckBox;
class DoubleLineEdit;
}
} // namespace DVGui
class CameraSettingsPopup;
@ -25,6 +28,24 @@ class CameraSettingsPopup;
// OutputSettingsPopup
//-----------------------------------------------------------------------------
class AnimatedLabel : public QLabel {
Q_OBJECT
Q_PROPERTY(QColor color READ color WRITE setColor)
public:
AnimatedLabel(const QString &text, QWidget *parent = 0)
: QLabel(text, parent) {
setObjectName("OutputSettingsLabel");
}
void setColor(QColor color) {
setStyleSheet(QString("background-color: rgba(%1,%2,%3,%4);")
.arg(color.red())
.arg(color.green())
.arg(color.blue())
.arg(color.alpha()));
}
QColor color() { return Qt::black; }
};
class OutputSettingsPopup : public DVGui::Dialog {
Q_OBJECT
@ -49,8 +70,6 @@ class OutputSettingsPopup : public DVGui::Dialog {
DVGui::DoubleLineEdit *m_frameRateFld;
QPushButton *m_fileFormatButton;
QPushButton *m_renderButton;
QPushButton *m_saveAndRenderButton;
CameraSettingsPopup *m_cameraSettings;
QComboBox *m_presetCombo;
@ -58,12 +77,24 @@ class OutputSettingsPopup : public DVGui::Dialog {
DVGui::CheckBox *m_addBoard;
QPushButton *m_boardSettingsBtn;
QScrollArea *m_scrollArea;
QLabel *m_generalLabel, *m_cameraLabel, *m_advancedLabel, *m_moreLabel;
QFrame *m_generalBox, *m_cameraBox, *m_advancedBox, *m_moreBox;
QPushButton *m_showCameraSettingsButton, *m_showAdvancedSettingsButton,
*m_showMoreSettingsButton;
bool m_isPreviewSettings;
bool m_hideAlreadyCalled = false;
void updatePresetComboItems();
void translateResampleOptions();
QFrame *createPanel(bool isPreview);
QFrame *createGeneralSettingsBox(bool isPreview);
QFrame *createCameraSettingsBox(bool isPreview);
QFrame *createAdvancedSettingsBox(bool isPreview);
QFrame *createMoreSettingsBox();
public:
OutputSettingsPopup(bool isPreview = false);
@ -108,6 +139,8 @@ protected slots:
// clapperboard
void onAddBoardChecked(int state);
void onBoardSettingsBtnClicked();
void onCategoryActivated(QListWidgetItem *);
};
class PreviewSettingsPopup final : public OutputSettingsPopup {

View file

@ -552,6 +552,13 @@ void PreferencesPopup::onShowQuickToolbarClicked() {
//-----------------------------------------------------------------------------
void PreferencesPopup::onModifyExpressionOnMovingReferencesChanged() {
TApp::instance()->getCurrentScene()->notifyPreferenceChanged(
"modifyExpressionOnMovingReferences");
}
//-----------------------------------------------------------------------------
void PreferencesPopup::onBlankCountChanged() {
TApp::instance()->getCurrentScene()->notifyPreferenceChanged("BlankCount");
}
@ -1104,6 +1111,9 @@ QString PreferencesPopup::getUIString(PreferencesItemId id) {
// Animation
{keyframeType, tr("Default Interpolation:")},
{animationStep, tr("Animation Step:")},
{modifyExpressionOnMovingReferences,
tr("[Experimental Feature] ") +
tr("Automatically Modify Expression On Moving Referenced Objects")},
// Preview
{blanksCount, tr("Blank Frames:")},
@ -1767,9 +1777,15 @@ QWidget* PreferencesPopup::createAnimationPage() {
insertUI(keyframeType, lay, getComboItemList(keyframeType));
insertUI(animationStep, lay);
insertUI(modifyExpressionOnMovingReferences, lay);
lay->setRowStretch(lay->rowCount(), 1);
widget->setLayout(lay);
m_onEditedFuncMap.insert(
modifyExpressionOnMovingReferences,
&PreferencesPopup::onModifyExpressionOnMovingReferencesChanged);
return widget;
}

View file

@ -146,6 +146,8 @@ private:
// Xsheet
void onShowKeyframesOnCellAreaChanged();
void onShowQuickToolbarClicked();
// Animation
void onModifyExpressionOnMovingReferencesChanged();
// Preview
void onBlankCountChanged();
void onBlankColorChanged();

View file

@ -3117,8 +3117,9 @@ void SceneViewer::posToColumnIndexes(const TPointD &p,
OnionSkinMask osm = app->getCurrentOnionSkin()->getOnionSkinMask();
TPointD pos = TPointD(p.x - width() / 2, p.y - height() / 2);
Stage::Picker picker(getViewMatrix(), pos, m_visualSettings);
picker.setDistance(distance);
Stage::Picker picker(getViewMatrix(), pos, m_visualSettings,
getDevPixRatio());
picker.setMinimumDistance(distance);
TXshSimpleLevel::m_rasterizePli = 0;
@ -3156,8 +3157,9 @@ int SceneViewer::posToRow(const TPointD &p, double distance,
OnionSkinMask osm = app->getCurrentOnionSkin()->getOnionSkinMask();
TPointD pos = TPointD(p.x - width() / 2, p.y - height() / 2);
Stage::Picker picker(getViewMatrix(), pos, m_visualSettings);
picker.setDistance(distance);
Stage::Picker picker(getViewMatrix(), pos, m_visualSettings,
getDevPixRatio());
picker.setMinimumDistance(distance);
if (app->getCurrentFrame()->isEditingLevel()) {
Stage::visit(picker, app->getCurrentLevel()->getLevel(),

View file

@ -30,6 +30,7 @@
#include "toonz/tstageobjecttree.h"
#include "toonz/tstageobjectspline.h"
#include "toonz/tcamera.h"
#include "toonz/expressionreferencemonitor.h"
// TnzQt includes
#include "toonzqt/menubarcommand.h"
@ -47,6 +48,7 @@
#include "tapp.h"
#include "columnselection.h"
#include "cellselection.h"
#include "expressionreferencemanager.h"
#include "subscenecommand.h"
@ -625,12 +627,10 @@ std::set<int> explodeStageObjects(
const GroupData &fxGroupData, QList<TStageObject *> &pegObjects,
QMap<TFx *, QPair<TFx *, int>> &fxs,
QMap<TStageObjectSpline *, TStageObjectSpline *> &splines,
bool onlyColumn) {
QMap<TStageObjectId, TStageObjectId> &ids, bool onlyColumn) {
/*- SubXsheet, 親Xsheet両方のツリーを取得 -*/
TStageObjectTree *innerTree = subXsh->getStageObjectTree();
TStageObjectTree *outerTree = xsh->getStageObjectTree();
// inner id->outer id
QMap<TStageObjectId, TStageObjectId> ids;
// innerSpline->outerSpline
int groupId = -1; // outerTree->getNewGroupId();
/*- Pegbarも持ち出す場合 -*/
@ -927,20 +927,58 @@ void explodeFxs(TXsheet *xsh, TXsheet *subXsh, const GroupData &fxGroupData,
//-----------------------------------------------------------------------------
template <typename ParamCont>
void setGrammerToParams(const ParamCont *cont,
const TSyntax::Grammar *grammer) {
for (int p = 0; p != cont->getParamCount(); ++p) {
TParam &param = *cont->getParam(p);
if (TDoubleParam *dp = dynamic_cast<TDoubleParam *>(&param))
dp->setGrammar(grammer);
else if (TParamSet *paramSet = dynamic_cast<TParamSet *>(&param))
setGrammerToParams(paramSet, grammer);
}
}
//-----------------------------------------------------------------------------
std::set<int> explode(TXsheet *xsh, TXsheet *subXsh, int index,
const TStageObjectId &parentId,
const GroupData &objGroupData, const TPointD &stageSubPos,
const GroupData &fxGroupData, const TPointD &fxSubPos,
QList<TStageObject *> &pegObjects,
QMap<TStageObjectSpline *, TStageObjectSpline *> &splines,
const std::vector<TFxPort *> &outPorts, bool onlyColumn,
bool linkToXsheet) {
const TStageObjectId &parentId, const GroupData &objGroupData,
const TPointD &stageSubPos, const GroupData &fxGroupData,
const TPointD &fxSubPos, QList<TStageObject *> &pegObjects,
QMap<TStageObjectSpline *, TStageObjectSpline *> &splines,
const std::vector<TFxPort *> &outPorts, bool onlyColumn,
bool linkToXsheet) {
// innerFx->outerFxs
QMap<TFx *, QPair<TFx *, int>> fxs;
// inner id->outer id
QMap<TStageObjectId, TStageObjectId> objIds;
std::set<int> indexes = explodeStageObjects(
xsh, subXsh, index, parentId, objGroupData, stageSubPos, fxGroupData,
pegObjects, fxs, splines, onlyColumn);
pegObjects, fxs, splines, objIds, onlyColumn);
explodeFxs(xsh, subXsh, fxGroupData, fxs, fxSubPos, outPorts, linkToXsheet);
assert(TApp::instance()->getCurrentXsheet()->getXsheet() == xsh);
// reset grammers for all parameters brought out to the parent xsheet
TSyntax::Grammar *grammer = xsh->getStageObjectTree()->getGrammar();
for (auto id : objIds.values()) {
TStageObject *obj = xsh->getStageObject(id);
for (int c = 0; c != TStageObject::T_ChannelCount; ++c)
obj->getParam((TStageObject::Channel)c)->setGrammar(grammer);
if (const PlasticSkeletonDeformationP &sd =
obj->getPlasticSkeletonDeformation())
sd->setGrammar(grammer);
}
QMap<TFx *, TFx *> fxMap;
for (auto it = fxs.constBegin(); it != fxs.constEnd(); ++it) {
setGrammerToParams(it.value().first->getParams(), grammer);
fxMap.insert(it.key(), it.value().first);
}
ExpressionReferenceManager::instance()->transferReference(subXsh, xsh, objIds,
fxMap);
return indexes;
}
@ -1160,9 +1198,9 @@ bool hasPegbarsToBringInsideChildXsheet(TXsheet *xsh,
//-----------------------------------------------------------------------------
void bringPegbarsInsideChildXsheet(TXsheet *xsh, TXsheet *childXsh,
std::set<int> indices,
std::set<int> newIndices) {
void bringPegbarsInsideChildXsheet(
TXsheet *xsh, TXsheet *childXsh, std::set<int> indices,
std::set<int> newIndices, QMap<TStageObjectId, TStageObjectId> &idTable) {
// columns in the child xsheet are all connected to the table for now.
// so we need to take parental connection information from the parent xsheet.
@ -1201,6 +1239,9 @@ void bringPegbarsInsideChildXsheet(TXsheet *xsh, TXsheet *childXsh,
for (int c = 0; c != TStageObject::T_ChannelCount; ++c)
childXsh->getStageObjectTree()->setGrammar(
obj->getParam((TStageObject::Channel)c));
// register pegbars to the table
idTable.insert(id, id);
}
}
@ -1249,11 +1290,15 @@ void collapseColumns(std::set<int> indices, bool columnsOnly) {
TApp *app = TApp::instance();
TXsheet *xsh = app->getCurrentXsheet()->getXsheet();
std::set<int> oldIndices = indices;
StageObjectsData *data = new StageObjectsData();
// store xsheet data to be collapsed
data->storeColumns(indices, xsh, StageObjectsData::eDoClone);
data->storeColumnFxs(indices, xsh, StageObjectsData::eDoClone);
ExpressionReferenceMonitor *monitor = xsh->getExpRefMonitor()->clone();
ToonzScene *scene = app->getCurrentScene()->getScene();
TXshLevel *xl = scene->createNewLevel(CHILD_XSHLEVEL);
assert(xl);
@ -1265,12 +1310,18 @@ void collapseColumns(std::set<int> indices, bool columnsOnly) {
std::set<int> newIndices;
std::list<int> restoredSplineIds;
QMap<TStageObjectId, TStageObjectId> idTable;
QMap<TFx *, TFx *> fxTable;
// restore data into sub xsheet
data->restoreObjects(newIndices, restoredSplineIds, childXsh, 0);
data->restoreObjects(newIndices, restoredSplineIds, childXsh, 0, idTable,
fxTable);
// bring pegbars into sub xsheet
if (!columnsOnly)
bringPegbarsInsideChildXsheet(xsh, childXsh, indices, newIndices);
bringPegbarsInsideChildXsheet(xsh, childXsh, indices, newIndices, idTable);
ExpressionReferenceManager::instance()->transferReference(xsh, childXsh,
idTable, fxTable);
childXsh->updateFrameCount();
@ -1339,8 +1390,9 @@ void collapseColumns(std::set<int> indices,
const QList<TStageObjectId> &objIds) {
if (indices.empty()) return;
TApp *app = TApp::instance();
TXsheet *xsh = app->getCurrentXsheet()->getXsheet();
TApp *app = TApp::instance();
TXsheet *xsh = app->getCurrentXsheet()->getXsheet();
std::set<int> oldIndices = indices;
int index = *indices.begin();
@ -1356,13 +1408,7 @@ void collapseColumns(std::set<int> indices,
StageObjectsData::eDoClone);
data->storeColumnFxs(indices, xsh, StageObjectsData::eDoClone);
app->getCurrentXsheet()->blockSignals(true);
app->getCurrentObject()->blockSignals(true);
ColumnCmd::deleteColumns(indices, false, true);
app->getCurrentXsheet()->blockSignals(false);
app->getCurrentObject()->blockSignals(false);
xsh->insertColumn(index);
ExpressionReferenceMonitor *monitor = xsh->getExpRefMonitor()->clone();
ToonzScene *scene = app->getCurrentScene()->getScene();
TXshLevel *xl = scene->createNewLevel(CHILD_XSHLEVEL);
@ -1375,9 +1421,23 @@ void collapseColumns(std::set<int> indices,
std::set<int> newIndices;
std::list<int> restoredSplineIds;
data->restoreObjects(newIndices, restoredSplineIds, childXsh, 0);
QMap<TStageObjectId, TStageObjectId> idTable;
QMap<TFx *, TFx *> fxTable;
data->restoreObjects(newIndices, restoredSplineIds, childXsh, 0, idTable,
fxTable);
childXsh->updateFrameCount();
ExpressionReferenceManager::instance()->transferReference(xsh, childXsh,
idTable, fxTable);
app->getCurrentXsheet()->blockSignals(true);
app->getCurrentObject()->blockSignals(true);
ColumnCmd::deleteColumns(indices, false, true);
app->getCurrentXsheet()->blockSignals(false);
app->getCurrentObject()->blockSignals(false);
xsh->insertColumn(index);
int r, rowCount = childXsh->getFrameCount();
for (r = 0; r < rowCount; r++)
xsh->setCell(r, index, TXshCell(xl, TFrameId(r + 1)));
@ -1405,12 +1465,15 @@ void collapseColumns(std::set<int> indices, const std::set<TFx *> &fxs,
TApp *app = TApp::instance();
TXsheet *xsh = app->getCurrentXsheet()->getXsheet();
std::set<int> oldIndices = indices;
//++++++++++++++++++++++++++++++
StageObjectsData *data = new StageObjectsData();
data->storeColumns(indices, xsh, StageObjectsData::eDoClone);
data->storeFxs(fxs, xsh, StageObjectsData::eDoClone);
ExpressionReferenceMonitor *monitor = xsh->getExpRefMonitor()->clone();
ToonzScene *scene = app->getCurrentScene()->getScene();
TXshLevel *xl = scene->createNewLevel(CHILD_XSHLEVEL);
assert(xl);
@ -1420,10 +1483,16 @@ void collapseColumns(std::set<int> indices, const std::set<TFx *> &fxs,
std::set<int> newIndices;
std::list<int> restoredSplineIds;
data->restoreObjects(newIndices, restoredSplineIds, childXsh, 0);
QMap<TStageObjectId, TStageObjectId> idTable;
QMap<TFx *, TFx *> fxTable;
data->restoreObjects(newIndices, restoredSplineIds, childXsh, 0, idTable,
fxTable);
if (!columnsOnly)
bringPegbarsInsideChildXsheet(xsh, childXsh, indices, newIndices);
bringPegbarsInsideChildXsheet(xsh, childXsh, indices, newIndices, idTable);
ExpressionReferenceManager::instance()->transferReference(xsh, childXsh,
idTable, fxTable);
childXsh->updateFrameCount();
@ -2224,6 +2293,7 @@ void SubsceneCmd::collapse(std::set<int> &indices) {
if (ret == 0) return;
onlyColumns = (ret == 2);
}
if (!ColumnCmd::checkExpressionReferences(indices, onlyColumns, true)) return;
std::set<int> oldIndices = indices;
int index = *indices.begin();
@ -2272,6 +2342,8 @@ void SubsceneCmd::collapse(const QList<TStageObjectId> &objects) {
std::set<int> indices;
getColumnIndexes(objects, indices);
if (!ColumnCmd::checkExpressionReferences(objects)) return;
std::set<int> oldIndices = indices;
int index = *indices.begin();
@ -2320,6 +2392,7 @@ void SubsceneCmd::collapse(const QList<TFxP> &fxs) {
TXsheet *xsh = TApp::instance()->getCurrentXsheet()->getXsheet();
bool onlyColumns = true;
if (hasPegbarsToBringInsideChildXsheet(xsh, indices)) {
// User must decide if pegbars must be collapsed too
QString question(QObject::tr("Collapsing columns: what you want to do?"));
QList<QString> list;
list.append(QObject::tr(
@ -2332,6 +2405,10 @@ void SubsceneCmd::collapse(const QList<TFxP> &fxs) {
onlyColumns = (ret == 2);
}
if (!ColumnCmd::checkExpressionReferences(indices, internalFx, onlyColumns,
true))
return;
std::set<int> oldIndices = indices;
int index = *indices.begin();
@ -2385,6 +2462,15 @@ void SubsceneCmd::explode(int index) {
TXshChildLevel *childLevel = cell.getChildLevel();
if (!childLevel) return;
// Cannot remove the column if it contains frames of a TXshSimpleLevel.
int from, to;
// removeColumn is true if the column contains only one subXsheetLevel (i.e.
// the column will be removed) removeColumn is false if there is another level
// in the same column (i.e. the column will remain)
bool removeColumn =
mustRemoveColumn(from, to, childLevel, xsh, index, frameIndex);
/*- Pegbarを親Sheetに持って出るかの質問ダイアログ -*/
QString question(QObject::tr("Exploding Sub-Scene: what you want to do?"));
QList<QString> list;
@ -2394,6 +2480,11 @@ void SubsceneCmd::explode(int index) {
QObject::tr("Bring columns in the main scene without parenting."));
int ret = DVGui::RadioButtonMsgBox(DVGui::WARNING, question, list);
if (ret == 0) return;
if (!ExpressionReferenceManager::instance()->checkExplode(
childLevel->getXsheet(), index, removeColumn, ret == 2))
return;
// Collect column stage object informations
TStageObjectId colId = TStageObjectId::ColumnId(index);
TStageObjectId parentId = xsh->getStageObjectParent(colId);
@ -2450,14 +2541,6 @@ void SubsceneCmd::explode(int index) {
std::vector<TFxPort *> outPorts;
// Cannot remove the column if it contains frames of a TXshSimpleLevel.
int from, to;
/*--
subXsheetLevelしか入っていない場合はremoveColumnはtrue
Levelが入っていた場合はremoveColumnはfalse
--*/
bool removeColumn =
mustRemoveColumn(from, to, childLevel, xsh, index, frameIndex);
QList<TStageObject *> pegObjects;
QMap<TStageObjectSpline *, TStageObjectSpline *> splines;
@ -2519,7 +2602,7 @@ void SubsceneCmd::explode(int index) {
objGroupNames);
TUndoManager::manager()->add(undo);
} else {
// keep outPorts empty since the exploded node will be re-cocnected to the
// keep outPorts empty since the exploded node will be re-connected to the
// xsheet node
// Collect information for undo

View file

@ -24,6 +24,7 @@
#include "historypane.h"
#include "cleanupsettingspane.h"
#include "vectorguideddrawingpane.h"
#include "expressionreferencemanager.h"
#include "stopmotioncontroller.h"
#include "motionpathpanel.h"
@ -35,6 +36,7 @@
#include "menubarcommandids.h"
#include "tapp.h"
#include "mainwindow.h"
#include "columncommand.h"
// TnzTools includes
#include "tools/tooloptions.h"
@ -52,6 +54,8 @@
#include "toonzqt/tmessageviewer.h"
#include "toonzqt/scriptconsole.h"
#include "toonzqt/fxsettings.h"
#include "toonzqt/fxselection.h"
#include "stageobjectselection.h"
// TnzLib includes
#include "toonz/palettecontroller.h"
@ -72,6 +76,8 @@
#include "toonz/preferences.h"
#include "tw/stringtable.h"
#include "toonz/toonzfolders.h"
#include "toonz/fxcommand.h"
#include "toonz/tstageobjectcmd.h"
// TnzBase includes
#include "trasterfx.h"
@ -223,6 +229,39 @@ int SchematicScenePanel::getViewType() {
//-----------------------------------------------------------------------------
void SchematicScenePanel::onDeleteFxs(const FxSelection *selection) {
if (selection->isEmpty()) return;
std::set<int> colIndices;
std::set<TFx *> fxs;
for (auto index : selection->getColumnIndexes()) colIndices.insert(index);
for (auto fx : selection->getFxs()) fxs.insert(fx.getPointer());
if (!ColumnCmd::checkExpressionReferences(colIndices, fxs)) return;
TApp *app = TApp::instance();
TFxCommand::deleteSelection(selection->getFxs().toStdList(),
selection->getLinks().toStdList(),
selection->getColumnIndexes().toStdList(),
app->getCurrentXsheet(), app->getCurrentFx());
}
//-----------------------------------------------------------------------------
void SchematicScenePanel::onDeleteStageObjects(
const StageObjectSelection *selection) {
if (!ExpressionReferenceManager::instance()->checkReferenceDeletion(
selection->getObjects()))
return;
TApp *app = TApp::instance();
TStageObjectCmd::deleteSelection(
selection->getObjects().toVector().toStdVector(),
selection->getLinks().toStdList(), selection->getSplines().toStdList(),
app->getCurrentXsheet(), app->getCurrentObject(), app->getCurrentFx());
}
//-----------------------------------------------------------------------------
void SchematicScenePanel::showEvent(QShowEvent *e) {
if (m_schematicViewer->isStageSchematicViewed())
setWindowTitle(QObject::tr("Stage Schematic"));
@ -238,8 +277,13 @@ void SchematicScenePanel::showEvent(QShowEvent *e) {
SLOT(onCollapse(QList<TStageObjectId>)));
connect(m_schematicViewer, SIGNAL(doExplodeChild(const QList<TFxP> &)), this,
SLOT(onExplodeChild(const QList<TFxP> &)));
connect(m_schematicViewer, SIGNAL(doDeleteFxs(const FxSelection *)), this,
SLOT(onDeleteFxs(const FxSelection *)));
connect(m_schematicViewer, SIGNAL(doExplodeChild(QList<TStageObjectId>)),
this, SLOT(onExplodeChild(QList<TStageObjectId>)));
connect(m_schematicViewer,
SIGNAL(doDeleteStageObjects(const StageObjectSelection *)), this,
SLOT(onDeleteStageObjects(const StageObjectSelection *)));
connect(m_schematicViewer, SIGNAL(editObject()), this, SLOT(onEditObject()));
connect(app->getCurrentLevel(), SIGNAL(xshLevelChanged()), m_schematicViewer,
SLOT(updateScenes()));

View file

@ -30,6 +30,8 @@ class ComboViewerPanel;
class SceneViewerPanel;
class FxSettings;
class VectorGuidedDrawingPane;
class FxSelection;
class StageObjectSelection;
//=========================================================
// PaletteViewerPanel
@ -187,6 +189,8 @@ protected slots:
void onExplodeChild(const QList<TFxP> &);
void onExplodeChild(QList<TStageObjectId>);
void onEditObject();
void onDeleteFxs(const FxSelection *);
void onDeleteStageObjects(const StageObjectSelection *);
};
//=========================================================

View file

@ -1051,7 +1051,10 @@ static void removeEmptyColumns() {
if (!column || column->isEmpty()) indices.insert(i);
}
if (indices.size()) ColumnCmd::deleteColumns(indices, false, false);
if (indices.empty()) return;
if (!ColumnCmd::checkExpressionReferences(indices)) return;
ColumnCmd::deleteColumns(indices, false, false);
app->getCurrentXsheet()->notifyXsheetChanged();
}

View file

@ -160,6 +160,8 @@ set(HEADERS
../include/toonz/vectorizerparameters.h
../include/toutputproperties.h
../include/toonz/preferencesitemids.h
../include/toonz/txsheetcolumnchange.h
../include/toonz/expressionreferencemonitor.h
)
set(SOURCES

View file

@ -1947,7 +1947,7 @@ void DeleteLinksUndo::redo() const {
outputFx->getInputPort(index)->setFx(0);
}
m_xshHandle->notifyXsheetChanged();
if (m_isLastInRedoBlock) m_xshHandle->notifyXsheetChanged();
}
//------------------------------------------------------
@ -2012,7 +2012,7 @@ void DeleteLinksUndo::undo() const {
}
}
m_xshHandle->notifyXsheetChanged();
if (m_isLastInBlock) m_xshHandle->notifyXsheetChanged();
}
//------------------------------------------------------
@ -2051,6 +2051,7 @@ static void deleteLinks(const std::list<TFxCommand::Link> &links,
TXsheetHandle *xshHandle) {
std::unique_ptr<FxCommandUndo> undo(new DeleteLinksUndo(links, xshHandle));
if (undo->isConsistent()) {
undo->m_isLastInRedoBlock = false;
undo->redo();
TUndoManager::manager()->add(undo.release());
}
@ -2245,7 +2246,8 @@ void DeleteFxOrColumnUndo::redo() const {
// Perform operation
FxCommandUndo::removeFxOrColumn(xsh, m_fx.getPointer(), m_colIdx);
m_xshHandle->notifyXsheetChanged(); // Add the rest...
if (m_isLastInRedoBlock)
m_xshHandle->notifyXsheetChanged(); // Add the rest...
}
//-------------------------------------------------------------
@ -2296,7 +2298,7 @@ void DeleteFxOrColumnUndo::undo() const {
// Re-establish fx links
DeleteLinksUndo::undo();
} else // Already covered by DeleteLinksUndo::undo()
} else if (m_isLastInBlock) // Already covered by DeleteLinksUndo::undo()
m_xshHandle->notifyXsheetChanged(); // in the other branch
}
@ -2327,6 +2329,9 @@ static void deleteFxs(const std::list<TFxP> &fxs, TXsheetHandle *xshHandle,
std::unique_ptr<FxCommandUndo> undo(
new DeleteFxOrColumnUndo(*ft, xshHandle, fxHandle));
if (undo->isConsistent()) {
// prevent emiting xsheetChanged signal for every undos which will cause
// multiple triggers of preview rendering
undo->m_isLastInRedoBlock = false;
undo->redo();
TUndoManager::manager()->add(undo.release());
}
@ -2377,6 +2382,9 @@ static void deleteColumns(const std::list<int> &columns,
std::unique_ptr<FxCommandUndo> undo(
new DeleteFxOrColumnUndo(cols[c]->getIndex(), xshHandle, fxHandle));
if (undo->isConsistent()) {
// prevent emiting xsheetChanged signal for every undos which will cause
// multiple triggers of preview rendering
undo->m_isLastInRedoBlock = false;
undo->redo();
undoManager->add(undo.release());
}
@ -2395,8 +2403,7 @@ void TFxCommand::deleteSelection(const std::list<TFxP> &fxs,
TXsheetHandle *xshHandle,
TFxHandle *fxHandle) {
// Prepare selected fxs - column fxs would be done twice if the corresponding
// columns have
// been supplied for deletion too
// columns have been supplied for deletion too
::FilterColumnFxs filterColumnFxs;
std::list<TFxP> filteredFxs(fxs);
@ -2407,11 +2414,13 @@ void TFxCommand::deleteSelection(const std::list<TFxP> &fxs,
// Perform deletions
TUndoManager::manager()->beginBlock();
deleteColumns(columns, xshHandle, fxHandle);
deleteFxs(filteredFxs, xshHandle, fxHandle);
deleteLinks(links, xshHandle);
if (!columns.empty()) deleteColumns(columns, xshHandle, fxHandle);
if (!filteredFxs.empty()) deleteFxs(filteredFxs, xshHandle, fxHandle);
if (!links.empty()) deleteLinks(links, xshHandle);
TUndoManager::manager()->endBlock();
// emit xsheetChanged once here
xshHandle->notifyXsheetChanged();
}
//**********************************************************************

View file

@ -532,6 +532,8 @@ void Preferences::definePreferenceItems() {
// Animation
define(keyframeType, "keyframeType", QMetaType::Int, 2); // Linear
define(animationStep, "animationStep", QMetaType::Int, 1, 1, 500);
define(modifyExpressionOnMovingReferences,
"modifyExpressionOnMovingReferences", QMetaType::Bool, false);
// Preview
define(blanksCount, "blanksCount", QMetaType::Int, 0, 0, 1000);

View file

@ -215,16 +215,20 @@ void onPlasticDeformedImage(TStageObject *playerObj,
//**********************************************************************************************
Picker::Picker(const TAffine &viewAff, const TPointD &point,
const ImagePainter::VisualSettings &vs)
const ImagePainter::VisualSettings &vs, int devPixRatio)
: Visitor(vs)
, m_viewAff(viewAff)
, m_point(point)
, m_columnIndexes()
, m_minDist2(1.0e10) {}
, m_minDist2(25.0)
, m_devPixRatio(devPixRatio) {}
//-----------------------------------------------------------------------------
void Picker::setDistance(double d) { m_minDist2 = d * d; }
void Picker::setMinimumDistance(double d) {
m_minDist2 = (double)(m_devPixRatio * m_devPixRatio) * d * d;
}
//-----------------------------------------------------------------------------
@ -251,21 +255,12 @@ void Picker::onImage(const Stage::Player &player) {
if (styleId != 0)
picked = true;
else if (vi->getNearestStroke(point, w, strokeIndex, dist2)) {
// based on TTool::Viewer::doPickGuideStroke
// m_minDist2 seems to be the pixel size to the power 4, so take the
// square root of the square root.
// Use abs() just in case m_minDist2 is negative, to avoid math errors.
double pixelSize = sqrt(sqrt(abs(m_minDist2)));
double maxDist = 5 * pixelSize;
double maxDist2 = maxDist * maxDist;
double checkDist = maxDist2 * 4;
dist2 *= aff.det();
TStroke *stroke = vi->getStroke(strokeIndex);
TThickPoint thickPoint = stroke->getThickPoint(w);
double thickness = thickPoint.thick;
double len = thickness * pixelSize * sqrt(m_viewAff.det());
checkDist = std::max(checkDist, (len * len));
double len2 = thickPoint.thick * thickPoint.thick * aff.det();
double checkDist = std::max(m_minDist2, len2);
if (dist2 < checkDist) picked = true;
}
} else if (TRasterImageP ri = img) {

View file

@ -406,7 +406,7 @@ public:
TXsheet *xsh = xshHandle->getXsheet();
TStageObject *obj = xsh->getStageObject(id);
assert(obj);
m_params = obj->getParams();
m_params = obj->getParams();
if (id.isColumn()) m_column = xsh->getColumn(id.getIndex());
}
@ -432,6 +432,7 @@ public:
linkedObj->setParent(m_objId);
}
m_xshHandle->notifyXsheetChanged();
xsh->notifyStageObjectAdded(m_objId);
}
void redo() const override {
@ -518,6 +519,7 @@ public:
terminalFxs->removeFx(m_notTerminalColumns[i]);
m_xshHandle->notifyXsheetChanged();
xsh->notifyFxAdded(m_deletedFx);
}
void redo() const override {
@ -1192,9 +1194,8 @@ public:
m_xshHandle->notifyXsheetChanged();
}
int getSize() const override {
return sizeof(*this) +
sizeof(TDoubleKeyframe) *
(m_xKeyframes.size() + m_yKeyframes.size());
return sizeof(*this) + sizeof(TDoubleKeyframe) *
(m_xKeyframes.size() + m_yKeyframes.size());
}
};
@ -1456,7 +1457,7 @@ TStageObjectSpline *TStageObjectCmd::addNewSpline(TXsheetHandle *xshHandle,
TStageObjectId objId = objHandle->getObjectId();
if (objId == TStageObjectId::NoneId) {
int col = colHandle->getColumnIndex();
int col = colHandle->getColumnIndex();
if (col >= 0) objId = TStageObjectId::ColumnId(col);
}
if (objId != TStageObjectId::NoneId) {
@ -1602,7 +1603,7 @@ void TStageObjectCmd::renameGroup(const QList<TStageObject *> objs,
int i;
for (i = 0; i < objs.size(); i++) {
if (i == 0) oldName = objs[i]->getGroupName(fromEditor);
int position = objs[i]->removeGroupName(fromEditor);
int position = objs[i]->removeGroupName(fromEditor);
objs[i]->setGroupName(name, position);
positions.push_back(position);
}

View file

@ -32,10 +32,14 @@
#include "toonz/textureutils.h"
#include "xshhandlemanager.h"
#include "orientation.h"
#include "toonz/expressionreferencemonitor.h"
#include "toonz/txsheet.h"
#include "toonz/preferences.h"
// STD includes
#include <set>
using namespace std;
DEFINE_CLASS_CODE(TXsheet, 18)
@ -98,6 +102,8 @@ struct TXsheet::TXsheetImp {
XshHandleManager *m_handleManager;
ToonzScene *m_scene;
ExpressionReferenceMonitor *m_expRefMonitor;
public:
TXsheetImp();
~TXsheetImp();
@ -150,7 +156,8 @@ TXsheet::TXsheetImp::TXsheetImp()
, m_soloColumn(-1)
, m_viewColumn(-1)
, m_mixedSound(0)
, m_scene(0) {
, m_scene(0)
, m_expRefMonitor(new ExpressionReferenceMonitor()) {
initColumnFans();
}
@ -189,7 +196,8 @@ TXsheet::TXsheet()
, m_player(0)
, m_imp(new TXsheet::TXsheetImp)
, m_notes(new TXshNoteSet())
, m_cameraColumnIndex(0) {
, m_cameraColumnIndex(0)
, m_observer(nullptr) {
// extern TSyntax::Grammar *createXsheetGrammar(TXsheet*);
m_soundProperties = new TXsheet::SoundProperties();
m_imp->m_handleManager = new XshHandleManager(this);
@ -1326,6 +1334,8 @@ void TXsheet::insertColumn(int col, TXshColumn *column) {
columnFan.rollRightFoldedState(col,
m_imp->m_columnSet.getColumnCount() - col);
}
notify(TXsheetColumnChange(TXsheetColumnChange::Insert, col));
}
//-----------------------------------------------------------------------------
@ -1349,6 +1359,8 @@ void TXsheet::removeColumn(int col) {
columnFan.rollLeftFoldedState(col,
m_imp->m_columnSet.getColumnCount() - col);
}
notify(TXsheetColumnChange(TXsheetColumnChange::Remove, col));
}
//-----------------------------------------------------------------------------
@ -1388,6 +1400,8 @@ void TXsheet::moveColumn(int srcIndex, int dstIndex) {
columnFan.rollRightFoldedState(c0, c1 - c0 + 1);
for (int c = c1 - 1; c >= c0; --c) m_imp->m_pegTree->swapColumns(c, c + 1);
}
notify(TXsheetColumnChange(TXsheetColumnChange::Move, srcIndex, dstIndex));
}
//-----------------------------------------------------------------------------
@ -1792,3 +1806,29 @@ void TXsheet::autoInputCellNumbers(int increment, int interval, int step,
}
}
}
//---------------------------------------------------------
void TXsheet::setObserver(TXsheetColumnChangeObserver *observer) {
m_observer = observer;
}
//---------------------------------------------------------
void TXsheet::notify(const TXsheetColumnChange &change) {
if (m_observer) m_observer->onChange(change);
}
void TXsheet::notifyFxAdded(const std::vector<TFx *> &fxs) {
if (m_observer) m_observer->onFxAdded(fxs);
}
void TXsheet::notifyStageObjectAdded(const TStageObjectId id) {
if (m_observer) m_observer->onStageObjectAdded(id);
}
bool TXsheet::isReferenceManagementIgnored(TDoubleParam *param) {
if (m_observer) return m_observer->isIgnored(param);
return false;
}
ExpressionReferenceMonitor *TXsheet::getExpRefMonitor() const {
return m_imp->m_expRefMonitor;
}
//---------------------------------------------------------

View file

@ -10,6 +10,8 @@
#include "texpression.h"
#include "tparser.h"
#include "tfx.h"
#include "tzeraryfx.h"
#include "tcolumnset.h"
#include "tw/stringtable.h"
#include "tunit.h"
@ -20,6 +22,9 @@
#include "toonz/tstageobjectid.h"
#include "toonz/tstageobject.h"
#include "toonz/fxdag.h"
#include "toonz/tstageobjecttree.h"
#include "toonz/tcolumnfxset.h"
#include "toonz/tcolumnfx.h"
// Boost includes
#include "boost/noncopyable.hpp"
@ -56,18 +61,51 @@ public:
bool found() const { return m_found; }
};
//===================================================================
/*
class ColumnReferenceFinder final : public TSyntax::CalculatorNodeVisitor {
QSet<int> m_indices;
public:
ColumnReferenceFinder() {}
void registerColumnIndex(int columnIndex) { m_indices.insert(columnIndex); }
QSet<int> indices() const { return m_indices; }
};
*/
//===================================================================
class ParamReferenceFinder final : public TSyntax::CalculatorNodeVisitor {
QSet<TDoubleParam *> m_refParams;
QSet<int> m_columnIndices;
public:
ParamReferenceFinder() {}
void registerRefParam(TDoubleParam *param) { m_refParams.insert(param); }
void registerColumnIndex(int columnIndex) {
m_columnIndices.insert(columnIndex);
}
QSet<int> columnIndices() const { return m_columnIndices; }
QSet<TDoubleParam *> refParams() const { return m_refParams; }
};
//===================================================================
//
// Calculator Nodes
//
//-------------------------------------------------------------------
class ParamCalculatorNode final : public CalculatorNode,
public TParamObserver,
public boost::noncopyable {
TDoubleParamP m_param;
class ParamCalculatorNode : public CalculatorNode,
public TParamObserver,
public boost::noncopyable {
std::unique_ptr<CalculatorNode> m_frame;
protected:
TDoubleParamP m_param;
public:
ParamCalculatorNode(Calculator *calculator, const TDoubleParamP &param,
std::unique_ptr<CalculatorNode> frame)
@ -88,10 +126,18 @@ public:
}
void accept(TSyntax::CalculatorNodeVisitor &visitor) override {
ParamReferenceFinder *prf = dynamic_cast<ParamReferenceFinder *>(&visitor);
if (prf) {
prf->registerRefParam(m_param.getPointer());
return;
}
ParamDependencyFinder *pdf =
dynamic_cast<ParamDependencyFinder *>(&visitor);
pdf->check(m_param.getPointer());
m_param->accept(visitor);
if (pdf) {
pdf->check(m_param.getPointer());
if (!pdf->found()) m_param->accept(visitor);
}
}
void onChange(const TParamChange &paramChange) override {
@ -113,6 +159,36 @@ public:
(*ot)->onChange(propagatedChange);
}
}
bool hasReference() const override { return true; }
};
// ParamCalculatorNode subclass to monitor referenced columns
class ColumnParamCalculatorNode final : public ParamCalculatorNode {
int m_columnIndex;
public:
ColumnParamCalculatorNode(Calculator *calculator, const TDoubleParamP &param,
std::unique_ptr<CalculatorNode> frame,
int columnIndex)
: ParamCalculatorNode(calculator, param, std::move(frame))
, m_columnIndex(columnIndex) {}
void accept(TSyntax::CalculatorNodeVisitor &visitor) override {
ParamReferenceFinder *prf = dynamic_cast<ParamReferenceFinder *>(&visitor);
if (prf) {
prf->registerRefParam(m_param.getPointer());
prf->registerColumnIndex(m_columnIndex);
return;
}
ParamDependencyFinder *pdf =
dynamic_cast<ParamDependencyFinder *>(&visitor);
if (pdf) {
pdf->check(m_param.getPointer());
if (!pdf->found()) m_param->accept(visitor);
}
}
};
//-------------------------------------------------------------------
@ -145,7 +221,12 @@ public:
return d;
}
void accept(TSyntax::CalculatorNodeVisitor &) override {}
void accept(TSyntax::CalculatorNodeVisitor &visitor) override {
ParamReferenceFinder *prf = dynamic_cast<ParamReferenceFinder *>(&visitor);
if (prf) prf->registerColumnIndex(m_columnIndex);
}
bool hasReference() const override { return true; }
};
//===================================================================
@ -191,6 +272,15 @@ public:
return TStageObjectId::NoneId;
}
TStageObjectId matchExistingObjectName(const Token &token) const {
TStageObjectId objId = matchObjectName(token);
if (objId != TStageObjectId::NoneId &&
m_xsh->getStageObjectTree()->getStageObject(objId, false))
return objId;
else
return TStageObjectId::NoneId;
}
TStageObject::Channel matchChannelName(const Token &token) const {
std::string s = toLower(token.getText());
if (s == "ns" || s == "y")
@ -227,7 +317,7 @@ public:
const Token &token) const override {
int i = (int)previousTokens.size();
if (i == 0)
return matchObjectName(token) != TStageObjectId::NoneId;
return matchExistingObjectName(token) != TStageObjectId::NoneId;
else if ((i == 1 && token.getText() == ".") ||
(i == 3 && token.getText() == "(") ||
(i == 5 && token.getText() == ")"))
@ -237,7 +327,7 @@ public:
return true;
else
return token.getText() == "cell" &&
matchObjectName(previousTokens[0]).isColumn();
matchExistingObjectName(previousTokens[0]).isColumn();
} else
return false;
}
@ -276,12 +366,20 @@ public:
stack.push_back(new XsheetDrawingCalculatorNode(calc, m_xsh, columnIndex,
std::move(frameNode)));
} else {
TStageObject *object = m_xsh->getStageObject(objectId);
// do not create object if it does not exist
TStageObject *object =
m_xsh->getStageObjectTree()->getStageObject(objectId, false);
if (!object) return;
TStageObject::Channel channelName = matchChannelName(tokens[2]);
TDoubleParam *channel = object->getParam(channelName);
if (channel)
stack.push_back(
new ParamCalculatorNode(calc, channel, std::move(frameNode)));
if (channel) {
if (objectId.isColumn())
stack.push_back(new ColumnParamCalculatorNode(
calc, channel, std::move(frameNode), objectId.getIndex()));
else
stack.push_back(
new ParamCalculatorNode(calc, channel, std::move(frameNode)));
}
}
}
};
@ -295,7 +393,20 @@ public:
FxReferencePattern(TXsheet *xsh) : m_xsh(xsh) {}
TFx *getFx(const Token &token) const {
return m_xsh->getFxDag()->getFxById(::to_wstring(toLower(token.getText())));
TFx *fx =
m_xsh->getFxDag()->getFxById(::to_wstring(toLower(token.getText())));
// removed fx cannot be referenced
if (!fx)
return nullptr;
else if (fx->isZerary()) {
TZeraryFx *zFx = dynamic_cast<TZeraryFx *>(fx);
// For now we cannot use zFx->getColumnFx()->getColumnIndex() < 0 to check
// existence of the column. See a comment in tcolumnset.h for details.
if (!zFx || !zFx->getColumnFx()->getXshColumn()->inColumnsSet())
return nullptr;
} else if (!m_xsh->getFxDag()->getInternalFxs()->containsFx(fx))
return nullptr;
return fx;
}
TParam *getParam(const TFx *fx, const Token &token) const {
int i;
@ -607,3 +718,11 @@ bool dependsOn(TDoubleParam *param, TDoubleParam *possiblyDependentParam) {
param->accept(pdf);
return pdf.found();
}
void referenceParams(TExpression &expr, QSet<int> &columnIndices,
QSet<TDoubleParam *> &params) {
ParamReferenceFinder prf;
expr.accept(prf);
columnIndices = prf.columnIndices();
params = prf.refParams();
}

View file

@ -0,0 +1,82 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Generator: Adobe Illustrator 21.0.2, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg
xmlns:osb="http://www.openswatchbook.org/uri/2009/osb"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
version="1.1"
id="svg2"
inkscape:version="0.92.1 r15371"
sodipodi:docname="paramignored_off.svg"
x="0px"
y="0px"
viewBox="0 0 21 17"
style="enable-background:new 0 0 21 17;"
xml:space="preserve"><metadata
id="metadata13"><rdf:RDF><cc:Work
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
id="defs11"><linearGradient
id="linearGradient4558"
osb:paint="solid"><stop
style="stop-color:#4b4b4b;stop-opacity:1;"
offset="0"
id="stop4556" /></linearGradient></defs><style
type="text/css"
id="style2">
.st0{fill:none;}
.st1{fill:none;stroke:#6F6C50;stroke-width:2;stroke-linecap:square;stroke-miterlimit:1.5;}
.st2{fill:#FFF082;}
.st3{stroke:#000000;stroke-width:0.5;stroke-linejoin:round;stroke-miterlimit:1.4142;}
</style><sodipodi:namedview
bordercolor="#666666"
borderopacity="1"
gridtolerance="10"
guidetolerance="10"
id="namedview15"
inkscape:current-layer="svg2"
inkscape:cx="26.553329"
inkscape:cy="7.6715202"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-height="851"
inkscape:window-maximized="0"
inkscape:window-width="1440"
inkscape:window-x="126"
inkscape:window-y="54"
inkscape:zoom="11.313709"
objecttolerance="10"
pagecolor="#ffffff"
showgrid="true"><inkscape:grid
type="xygrid"
id="grid4490" /></sodipodi:namedview><rect
id="rect5"
y="0"
class="st0"
width="21"
height="17" /><path
style="opacity:1;vector-effect:none;fill:#faafb5;fill-opacity:1;stroke-width:0.02723992;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
d="m 16.178576,13 c -0.08036,0.139006 -0.230014,0.225165 -0.390893,0.225165 H 5.2121385 c -0.1604971,0 -0.310371,-0.08616 -0.3903208,-0.225574 -0.080742,-0.139196 -0.081149,-0.311761 -3.808e-4,-0.450766 L 10.109304,3.3896748 c 0.08017,-0.139005 0.229796,-0.2253832 0.390893,-0.2253832 0.160716,0 0.310154,0.086374 0.390511,0.225602 l 5.287868,9.1587684 c 0.08036,0.139168 0.08036,0.312142 0,0.451338 z"
id="path6-3"
inkscape:connector-curvature="0" /><path
id="path4"
style="fill:#606060;stroke-width:0.02539061;fill-opacity:1"
d="m 10.50018,10.762063 c -0.426156,0 -0.7721536,0.345642 -0.7721536,0.771798 0,0.426334 0.3459976,0.772001 0.7721536,0.772001 0.426156,0 0.771799,-0.345667 0.771799,-0.772001 2.5e-5,-0.426156 -0.345617,-0.771798 -0.771799,-0.771798 z"
class="st0"
inkscape:connector-curvature="0" /><path
id="path6"
style="fill:#606060;stroke-width:0.02539061;font-variant-east_asian:normal;opacity:1;vector-effect:none;fill-opacity:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
d="M 16.824727,12.031745 11.636715,3.0457546 C 11.403045,2.6409267 10.96752,2.3894835 10.499799,2.3894835 c -0.467365,0 -0.9024835,0.2514686 -1.1361533,0.6562711 L 4.1752523,12.031364 c -0.2336698,0.404803 -0.2336698,0.90774 0,1.312543 C 4.4089475,13.748709 4.8444472,14 5.3118122,14 H 15.688193 c 0.467339,0 0.902864,-0.251291 1.136534,-0.656093 0.233695,-0.404803 0.233695,-0.90774 0,-1.312162 z m -1.031671,0.642027 c -0.0749,0.129569 -0.214398,0.209879 -0.364355,0.209879 H 5.5711265 c -0.1496015,0 -0.2893006,-0.08031 -0.3638221,-0.21026 -0.075258,-0.129746 -0.075639,-0.290595 -3.555e-4,-0.420163 L 10.135825,3.7158889 C 10.21055,3.5863207 10.35002,3.505807 10.50018,3.505807 c 0.149805,0 0.289098,0.080514 0.364,0.2102851 l 4.928876,8.5369829 c 0.0749,0.129721 0.0749,0.290951 0,0.420697 z"
class="st0"
inkscape:connector-curvature="0" /><path
id="path8"
style="fill:#606060;stroke-width:0.02539061;fill-opacity:1"
d="m 10.50018,5.5723742 c -0.426156,0 -0.7721536,0.3456423 -0.7721536,0.7720015 l 0.2965626,3.4908788 c 0,0.2626915 0.212722,0.4754135 0.475591,0.4754135 0.262488,0 0.475592,-0.212722 0.475592,-0.4754135 L 11.271979,6.3443757 C 11.272004,5.9179912 10.926362,5.5723742 10.50018,5.5723742 Z"
class="st0"
inkscape:connector-curvature="0" /></svg>

After

Width:  |  Height:  |  Size: 4.8 KiB

View file

@ -0,0 +1,82 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Generator: Adobe Illustrator 21.0.2, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg
xmlns:osb="http://www.openswatchbook.org/uri/2009/osb"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
version="1.1"
id="svg2"
inkscape:version="0.92.1 r15371"
sodipodi:docname="paramignored_on.svg"
x="0px"
y="0px"
viewBox="0 0 21 17"
style="enable-background:new 0 0 21 17;"
xml:space="preserve"><metadata
id="metadata13"><rdf:RDF><cc:Work
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
id="defs11"><linearGradient
id="linearGradient4558"
osb:paint="solid"><stop
style="stop-color:#4b4b4b;stop-opacity:1;"
offset="0"
id="stop4556" /></linearGradient></defs><style
type="text/css"
id="style2">
.st0{fill:none;}
.st1{fill:none;stroke:#6F6C50;stroke-width:2;stroke-linecap:square;stroke-miterlimit:1.5;}
.st2{fill:#FFF082;}
.st3{stroke:#000000;stroke-width:0.5;stroke-linejoin:round;stroke-miterlimit:1.4142;}
</style><sodipodi:namedview
bordercolor="#666666"
borderopacity="1"
gridtolerance="10"
guidetolerance="10"
id="namedview15"
inkscape:current-layer="svg2"
inkscape:cx="26.553329"
inkscape:cy="7.6715202"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-height="851"
inkscape:window-maximized="0"
inkscape:window-width="1440"
inkscape:window-x="126"
inkscape:window-y="54"
inkscape:zoom="11.313709"
objecttolerance="10"
pagecolor="#ffffff"
showgrid="true"><inkscape:grid
type="xygrid"
id="grid4490" /></sodipodi:namedview><rect
id="rect5"
y="0"
class="st0"
width="21"
height="17" /><path
style="opacity:1;vector-effect:none;fill:#fc5b68;fill-opacity:1;stroke-width:0.02723992;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
d="m 16.178576,13 c -0.08036,0.139006 -0.230014,0.225165 -0.390893,0.225165 H 5.2121385 c -0.1604971,0 -0.310371,-0.08616 -0.3903208,-0.225574 -0.080742,-0.139196 -0.081149,-0.311761 -3.808e-4,-0.450766 L 10.109304,3.3896748 c 0.08017,-0.139005 0.229796,-0.2253832 0.390893,-0.2253832 0.160716,0 0.310154,0.086374 0.390511,0.225602 l 5.287868,9.1587684 c 0.08036,0.139168 0.08036,0.312142 0,0.451338 z"
id="path6-3"
inkscape:connector-curvature="0" /><path
id="path4"
style="fill:#000000;stroke-width:0.02539061;fill-opacity:1"
d="m 10.50018,10.762063 c -0.426156,0 -0.7721536,0.345642 -0.7721536,0.771798 0,0.426334 0.3459976,0.772001 0.7721536,0.772001 0.426156,0 0.771799,-0.345667 0.771799,-0.772001 2.5e-5,-0.426156 -0.345617,-0.771798 -0.771799,-0.771798 z"
class="st0"
inkscape:connector-curvature="0" /><path
id="path6"
style="fill:#89363f;stroke-width:0.02539061;font-variant-east_asian:normal;opacity:1;vector-effect:none;fill-opacity:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
d="M 16.824727,12.031745 11.636715,3.0457546 C 11.403045,2.6409267 10.96752,2.3894835 10.499799,2.3894835 c -0.467365,0 -0.9024835,0.2514686 -1.1361533,0.6562711 L 4.1752523,12.031364 c -0.2336698,0.404803 -0.2336698,0.90774 0,1.312543 C 4.4089475,13.748709 4.8444472,14 5.3118122,14 H 15.688193 c 0.467339,0 0.902864,-0.251291 1.136534,-0.656093 0.233695,-0.404803 0.233695,-0.90774 0,-1.312162 z m -1.031671,0.642027 c -0.0749,0.129569 -0.214398,0.209879 -0.364355,0.209879 H 5.5711265 c -0.1496015,0 -0.2893006,-0.08031 -0.3638221,-0.21026 -0.075258,-0.129746 -0.075639,-0.290595 -3.555e-4,-0.420163 L 10.135825,3.7158889 C 10.21055,3.5863207 10.35002,3.505807 10.50018,3.505807 c 0.149805,0 0.289098,0.080514 0.364,0.2102851 l 4.928876,8.5369829 c 0.0749,0.129721 0.0749,0.290951 0,0.420697 z"
class="st0"
inkscape:connector-curvature="0" /><path
id="path8"
style="fill:#000000;stroke-width:0.02539061;fill-opacity:1"
d="m 10.50018,5.5723742 c -0.426156,0 -0.7721536,0.3456423 -0.7721536,0.7720015 l 0.2965626,3.4908788 c 0,0.2626915 0.212722,0.4754135 0.475591,0.4754135 0.262488,0 0.475592,-0.212722 0.475592,-0.4754135 L 11.271979,6.3443757 C 11.272004,5.9179912 10.926362,5.5723742 10.50018,5.5723742 Z"
class="st0"
inkscape:connector-curvature="0" /></svg>

After

Width:  |  Height:  |  Size: 4.8 KiB

View file

@ -591,9 +591,14 @@ void CameraSettingsWidget::setFields(const TCamera *camera) {
updatePresetListOm();
}
void CameraSettingsWidget::getFields(TCamera *camera) {
bool CameraSettingsWidget::getFields(TCamera *camera) {
TDimensionD old_sz = camera->getSize();
TDimension old_res = camera->getRes();
if (old_sz == getSize() && old_res == getRes()) return false;
camera->setSize(getSize());
camera->setRes(getRes());
return true;
}
TDimensionD CameraSettingsWidget::getSize() const {
@ -954,8 +959,8 @@ double CameraSettingsWidget::aspectRatioStringToValue(const QString &s) {
}
int i = s.indexOf("/");
if (i <= 0 || i + 1 >= s.length()) return s.toDouble();
int num = s.left(i).toInt();
int den = s.mid(i + 1).toInt();
int num = s.left(i).toInt();
int den = s.mid(i + 1).toInt();
if (den <= 0) den = 1;
return (double)num / (double)den;
}

View file

@ -12,6 +12,8 @@
#include "toonz/preferences.h"
#include "toonz/toonzfolders.h"
#include "toonz/tstageobject.h"
#include "toonz/txsheethandle.h"
#include "toonz/txsheet.h"
// TnzBase includes
#include "tunit.h"
@ -360,6 +362,14 @@ void FunctionSheetColumnHeadViewer::paintEvent(QPaintEvent *e) {
Qt::TextWrapAnywhere | Qt::AlignLeft | Qt::AlignVCenter,
text);
// warning of losing expression reference
TXsheet *xsh = m_sheet->getViewer()->getXsheetHandle()->getXsheet();
if (xsh->isReferenceManagementIgnored(channel->getParam())) {
static QIcon paramIgnoredIcon(":Resources/paramignored_on.svg");
painter.drawPixmap(QPoint(x0 + 30, y1 + 20),
paramIgnoredIcon.pixmap(21, 17));
}
// group name
if (firstGroupColumn) {
int tmpwidth = (lastGroupColumn) ? width : width * 2;
@ -389,13 +399,23 @@ void FunctionSheetColumnHeadViewer::mouseMoveEvent(QMouseEvent *e) {
Qt::DropAction dropAction = drag->exec();
return;
}
// get the column under the cursor
int col = getViewer()->xyToPosition(e->pos()).layer();
FunctionTreeModel::Channel *channel = m_sheet->getChannel(col);
if (!channel) {
setToolTip(QString(""));
} else
setToolTip(channel->getExprRefName());
} else {
QString tooltip = channel->getExprRefName();
TXsheet *xsh = m_sheet->getViewer()->getXsheetHandle()->getXsheet();
if (xsh->isReferenceManagementIgnored(channel->getParam()))
tooltip +=
"\n" + tr("Some key(s) in this parameter loses original reference in "
"expression.\nManually changing any keyframe will clear "
"the warning.");
setToolTip(tooltip);
}
// modify selected channel by left dragging
if (m_clickedColumn >= 0 && channel && e->buttons() & Qt::LeftButton) {
@ -616,16 +636,25 @@ void FunctionSheetCellViewer::drawCells(QPainter &painter, int r0, int c0,
QColor KeyFrameColor = getViewer()->getKeyFrameColor();
QColor KeyFrameBorderColor = getViewer()->getKeyFrameBorderColor();
QColor SelectedKeyFrameColor = getViewer()->getSelectedKeyFrameColor();
QColor IgnoredKeyFrameColor = getViewer()->getIgnoredKeyFrameColor();
QColor SelectedIgnoredKeyFrameColor =
getViewer()->getSelectedIgnoredKeyFrameColor();
// inbetween
QColor InBetweenColor = getViewer()->getInBetweenColor();
QColor InBetweenBorderColor = getViewer()->getInBetweenBorderColor();
QColor SelectedInBetweenColor = getViewer()->getSelectedInBetweenColor();
QColor IgnoredInBetweenColor = getViewer()->getIgnoredInBetweenColor();
QColor SelectedIgnoredInBetweenColor =
getViewer()->getSelectedIgnoredInBetweenColor();
// empty cells
QColor SelectedEmptyColor = getViewer()->getSelectedEmptyColor();
// empty cells in scene frame range
QColor SelectedSceneRangeEmptyColor =
getViewer()->getSelectedSceneRangeEmptyColor();
TXsheet *xsh = m_sheet->getViewer()->getXsheetHandle()->getXsheet();
// top and bottom pos
int y0 = getViewer()->rowToY(r0);
int y1 = getViewer()->rowToY(r1 + 1) - 1;
@ -656,6 +685,8 @@ void FunctionSheetCellViewer::drawCells(QPainter &painter, int r0, int c0,
bool isParamCycled = curve->isCycleEnabled();
int rowCount = getViewer()->getRowCount();
bool isRefMngIgnored = xsh->isReferenceManagementIgnored(curve);
// draw each cell
for (int row = r0; row <= r1; row++) {
int ya = m_sheet->rowToY(row);
@ -676,10 +707,18 @@ void FunctionSheetCellViewer::drawCells(QPainter &painter, int r0, int c0,
/*--- キーフレーム間の範囲だけ色をつける ---*/
if (kr0 <= row && row <= kr1) {
if (curve->isKeyframe(row)) {
cellColor = (isSelected) ? SelectedKeyFrameColor : KeyFrameColor;
cellColor =
(isRefMngIgnored)
? ((isSelected) ? SelectedIgnoredKeyFrameColor
: IgnoredKeyFrameColor)
: ((isSelected) ? SelectedKeyFrameColor : KeyFrameColor);
borderColor = KeyFrameBorderColor;
} else {
cellColor = (isSelected) ? SelectedInBetweenColor : InBetweenColor;
cellColor =
(isRefMngIgnored)
? ((isSelected) ? SelectedIgnoredInBetweenColor
: IgnoredInBetweenColor)
: ((isSelected) ? SelectedInBetweenColor : InBetweenColor);
borderColor = InBetweenBorderColor;
// when the inbetween values are hidden, change the cell colors to

View file

@ -132,29 +132,45 @@ bool FunctionTreeModel::ChannelGroup::isAnimated() const {
//-----------------------------------------------------------------------------
bool FunctionTreeModel::ChannelGroup::isIgnored() const {
// Same for the ignored ones, show warning icon if any of its children is.
int c, childCount = getChildCount();
for (c = 0; c != childCount; ++c)
if (static_cast<Item *>(getChild(c))->isIgnored()) return true;
return false;
}
//-----------------------------------------------------------------------------
QVariant FunctionTreeModel::ChannelGroup::data(int role) const {
if (role == Qt::DisplayRole)
return getLongName();
else if (role == Qt::DecorationRole) {
bool animated = isAnimated();
bool active = isActive();
bool ignored = (animated) ? isIgnored() : false;
if (active) {
static QIcon folderAnimOpen(createQIcon("folder_anim_on", true));
static QIcon folderAnimClose(createQIcon("folder_anim", true));
static QIcon folderOpen(createQIcon("folder_on", true));
static QIcon folderClose(createQIcon("folder", true));
static QIcon ignoredOn(":Resources/paramignored_on.svg");
return animated ? isOpen() ? folderAnimOpen : folderAnimClose
: isOpen() ? folderOpen : folderClose;
return animated ? (isOpen() ? folderAnimOpen
: (ignored ? ignoredOn : folderAnimClose))
: (isOpen() ? folderOpen : folderClose);
} else {
static QIcon folderAnimOpen(createQIcon("folder_anim_inactive_on", true));
static QIcon folderAnimClose(createQIcon("folder_anim_inactive", true));
static QIcon folderOpen(createQIcon("folder_inactive_on", true));
static QIcon folderClose(createQIcon("folder_inactive", true));
static QIcon ignoredOff(":Resources/paramignored_off.svg");
return animated ? isOpen() ? folderAnimOpen : folderAnimClose
: isOpen() ? folderOpen : folderClose;
return animated ? (isOpen() ? folderAnimOpen
: (ignored ? ignoredOff : folderAnimClose))
: (isOpen() ? folderOpen : folderClose);
}
} else
return Item::data(role);
@ -352,22 +368,27 @@ QVariant FxChannelGroup::data(int role) const {
isOneChildActive = true;
break;
}
bool ignored = (isAnimated) ? isIgnored() : false;
if (isOneChildActive) {
static QIcon folderAnimOpen(createQIcon("folder_anim_on", true));
static QIcon folderAnimClose(createQIcon("folder_anim", true));
static QIcon folderOpen(createQIcon("folder_on", true));
static QIcon folderClose(createQIcon("folder", true));
static QIcon ignoredOn(":Resources/paramignored_on.svg");
return isAnimated ? isOpen() ? folderAnimOpen : folderAnimClose
: isOpen() ? folderOpen : folderClose;
return isAnimated ? (isOpen() ? folderAnimOpen
: (ignored ? ignoredOn : folderAnimClose))
: (isOpen() ? folderOpen : folderClose);
} else {
static QIcon folderAnimOpen(createQIcon("folder_anim_inactive_on", true));
static QIcon folderAnimClose(createQIcon("folder_anim_inactive", true));
static QIcon folderOpen(createQIcon("folder_inactive_on", true));
static QIcon folderClose(createQIcon("folder_inactive", true));
static QIcon ignoredOff(":Resources/paramignored_off.svg");
return isAnimated ? isOpen() ? folderAnimOpen : folderAnimClose
: isOpen() ? folderOpen : folderClose;
return isAnimated ? (isOpen() ? folderAnimOpen
: (ignored ? ignoredOff : folderAnimClose))
: (isOpen() ? folderOpen : folderClose);
}
} else if (role == Qt::DisplayRole) {
std::wstring name = m_fx->getName();
@ -561,8 +582,24 @@ bool FunctionTreeModel::Channel::isAnimated() const {
//-----------------------------------------------------------------------------
bool FunctionTreeModel::Channel::isIgnored() const {
if (!isAnimated()) return false;
TDoubleParam *dp = dynamic_cast<TDoubleParam *>(m_param.getPointer());
if (!dp) return false;
FunctionTreeView *view = dynamic_cast<FunctionTreeView *>(m_model->m_view);
if (!view) return false;
return view->getXsheetHandle()->getXsheet()->isReferenceManagementIgnored(dp);
}
//-----------------------------------------------------------------------------
QVariant FunctionTreeModel::Channel::data(int role) const {
if (role == Qt::DecorationRole) {
static QIcon paramIgnoredOn(":Resources/paramignored_on.svg");
static QIcon paramIgnoredOff(":Resources/paramignored_off.svg");
if (isIgnored()) return isActive() ? paramIgnoredOn : paramIgnoredOff;
QPixmap pixmap(10, 10);
QColor color;
QString name = getShortName();
@ -620,6 +657,20 @@ QVariant FunctionTreeModel::Channel::data(int role) const {
#endif
return (isCurrent()) ? view->getViewer()->getCurrentTextColor()
: view->getTextColor();
} else if (role == Qt::ToolTipRole) {
if (m_param->hasKeyframes()) {
TDoubleParam *dp = dynamic_cast<TDoubleParam *>(m_param.getPointer());
FunctionTreeView *view =
dynamic_cast<FunctionTreeView *>(m_model->m_view);
if (dp && view &&
view->getXsheetHandle()->getXsheet()->isReferenceManagementIgnored(
dp))
return tr(
"Some key(s) in this parameter loses original reference in "
"expression.\nManually changing any keyframe will clear the "
"warning.");
}
return TreeModel::Item::data(role);
} else
return TreeModel::Item::data(role);
}
@ -638,7 +689,7 @@ QString FunctionTreeModel::Channel::getShortName() const {
//-----------------------------------------------------------------------------
QString FunctionTreeModel::Channel::getLongName() const {
QString name = getShortName();
QString name = getShortName();
if (getChannelGroup()) name = getChannelGroup()->getLongName() + " " + name;
return name;
}
@ -1117,7 +1168,7 @@ void FunctionTreeModel::addChannels(TFx *fx, ChannelGroup *groupItem,
std::wstring fxId = L"";
TMacroFx *macro = dynamic_cast<TMacroFx *>(fxItem->getFx());
if (macro) fxId = fx->getFxId();
if (macro) fxId = fx->getFxId();
const std::string &paramNamePref = fx->getFxType() + ".";
@ -1263,7 +1314,7 @@ void FunctionTreeModel::resetAll() {
void FunctionTreeModel::setCurrentFx(TFx *fx) {
TZeraryColumnFx *zcfx = dynamic_cast<TZeraryColumnFx *>(fx);
if (zcfx) fx = zcfx->getZeraryFx();
if (zcfx) fx = zcfx->getZeraryFx();
if (fx != m_currentFx) {
if (fx) fx->addRef();
if (m_currentFx) m_currentFx->release();

View file

@ -171,11 +171,11 @@ FunctionViewer::FunctionViewer(QWidget *parent, Qt::WFlags flags)
bool ret = true;
ret = ret && connect(m_toolbar, SIGNAL(numericalColumnToggled()), this,
SLOT(toggleMode()));
ret = ret && connect(ftModel, SIGNAL(activeChannelsChanged()),
ret = ret && connect(ftModel, SIGNAL(activeChannelsChanged()),
m_functionGraph, SLOT(update()));
ret = ret && connect(ftModel, SIGNAL(activeChannelsChanged()),
ret = ret && connect(ftModel, SIGNAL(activeChannelsChanged()),
m_numericalColumns, SLOT(updateAll()));
ret = ret && connect(ftModel, SIGNAL(curveChanged(bool)), m_treeView,
ret = ret && connect(ftModel, SIGNAL(curveChanged(bool)), m_treeView,
SLOT(update()));
ret = ret && connect(ftModel, SIGNAL(curveChanged(bool)), m_functionGraph,
SLOT(update()));
@ -388,6 +388,7 @@ void FunctionViewer::setXsheetHandle(TXsheetHandle *xshHandle) {
m_xshHandle = xshHandle;
m_segmentViewer->setXsheetHandle(xshHandle);
m_treeView->setXsheetHandle(xshHandle);
if (m_xshHandle && isVisible()) {
TXsheet *xsh = m_xshHandle->getXsheet();
@ -610,7 +611,7 @@ void FunctionViewer::onStageObjectChanged(bool isDragging) {
void FunctionViewer::onFxSwitched() {
TFx *fx = m_fxHandle->getFx();
TZeraryColumnFx *zfx = dynamic_cast<TZeraryColumnFx *>(fx);
if (zfx) fx = zfx->getZeraryFx();
if (zfx) fx = zfx->getZeraryFx();
static_cast<FunctionTreeModel *>(m_treeView->model())->setCurrentFx(fx);
m_treeView->updateAll();
m_functionGraph->update();

View file

@ -35,7 +35,7 @@ bool canGroup(TFx *fx) {
TOutputFx *ofx = dynamic_cast<TOutputFx *>(fx);
return (!xfx && !ofx);
}
}
} // namespace
//=========================================================
//
@ -156,10 +156,11 @@ bool FxSelection::isSelected(SchematicLink *link) {
//---------------------------------------------------------
void FxSelection::deleteSelection() {
std::list<TFxP, std::allocator<TFxP>> fxList = m_selectedFxs.toStdList();
TFxCommand::deleteSelection(fxList, m_selectedLinks.toStdList(),
m_selectedColIndexes.toStdList(), m_xshHandle,
m_fxHandle);
emit doDelete();
// std::list<TFxP, std::allocator<TFxP>> fxList = m_selectedFxs.toStdList();
// TFxCommand::deleteSelection(fxList, m_selectedLinks.toStdList(),
// m_selectedColIndexes.toStdList(), m_xshHandle,
// m_fxHandle);
}
//---------------------------------------------------------
@ -524,8 +525,8 @@ bool FxSelection::isConnected() {
TColumnFx *cfx = dynamic_cast<TColumnFx *>(selectedFx);
if (!cfx && !internalFxs->containsFx(selectedFx)) return false;
TZeraryColumnFx *zfx = dynamic_cast<TZeraryColumnFx *>(selectedFx);
if (zfx) selectedFx = zfx->getZeraryFx();
connected = connected && visitedFxs.contains(selectedFx);
if (zfx) selectedFx = zfx->getZeraryFx();
connected = connected && visitedFxs.contains(selectedFx);
}
return connected;
}
@ -535,14 +536,14 @@ bool FxSelection::isConnected() {
void FxSelection::visitFx(TFx *fx, QList<TFx *> &visitedFxs) {
if (visitedFxs.contains(fx)) return;
TZeraryColumnFx *zfx = dynamic_cast<TZeraryColumnFx *>(fx);
if (zfx) fx = zfx->getZeraryFx();
if (zfx) fx = zfx->getZeraryFx();
if (!canGroup(fx)) return;
visitedFxs.append(fx);
int i;
for (i = 0; i < fx->getInputPortCount(); i++) {
TFx *inputFx = fx->getInputPort(i)->getFx();
TZeraryColumnFx *onputZFx = dynamic_cast<TZeraryColumnFx *>(inputFx);
if (onputZFx) inputFx = onputZFx->getZeraryFx();
if (onputZFx) inputFx = onputZFx->getZeraryFx();
if (!inputFx) continue;
bool canBeGrouped = !inputFx->getAttributes()->isGrouped() ||
(inputFx->getAttributes()->getEditingGroupId() ==

View file

@ -13,6 +13,8 @@
#include "toonzqt/gutil.h"
#include "toonzqt/imageutils.h"
#include "toonzqt/dvscrollwidget.h"
#include "toonzqt/fxselection.h"
#include "stageobjectselection.h"
// TnzLib includes
#include "toonz/txsheethandle.h"
@ -397,12 +399,12 @@ void SchematicSceneViewer::wheelEvent(QWheelEvent *me) {
default: // Qt::MouseEventSynthesizedByQt,
// Qt::MouseEventSynthesizedByApplication
{
std::cout << "not supported event: Qt::MouseEventSynthesizedByQt, "
"Qt::MouseEventSynthesizedByApplication"
<< std::endl;
break;
}
{
std::cout << "not supported event: Qt::MouseEventSynthesizedByQt, "
"Qt::MouseEventSynthesizedByApplication"
<< std::endl;
break;
}
} // end switch
@ -435,8 +437,9 @@ void SchematicSceneViewer::zoomQt(bool zoomin, bool resetView) {
#endif
if ((scale2 < 100000 || !zoomin) && (scale2 > 0.001 * 0.05 || zoomin)) {
double oldZoomScale = sqrt(scale2);
double zoomScale = resetView ? 1 : ImageUtils::getQuantizedZoomFactor(
oldZoomScale, zoomin);
double zoomScale =
resetView ? 1
: ImageUtils::getQuantizedZoomFactor(oldZoomScale, zoomin);
QMatrix scale =
QMatrix().scale(zoomScale / oldZoomScale, zoomScale / oldZoomScale);
@ -701,10 +704,9 @@ bool SchematicSceneViewer::event(QEvent *e) {
}
*/
if (e->type() == QEvent::Gesture &&
CommandManager::instance()
->getAction(MI_TouchGestureControl)
->isChecked()) {
if (e->type() == QEvent::Gesture && CommandManager::instance()
->getAction(MI_TouchGestureControl)
->isChecked()) {
gestureEvent(static_cast<QGestureEvent *>(e));
return true;
}
@ -793,6 +795,11 @@ SchematicViewer::SchematicViewer(QWidget *parent)
connect(m_stageScene, SIGNAL(editObject()), this, SIGNAL(editObject()));
connect(m_fxScene, SIGNAL(editObject()), this, SIGNAL(editObject()));
connect(m_fxScene->getFxSelection(), SIGNAL(doDelete()), this,
SLOT(deleteFxs()));
connect(m_stageScene->getStageSelection(), SIGNAL(doDelete()), this,
SLOT(deleteStageObjects()));
m_viewer->setScene(m_stageScene);
m_fxToolbar->hide();
@ -942,10 +949,10 @@ void SchematicViewer::createActions() {
QIcon nodeSizeIcon =
createQIcon(m_maximizedNode ? "minimizenodes" : "maximizenodes");
m_nodeSize =
new QAction(nodeSizeIcon, m_maximizedNode ? tr("&Minimize Nodes")
: tr("&Maximize Nodes"),
m_commonToolbar);
m_nodeSize = new QAction(
nodeSizeIcon,
m_maximizedNode ? tr("&Minimize Nodes") : tr("&Maximize Nodes"),
m_commonToolbar);
connect(m_nodeSize, SIGNAL(triggered()), this, SLOT(changeNodeSize()));
QIcon selectModeIcon = createQIcon("selection_schematic");
@ -1219,3 +1226,15 @@ void SchematicViewer::zoomModeEnabled() { setCursorMode(CursorMode::Zoom); }
//------------------------------------------------------------------
void SchematicViewer::handModeEnabled() { setCursorMode(CursorMode::Hand); }
//------------------------------------------------------------------
void SchematicViewer::deleteFxs() {
emit doDeleteFxs(m_fxScene->getFxSelection());
}
//------------------------------------------------------------------
void SchematicViewer::deleteStageObjects() {
emit doDeleteStageObjects(m_stageScene->getStageSelection());
}

View file

@ -918,12 +918,25 @@ void StageObjectsData::storeSplines(const std::list<int> &splineIds,
std::vector<TStageObjectId> StageObjectsData::restoreObjects(
std::set<int> &columnIndices, std::list<int> &restoredSpline, TXsheet *xsh,
int fxFlags, const TPointD &pos) const {
QMap<TStageObjectId, TStageObjectId> idTable;
QMap<TFx *, TFx *> fxTable;
return restoreObjects(columnIndices, restoredSpline, xsh, fxFlags, idTable,
fxTable, pos);
}
// idTable : Trace stored/restored id pairings
// fxTable : Same for fxs
std::vector<TStageObjectId> StageObjectsData::restoreObjects(
std::set<int> &columnIndices, std::list<int> &restoredSpline, TXsheet *xsh,
int fxFlags, QMap<TStageObjectId, TStageObjectId> &idTable,
QMap<TFx *, TFx *> &fxTable, const TPointD &pos) const {
bool doClone = (fxFlags & eDoClone);
bool resetFxDagPositions = (fxFlags & eResetFxDagPositions);
QMap<TStageObjectId, TStageObjectId>
idTable; // Trace stored/restored id pairings
std::map<TFx *, TFx *> fxTable; // Same for fxs here
// QMap<TStageObjectId, TStageObjectId>
// idTable; // Trace stored/restored id pairings
// std::map<TFx *, TFx *> fxTable; // Same for fxs here
std::vector<TStageObjectId> restoredIds;
std::set<int>::iterator idxt = columnIndices.begin();
@ -1104,7 +1117,7 @@ std::vector<TStageObjectId> StageObjectsData::restoreObjects(
}
// Update the link, like in functions above
if (!fxTable.empty() && doClone) updateFxLinks(fxTable);
if (!fxTable.empty() && doClone) updateFxLinks(fxTable.toStdMap());
// Paste any associated spline (not stored im m_splines)
std::map<TStageObjectSpline *, TStageObjectSpline *> splines;
@ -1194,9 +1207,9 @@ std::vector<TStageObjectId> StageObjectsData::restoreObjects(
obj->getPlasticSkeletonDeformation())
sd->setGrammar(grammer);
}
std::map<TFx *, TFx *>::const_iterator it;
for (it = fxTable.begin(); it != fxTable.end(); ++it) {
setGrammerToParams(it->second->getParams(), grammer);
QMap<TFx *, TFx *>::const_iterator it;
for (it = fxTable.constBegin(); it != fxTable.constEnd(); ++it) {
setGrammerToParams(it.value()->getParams(), grammer);
}
return restoredIds;

View file

@ -108,7 +108,7 @@ public:
}
int getHistoryType() override { return HistoryType::Schematic; }
};
}
} // namespace
//======================================================================
//
@ -153,9 +153,10 @@ void StageObjectSelection::enableCommands() {
//-------------------------------------------------------
void StageObjectSelection::deleteSelection() {
TStageObjectCmd::deleteSelection(
m_selectedObjects.toVector().toStdVector(), m_selectedLinks.toStdList(),
m_selectedSplines.toStdList(), m_xshHandle, m_objHandle, m_fxHandle);
emit doDelete();
// TStageObjectCmd::deleteSelection(
// m_selectedObjects.toVector().toStdVector(), m_selectedLinks.toStdList(),
// m_selectedSplines.toStdList(), m_xshHandle, m_objHandle, m_fxHandle);
}
//-------------------------------------------------------

View file

@ -76,6 +76,7 @@ public:
const QList<QPair<TStageObjectId, TStageObjectId>> &getLinks() const {
return m_selectedLinks;
}
const QList<int> &getSplines() const { return m_selectedSplines; }
void setXsheetHandle(TXsheetHandle *xshHandle) { m_xshHandle = xshHandle; }
void setObjectHandle(TObjectHandle *objHandle) { m_objHandle = objHandle; }
@ -96,6 +97,7 @@ private:
signals:
void doCollapse(QList<TStageObjectId>);
void doExplodeChild(QList<TStageObjectId>);
void doDelete();
};
#endif

View file

@ -8,6 +8,8 @@
<file>Resources/param_on.svg</file>
<file>Resources/paramanim_off.svg</file>
<file>Resources/paramanim_on.svg</file>
<file>Resources/paramignored_off.svg</file>
<file>Resources/paramignored_on.svg</file>
<file>Resources/resizeColumnNode.svg</file>
<file>Resources/schematic_spin_arrows.svg</file>
<file>Resources/schematic_spline_aim_rhomb.svg</file>

View file

@ -171,7 +171,7 @@ TreeModel::~TreeModel() { delete m_rootItem; }
//------------------------------------------------------------------------------------------------------------------
void TreeModel::setExpandedItem(const QModelIndex &index, bool expanded) {
m_view->setExpanded(index, expanded);
if (m_view) m_view->setExpanded(index, expanded);
}
//------------------------------------------------------------------------------------------------------------------
@ -320,7 +320,7 @@ void TreeModel::setRootItem_NoFree(Item *rootItem) {
//---------------------------------------------------------------------------------------------------------------
void TreeModel::setRowHidden(int row, const QModelIndex &parent, bool hide) {
m_view->setRowHidden(row, parent, hide);
if (m_view) m_view->setRowHidden(row, parent, hide);
}
//====================================================================================================