| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187 |
- from krita import *
- from PyQt5.QtWidgets import QDialog, QVBoxLayout, QHBoxLayout, QLabel, QLineEdit, QComboBox, QCheckBox, QPushButton
- from PyQt5.QtCore import *
- class BoxGenerator(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("boxgen", "Box Generator")
- action.triggered.connect(self.box_generator)
- def box_generator(self):
- # Get the current selected layer, called a 'node'
- self.doc = Krita.instance().activeDocument()
- if not self.doc:
- # Create and show a new document (A4 300ppi).
- self.doc = Krita.instance().createDocument(3508, 2480, "", "RGBA", "U8", "", 300.0)
- Krita.instance().activeWindow().addView(self.doc)
- # Dialog creation.
- newDialog = QDialog()
- newDialog.setWindowTitle("Box Generator")
- # Description row.
- desc = QLabel('Creates outlines for a foldable box with lid.')
- desc.setAlignment(Qt.AlignCenter)
- row0 = QHBoxLayout()
- row0.addWidget(desc)
- # Dimension row.
- self.lengthInput = QLineEdit('67')
- self.widthInput = QLineEdit('93')
- self.heightInput = QLineEdit('20')
- self.unitInput = QComboBox()
- self.unitInput.addItems( ['mm', 'inch', 'px'] )
- row1 = QHBoxLayout()
- row1.addWidget(QLabel('Dimensions: L:'))
- row1.addWidget(self.lengthInput)
- row1.addWidget(QLabel(' x W:'))
- row1.addWidget(self.widthInput)
- row1.addWidget(QLabel(' x H:'))
- row1.addWidget(self.heightInput)
- row1.addWidget(self.unitInput)
- # Decision row.
- self.boxTypeInput = QComboBox()
- self.boxTypeInput.addItems( ['Tuckbox', 'Telescopic'] )
- row2 = QHBoxLayout()
- row2.addWidget(QLabel('Box Type:'))
- row2.addWidget(self.boxTypeInput)
- # Do It row.
- goButton = QPushButton("Create Box")
- goButton.setIcon( Krita.instance().icon('animation_play') )
- row3 = QHBoxLayout()
- row3.addWidget(goButton)
- layoutMain = QVBoxLayout()
- layoutMain.addLayout(row0)
- layoutMain.addLayout(row1)
- layoutMain.addLayout(row2)
- layoutMain.addLayout(row3)
- newDialog.setLayout(layoutMain)
- # hook up the actions.
- goButton.clicked.connect( self.generateBox )
- # self.unitInput.currentIndexChanged.connect( self.convertCount )
- # show the dialog.
- newDialog.exec_()
- ##########
- # Slots
- ##########
- # Actually generates the box!
- def generateBox(self, e):
- layer = self.doc.createVectorLayer("Box")
- root = self.doc.rootNode()
- root.addChildNode(layer, None)
- # Get dimensions in points. Points to mm conversion depends on document DPI.
- length_mm = float(self.lengthInput.text())
- width_mm = float(self.widthInput.text())
- height_mm = float(self.heightInput.text())
- # Assume input is in mm.
- pts_per_mm = 300 / 25.4
- length = length_mm * pts_per_mm
- height = height_mm * pts_per_mm
- width = width_mm * pts_per_mm
- # Create outline using SVG.
- if self.boxTypeInput.currentIndex() == 0: # Tuckbox
- total_length = length * 2 + height * 3
- total_width = width + height * 3
- leeway = pts_per_mm / 2 # Make certain flaps shorter by 0.5mm to account for paper thickness.
-
- stringy = f"""<svg style="stroke:black; fill:none; stroke-width:1">
- <path d="
- m {pts_per_mm+height*1.66}
- h {length-height*2*0.66}
- a {height*0.66} {height*0.66} 0 0 1 {height*0.66} {height*0.66}
- v {height}
- l {height*0.1} -{height}
- h {height*0.4}
- a {height*0.5} {height} 0 0 1 {height*0.5} {height}
- h {length+height-leeway}
- v {width}
- h -{height-leeway}
- v {height-leeway}
- h -{length}
- v -{height-leeway}
- l -{height*0.1} {height}
- h -{height*0.8}
- l -{height*0.1} -{height}
- v {height}
- h -{length}
- v -{height}
- l -{height*0.1} {height}
- h -{height*0.8}
- l -{height*0.1} -{height}
- v -{width}
- a {height*0.5} {height} 0 0 1 {height*0.5} -{height}
- h {height*0.4}
- l {height*0.1} {height}
- v -{height}
- a {height*0.66} {height*0.66} 0 0 1 {height*0.66} -{height*0.66}
- z
- "></path>
- <path d="
- M {pts_per_mm+height} {height*0.66}
- h -{pts_per_mm}
- M {pts_per_mm+height+length} {height*0.66}
- h {pts_per_mm}
- M 0 {height*1.66}
- h {pts_per_mm}
- M 0 {height*1.66+width}
- h {pts_per_mm}
- M {pts_per_mm+height*2+length*2} {height*1.66}
- v -{pts_per_mm}
- "></path>
- </svg>"""
- else: # Telescopic
- total_length = length + 5 * height
- total_width = width + 5 * height
- stringy = f"""<svg width="{total_length}" height="{total_width}" style="stroke:black; fill:none; stroke-width:1">
- <path d="
- m {height*3}
- h {length-height}
- l {height/2} {height/2}
- v {height}
- a {height} {height} 0 0 1 {height} {height}
- h {height}
- l {height/2} {height/2}
- v {width-height}
- l -{height/2} {height/2}
- h -{height}
- a {height} {height} 0 0 1 -{height} {height}
- v {height}
- l -{height/2} {height/2}
- h -{length-height}
- l -{height/2} -{height/2}
- v -{height}
- a {height} {height} 0 0 1 -{height} -{height}
- h -{height}
- l -{height/2} -{height/2}
- v -{width-height}
- l {height/2} -{height/2}
- h {height}
- a {height} {height} 0 0 1 {height} -{height}
- v -{height}
- Z
- "></path>
- </svg>"""
- layer.addShapesFromSvg(stringy)
|