.
While using Krita, I decided to make this plugin. which will convert hand-drawn lines into the perspective grid. and Krita keeps showing me this error
Here’s my .docker-Code. Plugin is called gesture-2-grid (G2G)
from krita import *
from PyQt5.QtWidgets import *
from PyQt5.QtCore import Qt, QPointF
class G2GDocker(DockWidget):
*def* \__init_\_(*self*):
super().\__init_\_()
*self*.setWindowTitle("Gesture-to-Grid")
main_widget = QWidget()
layout = QVBoxLayout()
\# UI Header
*self*.lbl_info = QLabel("Draw a gesture, then click Convert.")
*self*.lbl_info.setStyleSheet("font-size: 11px; color: #aaa;")
*self*.lbl_info.setWordWrap(True)
layout.addWidget(*self*.lbl_info)
\# Sensitivity Slider: Low = Straight Plane, High = Vanishing Curve
layout.addWidget(QLabel("Perspective Warp / Sensitivity:"))
*self*.slider_curve = QSlider(Qt.Horizontal)
*self*.slider_curve.setMinimum(0)
*self*.slider_curve.setMaximum(100)
*self*.slider_curve.setValue(40)
layout.addWidget(*self*.slider_curve)
\# The Action Button
*self*.btn_convert = QPushButton("Generate Smart Grid")
*self*.btn_convert.setStyleSheet("""
QPushButton { background-color: #2c3e50; color: white; padding: 12px; font-weight: bold; border-radius: 4px; }
QPushButton:hover { background-color: #34495e; }
""")
*self*.btn_convert.clicked.connect(*self*.run_conversion)
layout.addWidget(*self*.btn_convert)
layout.addStretch()
main_widget.setLayout(layout)
*self*.setWidget(main_widget)
*def* run_conversion(*self*):
doc = Krita.instance().activeDocument()
if not doc: return
node = doc.activeNode()
sensitivity = *self*.slider_curve.value()
points = \[\]
\# 1. LAYER TYPE CHECK & EXTRACTION
if node.type() == "vectorlayer":
points = *self*.get_vector_points(node)
elif node.type() == "paintlayer":
points = *self*.get_raster_points(node)
else:
*self*.lbl_info.setText("Error: Select a Paint or Vector layer.")
return
if not points or len(points) < 2:
*self*.lbl_info.setText("Error: No drawing found on layer.")
return
\# 2. ADAPTIVE LOGIC BRANCHING
if sensitivity < 35 and len(points) >= 4:
*self*.create_perspective_plane(doc, points\[:4\])
*self*.lbl_info.setText("Status: 4-Point Plane Generated")
else:
*self*.create_vanishing_curve(doc, points)
*self*.lbl_info.setText("Status: Vanishing Curve Generated")
*def* get_vector_points(*self*, *node*):
"""Extracts precise coordinates from vector shapes."""
shapes = *node*.shapes()
if not shapes: return \[\]
rect = shapes\[0\].boundingBox()
return \[
QPointF(rect.left(), rect.top()),
QPointF(rect.right(), rect.top()),
QPointF(rect.right(), rect.bottom()),
QPointF(rect.left(), rect.bottom())
\]
*def* get_raster_points(*self*, *node*):
"""Surface Mapping: Scans pixels to find 'Intention Points'."""
bound = *node*.bounds()
w, h = bound.width(), bound.height()
if w == 0 or h == 0: return \[\]
\# Bytearray fix for Krita pixelData
pixel_data = bytearray(*node*.pixelData(bound.x(), bound.y(), w, h))
pts = \[\]
step = 10
for y in range(0, h, step):
for x in range(0, w, step):
\# Safely compare int to int
if pixel_data\[(y \* w + x) \* 4 + 3\] > 20:
pts.append(QPointF(bound.x() + x, bound.y() + y))
if not pts: return \[\]
\# Find the 4 most extreme corners
tl = min(pts, *key*=*lambda* *p*: *p*.x() + *p*.y())
br = max(pts, *key*=*lambda* *p*: *p*.x() + *p*.y())
tr = max(pts, *key*=*lambda* *p*: *p*.x() - *p*.y())
bl = min(pts, *key*=*lambda* *p*: *p*.x() - *p*.y())
return \[tl, tr, br, bl\]
*def* create_perspective_plane(*self*, *doc*, *pts*):
"""Global initialization for Krita 5.2.x."""
\# We call the assistant creation from the main Krita instance
assistant = Krita.instance().createPaintingAssistant("perspective")
if assistant:
assistant.setPoint(0, *pts*\[0\])
assistant.setPoint(1, *pts*\[1\])
assistant.setPoint(2, *pts*\[2\])
assistant.setPoint(3, *pts*\[3\])
\# Add it to the document's list
*doc*.addAssistant(assistant)
*doc*.waitForDone()
else:
*self*.lbl_info.setText("Error: Could not initialize 'perspective' assistant.")
*def* create_vanishing_curve(*self*, *doc*, *pts*):
"""Global initialization for Krita 5.2.x."""
assistant = Krita.instance().createPaintingAssistant("vanishing_point")
if assistant:
assistant.setPoint(0, *pts*\[0\]) # Vanishing Point
assistant.setPoint(1, *pts*\[-1\]) # Direction Handle
*doc*.addAssistant(assistant)
*doc*.waitForDone()
else:
*self*.lbl_info.setText("Error: Could not initialize 'vanishing_point' assistant.")
*def* canvasChanged(*self*, *canvas*):
pass



