Merge branch 'CURA-12663_paintbrush_preview' into CURA-12634_panda_painting_alpha

This commit is contained in:
Remco Burema 2025-08-26 17:19:28 +02:00
commit 116be5e2bc
3 changed files with 61 additions and 14 deletions

View file

@ -355,10 +355,23 @@ class PaintTool(Tool):
is_moved = event.type == Event.MouseMoveEvent
is_pressed = event.type == Event.MousePressEvent
if (is_moved or is_pressed) and self._controller.getToolsEnabled():
if is_moved and not self._mouse_held:
return False
mouse_evt = cast(MouseEvent, event)
if not self._picking_pass:
self._picking_pass = CuraApplication.getInstance().getRenderer().getRenderPass("picking_selected")
if not self._picking_pass:
return False
brush_color = self._brush_color if self.getPaintType() != "extruder" else str(self._brush_extruder)
world_coords_vec = None
if is_moved:
world_coords_vec = self._picking_pass.getPickedPosition(mouse_evt.x, mouse_evt.y)
self._view.setCursor(world_coords_vec, self._brush_size / 128.0, brush_color)
if not self._mouse_held:
self._updateScene(node)
return False
if is_pressed:
if MouseEvent.LeftButton not in mouse_evt.buttons:
return False
@ -370,11 +383,6 @@ class PaintTool(Tool):
if not self._faces_selection_pass:
return False
if not self._picking_pass:
self._picking_pass = CuraApplication.getInstance().getRenderer().getRenderPass("picking_selected")
if not self._picking_pass:
return False
if self._camera is None:
self._updateCamera()
if self._camera is None:
@ -395,8 +403,10 @@ class PaintTool(Tool):
face_id = self._faces_selection_pass.getFaceIdAtPosition(mouse_evt.x, mouse_evt.y)
if face_id < 0 or face_id >= self._mesh_transformed_cache.getFaceCount():
return False
world_coords = self._picking_pass.getPickedPosition(mouse_evt.x, mouse_evt.y).getData()
if world_coords_vec is None:
world_coords_vec = self._picking_pass.getPickedPosition(mouse_evt.x, mouse_evt.y)
world_coords = world_coords_vec.getData()
if self._last_world_coords is None:
self._last_world_coords = world_coords
self._last_face_id = face_id
@ -405,7 +415,6 @@ class PaintTool(Tool):
if len(uv_areas) == 0:
return False
stroke_img, (start_x, start_y) = self._createStrokeImage(uv_areas)
brush_color = self._brush_color if self.getPaintType() != "extruder" else str(self._brush_extruder)
self._view.addStroke(stroke_img, start_x, start_y, brush_color, is_moved)
self._last_world_coords = world_coords

View file

@ -2,11 +2,12 @@
# Cura is released under the terms of the LGPLv3 or higher.
import os
from PyQt6.QtCore import QRect, pyqtSignal
from typing import Optional, Dict
from typing import Optional, List, Dict
from PyQt6.QtCore import QRect, pyqtSignal
from PyQt6.QtGui import QImage, QUndoStack, QColor
from UM.Math.Vector import Vector
from cura.CuraApplication import CuraApplication
from cura.BuildVolume import BuildVolume
from cura.CuraView import CuraView
@ -46,6 +47,10 @@ class PaintView(CuraView):
self._paint_undo_stack.canUndoChanged.connect(self.canUndoChanged)
self._paint_undo_stack.canRedoChanged.connect(self.canRedoChanged)
self._cursor_position: Vector = Vector(0.0, 0.0, 0.0)
self._cursor_size: float = 0.0
self._cursor_color: List[float] = [0.0, 0.0, 0.0, 1.0]
application = CuraApplication.getInstance()
application.engineCreatedSignal.connect(self._makePaintModes)
self._scene = application.getController().getScene()
@ -114,6 +119,11 @@ class PaintView(CuraView):
shader_filename = os.path.join(PluginRegistry.getInstance().getPluginPath("PaintTool"), "paint.shader")
self._paint_shader = OpenGL.getInstance().createShaderProgram(shader_filename)
def setCursor(self, position: Optional[Vector] = None, size: float = -1, color: Optional[str] = None) -> None:
self._cursor_position = position if position is not None else self._cursor_position
self._cursor_size = size if size >= 0 else self._cursor_size
self._cursor_color = self._paint_modes[self._current_paint_type][color].display_color if color is not None else self._cursor_color
def addStroke(self, stroke_mask: QImage, start_x: int, start_y: int, brush_color: str, merge_with_previous: bool) -> None:
if self._current_paint_texture is None or self._current_paint_texture.getImage() is None:
return
@ -208,6 +218,10 @@ class PaintView(CuraView):
self._paint_shader.setUniformValue("u_bitsRangesStart", self._current_bits_ranges[0])
self._paint_shader.setUniformValue("u_bitsRangesEnd", self._current_bits_ranges[1])
self._paint_shader.setUniformValue("u_cursorPos", self._cursor_position)
self._paint_shader.setUniformValue("u_cursorSize", self._cursor_size)
self._paint_shader.setUniformValue("u_cursorColor", self._cursor_color)
colors = [paint_type_obj.display_color for paint_type_obj in self._paint_modes[self._current_paint_type].values()]
colors_values = [[int(color_part * 255) for color_part in [color.r, color.g, color.b]] for color in colors]
self._paint_shader.setUniformValueArray("u_renderColors", colors_values)

View file

@ -33,6 +33,9 @@ fragment =
uniform mediump int u_bitsRangesStart;
uniform mediump int u_bitsRangesEnd;
uniform mediump vec3 u_renderColors[16];
uniform highp vec3 u_cursorPos;
uniform highp float u_cursorSize;
uniform lowp vec4 u_cursorColor;
varying highp vec3 v_vertex;
varying highp vec3 v_normal;
@ -57,8 +60,16 @@ fragment =
highp float n_dot_l = mix(0.3, 0.7, dot(normal, light_dir));
final_color += (n_dot_l * diffuse_color);
final_color.a = 1.0;
/* Cursor */
vec3 diff = v_vertex - u_cursorPos;
float squared_dist = dot(diff, diff);
if (squared_dist <= (u_cursorSize * u_cursorSize))
{
final_color.rgb = mix(final_color.rgb / 2.0, u_cursorColor.rgb, u_cursorColor.a);
}
/* Output */
final_color.a = 1.0;
frag_color = final_color;
}
@ -98,6 +109,9 @@ fragment41core =
uniform mediump int u_bitsRangesStart;
uniform mediump int u_bitsRangesEnd;
uniform mediump vec3 u_renderColors[16];
uniform highp vec3 u_cursorPos;
uniform highp float u_cursorSize;
uniform lowp vec4 u_cursorColor;
in highp vec3 v_vertex;
in highp vec3 v_normal;
@ -123,14 +137,24 @@ fragment41core =
highp float n_dot_l = mix(0.3, 0.7, dot(normal, light_dir));
final_color += (n_dot_l * diffuse_color);
final_color.a = 1.0;
/* Cursor */
vec3 diff = v_vertex - u_cursorPos;
float squared_dist = dot(diff, diff);
if (squared_dist <= (u_cursorSize * u_cursorSize))
{
final_color.rgb = mix(final_color.rgb / 2.0, u_cursorColor.rgb, u_cursorColor.a);
}
/* Output */
final_color.a = 1.0;
frag_color = final_color;
}
[defaults]
u_ambientColor = [0.3, 0.3, 0.3, 1.0]
u_texture = 0
u_cursorSize = 0.0
u_cursorColor = [0.0, 0.0, 0.0, 0.0]
[bindings]
u_modelMatrix = model_matrix