Merge pull request #634 from manongjohn/ot_patches_20210328

OpenToonz patches thru 3/28
This commit is contained in:
manongjohn 2021-04-01 17:07:39 -04:00 committed by GitHub
commit 489ea06570
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
40 changed files with 1379 additions and 539 deletions

View file

@ -0,0 +1,716 @@
<dvpreset fxId="STD_particlesFx" ver="1.0">
<params>
<source_ctrl>
0 0
</source_ctrl>
<bright_thres>
25 25
</bright_thres>
<multi_source>
0 0
</multi_source>
<center>
<x>
<default>
444.444
</default>
</x>
<y>
<default>
0
</default>
</y>
</center>
<length>
<default>
4.44444
</default>
</length>
<height>
<default>
480
</default>
</height>
<birth_rate>
<default>
1
</default>
</birth_rate>
<lifetime>
<min>
<default>
900
</default>
</min>
<max>
<default>
900
</default>
</max>
</lifetime>
<lifetime_ctrl>
0 0
</lifetime_ctrl>
<column_lifetime>
0 0
</column_lifetime>
<starting_frame>
1 1
</starting_frame>
<random_seed>
1 1
</random_seed>
<gravity>
<default>
0
</default>
</gravity>
<gravity_angle>
<default>
0
</default>
</gravity_angle>
<gravity_ctrl>
0 0
</gravity_ctrl>
<friction>
<default>
0
</default>
</friction>
<friction_ctrl>
0 0
</friction_ctrl>
<wind>
<default>
0
</default>
</wind>
<wind_angle>
<default>
0
</default>
</wind_angle>
<swing_mode>
1
</swing_mode>
<scattering_x>
<min>
<default>
0
</default>
</min>
<max>
<default>
0
</default>
</max>
</scattering_x>
<scattering_y>
<min>
<default>
0.444444
</default>
</min>
<max>
<default>
11.1111
</default>
</max>
</scattering_y>
<scattering_x_ctrl>
0 0
</scattering_x_ctrl>
<scattering_y_ctrl>
0 0
</scattering_y_ctrl>
<swing>
<min>
<default>
15
</default>
</min>
<max>
<default>
45
</default>
</max>
</swing>
<speed>
<min>
<default>
20
</default>
</min>
<max>
<default>
26.6667
</default>
</max>
</speed>
<speed_ctrl>
0 0
</speed_ctrl>
<speed_angle>
<min>
<default>
-105
</default>
</min>
<max>
<default>
-60
</default>
</max>
</speed_angle>
<speeda_ctrl>
0 0
</speeda_ctrl>
<speeda_use_gradient>
0 0
</speeda_use_gradient>
<speed_size>
0 1
</speed_size>
<top_layer>
3
</top_layer>
<mass>
<min>
<default>
1
</default>
</min>
<max>
<default>
1
</default>
</max>
</mass>
<scale>
<min>
<default>
30
</default>
</min>
<max>
<default>
75
</default>
</max>
</scale>
<scale_ctrl>
0 0
</scale_ctrl>
<scale_ctrl_all>
0 0
</scale_ctrl_all>
<rot>
<min>
<default>
0
</default>
</min>
<max>
<default>
0
</default>
</max>
</rot>
<rot_ctrl>
0 0
</rot_ctrl>
<trail>
<min>
<default>
0
</default>
</min>
<max>
<default>
0
</default>
</max>
</trail>
<trail_step>
<default>
0
</default>
</trail_step>
<spin_swing_mode>
0
</spin_swing_mode>
<spin_speed>
<default>
0
</default>
</spin_speed>
<spin_random>
<min>
<default>
0
</default>
</min>
<max>
<default>
0
</default>
</max>
</spin_random>
<spin_swing>
<min>
<default>
0
</default>
</min>
<max>
<default>
0
</default>
</max>
</spin_swing>
<path_aim>
0 0
</path_aim>
<opacity>
<min>
<default>
0
</default>
</min>
<max>
<default>
100
</default>
</max>
</opacity>
<opacity_ctrl>
0 0
</opacity_ctrl>
<trail_opacity>
<min>
<default>
0
</default>
</min>
<max>
<default>
100
</default>
</max>
</trail_opacity>
<scale_step>
<min>
<default>
-2
</default>
</min>
<max>
<default>
3
</default>
</max>
</scale_step>
<scale_step_ctrl>
0 0
</scale_step_ctrl>
<fade_in>
<default>
0
</default>
</fade_in>
<fade_out>
<default>
0
</default>
</fade_out>
<animation>
3
</animation>
<step>
1 1
</step>
<birth_color>
<spectrum>
<s_value>
<default>
0
</default>
<keyframes>
<S>
0 0 1 0
</S>
</keyframes>
</s_value>
<col_value>
<red>
<default>
1
</default>
<keyframes>
<S>
0 1 1 0
</S>
</keyframes>
</red>
<green>
<default>
0
</default>
<keyframes>
<S>
0 0 1 0
</S>
</keyframes>
</green>
<blue>
<default>
0
</default>
<keyframes>
<S>
0 0 1 0
</S>
</keyframes>
</blue>
<matte>
<default>
1
</default>
<keyframes>
<S>
0 1 1 0
</S>
</keyframes>
</matte>
</col_value>
<s_value>
<default>
1
</default>
<keyframes>
<S>
0 1 1 0
</S>
</keyframes>
</s_value>
<col_value>
<red>
<default>
1
</default>
<keyframes>
<S>
0 1 1 0
</S>
</keyframes>
</red>
<green>
<default>
0
</default>
<keyframes>
<S>
0 0 1 0
</S>
</keyframes>
</green>
<blue>
<default>
0
</default>
<keyframes>
<S>
0 0 1 0
</S>
</keyframes>
</blue>
<matte>
<default>
1
</default>
<keyframes>
<S>
0 1 1 0
</S>
</keyframes>
</matte>
</col_value>
</spectrum>
</birth_color>
<birth_color_ctrl>
0 0
</birth_color_ctrl>
<birth_color_spread>
<default>
0
</default>
</birth_color_spread>
<birth_color_fade>
<default>
0
</default>
</birth_color_fade>
<fadein_color>
<spectrum>
<s_value>
<default>
0
</default>
<keyframes>
<S>
0 0 1 0
</S>
</keyframes>
</s_value>
<col_value>
<red>
<default>
0
</default>
<keyframes>
<S>
0 0 1 0
</S>
</keyframes>
</red>
<green>
<default>
1
</default>
<keyframes>
<S>
0 1 1 0
</S>
</keyframes>
</green>
<blue>
<default>
0
</default>
<keyframes>
<S>
0 0 1 0
</S>
</keyframes>
</blue>
<matte>
<default>
1
</default>
<keyframes>
<S>
0 1 1 0
</S>
</keyframes>
</matte>
</col_value>
<s_value>
<default>
1
</default>
<keyframes>
<S>
0 1 1 0
</S>
</keyframes>
</s_value>
<col_value>
<red>
<default>
0
</default>
<keyframes>
<S>
0 0 1 0
</S>
</keyframes>
</red>
<green>
<default>
1
</default>
<keyframes>
<S>
0 1 1 0
</S>
</keyframes>
</green>
<blue>
<default>
0
</default>
<keyframes>
<S>
0 0 1 0
</S>
</keyframes>
</blue>
<matte>
<default>
1
</default>
<keyframes>
<S>
0 1 1 0
</S>
</keyframes>
</matte>
</col_value>
</spectrum>
</fadein_color>
<fadein_color_ctrl>
0 0
</fadein_color_ctrl>
<fadein_color_spread>
<default>
0
</default>
</fadein_color_spread>
<fadein_color_range>
<default>
0
</default>
</fadein_color_range>
<fadein_color_fade>
<default>
0
</default>
</fadein_color_fade>
<fadeout_color>
<spectrum>
<s_value>
<default>
0
</default>
<keyframes>
<S>
0 0 1 0
</S>
</keyframes>
</s_value>
<col_value>
<red>
<default>
0
</default>
<keyframes>
<S>
0 0 1 0
</S>
</keyframes>
</red>
<green>
<default>
0
</default>
<keyframes>
<S>
0 0 1 0
</S>
</keyframes>
</green>
<blue>
<default>
1
</default>
<keyframes>
<S>
0 1 1 0
</S>
</keyframes>
</blue>
<matte>
<default>
1
</default>
<keyframes>
<S>
0 1 1 0
</S>
</keyframes>
</matte>
</col_value>
<s_value>
<default>
1
</default>
<keyframes>
<S>
0 1 1 0
</S>
</keyframes>
</s_value>
<col_value>
<red>
<default>
0
</default>
<keyframes>
<S>
0 0 1 0
</S>
</keyframes>
</red>
<green>
<default>
0
</default>
<keyframes>
<S>
0 0 1 0
</S>
</keyframes>
</green>
<blue>
<default>
1
</default>
<keyframes>
<S>
0 1 1 0
</S>
</keyframes>
</blue>
<matte>
<default>
1
</default>
<keyframes>
<S>
0 1 1 0
</S>
</keyframes>
</matte>
</col_value>
</spectrum>
</fadeout_color>
<fadeout_color_ctrl>
0 0
</fadeout_color_ctrl>
<fadeout_color_spread>
<default>
0
</default>
</fadeout_color_spread>
<fadeout_color_range>
<default>
0
</default>
</fadeout_color_range>
<fadeout_color_fade>
<default>
0
</default>
</fadeout_color_fade>
<source_gradation>
0 0
</source_gradation>
<pick_color_for_every_frame>
0 0
</pick_color_for_every_frame>
<perspective_distribution>
0 1
</perspective_distribution>
</params>
</dvpreset>

View file

@ -145,7 +145,7 @@ if(BUILD_ENV_MSVC)
return()
endif()
set(QT_LIB_PATH ${QT_PATH})
set(CMAKE_PREFIX_PATH "${QT_PATH}/lib/cmake/")
set(CMAKE_PREFIX_PATH "${CMAKE_PREFIX_PATH};${QT_PATH}/lib/cmake/")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /wd4251")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4251")
add_definitions(
@ -159,12 +159,12 @@ elseif(BUILD_ENV_APPLE)
endif()
message("PLATFORM:" ${PLATFORM})
if(PLATFORM EQUAL 64)
set(QT_PATH "~/Qt5.9.2/5.9.2/clang_64/lib" CACHE PATH "Qt installation directory")
# set(QT_PATH "/usr/local/Cellar/qt/5.15.0/lib" CACHE PATH "Qt installation directory")
set(QT_PATH "~/Qt5.9.2/5.9.2/clang_${PLATFORM}/lib" CACHE PATH "Qt installation directory")
set(QT_LIB_PATH "${QT_PATH}/")
set(CMAKE_PREFIX_PATH "${QT_LIB_PATH}cmake/")
message("CMAKE_PREFIX_PATH:" ${CMAKE_PREFIX_PATH})
set(CMAKE_PREFIX_PATH "${CMAKE_PREFIX_PATH};${QT_LIB_PATH}cmake/")
foreach(path ${CMAKE_PREFIX_PATH})
message("CMAKE_PREFIX_PATH: " ${path})
endforeach(path)
add_definitions(
-DMACOSX
-Di386

View file

@ -204,7 +204,8 @@ public:
png_set_palette_to_rgb(m_png_ptr);
// treat the image as RGBA from now on
m_info.m_samplePerPixel = 4; // there are 4 channels per pixel (R, G, B, and A)
m_info.m_samplePerPixel =
4; // there are 4 channels per pixel (R, G, B, and A)
// if there is no alpha channel, then fill it with "255" (full opacity)
png_set_filler(m_png_ptr, 0xFF, PNG_FILLER_AFTER);
@ -349,7 +350,8 @@ public:
void writeRow(char *buffer) {
if (m_color_type == PNG_COLOR_TYPE_RGB_ALPHA ||
m_color_type == PNG_COLOR_TYPE_GRAY_ALPHA ||
m_color_type == PNG_COLOR_TYPE_PALETTE) { // PNG_COLOR_TYPE_PALETTE is expanded to RGBA
m_color_type == PNG_COLOR_TYPE_PALETTE) { // PNG_COLOR_TYPE_PALETTE is
// expanded to RGBA
if (m_bit_depth == 16) {
TPixel32 *pix = (TPixel32 *)buffer;
int i = -2;
@ -377,6 +379,9 @@ public:
#else
#error "unknown channel order"
#endif
// premultiply here
premult(pix[j]);
}
} else {
TPixel32 *pix = (TPixel32 *)buffer;
@ -405,6 +410,8 @@ public:
#else
#error "unknown channel order"
#endif
// premultiply here
premult(pix[j]);
}
}
} else // qui gestisce RGB senza alpha.
@ -454,7 +461,8 @@ public:
void writeRow(short *buffer) {
if (m_color_type == PNG_COLOR_TYPE_RGB_ALPHA ||
m_color_type == PNG_COLOR_TYPE_GRAY_ALPHA ||
m_color_type == PNG_COLOR_TYPE_PALETTE) { // PNG_COLOR_TYPE_PALETTE is expanded to RGBA
m_color_type == PNG_COLOR_TYPE_PALETTE) { // PNG_COLOR_TYPE_PALETTE is
// expanded to RGBA
TPixel64 *pix = (TPixel64 *)buffer;
int i = -2; // 0;
for (int j = 0; j < m_info.m_lx; j++) {
@ -474,6 +482,9 @@ public:
#error "unknown channel order"
#endif
// pix[j].m = 255;
// premultiply here
premult(pix[j]);
}
} else // qui gestisce RGB senza alpha.
{ // grayscale e' gestito come RGB perche' si usa png_set_gray_to_rgb
@ -862,7 +873,6 @@ void PngWriter::open(FILE *file, const TImageInfo &info) {
#error "unknownchannel order"
#endif
png_write_info(m_png_ptr, m_info_ptr);
png_set_pHYs(m_png_ptr, m_info_ptr, x_pixels_per_meter, y_pixels_per_meter,
1);
@ -873,6 +883,8 @@ void PngWriter::open(FILE *file, const TImageInfo &info) {
bgcolor.index = 0;
png_set_tRNS(m_png_ptr, m_info_ptr, alpha, 1, &bgcolor);
}
png_write_info(m_png_ptr, m_info_ptr);
}
//---------------------------------------------------------

View file

@ -112,9 +112,9 @@ public:
/*! \return The \a coded path to be used for import. */
TFilePath getImportedLevelPath(const TFilePath path)
const; //!< Builds the path to be used during a level import
//!< operation.
TFilePath getImportedLevelPath(
const TFilePath path) const; //!< Builds the path to be used during a
//!< level import operation.
/*! \details If convertion is required, a new level file will be created
and \p levelPath will be substituted with its new path.
@ -269,7 +269,9 @@ private:
TContentHistory *m_contentHistory;
bool m_isUntitled; //!< Whether the scene is untitled.
//! \sa The setUntitled() member function.
VersionNumber m_versionNumber;
VersionNumber m_versionNumber; // last saved scene file version. Note that
// currently it is not match with OT version.
// TODO: Revise VersionNumber with OT version
private:
// noncopyable

View file

@ -108,15 +108,14 @@ int DVAPI getDevPixRatio();
//-----------------------------------------------------------------------------
QPixmap DVAPI setOpacity(QPixmap pixmap, const qreal &opacity = 0.8);
QPixmap DVAPI compositePixmap(QPixmap pixmap, const qreal &opacity = 0.8,
const QSize &size = QSize(),
const int leftAdj = 0, const int topAdj = 0,
QColor bgColor = Qt::transparent);
QPixmap DVAPI recolorPixmap(
QPixmap pixmap, QColor color = Preferences::instance()->getIconTheme()
? Qt::black
: Qt::white);
QPixmap DVAPI compositePixmap(QPixmap pixmap, qreal opacity,
int canvasWidth = 20, int canvasHeight = 20,
int iconWidth = 16, int iconHeight = 16,
int offset = 0);
QIcon DVAPI createQIcon(const char *iconSVGName, bool useFullOpacity = false);
QIcon DVAPI createQIconPNG(const char *iconPNGName);
QIcon DVAPI createQIconOnOffPNG(const char *iconPNGName, bool withOver = true);

View file

@ -30,6 +30,9 @@
#include "toutputproperties.h"
#include "toonz/imagestyles.h"
#include "tproperty.h"
#include "toonz/levelset.h"
#include "toonz/txshsimplelevel.h"
#include "toonz/levelproperties.h"
// TnzSound includes
#include "tnzsound.h"
@ -226,6 +229,35 @@ void tcomposerRunOutOfContMemHandler(unsigned long size) {
TImageCache::instance()->clear(true);
exit(2);
}
// Check if the scene saved with the previous version AND the premultiply option
// is set to PNG level setting
void UnsetPremultiplyOptionsInPngLevels(ToonzScene *scene) {
if (scene->getVersionNumber() <
VersionNumber(71, 1)) { // V1.4 = 71.0 , V1.5 = 71.1
QStringList modifiedPNGLevelNames;
std::vector<TXshLevel *> levels;
scene->getLevelSet()->listLevels(levels);
for (auto level : levels) {
if (!level || !level->getSimpleLevel()) continue;
TFilePath path = level->getPath();
if (path.isEmpty() || path.getType() != "png") continue;
if (level->getSimpleLevel()->getProperties()->doPremultiply()) {
level->getSimpleLevel()->getProperties()->setDoPremultiply(false);
modifiedPNGLevelNames.append(QString::fromStdWString(level->getName()));
}
}
if (!modifiedPNGLevelNames.isEmpty()) {
std::string msg =
"The Premultiply options in the following levels are disabled, since "
"PNG files are premultiplied on loading in the current version:" +
modifiedPNGLevelNames.join(", ").toStdString();
cout << msg << endl;
m_userLog->info(msg);
}
}
}
} // namespace
//==============================================================================================
@ -820,6 +852,10 @@ int main(int argc, char *argv[]) {
// return false;
}
// Check if the scene saved with the previous version AND the premultiply
// option is set to PNG level setting
UnsetPremultiplyOptionsInPngLevels(scene);
msg = "scene loaded";
cout << "scene loaded" << endl;
m_userLog->info(msg);
@ -992,8 +1028,8 @@ int main(int argc, char *argv[]) {
DVGui::info(QString::fromStdString(msg));
TImageCache::instance()->clear(true);
} catch (TException &e) {
msg = "Untrapped exception: " + ::to_string(e.getMessage()), cout << msg
<< endl;
msg = "Untrapped exception: " + ::to_string(e.getMessage()),
cout << msg << endl;
m_userLog->error(msg);
TImageCache::instance()->clear(true);
} catch (...) {

View file

@ -326,7 +326,7 @@ void tglDraw(const TMeshImage &meshImage, const DrawableTextureData &texData,
GL_HINT_BIT); // Preserve original status bits
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_LINE_SMOOTH);
glLineWidth(1.0f);

View file

@ -565,7 +565,7 @@ void FingerTool::pick(const TPointD &pos) {
int styleId =
picker.pickStyleId(TScale(1.0 / subsampling) * pos + TPointD(-0.5, -0.5),
getPixelSize() * getPixelSize(), modeValue);
getPixelSize() * getPixelSize(), 1.0, modeValue);
if (styleId < 0) return;

View file

@ -19,6 +19,7 @@
#include "toonz/txsheethandle.h"
#include "toonz/txshlevelhandle.h"
#include "toonz/tobjecthandle.h"
#include "toonz/tframehandle.h"
#include "toonz/ttileset.h"
#include "toonz/ttilesaver.h"
#include "toonz/strokegenerator.h"
@ -291,7 +292,13 @@ bool FullColorBrushTool::askWrite(const TRect &rect) {
bool FullColorBrushTool::preLeftButtonDown() {
touchImage();
if (m_isFrameCreated) setWorkAndBackupImages();
if (m_isFrameCreated) {
setWorkAndBackupImages();
// When the xsheet frame is selected, whole viewer will be updated from
// SceneViewer::onXsheetChanged() on adding a new frame.
// We need to take care of a case when the level frame is selected.
if (m_application->getCurrentFrame()->isEditingLevel()) invalidate();
}
return true;
}

View file

@ -567,6 +567,7 @@ public:
bool getSmooth() { return m_param->m_smooth.getValue(); }
virtual TStroke *makeStroke() const = 0;
virtual bool canTouchImageOnPreLeftClick() { return true; }
};
//-----------------------------------------------------------------------------
@ -739,6 +740,9 @@ public:
void onImageChanged() override;
void setVertexes(const std::vector<TPointD> &vertex) { m_vertex = vertex; };
void setSpeedMoved(bool speedMoved) { m_speedMoved = speedMoved; };
// Only execute touchImage when clicking the first point of the polyline
bool canTouchImageOnPreLeftClick() override { return m_vertex.empty(); }
};
//-----------------------------------------------------------------------------
@ -849,6 +853,7 @@ public:
TStroke *makeStroke() const override;
void draw() override;
void leftButtonDown(const TPointD &pos, const TMouseEvent &e) override;
void leftButtonUp(const TPointD &pos, const TMouseEvent &) override;
void mouseMove(const TPointD &pos, const TMouseEvent &e) override;
void leftButtonDoubleClick(const TPointD &, const TMouseEvent &e) override;
@ -879,6 +884,9 @@ public:
void decreaseUndo() { --m_undoCount; }
void increaseUndo() { ++m_undoCount; }
// Only execute touchImage when clicking the first point of the multi arc
bool canTouchImageOnPreLeftClick() override { return m_clickNumber == 0; }
};
//-----------------------------------------------------------------------------
@ -1032,19 +1040,27 @@ public:
}
}
bool preLeftButtonDown() override {
if (getViewer() && getViewer()->getGuidedStrokePickerMode()) return false;
if (getApplication()->getCurrentObject()->isSpline()) return true;
// in the halfway through the drawing of Polyline / MultiArc primitive, OT
// should not call touchImage or the m_frameCreated / m_levelCreated flags
// will be reset.
if (m_primitive && !m_primitive->canTouchImageOnPreLeftClick()) return true;
// NEEDS to be done even if(m_active), due
// to the HORRIBLE m_frameCreated / m_levelCreated
// mechanism. touchImage() is the ONLY function
// resetting them to false... >_<
m_active = !!touchImage();
return true;
}
void leftButtonDown(const TPointD &p, const TMouseEvent &e) override {
if (getViewer() && getViewer()->getGuidedStrokePickerMode()) {
getViewer()->doPickGuideStroke(p);
return;
}
/* m_active = getApplication()->getCurrentObject()->isSpline() ||
(bool) getImage(true);*/
if (!getApplication()->getCurrentObject()->isSpline())
m_active = touchImage(); // NEEDS to be done even if(m_active), due
if (!m_active) // to the HORRIBLE m_frameCreated / m_levelCreated
return; // mechanism. touchImage() is the ONLY function
// resetting them to false... >_<
if (m_primitive) m_primitive->leftButtonDown(p, e);
invalidate();
}
@ -2397,6 +2413,17 @@ TStroke *MultiArcPrimitive::makeStroke() const {
//-----------------------------------------------------------------------------
void MultiArcPrimitive::leftButtonDown(const TPointD &pos,
const TMouseEvent &e) {
if (m_clickNumber == 0) {
TPointD newPos = calculateSnap(pos, e);
newPos = checkGuideSnapping(pos, e);
m_startPoint = newPos;
}
}
//-----------------------------------------------------------------------------
void MultiArcPrimitive::leftButtonUp(const TPointD &pos, const TMouseEvent &) {
TTool::Application *app = TTool::getApplication();
if (!app) return;

View file

@ -1973,9 +1973,8 @@ void PlasticTool::drawOnionSkinSkeletons_animate(double pixelSize) {
PlasticSkeleton skel;
m_sd->storeDeformedSkeleton(m_sd->skeletonId(sdFrame), sdFrame, skel);
UCHAR alpha =
255 -
255.0 * OnionSkinMask::getOnionSkinFade(abs(osRows[r] - currentRow));
UCHAR alpha = 255 - 255.0 * OnionSkinMask::getOnionSkinFade(
abs(osRows[r] - currentRow));
drawSkeleton(skel, pixelSize, alpha);
}
}
@ -2114,6 +2113,7 @@ void PlasticTool::draw() {
glPushAttrib(GL_LINE_BIT | GL_COLOR_BUFFER_BIT | GL_ENABLE_BIT);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_LINE_SMOOTH);
switch (m_mode.getIndex()) {

View file

@ -358,6 +358,7 @@ public:
void setCursorIndexFromPoint(TPointD point);
void mouseMove(const TPointD &pos, const TMouseEvent &) override;
bool preLeftButtonDown() override;
void leftButtonDown(const TPointD &pos, const TMouseEvent &) override;
void rightButtonDown(const TPointD &pos, const TMouseEvent &) override;
bool keyDown(QKeyEvent *event) override;
@ -1201,6 +1202,15 @@ void TypeTool::mouseMove(const TPointD &pos, const TMouseEvent &) {
//---------------------------------------------------------
bool TypeTool::preLeftButtonDown() {
if (getViewer() && getViewer()->getGuidedStrokePickerMode()) return false;
if (m_validFonts && !m_active) touchImage();
return true;
}
//---------------------------------------------------------
void TypeTool::leftButtonDown(const TPointD &pos, const TMouseEvent &) {
TSelection::setCurrent(0);
@ -1211,11 +1221,7 @@ void TypeTool::leftButtonDown(const TPointD &pos, const TMouseEvent &) {
if (!m_validFonts) return;
TImageP img;
if (!m_active)
img = touchImage();
else
img = getImage(true);
TImageP img = getImage(true);
TVectorImageP vi = img;
TToonzImageP ti = img;

View file

@ -175,11 +175,11 @@ AudioRecordingPopup::AudioRecordingPopup()
m_probe->setSource(m_audioRecorder);
QAudioEncoderSettings audioSettings;
audioSettings.setCodec("audio/PCM");
#ifdef MACOSX
// setting the sample rate to some value (like 44100)
// may cause divide-by-zero crash in QAudioDeviceInfo::nearestFormat()
// so here we set the value to -1, as the documentation says;
// "A value of -1 indicates the encoder should make an optimal choice"
audioSettings.setSampleRate(-1);
#else
audioSettings.setSampleRate(44100);
#endif
audioSettings.setChannelCount(1);
audioSettings.setBitRate(16);
audioSettings.setEncodingMode(QMultimedia::ConstantBitRateEncoding);

View file

@ -14,6 +14,7 @@
#include "tapp.h"
#include "xsheetviewer.h"
#include "levelcommand.h"
#include "columncommand.h"
// TnzTools includes
#include "tools/toolutils.h"
@ -120,7 +121,12 @@ void deleteCellsWithoutUndo(int &r0, int &c0, int &r1, int &c1) {
TXsheet *xsh = TApp::instance()->getCurrentXsheet()->getXsheet();
int c;
for (c = c0; c <= c1; c++) {
if (xsh->isColumnEmpty(c)) continue;
xsh->clearCells(r0, c, r1 - r0 + 1);
// when the column becomes empty after deletion,
// ColumnCmd::DeleteColumn() will take care of column related operations
// like disconnecting from fx nodes etc.
/*
TXshColumn* column = xsh->getColumn(c);
if (column && column->isEmpty()) {
column->resetColumnProperties();
@ -135,8 +141,8 @@ void deleteCellsWithoutUndo(int &r0, int &c0, int &r1, int &c1) {
xsh->getStageObjectTree()->removeStageObject(
TStageObjectId::ColumnId(c));
}
*/
}
TApp::instance()->getCurrentXsheet()->notifyXsheetChanged();
} catch (...) {
DVGui::error(QObject::tr("It is not possible to delete the selection."));
}
@ -149,6 +155,10 @@ void cutCellsWithoutUndo(int &r0, int &c0, int &r1, int &c1) {
int c;
for (c = c0; c <= c1; c++) {
xsh->removeCells(r0, c, r1 - r0 + 1);
// when the column becomes empty after deletion,
// ColumnCmd::DeleteColumn() will take care of column related operations
// like disconnecting from fx nodes etc.
/*
TXshColumn* column = xsh->getColumn(c);
if (column && column->isEmpty()) {
column->resetColumnProperties();
@ -161,13 +171,36 @@ void cutCellsWithoutUndo(int &r0, int &c0, int &r1, int &c1) {
}
xsh->getStageObjectTree()->removeStageObject(TStageObjectId::ColumnId(c));
}
*/
}
// Se la selezione corrente e' TCellSelection svuoto la selezione.
TCellSelection *cellSelection = dynamic_cast<TCellSelection *>(
TApp::instance()->getCurrentSelection()->getSelection());
if (cellSelection) cellSelection->selectNone();
TApp::instance()->getCurrentXsheet()->notifyXsheetChanged();
}
//-----------------------------------------------------------------------------
// check if the operation may remove expression reference as column becomes
// empty and deleted after the operation. return true to continue the operation.
bool checkColumnRemoval(const int r0, const int c0, const int r1, const int c1,
std::set<int> &removedColIds) {
TXsheet *xsh = TApp::instance()->getCurrentXsheet()->getXsheet();
// std::set<int> colIndicesToBeRemoved;
for (int c = c0; c <= c1; c++) {
TXshColumnP column = xsh->getColumn(c);
if (!column || column->isEmpty() || column->isLocked()) continue;
int tmp_r0, tmp_r1;
xsh->getCellRange(c, tmp_r0, tmp_r1);
if (r0 <= tmp_r0 && r1 >= tmp_r1) removedColIds.insert(c);
}
if (removedColIds.empty() ||
!Preferences::instance()->isModifyExpressionOnMovingReferencesEnabled())
return true;
std::set<TFx *> dummy_fxs;
return ColumnCmd::checkExpressionReferences(removedColIds, dummy_fxs, true);
}
//=============================================================================
@ -239,15 +272,15 @@ public:
//=============================================================================
// DeleteCellsUndo
// Recovering the column information (such as reconnecting nodes) when
// undoing deletion of entire column will be done by DeleteColumnsUndo which
// will be called in the same undo block. So here we only need to recover the
// cell arrangement.
//-----------------------------------------------------------------------------
class DeleteCellsUndo final : public TUndo {
TCellSelection *m_selection;
QMimeData *m_data;
QMap<int, QList<TFxPort *>> m_outputConnections;
QMap<int, TXshColumn *> m_columns;
QMap<TStageObjectId, QList<TStageObjectId>> m_columnObjChildren;
QMap<TStageObjectId, TStageObjectId> m_columnObjParents;
public:
DeleteCellsUndo(TCellSelection *selection, QMimeData *data) : m_data(data) {
@ -256,115 +289,26 @@ public:
if (c0 < 0) c0 = 0; // Ignore camera column
m_selection = new TCellSelection();
m_selection->selectCells(r0, c0, r1, c1);
TXsheet *xsh = TApp::instance()->getCurrentXsheet()->getXsheet();
int i;
for (i = c0; i <= c1; i++) {
TXshColumn *col = xsh->getColumn(i);
if (!col || col->isEmpty()) continue;
int colr0, colr1;
col->getRange(colr0, colr1);
if (r0 <= colr0 && r1 >= colr1 && !col->getLevelColumn()) {
// la colonna verra' rimossa dall'xsheet
m_columns[i] = col;
col->addRef();
}
// Store TStageObject children in case column is emptied and we need to
// restore it
int pegbarsCount = xsh->getStageObjectTree()->getStageObjectCount();
TStageObjectId id = TStageObjectId::ColumnId(i);
TStageObject *pegbar = xsh->getStageObject(id);
for (int k = 0; k < pegbarsCount; ++k) {
TStageObject *other = xsh->getStageObjectTree()->getStageObject(k);
if (other == pegbar) continue;
if (other->getParent() == id) {
// other->setParent(pegbar->getParent());
m_columnObjChildren[id].append(other->getId());
}
}
// Store TStageObject parent in case column is emptied and we need to
// restore it
m_columnObjParents[id] = pegbar->getParent();
TFx *fx = col->getFx();
if (!fx) continue;
int j;
QList<TFxPort *> fxPorts;
for (j = 0; j < fx->getOutputConnectionCount(); j++)
fxPorts.append(fx->getOutputConnection(j));
if (fxPorts.isEmpty()) continue;
m_outputConnections[i] = fxPorts;
}
}
~DeleteCellsUndo() {
delete m_selection;
QMap<int, TXshColumn *>::iterator it;
for (it = m_columns.begin(); it != m_columns.end(); it++)
it.value()->release();
}
~DeleteCellsUndo() { delete m_selection; }
void undo() const override {
TXsheet *xsh = TApp::instance()->getCurrentXsheet()->getXsheet();
// devo rimettere le colonne che ho rimosso dall'xsheet
QMap<int, TXshColumn *>::const_iterator colIt;
for (colIt = m_columns.begin(); colIt != m_columns.end(); colIt++) {
int index = colIt.key();
TXshColumn *column = colIt.value();
xsh->removeColumn(index);
xsh->insertColumn(index, column);
}
int r0, c0, r1, c1;
m_selection->getSelectedCells(r0, c0, r1, c1);
QMap<int, QList<TFxPort *>>::const_iterator it;
for (it = m_outputConnections.begin(); it != m_outputConnections.end();
it++) {
TXshColumn *col = xsh->getColumn(it.key());
QList<TFxPort *> fxPorts = it.value();
int i;
for (i = 0; i < fxPorts.size(); i++) fxPorts[i]->setFx(col->getFx());
}
// Restore TStageObject parent
QMap<TStageObjectId, TStageObjectId>::const_iterator it2;
for (it2 = m_columnObjParents.begin(); it2 != m_columnObjParents.end();
it2++) { // Parents
TStageObject *obj = xsh->getStageObject(it2.key());
if (obj) {
obj->setParent(it2.value());
}
}
// Restore TStageObject children
QMap<TStageObjectId, QList<TStageObjectId>>::const_iterator it3;
for (it3 = m_columnObjChildren.begin(); it3 != m_columnObjChildren.end();
it3++) { // Children
QList<TStageObjectId> children = it3.value();
int i;
for (i = 0; i < children.size(); i++) {
TStageObject *child = xsh->getStageObject(children[i]);
if (child) {
child->setParent(it3.key());
}
}
}
const TCellData *cellData = dynamic_cast<const TCellData *>(m_data);
pasteCellsWithoutUndo(cellData, r0, c0, r1, c1, false, false);
TApp::instance()->getCurrentXsheet()->notifyXsheetChanged();
TApp::instance()->getCurrentObject()->notifyObjectIdSwitched();
}
void redo() const override {
int r0, c0, r1, c1;
m_selection->getSelectedCells(r0, c0, r1, c1);
deleteCellsWithoutUndo(r0, c0, r1, c1);
TApp::instance()->getCurrentXsheet()->notifyXsheetChanged();
}
int getSize() const override { return sizeof(*this); }
@ -375,14 +319,14 @@ public:
//=============================================================================
// CutCellsUndo
// Just like DeleteCellsUndo, recovering the column information (such as
// reconnecting nodes) when undoing deletion of entire column will be done
// by DeleteColumnsUndo which will be called in the same undo block.
//-----------------------------------------------------------------------------
class CutCellsUndo final : public TUndo {
TCellSelection *m_selection;
TCellData *m_data;
QMap<int, QList<TFxPort *>> m_outputConnections;
QMap<TStageObjectId, QList<TStageObjectId>> m_columnObjChildren;
QMap<TStageObjectId, TStageObjectId> m_columnObjParents;
public:
CutCellsUndo(TCellSelection *selection) : m_data() {
@ -391,41 +335,6 @@ public:
if (c0 < 0) c0 = 0; // Ignore camera column
m_selection = new TCellSelection();
m_selection->selectCells(r0, c0, r1, c1);
TXsheet *xsh = TApp::instance()->getCurrentXsheet()->getXsheet();
int i;
for (i = c0; i <= c1; i++) {
TXshColumn *col = xsh->getColumn(i);
if (!col || col->isEmpty()) continue;
// Store TStageObject children in case column is emptied and we need to
// restore it
int pegbarsCount = xsh->getStageObjectTree()->getStageObjectCount();
TStageObjectId id = TStageObjectId::ColumnId(i);
TStageObject *pegbar = xsh->getStageObject(id);
for (int k = 0; k < pegbarsCount; ++k) {
TStageObject *other = xsh->getStageObjectTree()->getStageObject(k);
if (other == pegbar) continue;
if (other->getParent() == id) {
// other->setParent(pegbar->getParent());
m_columnObjChildren[id].append(other->getId());
}
}
// Store TStageObject parent in case column is emptied and we need to
// restore it
m_columnObjParents[id] = pegbar->getParent();
TFx *fx = col->getFx();
if (!fx) continue;
int j;
QList<TFxPort *> fxPorts;
for (j = 0; j < fx->getOutputConnectionCount(); j++)
fxPorts.append(fx->getOutputConnection(j));
if (fxPorts.isEmpty()) continue;
m_outputConnections[i] = fxPorts;
}
}
void setCurrentData(int r0, int c0, int r1, int c1) {
@ -443,43 +352,8 @@ public:
int r0, c0, r1, c1;
m_selection->getSelectedCells(r0, c0, r1, c1);
TXsheet *xsh = TApp::instance()->getCurrentXsheet()->getXsheet();
QMap<int, QList<TFxPort *>>::const_iterator it;
for (it = m_outputConnections.begin(); it != m_outputConnections.end();
it++) {
TXshColumn *col = xsh->getColumn(it.key());
QList<TFxPort *> fxPorts = it.value();
int i;
for (i = 0; i < fxPorts.size(); i++) fxPorts[i]->setFx(col->getFx());
}
// Restore TStageObject parent
QMap<TStageObjectId, TStageObjectId>::const_iterator it2;
for (it2 = m_columnObjParents.begin(); it2 != m_columnObjParents.end();
it2++) { // Parents
TStageObject *obj = xsh->getStageObject(it2.key());
if (obj) {
obj->setParent(it2.value());
}
}
// Restore TStageObject children
QMap<TStageObjectId, QList<TStageObjectId>>::const_iterator it3;
for (it3 = m_columnObjChildren.begin(); it3 != m_columnObjChildren.end();
it3++) { // Children
QList<TStageObjectId> children = it3.value();
int i;
for (i = 0; i < children.size(); i++) {
TStageObject *child = xsh->getStageObject(children[i]);
if (child) {
child->setParent(it3.key());
}
}
}
pasteCellsWithoutUndo(m_data, r0, c0, r1, c1, true);
TApp::instance()->getCurrentXsheet()->notifyXsheetChanged();
TApp::instance()->getCurrentObject()->notifyObjectIdSwitched();
}
void redo() const override {
@ -491,6 +365,7 @@ public:
cutCellsWithoutUndo(r0, c0, r1, c1);
clipboard->setMimeData(currentData, QClipboard::Clipboard);
TApp::instance()->getCurrentXsheet()->notifyXsheetChanged();
}
int getSize() const override { return sizeof(*this); }
@ -779,6 +654,8 @@ bool pasteRasterImageInCellWithoutUndo(int row, int col,
app->getCurrentLevel()->setLevel(sl);
app->getCurrentLevel()->notifyLevelChange();
sl->save();
// after saving you need to obtain the image again
img = sl->getFrame(fid, true);
} else {
img = sl->createEmptyFrame();
assert(img);
@ -788,6 +665,8 @@ bool pasteRasterImageInCellWithoutUndo(int row, int col,
sl->setFrame(fid, img);
}
xsh->setCell(row, col, TXshCell(sl, fid));
// to let the undo to know which frame is edited
TTool::m_cellsData.push_back({row, row, TTool::CellOps::BlankToNew});
} else {
sl = cell.getSimpleLevel();
fid = cell.getFrameId();
@ -1785,6 +1664,8 @@ static void pasteRasterImageInCell(int row, int col,
bool newLevel = false) {
TXsheet *xsh = TApp::instance()->getCurrentXsheet()->getXsheet();
// to let the undo to know which frame is edited
TTool::m_cellsData.clear();
bool createdFrame = false;
bool isLevelCreated = false;
TPaletteP oldPalette = 0;
@ -2599,12 +2480,36 @@ void TCellSelection::deleteCells() {
TXsheet *xsh = TApp::instance()->getCurrentXsheet()->getXsheet();
// if all the selected cells are already empty, then do nothing
if (xsh->isRectEmpty(CellPosition(r0, c0), CellPosition(r1, c1))) return;
std::set<int> removedColIds;
// check if the operation may remove expression reference as column becomes
// empty and deleted after the operation.
if (!checkColumnRemoval(r0, c0, r1, c1, removedColIds)) return;
TCellData *data = new TCellData();
data->setCells(xsh, r0, c0, r1, c1);
// clear empty column
if (!removedColIds.empty()) {
TUndoManager::manager()->beginBlock();
// remove, then insert empty column
for (auto colId : removedColIds) {
ColumnCmd::deleteColumn(colId, true);
ColumnCmd::insertEmptyColumn(colId);
}
}
DeleteCellsUndo *undo =
new DeleteCellsUndo(new TCellSelection(m_range), data);
deleteCellsWithoutUndo(r0, c0, r1, c1);
TUndoManager::manager()->add(undo);
if (!removedColIds.empty()) {
TUndoManager::manager()->endBlock();
}
// emit selectionChanged() signal so that the rename field will update
// accordingly
if (Preferences::instance()->isUseArrowKeyToShiftCellSelectionEnabled())
@ -2612,8 +2517,8 @@ void TCellSelection::deleteCells() {
else
selectNone();
TUndoManager::manager()->add(undo);
TApp::instance()->getCurrentScene()->setDirtyFlag(true);
TApp::instance()->getCurrentXsheet()->notifyXsheetChanged();
}
//-----------------------------------------------------------------------------
@ -2631,11 +2536,32 @@ void TCellSelection::cutCells(bool withoutCopy) {
getSelectedCells(r0, c0, r1, c1);
if (c0 < 0) c0 = 0; // Ignore camera column
std::set<int> removedColIds;
// check if the operation may remove expression reference as column becomes
// empty and deleted after the operation.
if (!checkColumnRemoval(r0, c0, r1, c1, removedColIds)) return;
undo->setCurrentData(r0, c0, r1, c1);
if (!withoutCopy) copyCellsWithoutUndo(r0, c0, r1, c1);
// clear empty column
if (!removedColIds.empty()) {
TUndoManager::manager()->beginBlock();
// remove, then insert empty column
for (auto colId : removedColIds) {
ColumnCmd::deleteColumn(colId, true);
ColumnCmd::insertEmptyColumn(colId);
}
}
cutCellsWithoutUndo(r0, c0, r1, c1);
TUndoManager::manager()->add(undo);
if (!removedColIds.empty()) {
TUndoManager::manager()->endBlock();
}
// cutCellsWithoutUndo will clear the selection, so select cells again
if (Preferences::instance()->isUseArrowKeyToShiftCellSelectionEnabled()) {
selectCells(r0, c0, r1, c1);

View file

@ -310,6 +310,9 @@ CleanupPopup::CleanupPopup()
m_imgViewBox->setChecked(false);
m_imageViewer->setVisible(false);
m_imageViewer->resize(406, 306);
ImagePainter::VisualSettings settings;
settings.m_bg = 0x80000; // set to white regardless of the flipbook bg
m_imageViewer->setVisual(settings);
//---layout
QVBoxLayout *mainLayout = new QVBoxLayout();
@ -563,7 +566,8 @@ bool CleanupPopup::analyzeCleanupList() {
}
// Prompt user for file conflict resolution
clt.m_resolution = Resolution(m_overwriteDialog->execute(&clt.m_outputPath));
clt.m_resolution =
Resolution(m_overwriteDialog->execute(&clt.m_outputPath));
switch (clt.m_resolution) {
case CANCEL:
return false;
@ -1253,7 +1257,9 @@ void CleanupPopup::cleanupFrame() {
// Update the level data about the cleanupped frame
sl->setFrameStatus(fid,
sl->getFrameStatus(fid) | TXshSimpleLevel::Cleanupped);
sl->setFrame(fid, TImageP()); // Invalidate the old image data
// sl->setFrame(fid, TImageP()); // Invalidate the old image data
sl->setFrame(fid, ti); // replace with the new image data
// Output the cleanupped image to disk
try {

View file

@ -303,11 +303,13 @@ void ColorModelViewer::pick(const QPoint &p) {
TPointD(viewP.x() - m_imageViewer->width() / 2,
-viewP.y() + m_imageViewer->height() / 2);
double scale2 = m_imageViewer->getViewAff().det();
/*---
Toolに合わせてPickモードを変更
0=Area, 1=Line, 2=Line&Areas(default)
---*/
int styleIndex = picker.pickStyleId(pos + TPointD(-0.5, -0.5), 1, m_mode);
int styleIndex =
picker.pickStyleId(pos + TPointD(-0.5, -0.5), 1, scale2, m_mode);
if (styleIndex < 0) return;

View file

@ -539,10 +539,13 @@ class DeleteColumnsUndo final : public TUndo {
QMap<TStageObjectId, TStageObjectId> m_columnObjParents;
mutable std::unique_ptr<StageObjectsData> m_data;
bool m_onlyColumns;
public:
DeleteColumnsUndo(const std::set<int> &indices)
: m_indices(indices), m_data(new StageObjectsData) {
DeleteColumnsUndo(const std::set<int> &indices, bool onlyColumns)
: m_indices(indices)
, m_data(new StageObjectsData)
, m_onlyColumns(onlyColumns) {
TApp *app = TApp::instance();
TXsheet *xsh = app->getCurrentXsheet()->getXsheet();
@ -597,7 +600,7 @@ public:
m_data->storeColumnFxs(m_indices, xsh, 0);
std::set<int> indices = m_indices;
deleteColumnsWithoutUndo(&indices);
deleteColumnsWithoutUndo(&indices, m_onlyColumns);
}
void undo() const override {
@ -816,8 +819,8 @@ void ColumnCmd::deleteColumns(std::set<int> &indices, bool onlyColumns,
indices.erase(-1); // Ignore camera column
if (indices.empty()) return;
if (!withoutUndo && !onlyColumns)
TUndoManager::manager()->add(new DeleteColumnsUndo(indices));
if (!withoutUndo)
TUndoManager::manager()->add(new DeleteColumnsUndo(indices, onlyColumns));
deleteColumnsWithoutUndo(&indices, onlyColumns);
TApp::instance()->getCurrentScene()->setDirtyFlag(true);
@ -827,10 +830,10 @@ void ColumnCmd::deleteColumns(std::set<int> &indices, bool onlyColumns,
// deleteColumn
//=============================================================================
void ColumnCmd::deleteColumn(int index) {
void ColumnCmd::deleteColumn(int index, bool onlyColumns) {
std::set<int> ii;
ii.insert(index);
ColumnCmd::deleteColumns(ii, false, false);
ColumnCmd::deleteColumns(ii, onlyColumns, false);
}
//=============================================================================
@ -845,7 +848,7 @@ static void cutColumnsWithoutUndo(std::set<int> *indices) {
void ColumnCmd::cutColumns(std::set<int> &indices) {
if (indices.empty()) return;
TUndoManager::manager()->add(new DeleteColumnsUndo(indices));
TUndoManager::manager()->add(new DeleteColumnsUndo(indices, false));
cutColumnsWithoutUndo(&indices);
TApp::instance()->getCurrentScene()->setDirtyFlag(true);

View file

@ -24,7 +24,7 @@ void cutColumns(std::set<int> &indices);
//! deleted
void deleteColumns(std::set<int> &indices, bool onlyColumns, bool withoutUndo);
//! helper function: deletes a single column, with undo
void deleteColumn(int index);
void deleteColumn(int index, bool onlyColumns = false);
//! if data==0 then uses clipboard
void pasteColumns(std::set<int> &indices, const StageObjectsData *data = 0);
//! helper function: copies srcIndex column and pastes it before dstIndex. Does

View file

@ -412,8 +412,11 @@ std::map<TFrameId, QString> clearFramesWithoutUndo(
"-" + QString::number(it->getNumber());
TImageCache::instance()->add(id, sl->getFrame(frameId, false));
clearedFrames[frameId] = id;
// empty frame must be created BEFORE erasing frame or it may initialize
// palette.
TImageP emptyFrame = sl->createEmptyFrame();
sl->eraseFrame(frameId);
sl->setFrame(*it, sl->createEmptyFrame());
sl->setFrame(*it, emptyFrame);
}
invalidateIcons(sl.getPointer(), frames);
TApp::instance()->getCurrentLevel()->notifyLevelChange();

View file

@ -1345,6 +1345,8 @@ void ImageViewer::onContextAboutToBeDestroyed() {
makeCurrent();
m_lutCalibrator->cleanup();
doneCurrent();
disconnect(context(), SIGNAL(aboutToBeDestroyed()), this,
SLOT(onContextAboutToBeDestroyed()));
}
//-----------------------------------------------------------------------------
@ -1352,6 +1354,9 @@ void ImageViewer::onContextAboutToBeDestroyed() {
void ImageViewer::onPreferenceChanged(const QString& prefName) {
if (prefName == "ColorCalibration") {
if (Preferences::instance()->isColorCalibrationEnabled()) {
// if the window is so shriked that the gl widget is empty,
// showEvent can be called before creating the context.
if (!context()) return;
makeCurrent();
if (!m_lutCalibrator)
m_lutCalibrator = new LutCalibrator();

View file

@ -671,6 +671,16 @@ void ChildLevelResourceImporter::process(TXshSimpleLevel *sl) {
sl->load();
} catch (...) {
}
// Check if the scene saved with the previous version AND the premultiply
// option is set to PNG level setting
if (m_childScene->getVersionNumber() <
VersionNumber(71, 1)) { // V1.4 = 71.0 , V1.5 = 71.1
if (!path.isEmpty() && path.getType() == "png" &&
sl->getProperties()->doPremultiply())
sl->getProperties()->setDoPremultiply(false);
}
sl->release();
}
@ -1994,6 +2004,31 @@ bool IoCmd::loadScene(const TFilePath &path, bool updateRecentFile,
}
}
// Check if the scene saved with the previous version AND the premultiply
// option is set to PNG level setting
if (scene->getVersionNumber() <
VersionNumber(71, 1)) { // V1.4 = 71.0 , V1.5 = 71.1
QStringList modifiedPNGLevelNames;
std::vector<TXshLevel *> levels;
scene->getLevelSet()->listLevels(levels);
for (auto level : levels) {
if (!level || !level->getSimpleLevel()) continue;
TFilePath path = level->getPath();
if (path.isEmpty() || path.getType() != "png") continue;
if (level->getSimpleLevel()->getProperties()->doPremultiply()) {
level->getSimpleLevel()->getProperties()->setDoPremultiply(false);
modifiedPNGLevelNames.append(QString::fromStdWString(level->getName()));
}
}
if (!modifiedPNGLevelNames.isEmpty()) {
DVGui::info(QObject::tr("The Premultiply options in the following levels "
"are disabled, since PNG files are premultiplied "
"on loading in the current version: %1")
.arg(modifiedPNGLevelNames.join(", ")));
app->getCurrentScene()->setDirtyFlag(true);
}
}
printf("%s:%s loadScene() completed :\n", __FILE__, __FUNCTION__);
return true;
}

View file

@ -55,6 +55,9 @@
#include <QPushButton>
#include <QLabel>
#include <QMessageBox>
#ifdef _WIN32
#include <QtPlatformHeaders/QWindowsWindowFunctions>
#endif
TEnv::IntVar ViewCameraToggleAction("ViewCameraToggleAction", 1);
TEnv::IntVar ViewTableToggleAction("ViewTableToggleAction", 0);
@ -1264,9 +1267,16 @@ void MainWindow::maximizePanel() {
void MainWindow::fullScreenWindow() {
if (isFullScreen())
setWindowState(Qt::WindowMaximized);
else
setWindowState(Qt::WindowFullScreen);
showNormal();
else {
#if defined(_WIN32)
// http://doc.qt.io/qt-5/windows-issues.html#fullscreen-opengl-based-windows
this->winId();
QWindowsWindowFunctions::setHasBorderInFullScreen(this->windowHandle(),
true);
#endif
this->showFullScreen();
}
}
//-----------------------------------------------------------------------------

View file

@ -263,34 +263,23 @@ void TPanelTitleBarButton::setPressed(bool pressed) {
//-----------------------------------------------------------------------------
void TPanelTitleBarButton::paintEvent(QPaintEvent *event) {
// Set unique pressed colors if filename contains the following words:
QColor bgColor = getPressedColor();
if (m_standardPixmapName.contains("freeze", Qt::CaseInsensitive))
bgColor = getFreezeColor();
if (m_standardPixmapName.contains("preview", Qt::CaseInsensitive))
bgColor = getPreviewColor();
QPixmap panePixmap = recolorPixmap(svgToPixmap(m_standardPixmapName));
QPixmap panePixmapOff = compositePixmap(panePixmap, 0.8);
QPixmap panePixmapOver =
compositePixmap(panePixmap, 1, QSize(), 0, 0, getOverColor());
QPixmap panePixmapOn = compositePixmap(panePixmap, 1, QSize(), 0, 0, bgColor);
QPainter painter(this);
// Create color states for the button
QPixmap normalPixmap(m_standardPixmap.size());
QPixmap onPixmap(m_standardPixmap.size());
QPixmap overPixmap(m_standardPixmap.size());
normalPixmap.fill(Qt::transparent);
onPixmap.fill(QColor(getPressedColor()));
overPixmap.fill(QColor(getOverColor()));
// Set unique 'pressed' colors if filename contains...
if (m_standardPixmapName.contains("freeze", Qt::CaseInsensitive)) {
onPixmap.fill(QColor(getFreezeColor()));
}
if (m_standardPixmapName.contains("preview", Qt::CaseInsensitive)) {
onPixmap.fill(QColor(getPreviewColor()));
}
// Compose the state colors
painter.drawPixmap(
0, 0, m_pressed ? onPixmap : m_rollover ? overPixmap : normalPixmap);
// Icon
QPixmap panePixmap = recolorPixmap(m_standardPixmap);
QPixmap paneOffPixmap = setOpacity(panePixmap, 0.8);
painter.drawPixmap(
0, 0, m_pressed ? panePixmap : m_rollover ? panePixmap : paneOffPixmap);
0, 0,
m_pressed ? panePixmapOn : m_rollover ? panePixmapOver : panePixmapOff);
painter.end();
}

View file

@ -1209,6 +1209,9 @@ void SceneViewer::onStopMotionLiveViewStopped() {
void SceneViewer::onPreferenceChanged(const QString &prefName) {
if (prefName == "ColorCalibration") {
if (Preferences::instance()->isColorCalibrationEnabled()) {
// if the window is so shriked that the gl widget is empty,
// showEvent can be called before creating the context.
if (!context()) return;
makeCurrent();
if (!m_lutCalibrator)
m_lutCalibrator = new LutCalibrator();
@ -3555,6 +3558,8 @@ void SceneViewer::onContextAboutToBeDestroyed() {
makeCurrent();
m_lutCalibrator->cleanup();
doneCurrent();
disconnect(context(), SIGNAL(aboutToBeDestroyed()), this,
SLOT(onContextAboutToBeDestroyed()));
}
//-----------------------------------------------------------------------------

View file

@ -16,6 +16,8 @@
#include "comboviewerpane.h"
#include "locatorpopup.h"
#include "cellselection.h"
#include "styleshortcutswitchablepanel.h"
#include "stopmotion.h"
#include "tstopwatch.h"
@ -1634,6 +1636,15 @@ void SceneViewer::keyPressEvent(QKeyEvent *event) {
event->modifiers() == Qt::KeypadModifier) &&
((Qt::Key_0 <= key && key <= Qt::Key_9) || key == Qt::Key_Tab ||
key == Qt::Key_Backtab)) {
// When the viewer is in full screen mode, directly call the style
// shortcut function since the viewer is retrieved from the parent
// panel.
if (parentWidget() &&
parentWidget()->windowState() & Qt::WindowFullScreen) {
StyleShortcutSwitchablePanel::onKeyPress(event);
return true;
}
event->ignore();
return true;
}

View file

@ -21,7 +21,7 @@
//-----------------------------------------------------------------------------
void StyleShortcutSwitchablePanel::keyPressEvent(QKeyEvent *event) {
void StyleShortcutSwitchablePanel::onKeyPress(QKeyEvent *event) {
if (!Preferences::instance()->isUseNumpadForSwitchingStylesEnabled()) return;
TTool *tool = TApp::instance()->getCurrentTool()->getTool();
if (!tool) return;
@ -57,6 +57,11 @@ void StyleShortcutSwitchablePanel::keyPressEvent(QKeyEvent *event) {
event->accept();
}
}
//-----------------------------------------------------------------------------
void StyleShortcutSwitchablePanel::keyPressEvent(QKeyEvent *event) {
StyleShortcutSwitchablePanel::onKeyPress(event);
}
//-----------------------------------------------------------------------------

View file

@ -26,6 +26,8 @@ public:
TDockWidget::Orientation orientation = TDockWidget::vertical)
: TPanel(parent, flags, orientation) {}
static void onKeyPress(QKeyEvent *event);
protected:
void keyPressEvent(QKeyEvent *event) override;
void showEvent(QShowEvent *) override;

View file

@ -463,6 +463,8 @@ bool XdtsIo::loadXdtsScene(ToonzScene *scene, const TFilePath &scenePath) {
// obtain level names
QStringList levelNames = xdtsData.getLevelNames();
// in case multiple columns have the same name
levelNames.removeDuplicates();
scene->clear();

View file

@ -474,15 +474,12 @@ NoteArea::NoteArea(XsheetViewer *parent, Qt::WFlags flags)
m_layerHeaderPanel = new LayerHeaderPanel(m_viewer, this);
//-----
//
// m_flipOrientationButton->setObjectName("flipOrientationButton");
// m_flipOrientationButton->setFocusPolicy(Qt::FocusPolicy::NoFocus);
// m_flipOrientationButton->setFixedSize(QSize(70, 23));
// m_flipOrientationButton->setIconSize(QSize(40, 20));
// QIcon flipOrientationIcon;
// flipOrientationIcon.addFile(QString(":Resources/xsheet2timeline.svg"),
// QSize(), QIcon::Normal);
// m_flipOrientationButton->setIcon(flipOrientationIcon);
// m_flipOrientationButton->setIconSize(QSize(20, 20));
// m_flipOrientationButton->setIcon(createQIcon("toggle_xsheet_orientation"));
// m_flipOrientationButton->setToolTip(tr("Toggle Xsheet/Timeline"));
m_newLevelButton->setObjectName("ToolbarToolButton");
@ -646,12 +643,8 @@ void NoteArea::updateButtons() {
void NoteArea::onXsheetOrientationChanged(const Orientation *newOrientation) {
// m_flipOrientationButton->setText(newOrientation->caption());
// QIcon flipOrientationIcon;
// QString iconFile = newOrientation->isVerticalTimeline()
// ? QString(":Resources/xsheet2timeline.svg")
// : QString(":Resources/timeline2xsheet.svg");
// flipOrientationIcon.addFile(iconFile, QSize(), QIcon::Normal);
// m_flipOrientationButton->setIcon(flipOrientationIcon);
// m_flipOrientationButton->setIcon(createQIcon("toggle_xsheet_orientation"));
// m_flipOrientationButton->setIconSize(QSize(20, 20));
removeLayout();
createLayout();

View file

@ -109,9 +109,10 @@ void getDefaultLevelFormats(LevelFormatVector &lfv) {
lfv[1].m_options.m_premultiply = true;
// for all PNG files, set premultiply by default
lfv[2].m_name = Preferences::tr("PNG");
lfv[2].m_pathFormat = QRegExp("..*\\.png", Qt::CaseInsensitive);
lfv[2].m_options.m_premultiply = true;
// UPDATE : from V1.5, PNG images are premultiplied on loading
// lfv[2].m_name = Preferences::tr("PNG");
// lfv[2].m_pathFormat = QRegExp("..*\\.png",
// Qt::CaseInsensitive); lfv[2].m_options.m_premultiply = true;
}
}
@ -193,6 +194,32 @@ void getValue(QSettings &settings,
getValue(settings, lfv[lf]);
}
settings.endArray();
// from OT V1.5, PNG images are premultiplied on loading.
// Leaving the premultiply option will cause unwanted double operation.
// So, check the loaded options and modify it "silently".
bool changed = false;
LevelFormatVector::iterator it = lfv.begin();
while (it != lfv.end()) {
if ((*it).m_name == Preferences::tr("PNG") &&
(*it).m_pathFormat == QRegExp("..*\\.png", Qt::CaseInsensitive) &&
(*it).m_options.m_premultiply == true) {
LevelOptions defaultValue;
defaultValue.m_premultiply = true;
// if other parameters are the same as deafault, just erase the item
if ((*it).m_options == defaultValue) it = lfv.erase(it);
// if there are some adjustments by user, then disable only premultiply
// option
else {
(*it).m_options.m_premultiply = false;
++it;
}
changed = true;
} else
++it;
}
// overwrite the setting
if (changed) _setValue(settings, lfv);
}
} // namespace

View file

@ -1405,6 +1405,7 @@ void onMeshImage(TMeshImage *mi, const Stage::Player &player,
// Prepare OpenGL
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_LINE_SMOOTH);
// Push mesh coordinates
@ -1581,6 +1582,7 @@ void onPlasticDeformedImage(TStageObject *playerObj,
// Set up OpenGL stuff
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_LINE_SMOOTH);
// Push mesh coordinates

View file

@ -591,7 +591,7 @@ void StudioPaletteCmd::mergeIntoCurrentPalette(TPaletteHandle *paletteHandle,
TUndoManager::manager()->add(
new PaletteAssignUndo(current, old, current->clone(), paletteHandle));
palette->setDirtyFlag(true);
current->setDirtyFlag(true);
paletteHandle->notifyPaletteChanged();
}

View file

@ -60,8 +60,11 @@ TOfflineGL *currentOfflineGL = 0;
// Utility functions
//=============================================================================
namespace {
const VersionNumber l_currentVersion(71, 0);
// tentatively update the scene file version from 71.0 to 71.1 in order to
// manage PNG level settings
const VersionNumber l_currentVersion(71, 1);
// TODO: Revise VersionNumber with OT version (converting 71.0 -> 14.0 , 71.1
// -> 15.0)
//-----------------------------------------------------------------------------
@ -345,12 +348,9 @@ bool ToonzScene::isUntitled() const {
//-----------------------------------------------------------------------------
void ToonzScene::load(const TFilePath &path, bool withProgressDialog) {
loadNoResources(path); // This loads a version number ..
loadResources(withProgressDialog); // .. this uses the version number ..
setVersionNumber(
VersionNumber()); // .. but scene instances in memory do not retain
} // a version number beyond resource loading
loadNoResources(path);
loadResources(withProgressDialog);
}
//-----------------------------------------------------------------------------
@ -456,6 +456,8 @@ void ToonzScene::loadTnzFile(const TFilePath &fp) {
while (is.matchTag(tagName)) {
if (tagName == "generator") {
std::string program = is.getString();
// TODO: This obsolete condition should be removed before releasing OT
// v2.2 !
reading22 = program.find("2.2") != std::string::npos;
} else if (tagName == "properties")
m_properties->loadData(is, false);
@ -685,6 +687,8 @@ void ToonzScene::save(const TFilePath &fp, TXsheet *subxsh) {
} else {
if (wasUntitled) deleteUntitledScene(oldScenePath.getParentDir());
}
// update the last saved version
setVersionNumber(l_currentVersion);
}
//-----------------------------------------------------------------------------

View file

@ -840,10 +840,15 @@ void TXshSimpleLevel::eraseFrame(const TFrameId &fid) {
getHookSet()->eraseFrame(fid);
ImageManager *im = ImageManager::instance();
TImageCache *ic = TImageCache::instance();
{
im->unbind(getImageId(fid, Normal));
im->unbind(getImageId(fid, Scanned));
im->unbind(getImageId(fid, CleanupPreview));
// remove icon cache as well
ic->remove(getIconId(fid, Normal));
ic->remove(getIconId(fid, Scanned));
ic->remove(getIconId(fid, CleanupPreview));
if (m_type == PLI_XSHLEVEL) im->unbind(rasterized(getImageId(fid)));
@ -858,13 +863,17 @@ void TXshSimpleLevel::eraseFrame(const TFrameId &fid) {
void TXshSimpleLevel::clearFrames() {
ImageManager *im = ImageManager::instance();
TImageCache *ic = TImageCache::instance();
// Unbind frames
FramesSet::iterator ft, fEnd = m_frames.end();
for (ft = m_frames.begin(); ft != fEnd; ++ft) {
im->unbind(getImageId(*ft, Scanned));
im->unbind(getImageId(*ft, Cleanupped));
im->unbind(getImageId(*ft, CleanupPreview));
// remove icon cache as well
ic->remove(getIconId(*ft, Normal));
ic->remove(getIconId(*ft, Scanned));
ic->remove(getIconId(*ft, CleanupPreview));
if (m_type == PLI_XSHLEVEL) im->unbind(rasterized(getImageId(*ft)));

View file

@ -1935,14 +1935,15 @@ void FxSchematicScene::simulateDisconnectSelection(bool disconnect) {
void FxSchematicScene::simulateInsertSelection(SchematicLink *link,
bool connect) {
if (!link || !connect) {
// first, remove all connected links
m_connectionLinks.showBridgeLinks();
m_connectionLinks.hideInputLinks();
m_connectionLinks.hideOutputLinks();
m_connectionLinks.removeBridgeLinks();
m_connectionLinks.removeInputLinks(true);
m_connectionLinks.removeOutputLinks(true);
} else {
if (!link || !connect) return;
if (m_disconnectionLinks.isABridgeLink(link) || m_selection->isEmpty())
return;
@ -1986,7 +1987,7 @@ void FxSchematicScene::simulateInsertSelection(SchematicLink *link,
m_connectionLinks.showInputLinks();
m_connectionLinks.showOutputLinks();
}
}
//------------------------------------------------------------
/*! in order to select nods after pasting the copied fx nodes from FxSelection
*/

View file

@ -222,26 +222,27 @@ QString getIconThemePath(const QString &fileSVGPath) {
//-----------------------------------------------------------------------------
QPixmap setOpacity(QPixmap pixmap, const qreal &opacity) {
QPixmap compositePixmap(QPixmap pixmap, const qreal &opacity, const QSize &size,
const int leftAdj, const int topAdj, QColor bgColor) {
static int devPixRatio = getDevPixRatio();
const QSize pixmapSize(pixmap.width() * devPixRatio,
pixmap.height() * devPixRatio);
QPixmap opacityPixmap(pixmapSize);
opacityPixmap.setDevicePixelRatio(devPixRatio);
opacityPixmap.fill(Qt::transparent);
// Sets size of destination pixmap for source to be drawn onto, if size is
// empty use source pixmap size, else use custom size.
QPixmap destination(size.isEmpty() ? pixmap.size() : size * devPixRatio);
destination.setDevicePixelRatio(devPixRatio);
destination.fill(bgColor);
if (!pixmap.isNull()) {
QPainter p(&opacityPixmap);
QPixmap normalPixmap = pixmap.scaled(pixmapSize, Qt::KeepAspectRatio);
normalPixmap.setDevicePixelRatio(devPixRatio);
QPainter p(&destination);
pixmap = pixmap.scaled(pixmap.size(), Qt::KeepAspectRatio);
pixmap.setDevicePixelRatio(devPixRatio);
p.setBackgroundMode(Qt::TransparentMode);
p.setBackground(QBrush(Qt::transparent));
p.eraseRect(normalPixmap.rect());
p.eraseRect(pixmap.rect());
p.setOpacity(opacity);
p.drawPixmap(0, 0, normalPixmap);
p.drawPixmap(leftAdj, topAdj, pixmap);
}
return opacityPixmap;
return destination;
}
//-----------------------------------------------------------------------------
@ -266,138 +267,126 @@ QPixmap recolorPixmap(QPixmap pixmap, QColor color) {
//-----------------------------------------------------------------------------
QPixmap compositePixmap(QPixmap pixmap, qreal opacity, int canvasWidth,
int canvasHeight, int iconWidth, int iconHeight,
int offset) {
/* Creates a composite pixmap from two pixmaps. The canvas controls the final
* size, whereas pixmap is the image to be composited ontop. You can control
* the position of pixmap by setting an offset (top-left), default is 0. */
static int devPixRatio = getDevPixRatio();
QPixmap canvas(canvasWidth, canvasHeight);
canvas.fill(Qt::transparent); // set this to a color to debug
QPixmap combined(canvasWidth, canvasHeight);
combined.fill(Qt::transparent);
if (!pixmap.isNull()) {
QPainter painter;
painter.begin(&combined);
QRect canvasRect(0, 0, canvasWidth, canvasHeight);
painter.drawPixmap(canvasRect, canvas);
painter.setOpacity(opacity);
QRect iconRect(offset, offset, iconWidth, iconHeight);
painter.drawPixmap(iconRect, pixmap);
painter.end();
}
return combined;
}
//-----------------------------------------------------------------------------
QIcon createQIcon(const char *iconSVGName, bool useFullOpacity) {
static int devPixRatio = getDevPixRatio();
// get icon size
QIcon themeIcon = QIcon::fromTheme(iconSVGName);
// Get icon dimensions
QSize iconSize(0, 0);
for (QList<QSize> sizes = themeIcon.availableSizes(); !sizes.isEmpty();
sizes.removeFirst())
if (sizes.first().width() > iconSize.width()) iconSize = sizes.first();
if (sizes.first().width() > iconSize.width())
iconSize = sizes.first() * devPixRatio;
// Control lightness of the icons
const qreal activeOpacity = 1;
const qreal baseOpacity = useFullOpacity ? 1 : 0.8;
const qreal disabledOpacity = 0.15;
// Psuedo state name strings
QString overStr = QString(iconSVGName) + "_over";
QString onStr = QString(iconSVGName) + "_on";
QPixmap themeIconPixmap = recolorPixmap(themeIcon.pixmap(iconSize));
QPixmap overPixmap =
recolorPixmap(QIcon::fromTheme(overStr).pixmap(iconSize));
QPixmap onPixmap = recolorPixmap(QIcon::fromTheme(onStr).pixmap(iconSize));
//----------
// Base pixmap
QPixmap themeIconPixmap(recolorPixmap(themeIcon.pixmap(iconSize)));
if (!themeIconPixmap.isNull()) { // suppress message
themeIconPixmap.setDevicePixelRatio(devPixRatio);
themeIconPixmap = themeIconPixmap.scaled(iconSize, Qt::KeepAspectRatio,
Qt::SmoothTransformation);
}
// Over pixmap
QPixmap overPixmap(recolorPixmap(QIcon::fromTheme(overStr).pixmap(iconSize)));
if (!overPixmap.isNull()) { // suppress message
overPixmap.setDevicePixelRatio(devPixRatio);
overPixmap = overPixmap.scaled(iconSize, Qt::KeepAspectRatio,
Qt::SmoothTransformation);
}
// On pixmap
QPixmap onPixmap(recolorPixmap(QIcon::fromTheme(onStr).pixmap(iconSize)));
if (!onPixmap.isNull()) { // suppress message
onPixmap.setDevicePixelRatio(devPixRatio);
onPixmap = onPixmap.scaled(iconSize, Qt::KeepAspectRatio,
Qt::SmoothTransformation);
}
//----------
QIcon icon;
// build icon
for (int devPixRatio = 1; devPixRatio <= 2; devPixRatio++) {
int iconW = themeIconPixmap.width();
int iconH = themeIconPixmap.height();
int canvasW = iconW;
int canvasH = iconH;
int offset = 0;
const qreal normalOpacity = useFullOpacity ? 1 : 0.8;
const qreal disabledOpacity = 0.15;
const qreal onOpacity = 1;
// Base icon
icon.addPixmap(compositePixmap(themeIconPixmap, baseOpacity), QIcon::Normal,
QIcon::Off);
icon.addPixmap(compositePixmap(themeIconPixmap, disabledOpacity),
QIcon::Disabled, QIcon::Off);
// off
icon.addPixmap(compositePixmap(themeIconPixmap, normalOpacity, canvasW,
canvasH, iconW, iconH),
QIcon::Normal, QIcon::Off);
icon.addPixmap(compositePixmap(themeIconPixmap, disabledOpacity, canvasW,
canvasH, iconW, iconH),
QIcon::Disabled);
// over
icon.addPixmap(
compositePixmap(!overPixmap.isNull() ? overPixmap : themeIconPixmap,
onOpacity, canvasW, canvasH, iconW, iconH),
// Over icon
icon.addPixmap(!overPixmap.isNull()
? compositePixmap(overPixmap, activeOpacity)
: compositePixmap(themeIconPixmap, activeOpacity),
QIcon::Active);
// on
// On icon
if (!onPixmap.isNull()) {
icon.addPixmap(
compositePixmap(onPixmap, onOpacity, canvasW, canvasH, iconW, iconH),
QIcon::Normal, QIcon::On);
icon.addPixmap(compositePixmap(onPixmap, normalOpacity, canvasW, canvasH,
iconW, iconH),
QIcon::Disabled, QIcon::On);
icon.addPixmap(compositePixmap(onPixmap, activeOpacity), QIcon::Normal,
QIcon::On);
icon.addPixmap(compositePixmap(onPixmap, disabledOpacity), QIcon::Disabled,
QIcon::On);
} else {
icon.addPixmap(compositePixmap(themeIconPixmap, onOpacity, canvasW,
canvasH, iconW, iconH),
icon.addPixmap(compositePixmap(themeIconPixmap, activeOpacity),
QIcon::Normal, QIcon::On);
icon.addPixmap(compositePixmap(themeIconPixmap, disabledOpacity, canvasW,
canvasH, iconW, iconH),
icon.addPixmap(compositePixmap(themeIconPixmap, disabledOpacity),
QIcon::Disabled, QIcon::On);
}
/* If size is 16x16 (suitable for menu) we composite it onto a separate
* 20x20 pixmap so that it is compatible with toolbars, otherwise it will be
* scaled up and blur. You need to add icons to all QIcon modes otherwise it
* will use the original size, which is undesirable. This is equal to having
* two sets loaded into the icon (16x16 and 20x20) and is dynamically used
* depending on iconSize for toolbars.
*/
if (iconSize == (QSize(16, 16))) {
canvasW = 20 * devPixRatio;
canvasH = 20 * devPixRatio;
offset = 2 * devPixRatio;
//----------
// off
icon.addPixmap(compositePixmap(themeIconPixmap, normalOpacity, canvasW,
canvasH, iconW, iconH, offset),
QIcon::Normal, QIcon::Off);
icon.addPixmap(compositePixmap(themeIconPixmap, disabledOpacity, canvasW,
canvasH, iconW, iconH, offset),
QIcon::Disabled);
// over
// For icons intended for menus that are 16x16 in dimensions, to repurpose
// them for use in toolbars that are set for 20x20 we want to draw them onto a
// 20x20 pixmap so they don't get resized in the GUI, they will be loaded into
// the icon along with the original 16x16 pixmap.
if (themeIconPixmap.size() == QSize(16 * devPixRatio, 16 * devPixRatio)) {
const QSize drawOnSize(20, 20);
const int x = (drawOnSize.width() - 16) / 2; // left adjust
const int y = (drawOnSize.height() - 16) / 2; // top adjust
// Base icon
icon.addPixmap(
compositePixmap(!overPixmap.isNull() ? overPixmap : themeIconPixmap,
onOpacity, canvasW, canvasH, iconW, iconH, offset),
compositePixmap(themeIconPixmap, baseOpacity, drawOnSize, x, y),
QIcon::Normal, QIcon::Off);
icon.addPixmap(
compositePixmap(themeIconPixmap, disabledOpacity, drawOnSize, x, y),
QIcon::Disabled, QIcon::Off);
// Over icon
icon.addPixmap(
!overPixmap.isNull()
? compositePixmap(overPixmap, activeOpacity, drawOnSize, x, y)
: compositePixmap(themeIconPixmap, activeOpacity, drawOnSize, x, y),
QIcon::Active);
// on
// On icon
if (!onPixmap.isNull()) {
icon.addPixmap(compositePixmap(onPixmap, onOpacity, canvasW, canvasH,
iconW, iconH, offset),
icon.addPixmap(compositePixmap(onPixmap, activeOpacity, drawOnSize, x, y),
QIcon::Normal, QIcon::On);
icon.addPixmap(compositePixmap(onPixmap, disabledOpacity, canvasW,
canvasH, iconW, iconH, offset),
icon.addPixmap(
compositePixmap(onPixmap, disabledOpacity, drawOnSize, x, y),
QIcon::Disabled, QIcon::On);
} else {
icon.addPixmap(compositePixmap(themeIconPixmap, onOpacity, canvasW,
canvasH, iconW, iconH, offset),
icon.addPixmap(
compositePixmap(themeIconPixmap, activeOpacity, drawOnSize, x, y),
QIcon::Normal, QIcon::On);
icon.addPixmap(compositePixmap(themeIconPixmap, disabledOpacity,
canvasW, canvasH, iconW, iconH, offset),
icon.addPixmap(
compositePixmap(themeIconPixmap, disabledOpacity, drawOnSize, x, y),
QIcon::Disabled, QIcon::On);
}
}
}
return icon;
}
@ -439,9 +428,9 @@ QIcon createQIconOnOffPNG(const char *iconPNGName, bool withOver) {
QIcon createTemporaryIconFromName(const char *commandName) {
const int visibleIconSize = 20;
const int menubarIconSize = 16;
const qreal normalOpacity = 0.8;
const qreal activeOpacity = 1;
const qreal baseOpacity = 0.8;
const qreal disabledOpacity = 0.15;
const qreal onOpacity = 1;
QString name(commandName);
QList<QChar> iconChar;
@ -495,22 +484,23 @@ QIcon createTemporaryIconFromName(const char *commandName) {
painter.end();
// For menu only
icon.addPixmap(transparentPm, QIcon::Normal, QIcon::Off);
icon.addPixmap(transparentPm, QIcon::Active);
icon.addPixmap(transparentPm, QIcon::Normal, QIcon::On);
icon.addPixmap(transparentPm, QIcon::Disabled);
icon.addPixmap(compositePixmap(pixmap, normalOpacity, pxSize, pxSize,
pixmap.width(), pixmap.height()),
QIcon::Normal, QIcon::Off);
icon.addPixmap(compositePixmap(pixmap, onOpacity, pxSize, pxSize,
pixmap.width(), pixmap.height()),
QIcon::Normal, QIcon::On);
icon.addPixmap(compositePixmap(pixmap, onOpacity, pxSize, pxSize,
pixmap.width(), pixmap.height()),
QIcon::Active);
icon.addPixmap(compositePixmap(pixmap, disabledOpacity, pxSize, pxSize,
pixmap.width(), pixmap.height()),
QIcon::Disabled);
icon.addPixmap(transparentPm, QIcon::Disabled, QIcon::Off);
icon.addPixmap(transparentPm, QIcon::Disabled, QIcon::On);
// For toolbars
icon.addPixmap(compositePixmap(pixmap, baseOpacity), QIcon::Normal,
QIcon::Off);
icon.addPixmap(compositePixmap(pixmap, disabledOpacity), QIcon::Disabled,
QIcon::Off);
icon.addPixmap(compositePixmap(pixmap, activeOpacity), QIcon::Active);
icon.addPixmap(compositePixmap(pixmap, activeOpacity), QIcon::Normal,
QIcon::On);
icon.addPixmap(compositePixmap(pixmap, disabledOpacity), QIcon::Disabled,
QIcon::On);
}
return icon;
}

View file

@ -929,7 +929,6 @@ bool FullScreenWidget::toggleFullScreen(
// Define some constants for setting and clearing window flags.
const Qt::WindowFlags kwfFullScreenWidgetFlags =
Qt::Window | // <-- Make the widget become a window.
Qt::WindowStaysOnTopHint | // <-- Ensure the window stays on top.
Qt::FramelessWindowHint; // <-- Full screen windows have no border.
const Qt::WindowFlags kwfFullScreenWidgetExcludedFlagsMask =
@ -1032,8 +1031,7 @@ bool FullScreenWidget::toggleFullScreen(
// effect.
this->show();
#else
this->setWindowFlags(this->windowFlags() | Qt::Window |
Qt::WindowStaysOnTopHint);
this->setWindowFlags(this->windowFlags() | Qt::Window);
this->window()->windowHandle()->setScreen(ptrScreenThisWindowIsOn);
// http://doc.qt.io/qt-5/windows-issues.html#fullscreen-opengl-based-windows

View file

@ -989,6 +989,8 @@ void HexagonalColorWheel::onContextAboutToBeDestroyed() {
makeCurrent();
m_lutCalibrator->cleanup();
doneCurrent();
disconnect(context(), SIGNAL(aboutToBeDestroyed()), this,
SLOT(onContextAboutToBeDestroyed()));
}
//*****************************************************************************

View file

@ -185,6 +185,10 @@ void TreeModel::endRefresh() {
int i;
QList<Item *>::iterator it;
// comment out as no subclass of TreeModel reimplement removeRows() for now
// and it causes assertion failure on calling beginRemoveRows() when deleting
// the last column in the xsheet
/*
for (i = m_itemsToDelete.size() - 1; i >= 0; i--) {
int row = m_itemsToDelete[i]->getRow();
Item *parentItem = m_itemsToDelete[i]->getParent();
@ -192,10 +196,11 @@ void TreeModel::endRefresh() {
parentItem ? parentItem->createIndex() : QModelIndex();
beginRemoveRows(parentIndex, row, row);
removeRow(row, parentIndex); // NOTE: This is currently doing NOTHING? (see
removeRows(row, 1, parentIndex); // NOTE: This is currently doing NOTHING?
(see
// Qt's manual)
endRemoveRows();
}
}*/
qDeleteAll(m_itemsToDelete);
m_itemsToDelete.clear();