mirror of
https://github.com/Ultimaker/Cura.git
synced 2025-07-13 09:47:50 -06:00
Merge remote-tracking branch 'origin/CURA-12543_painting_ux' into CURA-12528_unwrap_uvs
This commit is contained in:
commit
fbf3c1395d
13 changed files with 1180 additions and 56 deletions
|
@ -1,6 +1,8 @@
|
||||||
import copy
|
import copy
|
||||||
|
|
||||||
from typing import Optional
|
from typing import Optional, Dict
|
||||||
|
|
||||||
|
from PyQt6.QtGui import QImage
|
||||||
|
|
||||||
import UM.View.GL.Texture
|
import UM.View.GL.Texture
|
||||||
from UM.Scene.SceneNodeDecorator import SceneNodeDecorator
|
from UM.Scene.SceneNodeDecorator import SceneNodeDecorator
|
||||||
|
@ -16,6 +18,7 @@ class SliceableObjectDecorator(SceneNodeDecorator):
|
||||||
def __init__(self) -> None:
|
def __init__(self) -> None:
|
||||||
super().__init__()
|
super().__init__()
|
||||||
self._paint_texture = None
|
self._paint_texture = None
|
||||||
|
self._texture_data_mapping: Dict[str, tuple[int, int]] = {}
|
||||||
|
|
||||||
def isSliceable(self) -> bool:
|
def isSliceable(self) -> bool:
|
||||||
return True
|
return True
|
||||||
|
@ -23,12 +26,22 @@ class SliceableObjectDecorator(SceneNodeDecorator):
|
||||||
def getPaintTexture(self, create_if_required: bool = True) -> Optional[UM.View.GL.Texture.Texture]:
|
def getPaintTexture(self, create_if_required: bool = True) -> Optional[UM.View.GL.Texture.Texture]:
|
||||||
if self._paint_texture is None and create_if_required:
|
if self._paint_texture is None and create_if_required:
|
||||||
self._paint_texture = OpenGL.getInstance().createTexture(TEXTURE_WIDTH, TEXTURE_HEIGHT)
|
self._paint_texture = OpenGL.getInstance().createTexture(TEXTURE_WIDTH, TEXTURE_HEIGHT)
|
||||||
|
image = QImage(TEXTURE_WIDTH, TEXTURE_HEIGHT, QImage.Format.Format_RGB32)
|
||||||
|
image.fill(0)
|
||||||
|
self._paint_texture.setImage(image)
|
||||||
return self._paint_texture
|
return self._paint_texture
|
||||||
|
|
||||||
def setPaintTexture(self, texture: UM.View.GL.Texture) -> None:
|
def setPaintTexture(self, texture: UM.View.GL.Texture) -> None:
|
||||||
self._paint_texture = texture
|
self._paint_texture = texture
|
||||||
|
|
||||||
|
def getTextureDataMapping(self) -> Dict[str, tuple[int, int]]:
|
||||||
|
return self._texture_data_mapping
|
||||||
|
|
||||||
|
def setTextureDataMapping(self, mapping: Dict[str, tuple[int, int]]) -> None:
|
||||||
|
self._texture_data_mapping = mapping
|
||||||
|
|
||||||
def __deepcopy__(self, memo) -> "SliceableObjectDecorator":
|
def __deepcopy__(self, memo) -> "SliceableObjectDecorator":
|
||||||
copied_decorator = SliceableObjectDecorator()
|
copied_decorator = SliceableObjectDecorator()
|
||||||
copied_decorator.setPaintTexture(copy.deepcopy(self.getPaintTexture()))
|
copied_decorator.setPaintTexture(copy.deepcopy(self.getPaintTexture()))
|
||||||
|
copied_decorator.setTextureDataMapping(copy.deepcopy(self.getTextureDataMapping()))
|
||||||
return copied_decorator
|
return copied_decorator
|
||||||
|
|
|
@ -39,14 +39,6 @@ class PaintTool(Tool):
|
||||||
self._mesh_transformed_cache = None
|
self._mesh_transformed_cache = None
|
||||||
self._cache_dirty: bool = True
|
self._cache_dirty: bool = True
|
||||||
|
|
||||||
# TODO: Colors will need to be replaced on a 'per type of painting' basis.
|
|
||||||
self._color_str_to_rgba: Dict[str, List[int]] = {
|
|
||||||
"A": [192, 0, 192, 255],
|
|
||||||
"B": [232, 128, 0, 255],
|
|
||||||
"C": [0, 255, 0, 255],
|
|
||||||
"D": [255, 255, 255, 255],
|
|
||||||
}
|
|
||||||
|
|
||||||
self._brush_size: int = 10
|
self._brush_size: int = 10
|
||||||
self._brush_color: str = "A"
|
self._brush_color: str = "A"
|
||||||
self._brush_shape: PaintTool.BrushShape = PaintTool.BrushShape.SQUARE
|
self._brush_shape: PaintTool.BrushShape = PaintTool.BrushShape.SQUARE
|
||||||
|
@ -61,8 +53,8 @@ class PaintTool(Tool):
|
||||||
def _createBrushPen(self) -> QPen:
|
def _createBrushPen(self) -> QPen:
|
||||||
pen = QPen()
|
pen = QPen()
|
||||||
pen.setWidth(self._brush_size)
|
pen.setWidth(self._brush_size)
|
||||||
color = self._color_str_to_rgba[self._brush_color]
|
pen.setColor(Qt.GlobalColor.white)
|
||||||
pen.setColor(QColor(color[0], color[1], color[2], color[3]))
|
|
||||||
match self._brush_shape:
|
match self._brush_shape:
|
||||||
case PaintTool.BrushShape.SQUARE:
|
case PaintTool.BrushShape.SQUARE:
|
||||||
pen.setCapStyle(Qt.PenCapStyle.SquareCap)
|
pen.setCapStyle(Qt.PenCapStyle.SquareCap)
|
||||||
|
@ -78,8 +70,8 @@ class PaintTool(Tool):
|
||||||
start_x = int(min(x0, x1) - half_brush_size)
|
start_x = int(min(x0, x1) - half_brush_size)
|
||||||
start_y = int(min(y0, y1) - half_brush_size)
|
start_y = int(min(y0, y1) - half_brush_size)
|
||||||
|
|
||||||
stroke_image = QImage(abs(xdiff) + self._brush_size, abs(ydiff) + self._brush_size, QImage.Format.Format_RGBA8888)
|
stroke_image = QImage(abs(xdiff) + self._brush_size, abs(ydiff) + self._brush_size, QImage.Format.Format_RGB32)
|
||||||
stroke_image.fill(QColor(0,0,0,0))
|
stroke_image.fill(0)
|
||||||
|
|
||||||
painter = QPainter(stroke_image)
|
painter = QPainter(stroke_image)
|
||||||
painter.setRenderHint(QPainter.RenderHint.Antialiasing, False)
|
painter.setRenderHint(QPainter.RenderHint.Antialiasing, False)
|
||||||
|
@ -93,8 +85,14 @@ class PaintTool(Tool):
|
||||||
return stroke_image, (start_x, start_y)
|
return stroke_image, (start_x, start_y)
|
||||||
|
|
||||||
def setPaintType(self, paint_type: str) -> None:
|
def setPaintType(self, paint_type: str) -> None:
|
||||||
Logger.warning(f"TODO: Implement paint-types ({paint_type}).")
|
paint_view = self._get_paint_view()
|
||||||
pass # FIXME: ... and also please call `self._brush_pen = self._createBrushPen()` (see other funcs).
|
if paint_view is None:
|
||||||
|
return
|
||||||
|
|
||||||
|
paint_view.setPaintType(paint_type)
|
||||||
|
|
||||||
|
self._brush_pen = self._createBrushPen()
|
||||||
|
self._updateScene()
|
||||||
|
|
||||||
def setBrushSize(self, brush_size: float) -> None:
|
def setBrushSize(self, brush_size: float) -> None:
|
||||||
if brush_size != self._brush_size:
|
if brush_size != self._brush_size:
|
||||||
|
@ -102,9 +100,7 @@ class PaintTool(Tool):
|
||||||
self._brush_pen = self._createBrushPen()
|
self._brush_pen = self._createBrushPen()
|
||||||
|
|
||||||
def setBrushColor(self, brush_color: str) -> None:
|
def setBrushColor(self, brush_color: str) -> None:
|
||||||
if brush_color != self._brush_color:
|
|
||||||
self._brush_color = brush_color
|
self._brush_color = brush_color
|
||||||
self._brush_pen = self._createBrushPen()
|
|
||||||
|
|
||||||
def setBrushShape(self, brush_shape: int) -> None:
|
def setBrushShape(self, brush_shape: int) -> None:
|
||||||
if brush_shape != self._brush_shape:
|
if brush_shape != self._brush_shape:
|
||||||
|
@ -112,19 +108,25 @@ class PaintTool(Tool):
|
||||||
self._brush_pen = self._createBrushPen()
|
self._brush_pen = self._createBrushPen()
|
||||||
|
|
||||||
def undoStackAction(self, redo_instead: bool) -> bool:
|
def undoStackAction(self, redo_instead: bool) -> bool:
|
||||||
paintview = Application.getInstance().getController().getActiveView()
|
paint_view = self._get_paint_view()
|
||||||
if paintview is None or paintview.getPluginId() != "PaintTool":
|
if paint_view is None:
|
||||||
return False
|
return False
|
||||||
paintview = cast(PaintView, paintview)
|
|
||||||
if redo_instead:
|
if redo_instead:
|
||||||
paintview.redoStroke()
|
paint_view.redoStroke()
|
||||||
else:
|
else:
|
||||||
paintview.undoStroke()
|
paint_view.undoStroke()
|
||||||
node = Selection.getSelectedObject(0)
|
|
||||||
if node is not None:
|
self._updateScene()
|
||||||
Application.getInstance().getController().getScene().sceneChanged.emit(node)
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _get_paint_view() -> Optional[PaintView]:
|
||||||
|
paint_view = Application.getInstance().getController().getActiveView()
|
||||||
|
if paint_view is None or paint_view.getPluginId() != "PaintTool":
|
||||||
|
return None
|
||||||
|
return cast(PaintView, paint_view)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _get_intersect_ratio_via_pt(a: numpy.ndarray, pt: numpy.ndarray, b: numpy.ndarray, c: numpy.ndarray) -> float:
|
def _get_intersect_ratio_via_pt(a: numpy.ndarray, pt: numpy.ndarray, b: numpy.ndarray, c: numpy.ndarray) -> float:
|
||||||
# compute the intersection of (param) A - pt with (param) B - (param) C
|
# compute the intersection of (param) A - pt with (param) B - (param) C
|
||||||
|
@ -314,12 +316,19 @@ class PaintTool(Tool):
|
||||||
end_coords[0] * w,
|
end_coords[0] * w,
|
||||||
end_coords[1] * h
|
end_coords[1] * h
|
||||||
)
|
)
|
||||||
paintview.addStroke(sub_image, start_x, start_y)
|
paintview.addStroke(sub_image, start_x, start_y, self._brush_color)
|
||||||
|
|
||||||
self._last_text_coords = texcoords
|
self._last_text_coords = texcoords
|
||||||
self._last_mouse_coords = (mouse_evt.x, mouse_evt.y)
|
self._last_mouse_coords = (mouse_evt.x, mouse_evt.y)
|
||||||
self._last_face_id = face_id
|
self._last_face_id = face_id
|
||||||
Application.getInstance().getController().getScene().sceneChanged.emit(node)
|
self._updateScene(node)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _updateScene(node: SceneNode = None):
|
||||||
|
if node is None:
|
||||||
|
node = Selection.getSelectedObject(0)
|
||||||
|
if node is not None:
|
||||||
|
Application.getInstance().getController().getScene().sceneChanged.emit(node)
|
|
@ -2,10 +2,12 @@
|
||||||
# Cura is released under the terms of the LGPLv3 or higher.
|
# Cura is released under the terms of the LGPLv3 or higher.
|
||||||
|
|
||||||
import os
|
import os
|
||||||
from typing import Optional, List, Tuple
|
from PyQt6.QtCore import QRect
|
||||||
|
from typing import Optional, List, Tuple, Dict
|
||||||
|
|
||||||
from PyQt6.QtGui import QImage, QColor, QPainter
|
from PyQt6.QtGui import QImage, QColor, QPainter
|
||||||
|
|
||||||
|
from cura.CuraApplication import CuraApplication
|
||||||
from UM.PluginRegistry import PluginRegistry
|
from UM.PluginRegistry import PluginRegistry
|
||||||
from UM.View.GL.ShaderProgram import ShaderProgram
|
from UM.View.GL.ShaderProgram import ShaderProgram
|
||||||
from UM.View.GL.Texture import Texture
|
from UM.View.GL.Texture import Texture
|
||||||
|
@ -13,6 +15,7 @@ from UM.View.View import View
|
||||||
from UM.Scene.Selection import Selection
|
from UM.Scene.Selection import Selection
|
||||||
from UM.View.GL.OpenGL import OpenGL
|
from UM.View.GL.OpenGL import OpenGL
|
||||||
from UM.i18n import i18nCatalog
|
from UM.i18n import i18nCatalog
|
||||||
|
from UM.Math.Color import Color
|
||||||
|
|
||||||
catalog = i18nCatalog("cura")
|
catalog = i18nCatalog("cura")
|
||||||
|
|
||||||
|
@ -22,10 +25,24 @@ class PaintView(View):
|
||||||
|
|
||||||
UNDO_STACK_SIZE = 1024
|
UNDO_STACK_SIZE = 1024
|
||||||
|
|
||||||
|
class PaintType:
|
||||||
|
def __init__(self, icon: str, display_color: Color, value: int):
|
||||||
|
self.icon: str = icon
|
||||||
|
self.display_color: Color = display_color
|
||||||
|
self.value: int = value
|
||||||
|
|
||||||
|
class PaintMode:
|
||||||
|
def __init__(self, icon: str, types: Dict[str, "PaintView.PaintType"]):
|
||||||
|
self.icon: str = icon
|
||||||
|
self.types = types
|
||||||
|
|
||||||
def __init__(self) -> None:
|
def __init__(self) -> None:
|
||||||
super().__init__()
|
super().__init__()
|
||||||
self._paint_shader: Optional[ShaderProgram] = None
|
self._paint_shader: Optional[ShaderProgram] = None
|
||||||
self._current_paint_texture: Optional[Texture] = None
|
self._current_paint_texture: Optional[Texture] = None
|
||||||
|
self._current_bits_ranges: tuple[int, int] = (0, 0)
|
||||||
|
self._current_paint_type = ""
|
||||||
|
self._paint_modes: Dict[str, PaintView.PaintMode] = {}
|
||||||
|
|
||||||
self._stroke_undo_stack: List[Tuple[QImage, int, int]] = []
|
self._stroke_undo_stack: List[Tuple[QImage, int, int]] = []
|
||||||
self._stroke_redo_stack: List[Tuple[QImage, int, int]] = []
|
self._stroke_redo_stack: List[Tuple[QImage, int, int]] = []
|
||||||
|
@ -33,6 +50,18 @@ class PaintView(View):
|
||||||
self._force_opaque_mask = QImage(2, 2, QImage.Format.Format_Mono)
|
self._force_opaque_mask = QImage(2, 2, QImage.Format.Format_Mono)
|
||||||
self._force_opaque_mask.fill(1)
|
self._force_opaque_mask.fill(1)
|
||||||
|
|
||||||
|
CuraApplication.getInstance().engineCreatedSignal.connect(self._makePaintModes)
|
||||||
|
|
||||||
|
def _makePaintModes(self):
|
||||||
|
theme = CuraApplication.getInstance().getTheme()
|
||||||
|
usual_types = {"A": self.PaintType("Buildplate", Color(*theme.getColor("paint_normal_area").getRgb()), 0),
|
||||||
|
"B": self.PaintType("BlackMagic", Color(*theme.getColor("paint_preferred_area").getRgb()), 1),
|
||||||
|
"C": self.PaintType("Eye", Color(*theme.getColor("paint_avoid_area").getRgb()), 2)}
|
||||||
|
self._paint_modes = {
|
||||||
|
"A": self.PaintMode("MeshTypeNormal", usual_types),
|
||||||
|
"B": self.PaintMode("CircleOutline", usual_types),
|
||||||
|
}
|
||||||
|
|
||||||
def _checkSetup(self):
|
def _checkSetup(self):
|
||||||
if not self._paint_shader:
|
if not self._paint_shader:
|
||||||
shader_filename = os.path.join(PluginRegistry.getInstance().getPluginPath("PaintTool"), "paint.shader")
|
shader_filename = os.path.join(PluginRegistry.getInstance().getPluginPath("PaintTool"), "paint.shader")
|
||||||
|
@ -49,14 +78,43 @@ class PaintView(View):
|
||||||
res.setAlphaChannel(self._force_opaque_mask.scaled(image.width(), image.height()))
|
res.setAlphaChannel(self._force_opaque_mask.scaled(image.width(), image.height()))
|
||||||
return res
|
return res
|
||||||
|
|
||||||
def addStroke(self, stroke_image: QImage, start_x: int, start_y: int) -> None:
|
def addStroke(self, stroke_image: QImage, start_x: int, start_y: int, brush_color: str) -> None:
|
||||||
if self._current_paint_texture is None:
|
if self._current_paint_texture is None or self._current_paint_texture.getImage() is None:
|
||||||
return
|
return
|
||||||
|
|
||||||
|
actual_image = self._current_paint_texture.getImage()
|
||||||
|
|
||||||
|
bit_range_start, bit_range_end = self._current_bits_ranges
|
||||||
|
set_value = self._paint_modes[self._current_paint_type].types[brush_color].value << self._current_bits_ranges[0]
|
||||||
|
full_int32 = 0xffffffff
|
||||||
|
clear_mask = full_int32 ^ (((full_int32 << (32 - 1 - (bit_range_end - bit_range_start))) & full_int32) >> (32 - 1 - bit_range_end))
|
||||||
|
image_rect = QRect(0, 0, stroke_image.width(), stroke_image.height())
|
||||||
|
|
||||||
|
clear_bits_image = stroke_image.copy()
|
||||||
|
clear_bits_image.invertPixels()
|
||||||
|
painter = QPainter(clear_bits_image)
|
||||||
|
painter.setCompositionMode(QPainter.CompositionMode.CompositionMode_Lighten)
|
||||||
|
painter.fillRect(image_rect, clear_mask)
|
||||||
|
painter.end()
|
||||||
|
|
||||||
|
set_value_image = stroke_image.copy()
|
||||||
|
painter = QPainter(set_value_image)
|
||||||
|
painter.setCompositionMode(QPainter.CompositionMode.CompositionMode_Multiply)
|
||||||
|
painter.fillRect(image_rect, set_value)
|
||||||
|
painter.end()
|
||||||
|
|
||||||
|
stroked_image = actual_image.copy(start_x, start_y, stroke_image.width(), stroke_image.height())
|
||||||
|
painter = QPainter(stroked_image)
|
||||||
|
painter.setCompositionMode(QPainter.CompositionMode.RasterOp_SourceAndDestination)
|
||||||
|
painter.drawImage(0, 0, clear_bits_image)
|
||||||
|
painter.setCompositionMode(QPainter.CompositionMode.RasterOp_SourceOrDestination)
|
||||||
|
painter.drawImage(0, 0, set_value_image)
|
||||||
|
painter.end()
|
||||||
|
|
||||||
self._stroke_redo_stack.clear()
|
self._stroke_redo_stack.clear()
|
||||||
if len(self._stroke_undo_stack) >= PaintView.UNDO_STACK_SIZE:
|
if len(self._stroke_undo_stack) >= PaintView.UNDO_STACK_SIZE:
|
||||||
self._stroke_undo_stack.pop(0)
|
self._stroke_undo_stack.pop(0)
|
||||||
undo_image = self._forceOpaqueDeepCopy(self._current_paint_texture.setSubImage(stroke_image, start_x, start_y))
|
undo_image = self._forceOpaqueDeepCopy(self._current_paint_texture.setSubImage(stroked_image, start_x, start_y))
|
||||||
if undo_image is not None:
|
if undo_image is not None:
|
||||||
self._stroke_undo_stack.append((undo_image, start_x, start_y))
|
self._stroke_undo_stack.append((undo_image, start_x, start_y))
|
||||||
|
|
||||||
|
@ -83,6 +141,31 @@ class PaintView(View):
|
||||||
return self._current_paint_texture.getWidth(), self._current_paint_texture.getHeight()
|
return self._current_paint_texture.getWidth(), self._current_paint_texture.getHeight()
|
||||||
return 0, 0
|
return 0, 0
|
||||||
|
|
||||||
|
def setPaintType(self, paint_type: str) -> None:
|
||||||
|
node = Selection.getAllSelectedObjects()[0]
|
||||||
|
if node is None:
|
||||||
|
return
|
||||||
|
|
||||||
|
paint_data_mapping = node.callDecoration("getTextureDataMapping")
|
||||||
|
|
||||||
|
if paint_type not in paint_data_mapping:
|
||||||
|
new_mapping = self._add_mapping(paint_data_mapping, len(self._paint_modes[paint_type].types))
|
||||||
|
paint_data_mapping[paint_type] = new_mapping
|
||||||
|
node.callDecoration("setTextureDataMapping", paint_data_mapping)
|
||||||
|
|
||||||
|
self._current_paint_type = paint_type
|
||||||
|
self._current_bits_ranges = paint_data_mapping[paint_type]
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _add_mapping(actual_mapping: Dict[str, tuple[int, int]], nb_storable_values: int) -> tuple[int, int]:
|
||||||
|
start_index = 0
|
||||||
|
if actual_mapping:
|
||||||
|
start_index = max(end_index for _, end_index in actual_mapping.values()) + 1
|
||||||
|
|
||||||
|
end_index = start_index + int.bit_length(nb_storable_values - 1) - 1
|
||||||
|
|
||||||
|
return start_index, end_index
|
||||||
|
|
||||||
def beginRendering(self) -> None:
|
def beginRendering(self) -> None:
|
||||||
renderer = self.getRenderer()
|
renderer = self.getRenderer()
|
||||||
self._checkSetup()
|
self._checkSetup()
|
||||||
|
@ -93,6 +176,17 @@ class PaintView(View):
|
||||||
if node is None:
|
if node is None:
|
||||||
return
|
return
|
||||||
|
|
||||||
|
if self._current_paint_type == "":
|
||||||
|
self.setPaintType("A")
|
||||||
|
|
||||||
|
self._paint_shader.setUniformValue("u_bitsRangesStart", self._current_bits_ranges[0])
|
||||||
|
self._paint_shader.setUniformValue("u_bitsRangesEnd", self._current_bits_ranges[1])
|
||||||
|
|
||||||
|
colors = [paint_type_obj.display_color for paint_type_obj in self._paint_modes[self._current_paint_type].types.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)
|
||||||
|
|
||||||
self._current_paint_texture = node.callDecoration("getPaintTexture")
|
self._current_paint_texture = node.callDecoration("getPaintTexture")
|
||||||
self._paint_shader.setTexture(0, self._current_paint_texture)
|
self._paint_shader.setTexture(0, self._current_paint_texture)
|
||||||
|
|
||||||
paint_batch.addItem(node.getWorldTransformation(copy=False), node.getMeshData(), normal_transformation=node.getCachedNormalMatrix())
|
paint_batch.addItem(node.getWorldTransformation(copy=False), node.getMeshData(), normal_transformation=node.getCachedNormalMatrix())
|
||||||
|
|
|
@ -27,11 +27,13 @@ vertex =
|
||||||
|
|
||||||
fragment =
|
fragment =
|
||||||
uniform mediump vec4 u_ambientColor;
|
uniform mediump vec4 u_ambientColor;
|
||||||
uniform mediump vec4 u_diffuseColor;
|
|
||||||
uniform highp vec3 u_lightPosition;
|
uniform highp vec3 u_lightPosition;
|
||||||
uniform highp vec3 u_viewPosition;
|
uniform highp vec3 u_viewPosition;
|
||||||
uniform mediump float u_opacity;
|
uniform mediump float u_opacity;
|
||||||
uniform sampler2D u_texture;
|
uniform sampler2D u_texture;
|
||||||
|
uniform mediump int u_bitsRangesStart;
|
||||||
|
uniform mediump int u_bitsRangesEnd;
|
||||||
|
uniform mediump vec3 u_renderColors[16];
|
||||||
|
|
||||||
varying highp vec3 v_vertex;
|
varying highp vec3 v_vertex;
|
||||||
varying highp vec3 v_normal;
|
varying highp vec3 v_normal;
|
||||||
|
@ -48,15 +50,17 @@ fragment =
|
||||||
highp vec3 light_dir = normalize(u_lightPosition - v_vertex);
|
highp vec3 light_dir = normalize(u_lightPosition - v_vertex);
|
||||||
|
|
||||||
/* Diffuse Component */
|
/* Diffuse Component */
|
||||||
|
ivec4 texture = ivec4(texture(u_texture, v_uvs) * 255.0);
|
||||||
|
uint color_index = (texture.r << 16) | (texture.g << 8) | texture.b;
|
||||||
|
color_index = (color_index << (32 - 1 - u_bitsRangesEnd)) >> 32 - 1 - (u_bitsRangesEnd - u_bitsRangesStart);
|
||||||
|
|
||||||
|
vec4 diffuse_color = vec4(u_renderColors[color_index] / 255.0, 1.0);
|
||||||
highp float n_dot_l = clamp(dot(normal, light_dir), 0.0, 1.0);
|
highp float n_dot_l = clamp(dot(normal, light_dir), 0.0, 1.0);
|
||||||
final_color += (n_dot_l * u_diffuseColor);
|
final_color += (n_dot_l * diffuse_color);
|
||||||
|
|
||||||
final_color.a = u_opacity;
|
final_color.a = u_opacity;
|
||||||
|
|
||||||
lowp vec4 texture = texture2D(u_texture, v_uvs);
|
frag_color = final_color;
|
||||||
final_color = mix(final_color, texture, texture.a);
|
|
||||||
|
|
||||||
gl_FragColor = final_color;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
vertex41core =
|
vertex41core =
|
||||||
|
@ -89,11 +93,13 @@ vertex41core =
|
||||||
fragment41core =
|
fragment41core =
|
||||||
#version 410
|
#version 410
|
||||||
uniform mediump vec4 u_ambientColor;
|
uniform mediump vec4 u_ambientColor;
|
||||||
uniform mediump vec4 u_diffuseColor;
|
|
||||||
uniform highp vec3 u_lightPosition;
|
uniform highp vec3 u_lightPosition;
|
||||||
uniform highp vec3 u_viewPosition;
|
uniform highp vec3 u_viewPosition;
|
||||||
uniform mediump float u_opacity;
|
uniform mediump float u_opacity;
|
||||||
uniform sampler2D u_texture;
|
uniform sampler2D u_texture;
|
||||||
|
uniform mediump int u_bitsRangesStart;
|
||||||
|
uniform mediump int u_bitsRangesEnd;
|
||||||
|
uniform mediump vec3 u_renderColors[16];
|
||||||
|
|
||||||
in highp vec3 v_vertex;
|
in highp vec3 v_vertex;
|
||||||
in highp vec3 v_normal;
|
in highp vec3 v_normal;
|
||||||
|
@ -111,20 +117,21 @@ fragment41core =
|
||||||
highp vec3 light_dir = normalize(u_lightPosition - v_vertex);
|
highp vec3 light_dir = normalize(u_lightPosition - v_vertex);
|
||||||
|
|
||||||
/* Diffuse Component */
|
/* Diffuse Component */
|
||||||
|
ivec4 texture = ivec4(texture(u_texture, v_uvs) * 255.0);
|
||||||
|
uint color_index = (texture.r << 16) | (texture.g << 8) | texture.b;
|
||||||
|
color_index = (color_index << (32 - 1 - u_bitsRangesEnd)) >> 32 - 1 - (u_bitsRangesEnd - u_bitsRangesStart);
|
||||||
|
|
||||||
|
vec4 diffuse_color = vec4(u_renderColors[color_index] / 255.0, 1.0);
|
||||||
highp float n_dot_l = clamp(dot(normal, light_dir), 0.0, 1.0);
|
highp float n_dot_l = clamp(dot(normal, light_dir), 0.0, 1.0);
|
||||||
final_color += (n_dot_l * u_diffuseColor);
|
final_color += (n_dot_l * diffuse_color);
|
||||||
|
|
||||||
final_color.a = u_opacity;
|
final_color.a = u_opacity;
|
||||||
|
|
||||||
lowp vec4 texture = texture(u_texture, v_uvs);
|
|
||||||
final_color = mix(final_color, texture, texture.a);
|
|
||||||
|
|
||||||
frag_color = final_color;
|
frag_color = final_color;
|
||||||
}
|
}
|
||||||
|
|
||||||
[defaults]
|
[defaults]
|
||||||
u_ambientColor = [0.3, 0.3, 0.3, 1.0]
|
u_ambientColor = [0.3, 0.3, 0.3, 1.0]
|
||||||
u_diffuseColor = [1.0, 1.0, 1.0, 1.0]
|
|
||||||
u_opacity = 0.5
|
u_opacity = 0.5
|
||||||
u_texture = 0
|
u_texture = 0
|
||||||
|
|
||||||
|
|
|
@ -103,8 +103,8 @@ geometry41core =
|
||||||
vec4 g_vertex_offset_vert;
|
vec4 g_vertex_offset_vert;
|
||||||
vec3 g_vertex_normal_horz_head;
|
vec3 g_vertex_normal_horz_head;
|
||||||
vec4 g_vertex_offset_horz_head;
|
vec4 g_vertex_offset_horz_head;
|
||||||
vec3 g_axial_plan_vector;
|
vec3 g_axial_plane_vector;
|
||||||
vec3 g_radial_plan_vector;
|
vec3 g_radial_plane_vector;
|
||||||
|
|
||||||
float size_x;
|
float size_x;
|
||||||
float size_y;
|
float size_y;
|
||||||
|
@ -143,25 +143,25 @@ geometry41core =
|
||||||
|
|
||||||
if (g_vertex_delta.y == 0.0)
|
if (g_vertex_delta.y == 0.0)
|
||||||
{
|
{
|
||||||
// vector is in the horizontal plan, radial vector is a simple rotation around Y axis
|
// vector is in the horizontal plane, radial vector is a simple rotation around Y axis
|
||||||
g_radial_plan_vector = vec3(g_vertex_delta.z, 0.0, -g_vertex_delta.x);
|
g_radial_plane_vector = vec3(g_vertex_delta.z, 0.0, -g_vertex_delta.x);
|
||||||
}
|
}
|
||||||
else if(g_vertex_delta.x == 0.0 && g_vertex_delta.z == 0.0)
|
else if(g_vertex_delta.x == 0.0 && g_vertex_delta.z == 0.0)
|
||||||
{
|
{
|
||||||
// delta vector is purely vertical, display the line rotated vertically so that it is visible in front and side views
|
// delta vector is purely vertical, display the line rotated vertically so that it is visible in front and side views
|
||||||
g_radial_plan_vector = vec3(1.0, 0.0, -1.0);
|
g_radial_plane_vector = vec3(1.0, 0.0, -1.0);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// delta vector is completely 3D
|
// delta vector is completely 3D
|
||||||
g_axial_plan_vector = vec3(g_vertex_delta.x, 0.0, g_vertex_delta.z); // Vector projected in the horizontal plan
|
g_axial_plane_vector = vec3(g_vertex_delta.x, 0.0, g_vertex_delta.z); // Vector projected in the horizontal plane
|
||||||
g_radial_plan_vector = cross(g_vertex_delta, g_axial_plan_vector); // Radial vector in the horizontal plan, pointing right.
|
g_radial_plane_vector = cross(g_vertex_delta, g_axial_plane_vector); // Radial vector in the horizontal plane, pointing right.
|
||||||
}
|
}
|
||||||
|
|
||||||
g_vertex_normal_horz_head = normalize(g_vertex_delta); //Lengthwise normal vector
|
g_vertex_normal_horz_head = normalize(g_vertex_delta); //Lengthwise normal vector
|
||||||
g_vertex_offset_horz_head = vec4(g_vertex_normal_horz_head * size_x, 0.0); //Lengthwise offset vector
|
g_vertex_offset_horz_head = vec4(g_vertex_normal_horz_head * size_x, 0.0); //Lengthwise offset vector
|
||||||
|
|
||||||
g_vertex_normal_horz = normalize(g_radial_plan_vector); //Normal vector pointing right.
|
g_vertex_normal_horz = normalize(g_radial_plane_vector); //Normal vector pointing right.
|
||||||
g_vertex_offset_horz = vec4(g_vertex_normal_horz * size_x, 0.0); //Offset vector pointing right.
|
g_vertex_offset_horz = vec4(g_vertex_normal_horz * size_x, 0.0); //Offset vector pointing right.
|
||||||
|
|
||||||
g_vertex_normal_vert = vec3(0.0, 1.0, 0.0); //Upwards normal vector.
|
g_vertex_normal_vert = vec3(0.0, 1.0, 0.0); //Upwards normal vector.
|
||||||
|
|
|
@ -0,0 +1,15 @@
|
||||||
|
[general]
|
||||||
|
definition = ultimaker_s8
|
||||||
|
name = Extra Fine
|
||||||
|
version = 4
|
||||||
|
|
||||||
|
[metadata]
|
||||||
|
global_quality = True
|
||||||
|
quality_type = high
|
||||||
|
setting_version = 25
|
||||||
|
type = quality
|
||||||
|
weight = 1
|
||||||
|
|
||||||
|
[values]
|
||||||
|
layer_height = =round(0.06 * material_shrinkage_percentage_z / 100, 5)
|
||||||
|
|
|
@ -0,0 +1,15 @@
|
||||||
|
[general]
|
||||||
|
definition = ultimaker_s8
|
||||||
|
name = Sprint
|
||||||
|
version = 4
|
||||||
|
|
||||||
|
[metadata]
|
||||||
|
global_quality = True
|
||||||
|
quality_type = superdraft
|
||||||
|
setting_version = 25
|
||||||
|
type = quality
|
||||||
|
weight = -4
|
||||||
|
|
||||||
|
[values]
|
||||||
|
layer_height = =round(0.4 * material_shrinkage_percentage_z / 100, 5)
|
||||||
|
|
|
@ -1 +1,26 @@
|
||||||
{"metadata": {"name": "Colorblind Assist Dark", "inherits": "cura-dark"}, "colors": {"x_axis": [212, 0, 0, 255], "y_axis": [64, 64, 255, 255], "model_overhang": [200, 0, 255, 255], "xray": [26, 26, 62, 255], "xray_error": [255, 0, 0, 255], "layerview_inset_0": [255, 64, 0, 255], "layerview_inset_x": [0, 156, 128, 255], "layerview_skin": [255, 255, 86, 255], "layerview_support": [255, 255, 0, 255], "layerview_infill": [0, 255, 255, 255], "layerview_support_infill": [0, 200, 200, 255], "layerview_move_retraction": [0, 100, 255, 255], "main_window_header_background": [192, 199, 65, 255]}}
|
{
|
||||||
|
"metadata": {
|
||||||
|
"name": "Colorblind Assist Dark",
|
||||||
|
"inherits": "cura-dark"
|
||||||
|
},
|
||||||
|
|
||||||
|
"colors": {
|
||||||
|
"x_axis": [212, 0, 0, 255],
|
||||||
|
"y_axis": [64, 64, 255, 255],
|
||||||
|
|
||||||
|
"model_overhang": [200, 0, 255, 255],
|
||||||
|
|
||||||
|
"xray": [26, 26, 62, 255],
|
||||||
|
"xray_error": [255, 0, 0, 255],
|
||||||
|
|
||||||
|
"layerview_inset_0": [255, 64, 0, 255],
|
||||||
|
"layerview_inset_x": [0, 156, 128, 255],
|
||||||
|
"layerview_skin": [255, 255, 86, 255],
|
||||||
|
"layerview_support": [255, 255, 0, 255],
|
||||||
|
|
||||||
|
"layerview_infill": [0, 255, 255, 255],
|
||||||
|
"layerview_support_infill": [0, 200, 200, 255],
|
||||||
|
|
||||||
|
"layerview_move_retraction": [0, 100, 255, 255]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
File diff suppressed because one or more lines are too long
|
@ -1 +1,29 @@
|
||||||
{"metadata": {"name": "Colorblind Assist Light", "inherits": "cura-light"}, "colors": {"x_axis": [200, 0, 0, 255], "y_axis": [64, 64, 255, 255], "model_overhang": [200, 0, 255, 255], "model_selection_outline": [12, 169, 227, 255], "xray_error_dark": [255, 0, 0, 255], "xray_error_light": [255, 255, 0, 255], "xray": [26, 26, 62, 255], "xray_error": [255, 0, 0, 255], "layerview_inset_0": [255, 64, 0, 255], "layerview_inset_x": [0, 156, 128, 255], "layerview_skin": [255, 255, 86, 255], "layerview_support": [255, 255, 0, 255], "layerview_infill": [0, 255, 255, 255], "layerview_support_infill": [0, 200, 200, 255], "layerview_move_retraction": [0, 100, 255, 255], "main_window_header_background": [192, 199, 65, 255]}}
|
{
|
||||||
|
"metadata": {
|
||||||
|
"name": "Colorblind Assist Light",
|
||||||
|
"inherits": "cura-light"
|
||||||
|
},
|
||||||
|
|
||||||
|
"colors": {
|
||||||
|
|
||||||
|
"x_axis": [200, 0, 0, 255],
|
||||||
|
"y_axis": [64, 64, 255, 255],
|
||||||
|
"model_overhang": [200, 0, 255, 255],
|
||||||
|
"model_selection_outline": [12, 169, 227, 255],
|
||||||
|
|
||||||
|
"xray_error_dark": [255, 0, 0, 255],
|
||||||
|
"xray_error_light": [255, 255, 0, 255],
|
||||||
|
"xray": [26, 26, 62, 255],
|
||||||
|
"xray_error": [255, 0, 0, 255],
|
||||||
|
|
||||||
|
"layerview_inset_0": [255, 64, 0, 255],
|
||||||
|
"layerview_inset_x": [0, 156, 128, 255],
|
||||||
|
"layerview_skin": [255, 255, 86, 255],
|
||||||
|
"layerview_support": [255, 255, 0, 255],
|
||||||
|
|
||||||
|
"layerview_infill": [0, 255, 255, 255],
|
||||||
|
"layerview_support_infill": [0, 200, 200, 255],
|
||||||
|
|
||||||
|
"layerview_move_retraction": [0, 100, 255, 255]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
File diff suppressed because one or more lines are too long
16
resources/themes/daily_test_colors.json
Normal file
16
resources/themes/daily_test_colors.json
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
[
|
||||||
|
[ 62, 33, 55, 255],
|
||||||
|
[126, 196, 193, 255],
|
||||||
|
[126, 196, 193, 255],
|
||||||
|
[215, 155, 125, 255],
|
||||||
|
[228, 148, 58, 255],
|
||||||
|
[192, 199, 65, 255],
|
||||||
|
[157, 48, 59, 255],
|
||||||
|
[140, 143, 174, 255],
|
||||||
|
[ 23, 67, 75, 255],
|
||||||
|
[ 23, 67, 75, 255],
|
||||||
|
[154, 99, 72, 255],
|
||||||
|
[112, 55, 127, 255],
|
||||||
|
[100, 125, 52, 255],
|
||||||
|
[210, 100, 113, 255]
|
||||||
|
]
|
|
@ -11,6 +11,7 @@ type = variant
|
||||||
[values]
|
[values]
|
||||||
machine_nozzle_heat_up_speed = 1.5
|
machine_nozzle_heat_up_speed = 1.5
|
||||||
machine_nozzle_id = BB 0.4
|
machine_nozzle_id = BB 0.4
|
||||||
|
machine_nozzle_size = 0.4
|
||||||
machine_nozzle_tip_outer_diameter = 1.0
|
machine_nozzle_tip_outer_diameter = 1.0
|
||||||
retraction_amount = 4.5
|
retraction_amount = 4.5
|
||||||
support_bottom_height = =layer_height * 2
|
support_bottom_height = =layer_height * 2
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue