Explorar o código

Add Button Shy PNP Expander docker

This plugin will automate expanding a Button Shy 6-card PNP template
into an 8-card template.
cinaeco %!s(int64=4) %!d(string=hai) anos
pai
achega
8bd60985ec

+ 8 - 0
bs_pnp_expander_docker.desktop

@@ -0,0 +1,8 @@
+[Desktop Entry]
+Type=Service
+ServiceTypes=Krita/PythonPlugin
+X-KDE-Library=bs_pnp_expander_docker
+X-Python-2-Compatible=false
+X-Krita-Manual=Manual.html
+Name=Button Shy PNP Expander Docker
+Comment=Converts Button Shy 6-card layouts into 8-card layouts. Does 2 pages (front and back) at a time.

+ 29 - 0
bs_pnp_expander_docker/Manual.html

@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE html>
+
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head><title>Image Fitter Documentation</title>
+</head>
+<body>
+<h3>Image Fitter Documentation</h3>
+
+<p>
+This extension allows a user to automatically rescale an image to fit a
+rectangle defined by horizontal and vertical guides.
+</p>
+
+<p>
+Users can choose whether to fit horizontally or vertically, when the aspect
+ratio of the image layer does not match that of the rectangle. The image will be
+centered on the rectangle.
+</p>
+
+<h3>Usage</h3>
+
+<p>
+Select a paint layer. Set up at least 4 guides to define a rectangle to be
+fitted to. Press the "Fit" button.
+</p>
+
+</body>
+</html>

+ 10 - 0
bs_pnp_expander_docker/__init__.py

@@ -0,0 +1,10 @@
+from krita import DockWidgetFactory, DockWidgetFactoryBase
+from .bs_pnp_expander_docker import BsPnpExpander
+
+DOCKER_ID = 'bs_pnp_expander'
+instance = Krita.instance()
+dock_widget_factory = DockWidgetFactory(DOCKER_ID,
+                                        DockWidgetFactoryBase.DockRight,
+                                        BsPnpExpander)
+
+instance.addDockWidgetFactory(dock_widget_factory)

+ 128 - 0
bs_pnp_expander_docker/bs_pnp_expander_docker.py

@@ -0,0 +1,128 @@
+from krita import DockWidget
+from PyQt5.QtWidgets import QWidget, QDialog, QVBoxLayout, QHBoxLayout, QLabel, QComboBox, QPushButton
+from PyQt5.QtCore import QByteArray
+
+DOCKER_TITLE = 'Button Shy PNP Expander'
+
+class BsPnpExpander(DockWidget):
+
+    def __init__(self):
+        super().__init__()
+        self.setWindowTitle(DOCKER_TITLE)
+        widget = QWidget()
+        layout = QVBoxLayout()
+        widget.setLayout(layout)
+
+        layout.addSpacing(10)
+        layout.addWidget(QLabel('Expand the Button Shy 6-card PNP layout to 8-cards'))
+
+        # Expand Direction. Do we put the 2 new cards on the left or right?
+        self.expandDir = QComboBox()
+        dirs = ['Right', 'Left']
+        self.expandDir.addItems(dirs)
+        row0 = QHBoxLayout()
+        row0.addWidget(QLabel('Expand Direction:'))
+        row0.addWidget(self.expandDir)
+        layout.addLayout(row0)
+
+        # Button (Shy)!
+        layout.addSpacing(20)
+        goButton = QPushButton("Expand")
+        goButton.setIcon( Krita.instance().icon('animation_play') )
+        layout.addWidget(goButton)
+
+        # Add a stretch to prevent the rest of the content from stretching.
+        layout.addStretch()
+
+        # Add widget to the docker.
+        self.setWidget(widget)
+
+        # Hook up the action to the button.
+        goButton.clicked.connect( self.expandBsPnp )
+
+
+    # notifies when views are added or removed
+    # 'pass' means do not do anything
+    def canvasChanged(self, canvas):
+        pass
+
+
+    ##########
+    # Slots
+    ##########
+
+    # Actually expands the PNP.
+    def expandBsPnp(self, e):
+
+        # dialog = QDialog()
+        # dialog.setWindowTitle("DEBUG")
+        # layout = QVBoxLayout()
+        # dialog.setLayout(layout)
+
+        # Get the current layer.
+        doc = Krita.instance().activeDocument()
+        layer = doc.activeNode()
+        if layer.type() != 'paintlayer':
+            dialog = QDialog()
+            dialog.setWindowTitle("Paint Layer Required")
+            layout = QVBoxLayout()
+            layout.addWidget(QLabel('Expander only works on paint layers. Please select one.'))
+            dialog.setLayout(layout)
+            dialog.exec_()
+            return
+
+        direction = self.expandDir.currentText()
+        layerPos = layer.position()
+
+        # Move layer 411 pixels left or right
+        xDiff = 411 if direction == 'Left' else -411
+        layer.move(layerPos.x() + xDiff, layerPos.y())
+
+        # Fill in empty document area with white
+        overlapHCrop = 341 # x-offset to overwrite old horizontal crop marks.
+        whitePixel = b'\xff\xff\xff\xff'
+        bds = layer.bounds()
+        fillX = 0 if direction == 'Left' else bds.right() - overlapHCrop
+        fillY = 0
+        fillWidth = bds.left() + overlapHCrop if direction == 'Left' else doc.width() - fillX
+        fillHeight = doc.height()
+        whiteFill = QByteArray(whitePixel * fillWidth * fillHeight)
+        layer.setPixelData(whiteFill, fillX, fillY, fillWidth, fillHeight)
+
+        # Create horizontal cropmarks at image edges.
+        # positions 106 1153 1228 2276. 61px long.
+        blackPixel = b'\x00\x00\x00\xff'
+        cropMarkWidth = 61
+        cropMarkHeight = 2
+        cropMark = QByteArray(blackPixel * cropMarkWidth * cropMarkHeight)
+        ySet = [106, 1153, 1228, 2276]
+        for x in [0, doc.width() - cropMarkWidth]:
+            for y in ySet:
+                layer.setPixelData(cropMark, x, y, cropMarkWidth, cropMarkHeight)
+
+        # Create vertical cropmarks for new card spaces
+        # positions 96 848 2562 3314. 37px long.
+        cropMarkWidth = 2
+        cropMarkHeight = 37
+        cropMark = QByteArray(blackPixel * cropMarkWidth * cropMarkHeight)
+        xSet = [96, 868] if direction == 'Left' else [2562, 3314]
+        for y in [0, doc.height() - cropMarkHeight]:
+            for x in xSet:
+                layer.setPixelData(cropMark, x, y, cropMarkWidth, cropMarkHeight)
+
+        # Place guides on crop marks for new card spaces
+        vList = doc.verticalGuides()
+        hList = doc.horizontalGuides()
+        vList.clear()
+        hList.clear()
+        for x in xSet:
+            vList.append(x + 1)
+        for y in ySet:
+            hList.append(y + 1)
+        doc.setVerticalGuides(vList)
+        doc.setHorizontalGuides(hList)
+        doc.setGuidesLocked(True)
+        doc.setGuidesVisible(True)
+
+        # Refresh the view, or the moved will not be immediately reflected.
+        doc.refreshProjection()