瀏覽代碼

Add Card Grid Generator

This plugin will create a grid of guides and/or cropmarks based on a
given card and bleed size. The number of rows and columns can be
specified, or the plugin can simply work out the maximum possible cards
for the given document.
cinaeco 4 年之前
父節點
當前提交
be8cb5827c

+ 8 - 0
card_grid_generator.desktop

@@ -0,0 +1,8 @@
+[Desktop Entry]
+Type=Service
+ServiceTypes=Krita/PythonPlugin
+X-KDE-Library=card_grid_generator
+X-Python-2-Compatible=false
+X-Krita-Manual=Manual.html
+Name=Card Grid Generator
+Comment=Creates guide and cropmark grids for a given dimension of card.

+ 23 - 0
card_grid_generator/Manual.html

@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE html>
+
+<html xmlns="http://www.w3.org/1999/xhtml">
+<!--BBD's Krita Script Starter, Feb 2018 -->
+<head><title>Extension Template Documentation</title>
+</head>
+<body>
+<h3>Box Generator documentation</h3>
+
+This creates artificial "bleed" on the edges of a given layer, but simply
+cloning the edges outward. This is mainly used for printing double sided print
+and play card games. Defaults to 2mm bleed on all sides.
+
+<h3>Usage</h3>
+
+Run the generator after the desired paint layer is selected. Bleed amount can be
+specified in millimetres, inches and pixels. "Offset" allows the use of pixel
+lines other than the edge. A -1 offset means bleed will be copied from 1 line
+just inside the edge, -2 means 2 lines in, etc.
+
+</body>
+</html>

+ 3 - 0
card_grid_generator/__init__.py

@@ -0,0 +1,3 @@
+from .card_grid_generator_extension import CardGridGenerator
+
+Krita.instance().addExtension(CardGridGenerator(Krita.instance()))

+ 204 - 0
card_grid_generator/card_grid_generator_extension.py

@@ -0,0 +1,204 @@
+from krita import Extension
+from PyQt5.QtWidgets import QDialog, QVBoxLayout, QHBoxLayout, QLabel, QLineEdit, QComboBox, QCheckBox, QPushButton
+from PyQt5.QtCore import Qt, QByteArray
+from math import floor
+
+class CardGridGenerator(Extension):
+
+    def __init__(self, parent):
+        super().__init__(parent)
+
+    # Krita.instance() exists, so do any setup work
+    def setup(self):
+        pass
+
+    # called after setup(self)
+    def createActions(self, window):
+        # Create menu item in Tools > Scripts.
+        action = window.createAction("cardgridgen", "Card Grid Generator")
+        action.triggered.connect(self.card_grid_generator)
+
+    def card_grid_generator(self):
+        # Dialog creation.
+        newDialog = QDialog()
+        newDialog.setWindowTitle("Card Grid Generator")
+        layout = QVBoxLayout()
+        newDialog.setLayout(layout)
+
+
+        # Description row.
+        desc = QLabel('Creates a grid of guides and cropmarks for a given card size.')
+        desc.setAlignment(Qt.AlignCenter)
+        row0 = QHBoxLayout()
+        row0.addWidget(desc)
+        layout.addLayout(row0)
+
+        # Card dimension row.
+        self.widthInput = QLineEdit('750')
+        self.heightInput = QLineEdit('1050')
+        self.unitInput = QComboBox()
+        self.unitInput.addItems( ['px', 'mm', 'inch'] )
+        row1 = QHBoxLayout()
+        row1.addWidget(QLabel('Card size: W:'))
+        row1.addWidget(self.widthInput)
+        row1.addWidget(QLabel(' x H:'))
+        row1.addWidget(self.heightInput)
+        row1.addWidget(self.unitInput)
+        layout.addLayout(row1)
+
+        # Bleed dimension row. Also, guides or cropmarks selection.
+        self.bleedInput = QLineEdit('24')
+        self.guidesCheck = QCheckBox('Guides')
+        self.guidesCheck.setChecked(True)
+        self.cropmarksCheck = QCheckBox('Cropmarks')
+        self.cropmarksCheck.setChecked(True)
+        row2 = QHBoxLayout()
+        row2.addWidget(QLabel('Bleed size:'))
+        row2.addWidget(self.bleedInput)
+        row2.addWidget(self.guidesCheck)
+        row2.addWidget(self.cropmarksCheck)
+        layout.addLayout(row2)
+
+        # How many cards row.
+        self.rowsInput = QLineEdit('0')
+        self.colsInput = QLineEdit('0')
+        self.maxCheck = QCheckBox('Max Possible')
+        self.maxCheck.setChecked(True)
+        row3 = QHBoxLayout()
+        row3.addWidget(QLabel('Grid: Columns:'))
+        row3.addWidget(self.colsInput)
+        row3.addWidget(QLabel('Rows:'))
+        row3.addWidget(self.rowsInput)
+        row3.addWidget(self.maxCheck)
+        layout.addLayout(row3)
+
+        # Do It row.
+        goButton = QPushButton("Create Card Grid")
+        goButton.setIcon( Krita.instance().icon('animation_play') )
+        row4 = QHBoxLayout()
+        row4.addWidget(goButton)
+        layout.addLayout(row4)
+
+        # Hook up the actions.
+        goButton.clicked.connect( self.generateCardGrid )
+
+        # Show the dialog.
+        newDialog.exec_()
+
+
+    ##########
+    # Slots
+    ##########
+
+    # Actually generates the card grid!
+    def generateCardGrid(self, e):
+
+        doc = Krita.instance().activeDocument()
+
+        # If there is no open document, create a new one (A4 300ppi).
+        if not doc:
+            doc = Krita.instance().createDocument(3508, 2480, "Card Grid", "RGBA", "U8", "", 300.0)
+            Krita.instance().activeWindow().addView(doc)
+
+        # Document dimensions.
+        docWidth = doc.width()
+        docHeight = doc.height()
+
+        # Card dimensions with bleed.
+        bleedSize = int(self.bleedInput.text())
+        cardWidth = int(self.widthInput.text())
+        cardHeight = int(self.heightInput.text())
+        cardBledWidth = cardWidth + bleedSize * 2
+        cardBledHeight = cardHeight + bleedSize * 2
+
+        # Determine layout.
+        colCount = 0
+        rowCount = 0
+        if self.maxCheck.checkState():
+            # Create the maximum-possible card layout
+            colCount = floor(docWidth / cardBledWidth)
+            rowCount = floor(docHeight / cardBledHeight)
+        else:
+            # Create card layout according to user specified rows and columns.
+            colCount = int(self.colsInput.text())
+            rowCount = int(self.rowsInput.text())
+
+        # Calculate offset for centering.
+        # Remainder pixels of row and column, divide by 2.
+        # Bias odd pixel calculations to top left via floor.
+        widthOffset = floor((docWidth - colCount * cardBledWidth) / 2)
+        heightOffset = floor((docHeight - rowCount * cardBledHeight) / 2)
+
+        # Create xSet and ySet (remember, both bleed + edge dimensions).
+        # Also create Cards-Only sets for cropmarks.
+        xSet = [widthOffset]
+        ySet = [heightOffset]
+        xSetCardsOnly = []
+        ySetCardsOnly = []
+
+        for i in range(colCount):
+            base = widthOffset + i * cardBledWidth
+            bleed1 = base + bleedSize
+            card = bleed1 + cardWidth
+            bleed2 = card + bleedSize
+            # Cut down the number of guides if there is no bleed.
+            xSet += [bleed1, card, bleed2] if bleedSize > 0 else [card]
+            xSetCardsOnly += [bleed1, card] if bleedSize > 0 else [card]
+
+        for i in range(rowCount):
+            base = heightOffset + i * cardBledHeight
+            bleed1 = base + bleedSize
+            card = bleed1 + cardHeight
+            bleed2 = card + bleedSize
+            # Cut down the number of guides if there is no bleed.
+            ySet +=[bleed1, card, bleed2] if bleedSize > 0 else [card]
+            ySetCardsOnly += [bleed1, card] if bleedSize > 0 else [card]
+
+        xSet.sort()
+        ySet.sort()
+
+        # Create guides. dump xSet ySet into guide functions.
+        if self.guidesCheck.checkState():
+            vList = doc.verticalGuides()
+            hList = doc.horizontalGuides()
+            vList.clear()
+            hList.clear()
+            doc.setVerticalGuides(xSet)
+            doc.setHorizontalGuides(ySet)
+            doc.setGuidesLocked(True)
+            doc.setGuidesVisible(True)
+
+        # Create cropmarks.
+        if self.cropmarksCheck.checkState():
+
+            # Cropmarks will be on a new layer.
+            layer = doc.createNode('CardGridCropmarks', 'paintLayer')
+            root = doc.rootNode()
+            root.addChildNode(layer, None)
+
+            # Create vertical cropmarks.
+            blackPixel = b'\x00\x00\x00\xff'
+            cropMarkWidth = 2
+            cropMarkHeight = 48
+            cropMark = QByteArray(blackPixel * cropMarkWidth * cropMarkHeight)
+            for x in xSetCardsOnly:
+                # top
+                y = ySet[0] - cropMarkHeight
+                layer.setPixelData(cropMark, x - 1, y, cropMarkWidth, cropMarkHeight)
+                # bottom
+                layer.setPixelData(cropMark, x - 1, ySet[-1], cropMarkWidth, cropMarkHeight)
+
+            # Create horizontal cropmarks.
+            cropMarkWidth = 48
+            cropMarkHeight = 2
+            cropMark = QByteArray(blackPixel * cropMarkWidth * cropMarkHeight)
+            for y in ySetCardsOnly:
+                # left
+                x = xSet[0] - cropMarkWidth
+                layer.setPixelData(cropMark, x, y - 1, cropMarkWidth, cropMarkHeight)
+                # right
+                layer.setPixelData(cropMark, xSet[-1], y - 1, cropMarkWidth, cropMarkHeight)
+
+            # Refresh the view, or the cropmarks will not be immediately shown.
+            doc.refreshProjection()
+