diff --git a/krita/krita4.xmlgui b/krita/krita4.xmlgui
--- a/krita/krita4.xmlgui
+++ b/krita/krita4.xmlgui
@@ -73,7 +73,17 @@
&View
-
+
+
+
+
+
diff --git a/krita/kritamenu.action b/krita/kritamenu.action
--- a/krita/kritamenu.action
+++ b/krita/kritamenu.action
@@ -597,6 +597,36 @@
true
+
+
+
+ &Show Horizontal Wrap Around
+
+ Show Horizontal Wrap Around
+ Show Horizontal Wrap Around
+ 1
+ 0
+
+ true
+
+
+
+
+
+ &Show Vertical Wrap Around
+
+ Show Vertical Wrap Around
+ Show Vertical Wrap Around
+ 1
+ 0
+
+ true
+
+
+
+
+
+
&Instant Preview Mode
diff --git a/libs/global/kis_config_notifier.h b/libs/global/kis_config_notifier.h
--- a/libs/global/kis_config_notifier.h
+++ b/libs/global/kis_config_notifier.h
@@ -47,6 +47,7 @@
void notifyDropFramesModeChanged();
void notifyPixelGridModeChanged();
+ void notifyWraparoundModeChanged();
Q_SIGNALS:
/**
@@ -55,6 +56,7 @@
void configChanged(void);
void dropFramesModeChanged();
void pixelGridModeChanged();
+ void wraparoundModeChanged();
private:
KisConfigNotifier(const KisConfigNotifier&);
KisConfigNotifier operator=(const KisConfigNotifier&);
diff --git a/libs/global/kis_config_notifier.cpp b/libs/global/kis_config_notifier.cpp
--- a/libs/global/kis_config_notifier.cpp
+++ b/libs/global/kis_config_notifier.cpp
@@ -61,3 +61,9 @@
{
emit pixelGridModeChanged();
}
+
+void KisConfigNotifier::notifyWraparoundModeChanged()
+{
+ emit wraparoundModeChanged();
+}
+
diff --git a/libs/ui/KisViewManager.cpp b/libs/ui/KisViewManager.cpp
--- a/libs/ui/KisViewManager.cpp
+++ b/libs/ui/KisViewManager.cpp
@@ -165,6 +165,8 @@
, rotateCanvasLeft(0)
, resetCanvasRotation(0)
, wrapAroundAction(0)
+ , wrapAroundHorizontalAction(0)
+ , wrapAroundVerticalAction(0)
, levelOfDetailAction(0)
, showRulersAction(0)
, rulersTrackMouseAction(0)
@@ -206,6 +208,8 @@
KisAction *rotateCanvasLeft;
KisAction *resetCanvasRotation;
KisAction *wrapAroundAction;
+ KisAction *wrapAroundHorizontalAction;
+ KisAction *wrapAroundVerticalAction;
KisAction *levelOfDetailAction;
KisAction *showRulersAction;
KisAction *rulersTrackMouseAction;
@@ -459,6 +463,12 @@
d->viewConnections.addUniqueConnection(d->wrapAroundAction, SIGNAL(toggled(bool)), canvasController, SLOT(slotToggleWrapAroundMode(bool)));
d->wrapAroundAction->setChecked(canvasController->wrapAroundMode());
+
+ d->viewConnections.addUniqueConnection(d->wrapAroundHorizontalAction, SIGNAL(toggled(bool)), canvasController, SLOT(slotToggleWrapAroundModeHorizontal(bool)));
+ d->viewConnections.addUniqueConnection(d->wrapAroundVerticalAction, SIGNAL(toggled(bool)), canvasController, SLOT(slotToggleWrapAroundModeVertical(bool)));
+
+
+
d->viewConnections.addUniqueConnection(d->levelOfDetailAction, SIGNAL(toggled(bool)), canvasController, SLOT(slotToggleLevelOfDetailMode(bool)));
d->levelOfDetailAction->setChecked(canvasController->levelOfDetailMode());
@@ -692,6 +702,13 @@
d->rotateCanvasLeft = actionManager()->createAction("rotate_canvas_left");
d->resetCanvasRotation = actionManager()->createAction("reset_canvas_rotation");
d->wrapAroundAction = actionManager()->createAction("wrap_around_mode");
+
+ d->wrapAroundHorizontalAction = actionManager()->createAction("wrap_around_mode_horizontal");
+ d->wrapAroundHorizontalAction->setChecked(cfg.wraparoundModeHorizontalEnabled());
+
+ d->wrapAroundVerticalAction = actionManager()->createAction("wrap_around_mode_vertical");
+ d->wrapAroundVerticalAction->setChecked(cfg.wraparoundModeVerticalEnabled());
+
d->levelOfDetailAction = actionManager()->createAction("level_of_detail_mode");
d->softProof = actionManager()->createAction("softProof");
d->gamutCheck = actionManager()->createAction("gamutCheck");
diff --git a/libs/ui/canvas/kis_canvas_controller.h b/libs/ui/canvas/kis_canvas_controller.h
--- a/libs/ui/canvas/kis_canvas_controller.h
+++ b/libs/ui/canvas/kis_canvas_controller.h
@@ -41,6 +41,7 @@
bool eventFilter(QObject *watched, QEvent *event) override;
void updateDocumentSize(const QSize &sz, bool recalculateCenter) override;
void activate() override;
+ virtual void changeCanvasWidget(QWidget* widget) override;
QPointF currentCursorPosition() const override;
@@ -63,6 +64,8 @@
qreal rotation() const;
void resetCanvasRotation();
void slotToggleWrapAroundMode(bool value);
+ void slotToggleWrapAroundModeHorizontal(bool value);
+ void slotToggleWrapAroundModeVertical(bool value);
void slotTogglePixelGrid(bool value);
void slotToggleLevelOfDetailMode(bool value);
diff --git a/libs/ui/canvas/kis_canvas_controller.cpp b/libs/ui/canvas/kis_canvas_controller.cpp
--- a/libs/ui/canvas/kis_canvas_controller.cpp
+++ b/libs/ui/canvas/kis_canvas_controller.cpp
@@ -97,6 +97,7 @@
m_d(new Private(this))
{
m_d->view = parent;
+
}
KisCanvasController::~KisCanvasController()
@@ -130,6 +131,18 @@
KoCanvasControllerWidget::activate();
}
+void KisCanvasController::changeCanvasWidget(QWidget* widget)
+{
+ KoCanvasControllerWidget::changeCanvasWidget(widget);
+
+ KisCanvas2 *kritaCanvas = dynamic_cast(canvas());
+ Q_ASSERT(kritaCanvas);
+
+ if (canvas()->canvasIsOpenGL() ) {
+ kritaCanvas->setWrapAroundViewingMode(wrapAroundMode());
+ }
+}
+
QPointF KisCanvasController::currentCursorPosition() const
{
KoCanvasBase *canvas = m_d->view->canvasBase();
@@ -279,6 +292,22 @@
return kritaCanvas->wrapAroundViewingMode();
}
+void KisCanvasController::slotToggleWrapAroundModeHorizontal(bool value)
+{
+ KisConfig cfg(false);
+ cfg.enableWraparoundModeHorizontal(value);
+
+ KisConfigNotifier::instance()->notifyWraparoundModeChanged();
+}
+
+void KisCanvasController::slotToggleWrapAroundModeVertical(bool value)
+{
+ KisConfig cfg(false);
+ cfg.setWraparoundModeHorizontalEnabled(value);
+
+ KisConfigNotifier::instance()->notifyWraparoundModeChanged();
+}
+
void KisCanvasController::slotTogglePixelGrid(bool value)
{
KisConfig cfg(false);
diff --git a/libs/ui/kis_config.h b/libs/ui/kis_config.h
--- a/libs/ui/kis_config.h
+++ b/libs/ui/kis_config.h
@@ -216,6 +216,12 @@
bool pixelGridEnabled(bool defaultValue = false) const;
void enablePixelGrid(bool v) const;
+ bool wraparoundModeHorizontalEnabled(bool defaultValue = false) const;
+ void enableWraparoundModeHorizontal(bool v) const;
+
+ bool wraparoundModeVerticalEnabled(bool defaultValue = false) const;
+ void setWraparoundModeHorizontalEnabled(bool v) const;
+
quint32 guidesLineStyle(bool defaultValue = false) const;
void setGuidesLineStyle(quint32 v) const;
QColor guidesColor(bool defaultValue = false) const;
diff --git a/libs/ui/kis_config.cc b/libs/ui/kis_config.cc
--- a/libs/ui/kis_config.cc
+++ b/libs/ui/kis_config.cc
@@ -809,6 +809,29 @@
m_cfg.writeEntry("pixelGridEnabled", v);
}
+void KisConfig::enableWraparoundModeHorizontal(bool v) const
+{
+ m_cfg.writeEntry("wraparoundModeHorizontal", v);
+}
+
+bool KisConfig::wraparoundModeHorizontalEnabled(bool defaultValue) const
+{
+ bool enabled = true;
+ return (defaultValue ? enabled : m_cfg.readEntry("wraparoundModeHorizontal", enabled));
+}
+
+void KisConfig::setWraparoundModeHorizontalEnabled(bool v) const
+{
+ m_cfg.writeEntry("wraparoundModeVertical", v);
+}
+
+
+bool KisConfig::wraparoundModeVerticalEnabled(bool defaultValue) const
+{
+ bool enabled = true;
+ return (defaultValue ? enabled : m_cfg.readEntry("wraparoundModeVertical", enabled));
+}
+
quint32 KisConfig::guidesLineStyle(bool defaultValue) const
{
int v = m_cfg.readEntry("guidesLineStyle", 0);
diff --git a/libs/ui/opengl/kis_opengl_canvas2.h b/libs/ui/opengl/kis_opengl_canvas2.h
--- a/libs/ui/opengl/kis_opengl_canvas2.h
+++ b/libs/ui/opengl/kis_opengl_canvas2.h
@@ -105,6 +105,7 @@
public Q_SLOTS:
void slotConfigChanged();
void slotPixelGridModeChanged();
+ void slotWraparoundModeChanged();
protected: // KisCanvasWidgetBase
bool callFocusNextPrevChild(bool next) override;
@@ -117,6 +118,7 @@
void drawImage();
void drawCheckers();
void drawGrid();
+ void updateActiveCanvasArea();
private:
diff --git a/libs/ui/opengl/kis_opengl_canvas2.cpp b/libs/ui/opengl/kis_opengl_canvas2.cpp
--- a/libs/ui/opengl/kis_opengl_canvas2.cpp
+++ b/libs/ui/opengl/kis_opengl_canvas2.cpp
@@ -91,6 +91,9 @@
bool wrapAroundMode{false};
+ QRect activeCanvasArea; // changes depending on wrap-around mode
+ QRectF canvasWidgetRect;
+
// Stores a quad for drawing the canvas
QOpenGLVertexArrayObject quadVAO;
QOpenGLBuffer quadBuffers[2];
@@ -111,6 +114,10 @@
QColor gridColor;
QColor cursorColor;
+ // individually turn on/off horizontal or vertical aspect of wrap-around mode
+ bool isHorizontalWrapAround = true;
+ bool isVerticalWrapAround = true;
+
bool lodSwitchInProgress = false;
int xToColWithWrapCompensation(int x, const QRect &imageRect) {
@@ -172,6 +179,9 @@
connect(KisConfigNotifier::instance(), SIGNAL(configChanged()), SLOT(slotConfigChanged()));
connect(KisConfigNotifier::instance(), SIGNAL(pixelGridModeChanged()), SLOT(slotPixelGridModeChanged()));
+ connect(KisConfigNotifier::instance(), SIGNAL(wraparoundModeChanged()), SLOT(slotWraparoundModeChanged()));
+
+
slotConfigChanged();
slotPixelGridModeChanged();
cfg.writeEntry("canvasState", "OPENGL_SUCCESS");
@@ -207,6 +217,7 @@
void KisOpenGLCanvas2::setWrapAroundViewingMode(bool value)
{
d->wrapAroundMode = value;
+ slotWraparoundModeChanged();
update();
}
@@ -488,14 +499,12 @@
QRectF textureRect;
QRectF modelRect;
- QRectF viewportRect = !d->wrapAroundMode ?
- converter->imageRectInViewportPixels() :
- converter->widgetToViewport(this->rect());
+ updateActiveCanvasArea();
+ QRectF viewportRect = d->activeCanvasArea;
+
+ const QRect vrect = converter->imageToViewport(canvas()->renderingLimit()).toAlignedRect();
+ viewportRect = vrect;
- if (!canvas()->renderingLimit().isEmpty()) {
- const QRect vrect = converter->imageToViewport(canvas()->renderingLimit()).toAlignedRect();
- viewportRect &= vrect;
- }
converter->getOpenGLCheckersInfo(viewportRect,
&textureTransform, &modelTransform, &textureRect, &modelRect, d->scrollCheckers);
@@ -552,6 +561,42 @@
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
+void KisOpenGLCanvas2::updateActiveCanvasArea()
+{
+ QRect imageRect = d->openGLImageTextures->storedImageBounds(); // original image
+
+ QRectF widgetRect(0,0, width(), height());
+ QRectF widgetRectInImagePixels = coordinatesConverter()->documentToImage(coordinatesConverter()->widgetToDocument(widgetRect));
+ QRect wigetAlignedRect = widgetRectInImagePixels.toAlignedRect(); // full canvas used for wrap-around mode
+
+ if (!d->wrapAroundMode ) {
+ d->activeCanvasArea = imageRect;
+ d->canvasWidgetRect = imageRect;
+ return;
+ } else if( d->wrapAroundMode && d->isVerticalWrapAround == false && d->isHorizontalWrapAround == false ) {
+ d->activeCanvasArea = imageRect;
+ d->canvasWidgetRect = imageRect;
+ return;
+ }
+
+ // has some form of wrap-around mode enabled
+ if (d->isVerticalWrapAround == true && d->isHorizontalWrapAround == false) {
+ // only wrap vertically
+ d->activeCanvasArea = QRect(imageRect.x(), wigetAlignedRect.y(), imageRect.width(), wigetAlignedRect.height() );
+ d->canvasWidgetRect = QRectF(imageRect.x(), imageRect.y(), wigetAlignedRect.width(), imageRect.height());
+
+ } else if (d->isVerticalWrapAround == false && d->isHorizontalWrapAround == true) {
+ // only wrap horizontally
+ d->activeCanvasArea = QRect(wigetAlignedRect.x(), imageRect.y(), wigetAlignedRect.width(), imageRect.height() );
+ d->canvasWidgetRect = QRectF(d->canvasWidgetRect.x(), imageRect.y(), d->canvasWidgetRect.width(), imageRect.height());
+ }
+ else {
+ // display both vertical and horizontal
+ d->activeCanvasArea = wigetAlignedRect;
+ }
+}
+
+
void KisOpenGLCanvas2::drawGrid()
{
if (!d->solidColorShader->bind()) {
@@ -580,18 +625,13 @@
d->lineBuffer.bind();
}
- QRectF widgetRect(0,0, width(), height());
- QRectF widgetRectInImagePixels = coordinatesConverter()->documentToImage(coordinatesConverter()->widgetToDocument(widgetRect));
- QRect wr = widgetRectInImagePixels.toAlignedRect();
-
- if (!d->wrapAroundMode) {
- wr &= d->openGLImageTextures->storedImageBounds();
- }
+ updateActiveCanvasArea();
- QPoint topLeftCorner = wr.topLeft();
- QPoint bottomRightCorner = wr.bottomRight() + QPoint(1, 1);
+ QPoint topLeftCorner = d->activeCanvasArea.topLeft();
+ QPoint bottomRightCorner = d->activeCanvasArea.bottomRight() + QPoint(1, 1);
QVector grid;
+
for (int i = topLeftCorner.x(); i <= bottomRightCorner.x(); ++i) {
grid.append(QVector3D(i, topLeftCorner.y(), 0));
grid.append(QVector3D(i, bottomRightCorner.y(), 0));
@@ -662,24 +702,21 @@
d->displayShader->setUniformValue(d->displayShader->location(Uniform::ViewportScale), (GLfloat) scaleX);
d->displayShader->setUniformValue(d->displayShader->location(Uniform::TexelSize), (GLfloat) d->openGLImageTextures->texelSize());
- QRect ir = d->openGLImageTextures->storedImageBounds();
- QRect wr = widgetRectInImagePixels.toAlignedRect();
+ updateActiveCanvasArea();
- if (!d->wrapAroundMode) {
- // if we don't want to paint wrapping images, just limit the
- // processing area, and the code will handle all the rest
- wr &= ir;
- }
+ QRect imageRect = d->openGLImageTextures->storedImageBounds(); // original image
+
+ int firstColumn = d->xToColWithWrapCompensation(d->activeCanvasArea.left(), imageRect);
+ int lastColumn = d->xToColWithWrapCompensation(d->activeCanvasArea.right(), imageRect);
- int firstColumn = d->xToColWithWrapCompensation(wr.left(), ir);
- int lastColumn = d->xToColWithWrapCompensation(wr.right(), ir);
- int firstRow = d->yToRowWithWrapCompensation(wr.top(), ir);
- int lastRow = d->yToRowWithWrapCompensation(wr.bottom(), ir);
+ int firstRow = d->yToRowWithWrapCompensation(d->activeCanvasArea.top(), imageRect);
+ int lastRow = d->yToRowWithWrapCompensation(d->activeCanvasArea.bottom(), imageRect);
- int minColumn = d->openGLImageTextures->xToCol(ir.left());
- int maxColumn = d->openGLImageTextures->xToCol(ir.right());
- int minRow = d->openGLImageTextures->yToRow(ir.top());
- int maxRow = d->openGLImageTextures->yToRow(ir.bottom());
+
+ int minColumn = d->openGLImageTextures->xToCol(imageRect.left());
+ int maxColumn = d->openGLImageTextures->xToCol(imageRect.right());
+ int minRow = d->openGLImageTextures->yToRow(imageRect.top());
+ int maxRow = d->openGLImageTextures->yToRow(imageRect.bottom());
int imageColumns = maxColumn - minColumn + 1;
int imageRows = maxRow - minRow + 1;
@@ -689,20 +726,21 @@
int effectiveCol = col;
int effectiveRow = row;
+
QPointF tileWrappingTranslation;
if (effectiveCol > maxColumn || effectiveCol < minColumn) {
int translationStep = floor(qreal(col) / imageColumns);
int originCol = translationStep * imageColumns;
effectiveCol = col - originCol;
- tileWrappingTranslation.rx() = translationStep * ir.width();
+ tileWrappingTranslation.rx() = translationStep * imageRect.width();
}
if (effectiveRow > maxRow || effectiveRow < minRow) {
int translationStep = floor(qreal(row) / imageRows);
int originRow = translationStep * imageRows;
effectiveRow = row - originRow;
- tileWrappingTranslation.ry() = translationStep * ir.height();
+ tileWrappingTranslation.ry() = translationStep * imageRect.height();
}
KisTextureTile *tile =
@@ -831,6 +869,15 @@
update();
}
+void KisOpenGLCanvas2::slotWraparoundModeChanged()
+{
+ KisConfig cfg(true);
+
+ d->isHorizontalWrapAround = cfg.wraparoundModeHorizontalEnabled();
+ d->isVerticalWrapAround = cfg.wraparoundModeVerticalEnabled();
+ update();
+}
+
QVariant KisOpenGLCanvas2::inputMethodQuery(Qt::InputMethodQuery query) const
{
return processInputMethodQuery(query);