diff --git a/.gitignore b/.gitignore index 54f1d00..66d45c1 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ /releases +*.zip diff --git a/grid_generator.zip b/grid_generator.zip deleted file mode 100644 index 36d27df..0000000 Binary files a/grid_generator.zip and /dev/null differ diff --git a/pykrita/grid_generator/__pycache__/grid_docker.cpython-313.pyc b/pykrita/grid_generator/__pycache__/grid_docker.cpython-313.pyc index a45c599..a9c36e0 100644 Binary files a/pykrita/grid_generator/__pycache__/grid_docker.cpython-313.pyc and b/pykrita/grid_generator/__pycache__/grid_docker.cpython-313.pyc differ diff --git a/pykrita/grid_generator/grid_docker.py b/pykrita/grid_generator/grid_docker.py index 53a2f66..8636d6f 100644 --- a/pykrita/grid_generator/grid_docker.py +++ b/pykrita/grid_generator/grid_docker.py @@ -36,24 +36,40 @@ class GridDocker(DockWidget): layout.addLayout(thickness_layout) # Width - width_layout = QHBoxLayout() + self.width_container = QWidget() + width_layout = QHBoxLayout(self.width_container) + width_layout.setContentsMargins(0, 0, 0, 0) width_layout.addWidget(QLabel("Width (px):")) self.width_spin = QDoubleSpinBox() self.width_spin.setRange(1.0, 10000.0) self.width_spin.setValue(100.0) self.width_spin.valueChanged.connect(self.on_width_changed) width_layout.addWidget(self.width_spin) - layout.addLayout(width_layout) + layout.addWidget(self.width_container) # Height - height_layout = QHBoxLayout() + self.height_container = QWidget() + height_layout = QHBoxLayout(self.height_container) + height_layout.setContentsMargins(0, 0, 0, 0) height_layout.addWidget(QLabel("Height (px):")) self.height_spin = QDoubleSpinBox() self.height_spin.setRange(1.0, 10000.0) self.height_spin.setValue(100.0) self.height_spin.valueChanged.connect(self.on_height_changed) height_layout.addWidget(self.height_spin) - layout.addLayout(height_layout) + layout.addWidget(self.height_container) + + # Side Length (Hexagon Only) + self.side_container = QWidget() + side_layout = QHBoxLayout(self.side_container) + side_layout.setContentsMargins(0, 0, 0, 0) + side_layout.addWidget(QLabel("Side Length (px):")) + self.side_spin = QDoubleSpinBox() + self.side_spin.setRange(1.0, 10000.0) + self.side_spin.setValue(50.0) + side_layout.addWidget(self.side_spin) + layout.addWidget(self.side_container) + self.side_container.hide() # Lock Width/Height self.lock_check = QCheckBox("Lock Aspect Ratio") @@ -65,17 +81,10 @@ class GridDocker(DockWidget): type_layout.addWidget(QLabel("Type:")) self.type_combo = QComboBox() self.type_combo.addItems(["Square", "Hexagon"]) + self.type_combo.currentTextChanged.connect(self.on_type_changed) type_layout.addWidget(self.type_combo) layout.addLayout(type_layout) - # Layer Option - layer_layout = QHBoxLayout() - layer_layout.addWidget(QLabel("On:")) - self.layer_combo = QComboBox() - self.layer_combo.addItems(["New Layer", "Current Layer"]) - layer_layout.addWidget(self.layer_combo) - layout.addLayout(layer_layout) - # Color Option color_layout = QHBoxLayout() color_layout.addWidget(QLabel("Color:")) @@ -92,6 +101,13 @@ class GridDocker(DockWidget): layout.addStretch() self.setWidget(main_widget) + def on_type_changed(self, grid_type): + is_square = grid_type == "Square" + self.width_container.setVisible(is_square) + self.height_container.setVisible(is_square) + self.lock_check.setVisible(is_square) + self.side_container.setVisible(not is_square) + def on_width_changed(self, value): if self.lock_check.isChecked(): self.height_spin.blockSignals(True) @@ -123,11 +139,7 @@ class GridDocker(DockWidget): else: color = view.backgroundColor() - # Ensure the color is in RGBA U8 sRGB for easy extraction - # setColorSpace signature: (colorModelId, bitDepthId, profileName) color.setColorSpace("RGBA", "U8", "sRGB built-in") - - # componentsOrdered returns normalized floats [R, G, B, A] comps = color.componentsOrdered() r = int(max(0, min(1, comps[0])) * 255) @@ -143,46 +155,32 @@ class GridDocker(DockWidget): return thickness = self.thickness_spin.value() - width = self.width_spin.value() - height = self.height_spin.value() grid_type = self.type_combo.currentText() - layer_option = self.layer_combo.currentText() color_hex = self.get_color_hex() - # Determine target layer - target_node = None - if layer_option == "New Layer": - target_node = doc.createVectorLayer("grid") - doc.rootNode().addChildNode(target_node, None) - else: - target_node = doc.activeNode() - if target_node and target_node.type() != "vectorlayer": - parent = target_node.parentNode() - new_vector = doc.createVectorLayer("grid") - parent.addChildNode(new_vector, target_node) - target_node = new_vector - - if not target_node: - target_node = doc.createVectorLayer("grid") - doc.rootNode().addChildNode(target_node, None) + # Always create a new vector layer for the grid + target_node = doc.createVectorLayer("grid") + doc.rootNode().addChildNode(target_node, None) if hasattr(target_node, "addShapesFromSvg"): - self.draw_grid( - target_node, doc, thickness, width, height, grid_type, color_hex - ) + if grid_type == "Square": + width = self.width_spin.value() + height = self.height_spin.value() + self.draw_square_grid( + target_node, doc, thickness, width, height, color_hex + ) + else: + side_length = self.side_spin.value() + self.draw_hexagon_grid( + target_node, doc, thickness, side_length, color_hex + ) else: print( - "Error: Target node does not support SVG shapes. Please ensure you are using Krita 5.0+ and a Vector Layer." + "Error: Target node does not support SVG shapes. Please ensure you are using Krita 5.0+." ) doc.refreshProjection() - def draw_grid(self, node, doc, thickness, width, height, grid_type, color_hex): - if grid_type == "Square": - self.draw_square_grid(node, doc, thickness, width, height, color_hex) - else: - self.draw_hexagon_grid(node, doc, thickness, width, height, color_hex) - def draw_square_grid(self, node, doc, thickness, width, height, color_hex): svg = f'' x = 0 @@ -196,32 +194,36 @@ class GridDocker(DockWidget): svg += "" node.addShapesFromSvg(svg) - def draw_hexagon_grid(self, node, doc, thickness, width, height, color_hex): + def draw_hexagon_grid(self, node, doc, thickness, side_length, color_hex): + h_width = math.sqrt(3) * side_length + v_spacing = 1.5 * side_length + svg = f'' - v_spacing = height * 0.75 - h_spacing = width + rows = int(doc.height() / v_spacing) + 2 - cols = int(doc.width() / h_spacing) + 2 + cols = int(doc.width() / h_width) + 2 + for r in range(rows): - offset_x = (width / 2) if (r % 2 == 1) else 0 + offset_x = (h_width / 2) if (r % 2 == 1) else 0 for c in range(cols): - cx = c * h_spacing + offset_x + cx = c * h_width + offset_x cy = r * v_spacing - v = [ - (cx, cy - height / 2), - (cx + width / 2, cy - height / 4), - (cx + width / 2, cy + height / 4), - (cx, cy + height / 2), - (cx - width / 2, cy + height / 4), - (cx - width / 2, cy - height / 4), - ] + + v = [] + for i in range(6): + angle_deg = 60 * i - 90 + angle_rad = math.pi / 180 * angle_deg + px = cx + side_length * math.cos(angle_rad) + py = cy + side_length * math.sin(angle_rad) + v.append((px, py)) + points = " ".join([f"{px},{py}" for px, py in v]) svg += f'' + svg += "" node.addShapesFromSvg(svg) -# Register the docker Krita.instance().addDockWidgetFactory( DockWidgetFactory(DOCKER_ID, DockWidgetFactoryBase.DockRight, GridDocker) )