diff --git a/krita/krita4.xmlgui b/krita/krita4.xmlgui --- a/krita/krita4.xmlgui +++ b/krita/krita4.xmlgui @@ -73,7 +73,17 @@ &View - + + + + Wraparound Mode + + + + + + + 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,11 @@ 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 +701,10 @@ 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(true); + d->wrapAroundVerticalAction = actionManager()->createAction("wrap_around_mode_vertical"); + d->wrapAroundVerticalAction->setChecked(true); 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 @@ -63,6 +63,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 @@ -279,6 +279,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.enableWraparoundModeVertical(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 enableWraparoundModeVertical(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,28 @@ 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::enableWraparoundModeVertical(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; 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 @@ -111,6 +111,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 +176,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"); @@ -488,9 +495,24 @@ QRectF textureRect; QRectF modelRect; - QRectF viewportRect = !d->wrapAroundMode ? - converter->imageRectInViewportPixels() : - converter->widgetToViewport(this->rect()); + QRectF canvasWidgetRect = converter->widgetToViewport(this->rect()); + QRectF imageRect = converter->imageRectInViewportPixels(); + + QRectF viewportRect = !d->wrapAroundMode ? imageRect : canvasWidgetRect; + + + if (d->wrapAroundMode) { + if (d->isHorizontalWrapAround == true && d->isVerticalWrapAround == false ) { + viewportRect = QRectF(canvasWidgetRect.x(), imageRect.y(), canvasWidgetRect.width(), imageRect.height()); + } + else if (d->isVerticalWrapAround == true && d->isHorizontalWrapAround == false) { + viewportRect = QRectF(imageRect.x(), canvasWidgetRect.y(), imageRect.width(), canvasWidgetRect.height()); + } + else if (d->isVerticalWrapAround == false && d->isHorizontalWrapAround == false) { + viewportRect = imageRect; + } + } + if (!canvas()->renderingLimit().isEmpty()) { const QRect vrect = converter->imageToViewport(canvas()->renderingLimit()).toAlignedRect(); @@ -665,6 +687,7 @@ QRect ir = d->openGLImageTextures->storedImageBounds(); QRect wr = widgetRectInImagePixels.toAlignedRect(); + // the order of this if statement is important, so don't move to the other wrapAroundMode logic 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 @@ -673,9 +696,32 @@ 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); + + if (d->wrapAroundMode) { + + if (d->isHorizontalWrapAround == true && d->isVerticalWrapAround == false ) { + // only wrap-around horizontal + firstRow = d->yToRowWithWrapCompensation(ir.top(), ir); + lastRow = d->yToRowWithWrapCompensation(ir.bottom(), ir); + + }else if (d->isVerticalWrapAround == true && d->isHorizontalWrapAround == false) { + // only wrap vertically + firstColumn = d->xToColWithWrapCompensation(ir.left(), ir); + lastColumn = d->xToColWithWrapCompensation(ir.right(), ir); + + } else if (d->isVerticalWrapAround == false && d->isHorizontalWrapAround == false) { + // wrap along both axis, but don't actually display both axes + firstColumn = d->xToColWithWrapCompensation(ir.left(), ir); + lastColumn = d->xToColWithWrapCompensation(ir.right(), ir); + firstRow = d->yToRowWithWrapCompensation(ir.top(), ir); + lastRow = d->yToRowWithWrapCompensation(ir.bottom(), ir); + } + } + int minColumn = d->openGLImageTextures->xToCol(ir.left()); int maxColumn = d->openGLImageTextures->xToCol(ir.right()); int minRow = d->openGLImageTextures->yToRow(ir.top()); @@ -689,6 +735,7 @@ int effectiveCol = col; int effectiveRow = row; + QPointF tileWrappingTranslation; if (effectiveCol > maxColumn || effectiveCol < minColumn) { @@ -831,6 +878,16 @@ 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);