diff --git a/cura/LayerDataBuilder.py b/cura/LayerDataBuilder.py index d8801c9e7b..ff80307223 100755 --- a/cura/LayerDataBuilder.py +++ b/cura/LayerDataBuilder.py @@ -80,9 +80,13 @@ class LayerDataBuilder(MeshBuilder): material_colors = numpy.zeros((line_dimensions.shape[0], 4), dtype=numpy.float32) for extruder_nr in range(material_color_map.shape[0]): material_colors[extruders == extruder_nr] = material_color_map[extruder_nr] - # Set material_colors with indices where line_types (also numpy array) == MoveCombingType - material_colors[line_types == LayerPolygon.MoveCombingType] = colors[line_types == LayerPolygon.MoveCombingType] - material_colors[line_types == LayerPolygon.MoveRetractionType] = colors[line_types == LayerPolygon.MoveRetractionType] + # Set material_colors with indices where line_types (also numpy array) == MoveUnretractedType + material_colors[line_types == LayerPolygon.MoveUnretractedType] = colors[line_types == LayerPolygon.MoveUnretractedType] + material_colors[line_types == LayerPolygon.MoveRetractedType] = colors[line_types == LayerPolygon.MoveRetractedType] + material_colors[line_types == LayerPolygon.MoveWhileRetractingType] = colors[ + line_types == LayerPolygon.MoveWhileRetractingType] + material_colors[line_types == LayerPolygon.MoveWhileUnretractingType] = colors[ + line_types == LayerPolygon.MoveWhileUnretractingType] attributes = { "line_dimensions": { diff --git a/cura/LayerPolygon.py b/cura/LayerPolygon.py index e772a8b78e..c4d57c07a0 100644 --- a/cura/LayerPolygon.py +++ b/cura/LayerPolygon.py @@ -19,15 +19,21 @@ class LayerPolygon: SkirtType = 5 InfillType = 6 SupportInfillType = 7 - MoveCombingType = 8 - MoveRetractionType = 9 + MoveUnretractedType = 8 + MoveRetractedType = 9 SupportInterfaceType = 10 PrimeTowerType = 11 - __number_of_types = 12 + MoveWhileRetractingType = 12 + MoveWhileUnretractingType = 13 + __number_of_types = 14 - __jump_map = numpy.logical_or(numpy.logical_or(numpy.arange(__number_of_types) == NoneType, - numpy.arange(__number_of_types) == MoveCombingType), - numpy.arange(__number_of_types) == MoveRetractionType) + __jump_map = numpy.logical_or(numpy.logical_or(numpy.logical_or( + numpy.arange(__number_of_types) == NoneType, + numpy.arange(__number_of_types) == MoveUnretractedType), + numpy.logical_or( + numpy.arange(__number_of_types) == MoveRetractedType, + numpy.arange(__number_of_types) == MoveWhileRetractingType)), + numpy.arange(__number_of_types) == MoveWhileUnretractingType) def __init__(self, extruder: int, line_types: numpy.ndarray, data: numpy.ndarray, line_widths: numpy.ndarray, line_thicknesses: numpy.ndarray, line_feedrates: numpy.ndarray) -> None: @@ -269,10 +275,12 @@ class LayerPolygon: theme.getColor("layerview_skirt").getRgbF(), # SkirtType theme.getColor("layerview_infill").getRgbF(), # InfillType theme.getColor("layerview_support_infill").getRgbF(), # SupportInfillType - theme.getColor("layerview_move_combing").getRgbF(), # MoveCombingType - theme.getColor("layerview_move_retraction").getRgbF(), # MoveRetractionType + theme.getColor("layerview_move_combing").getRgbF(), # MoveUnretractedType + theme.getColor("layerview_move_retraction").getRgbF(), # MoveRetractedType theme.getColor("layerview_support_interface").getRgbF(), # SupportInterfaceType - theme.getColor("layerview_prime_tower").getRgbF() # PrimeTowerType + theme.getColor("layerview_prime_tower").getRgbF(), # PrimeTowerType + theme.getColor("layerview_move_while_retracting").getRgbF(), # MoveWhileRetracting + theme.getColor("layerview_move_while_unretracting").getRgbF(), # MoveWhileUnretracting ]) return cls.__color_map diff --git a/cura/Scene/SliceableObjectDecorator.py b/cura/Scene/SliceableObjectDecorator.py index ad51f7d755..c26848ed1a 100644 --- a/cura/Scene/SliceableObjectDecorator.py +++ b/cura/Scene/SliceableObjectDecorator.py @@ -1,12 +1,34 @@ -from UM.Scene.SceneNodeDecorator import SceneNodeDecorator +import copy +from typing import Optional + +import UM.View.GL.Texture +from UM.Scene.SceneNodeDecorator import SceneNodeDecorator +from UM.View.GL.OpenGL import OpenGL +from UM.View.GL.Texture import Texture + + +# FIXME: When the texture UV-unwrapping is done, these two values will need to be set to a proper value (suggest 4096 for both). +TEXTURE_WIDTH = 512 +TEXTURE_HEIGHT = 512 class SliceableObjectDecorator(SceneNodeDecorator): def __init__(self) -> None: super().__init__() + self._paint_texture = None def isSliceable(self) -> bool: return True + def getPaintTexture(self, create_if_required: bool = True) -> Optional[UM.View.GL.Texture.Texture]: + if self._paint_texture is None and create_if_required: + self._paint_texture = OpenGL.getInstance().createTexture(TEXTURE_WIDTH, TEXTURE_HEIGHT) + return self._paint_texture + + def setPaintTexture(self, texture: UM.View.GL.Texture) -> None: + self._paint_texture = texture + def __deepcopy__(self, memo) -> "SliceableObjectDecorator": - return type(self)() + copied_decorator = SliceableObjectDecorator() + copied_decorator.setPaintTexture(copy.deepcopy(self.getPaintTexture())) + return copied_decorator diff --git a/plugins/3MFReader/ThreeMFReader.py b/plugins/3MFReader/ThreeMFReader.py index 98cae593e1..cf14ed41f3 100755 --- a/plugins/3MFReader/ThreeMFReader.py +++ b/plugins/3MFReader/ThreeMFReader.py @@ -7,6 +7,7 @@ from typing import List, Optional, Union, TYPE_CHECKING, cast import pySavitar as Savitar import numpy +from PyQt6.QtGui import QImage from UM.Logger import Logger from UM.Math.Matrix import Matrix @@ -18,6 +19,8 @@ from UM.Scene.GroupDecorator import GroupDecorator from UM.Scene.SceneNode import SceneNode # For typing. from UM.Scene.SceneNodeSettings import SceneNodeSettings from UM.Util import parseBool +from UM.View.GL.OpenGL import OpenGL +from UM.View.GL.Texture import Texture from cura.CuraApplication import CuraApplication from cura.Machines.ContainerTree import ContainerTree from cura.Scene.BuildPlateDecorator import BuildPlateDecorator @@ -94,14 +97,14 @@ class ThreeMFReader(MeshReader): return temp_mat @staticmethod - def _convertSavitarNodeToUMNode(savitar_node: Savitar.SceneNode, file_name: str = "", archive: zipfile.ZipFile = None) -> Optional[SceneNode]: + def _convertSavitarNodeToUMNode(savitar_node: Savitar.SceneNode, file_name: str = "", archive: zipfile.ZipFile = None, scene: Savitar.Scene = None) -> Optional[SceneNode]: """Convenience function that converts a SceneNode object (as obtained from libSavitar) to a scene node. :returns: Scene node. """ try: node_name = savitar_node.getName() - node_id = savitar_node.getId() + node_id = str(savitar_node.getId()) except AttributeError: Logger.log("e", "Outdated version of libSavitar detected! Please update to the newest version!") node_name = "" @@ -131,12 +134,19 @@ class ThreeMFReader(MeshReader): um_node.setTransformation(transformation) mesh_builder = MeshBuilder() - data = numpy.fromstring(savitar_node.getMeshData().getFlatVerticesAsBytes(), dtype=numpy.float32) + mesh_data = savitar_node.getMeshData() + + vertices_data = numpy.fromstring(mesh_data.getFlatVerticesAsBytes(), dtype=numpy.float32) + vertices = numpy.resize(vertices_data, (int(vertices_data.size / 3), 3)) + + texture_path = mesh_data.getTexturePath(scene) + uv_data = numpy.fromstring(mesh_data.getUVCoordinatesPerVertexAsBytes(scene), dtype=numpy.float32) + uv_coordinates = numpy.resize(uv_data, (int(uv_data.size / 2), 2)) - vertices = numpy.resize(data, (int(data.size / 3), 3)) mesh_builder.setVertices(vertices) mesh_builder.calculateNormals(fast=True) mesh_builder.setMeshId(node_id) + mesh_builder.setUVCoordinates(uv_coordinates) if file_name: # The filename is used to give the user the option to reload the file if it is changed on disk # It is only set for the root node of the 3mf file @@ -150,7 +160,7 @@ class ThreeMFReader(MeshReader): um_node.setMeshData(mesh_data) for child in savitar_node.getChildren(): - child_node = ThreeMFReader._convertSavitarNodeToUMNode(child, archive=archive) + child_node = ThreeMFReader._convertSavitarNodeToUMNode(child, archive=archive, scene=scene) if child_node: um_node.addChild(child_node) @@ -222,6 +232,14 @@ class ThreeMFReader(MeshReader): # affects (auto) slicing sliceable_decorator = SliceableObjectDecorator() um_node.addDecorator(sliceable_decorator) + + if texture_path != "" and archive is not None: + texture_data = archive.open(texture_path).read() + texture_image = QImage.fromData(texture_data, "PNG") + texture = Texture(OpenGL.getInstance()) + texture.setImage(texture_image) + sliceable_decorator.setPaintTexture(texture) + return um_node def _read(self, file_name: str) -> Union[SceneNode, List[SceneNode]]: @@ -239,7 +257,7 @@ class ThreeMFReader(MeshReader): CuraApplication.getInstance().getController().getScene().setMetaDataEntry(key, value) for node in scene_3mf.getSceneNodes(): - um_node = ThreeMFReader._convertSavitarNodeToUMNode(node, file_name, archive) + um_node = ThreeMFReader._convertSavitarNodeToUMNode(node, file_name, archive, scene_3mf) if um_node is None: continue @@ -339,7 +357,7 @@ class ThreeMFReader(MeshReader): # Convert the scene to scene nodes nodes = [] for savitar_node in scene.getSceneNodes(): - scene_node = ThreeMFReader._convertSavitarNodeToUMNode(savitar_node, "file_name") + scene_node = ThreeMFReader._convertSavitarNodeToUMNode(savitar_node, "file_name", scene=scene) if scene_node is None: continue nodes.append(scene_node) diff --git a/plugins/3MFWriter/ThreeMFWriter.py b/plugins/3MFWriter/ThreeMFWriter.py index 558b36576f..4cb7840841 100644 --- a/plugins/3MFWriter/ThreeMFWriter.py +++ b/plugins/3MFWriter/ThreeMFWriter.py @@ -58,6 +58,8 @@ catalog = i18nCatalog("cura") MODEL_PATH = "3D/3dmodel.model" PACKAGE_METADATA_PATH = "Cura/packages.json" +TEXTURES_PATH = "3D/Textures" +MODEL_RELATIONS_PATH = "3D/_rels/3dmodel.model.rels" class ThreeMFWriter(MeshWriter): def __init__(self): @@ -109,7 +111,11 @@ class ThreeMFWriter(MeshWriter): def _convertUMNodeToSavitarNode(um_node, transformation = Matrix(), exported_settings: Optional[Dict[str, Set[str]]] = None, - center_mesh = False): + center_mesh = False, + scene: Savitar.Scene = None, + archive: zipfile.ZipFile = None, + model_relations_element: ET.Element = None, + content_types_element: ET.Element = None): """Convenience function that converts an Uranium SceneNode object to a SavitarSceneNode :returns: Uranium Scene node. @@ -150,7 +156,35 @@ class ThreeMFWriter(MeshWriter): if indices_array is not None: savitar_node.getMeshData().setFacesFromBytes(indices_array) else: - savitar_node.getMeshData().setFacesFromBytes(numpy.arange(mesh_data.getVertices().size / 3, dtype=numpy.int32).tostring()) + savitar_node.getMeshData().setFacesFromBytes(numpy.arange(mesh_data.getVertices().size / 3, dtype=numpy.int32).tobytes()) + + texture = um_node.callDecoration("getPaintTexture") + uv_coordinates_array = mesh_data.getUVCoordinatesAsByteArray() + if texture is not None and archive is not None and uv_coordinates_array is not None and len(uv_coordinates_array) > 0: + texture_image = texture.getImage() + if texture_image is not None: + texture_path = f"{TEXTURES_PATH}/{id(um_node)}.png" + + texture_buffer = QBuffer() + texture_buffer.open(QBuffer.OpenModeFlag.ReadWrite) + texture_image.save(texture_buffer, "PNG") + + texture_file = zipfile.ZipInfo(texture_path) + # Don't try to compress texture file, because the PNG is pretty much as compact as it will get + archive.writestr(texture_file, texture_buffer.data()) + + savitar_node.getMeshData().setUVCoordinatesPerVertexAsBytes(uv_coordinates_array, texture_path, scene) + + # Add texture relation to model relations file + if model_relations_element is not None: + ET.SubElement(model_relations_element, "Relationship", + Target=texture_path, Id=f"rel{len(model_relations_element)+1}", + Type="http://schemas.microsoft.com/3dmanufacturing/2013/01/3dtexture") + + if content_types_element is not None: + ET.SubElement(content_types_element, "Override", PartName=texture_path, + ContentType="application/vnd.ms-package.3dmanufacturing-3dmodeltexture") + # Handle per object settings (if any) stack = um_node.callDecoration("getStack") @@ -187,7 +221,11 @@ class ThreeMFWriter(MeshWriter): if child_node.callDecoration("getBuildPlateNumber") != active_build_plate_nr: continue savitar_child_node = ThreeMFWriter._convertUMNodeToSavitarNode(child_node, - exported_settings = exported_settings) + exported_settings = exported_settings, + scene = scene, + archive = archive, + model_relations_element = model_relations_element, + content_types_element = content_types_element) if savitar_child_node is not None: savitar_node.addChild(savitar_child_node) @@ -249,6 +287,9 @@ class ThreeMFWriter(MeshWriter): # Create Metadata/_rels/model_settings.config.rels metadata_relations_element = self._makeRelationsTree() + # Create model relations + model_relations_element = self._makeRelationsTree() + # Let the variant add its specific files variant.add_extra_files(archive, metadata_relations_element) @@ -320,13 +361,21 @@ class ThreeMFWriter(MeshWriter): savitar_node = ThreeMFWriter._convertUMNodeToSavitarNode(root_child, transformation_matrix, exported_model_settings, - center_mesh = True) + center_mesh = True, + scene = savitar_scene, + archive = archive, + model_relations_element = model_relations_element, + content_types_element = content_types) if savitar_node: savitar_scene.addSceneNode(savitar_node) else: savitar_node = self._convertUMNodeToSavitarNode(node, transformation_matrix, - exported_model_settings) + exported_model_settings, + scene = savitar_scene, + archive = archive, + model_relations_element = model_relations_element, + content_types_element = content_types) if savitar_node: savitar_scene.addSceneNode(savitar_node) @@ -338,6 +387,8 @@ class ThreeMFWriter(MeshWriter): self._storeElementTree(archive, "_rels/.rels", relations_element) if len(metadata_relations_element) > 0: self._storeElementTree(archive, "Metadata/_rels/model_settings.config.rels", metadata_relations_element) + if len(model_relations_element) > 0: + self._storeElementTree(archive, MODEL_RELATIONS_PATH, model_relations_element) except Exception as error: Logger.logException("e", "Error writing zip file") self.setInformation(str(error)) @@ -500,7 +551,7 @@ class ThreeMFWriter(MeshWriter): def sceneNodesToString(scene_nodes: [SceneNode]) -> str: savitar_scene = Savitar.Scene() for scene_node in scene_nodes: - savitar_node = ThreeMFWriter._convertUMNodeToSavitarNode(scene_node, center_mesh = True) + savitar_node = ThreeMFWriter._convertUMNodeToSavitarNode(scene_node, center_mesh = True, scene = savitar_scene) savitar_scene.addSceneNode(savitar_node) parser = Savitar.ThreeMFParser() scene_string = parser.sceneToString(savitar_scene) diff --git a/plugins/CuraEngineBackend/Cura.proto b/plugins/CuraEngineBackend/Cura.proto index 238829ba64..8018c9186f 100644 --- a/plugins/CuraEngineBackend/Cura.proto +++ b/plugins/CuraEngineBackend/Cura.proto @@ -78,8 +78,8 @@ message Polygon { SkirtType = 5; InfillType = 6; SupportInfillType = 7; - MoveCombingType = 8; - MoveRetractionType = 9; + MoveUnretractedType = 8; + MoveRetractedType = 9; SupportInterfaceType = 10; PrimeTowerType = 11; } diff --git a/plugins/GCodeReader/FlavorParser.py b/plugins/GCodeReader/FlavorParser.py index 74dbeadec0..f83a9bbb34 100644 --- a/plugins/GCodeReader/FlavorParser.py +++ b/plugins/GCodeReader/FlavorParser.py @@ -133,7 +133,10 @@ class FlavorParser: if i > 0: line_feedrates[i - 1] = point[3] line_types[i - 1] = point[5] - if point[5] in [LayerPolygon.MoveCombingType, LayerPolygon.MoveRetractionType]: + if point[5] in [LayerPolygon.MoveUnretractedType, + LayerPolygon.MoveRetractedType, + LayerPolygon.MoveWhileRetractingType, + LayerPolygon.MoveWhileUnretractingType]: line_widths[i - 1] = 0.1 line_thicknesses[i - 1] = 0.0 # Travels are set as zero thickness lines else: @@ -196,7 +199,7 @@ class FlavorParser: path.append([x, y, z, f, new_extrusion_value + self._extrusion_length_offset[self._extruder_number], self._layer_type]) # extrusion self._previous_extrusion_value = new_extrusion_value else: - path.append([x, y, z, f, new_extrusion_value + self._extrusion_length_offset[self._extruder_number], LayerPolygon.MoveRetractionType]) # retraction + path.append([x, y, z, f, new_extrusion_value + self._extrusion_length_offset[self._extruder_number], LayerPolygon.MoveRetractedType]) # retraction e[self._extruder_number] = new_extrusion_value # Only when extruding we can determine the latest known "layer height" which is the difference in height between extrusions @@ -205,9 +208,9 @@ class FlavorParser: self._current_layer_thickness = z - self._previous_z # allow a tiny overlap self._previous_z = z elif self._previous_extrusion_value > e[self._extruder_number]: - path.append([x, y, z, f, e[self._extruder_number] + self._extrusion_length_offset[self._extruder_number], LayerPolygon.MoveRetractionType]) + path.append([x, y, z, f, e[self._extruder_number] + self._extrusion_length_offset[self._extruder_number], LayerPolygon.MoveRetractedType]) else: - path.append([x, y, z, f, e[self._extruder_number] + self._extrusion_length_offset[self._extruder_number], LayerPolygon.MoveCombingType]) + path.append([x, y, z, f, e[self._extruder_number] + self._extrusion_length_offset[self._extruder_number], LayerPolygon.MoveUnretractedType]) return self._position(x, y, z, f, e) @@ -419,7 +422,7 @@ class FlavorParser: self._createPolygon(self._current_layer_thickness, current_path, self._extruder_offsets.get(self._extruder_number, [0, 0])) current_path.clear() # Start the new layer at the end position of the last layer - current_path.append([current_position.x, current_position.y, current_position.z, current_position.f, current_position.e[self._extruder_number], LayerPolygon.MoveCombingType]) + current_path.append([current_position.x, current_position.y, current_position.z, current_position.f, current_position.e[self._extruder_number], LayerPolygon.MoveUnretractedType]) # When using a raft, the raft layers are stored as layers < 0, it mimics the same behavior # as in ProcessSlicedLayersJob @@ -461,9 +464,9 @@ class FlavorParser: # When changing tool, store the end point of the previous path, then process the code and finally # add another point with the new position of the head. - current_path.append([current_position.x, current_position.y, current_position.z, current_position.f, current_position.e[self._extruder_number], LayerPolygon.MoveCombingType]) + current_path.append([current_position.x, current_position.y, current_position.z, current_position.f, current_position.e[self._extruder_number], LayerPolygon.MoveUnretractedType]) current_position = self.processTCode(global_stack, T, line, current_position, current_path) - current_path.append([current_position.x, current_position.y, current_position.z, current_position.f, current_position.e[self._extruder_number], LayerPolygon.MoveCombingType]) + current_path.append([current_position.x, current_position.y, current_position.z, current_position.f, current_position.e[self._extruder_number], LayerPolygon.MoveUnretractedType]) if line.startswith("M"): M = self._getInt(line, "M") diff --git a/plugins/PaintTool/PaintTool.py b/plugins/PaintTool/PaintTool.py new file mode 100644 index 0000000000..2f6d3736f3 --- /dev/null +++ b/plugins/PaintTool/PaintTool.py @@ -0,0 +1,286 @@ +# Copyright (c) 2025 UltiMaker +# Cura is released under the terms of the LGPLv3 or higher. + +import numpy +from PyQt6.QtCore import Qt +from PyQt6.QtGui import QImage, QPainter, QColor, QBrush, QPen +from typing import cast, Dict, List, Optional, Tuple + +from UM.Application import Application +from UM.Event import Event, MouseEvent, KeyEvent +from UM.Logger import Logger +from UM.Scene.SceneNode import SceneNode +from UM.Scene.Selection import Selection +from UM.Tool import Tool + +from cura.PickingPass import PickingPass +from .PaintView import PaintView + + +class PaintTool(Tool): + """Provides the tool to paint meshes.""" + + def __init__(self) -> None: + super().__init__() + + self._picking_pass: Optional[PickingPass] = None + + self._shortcut_key: Qt.Key = Qt.Key.Key_P + + self._node_cache: Optional[SceneNode] = None + self._mesh_transformed_cache = None + self._cache_dirty: bool = True + + 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_color: str = "A" + self._brush_shape: str = "A" + self._brush_pen: QPen = self._createBrushPen() + + self._mouse_held: bool = False + self._ctrl_held: bool = False + self._shift_held: bool = False + + self._last_text_coords: Optional[Tuple[int, int]] = None + + def _createBrushPen(self) -> QPen: + pen = QPen() + pen.setWidth(self._brush_size) + color = self._color_str_to_rgba[self._brush_color] + pen.setColor(QColor(color[0], color[1], color[2], color[3])) + match self._brush_shape: + case "A": + pen.setCapStyle(Qt.PenCapStyle.SquareCap) + case "B": + pen.setCapStyle(Qt.PenCapStyle.RoundCap) + return pen + + def _createStrokeImage(self, x0: float, y0: float, x1: float, y1: float) -> Tuple[QImage, Tuple[int, int]]: + xdiff = int(x1 - x0) + ydiff = int(y1 - y0) + + half_brush_size = self._brush_size // 2 + start_x = int(min(x0, x1) - 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.fill(QColor(0,0,0,0)) + + painter = QPainter(stroke_image) + painter.setRenderHint(QPainter.RenderHint.Antialiasing, False) + painter.setPen(self._brush_pen) + if xdiff == 0 and ydiff == 0: + painter.drawPoint(int(x0 - start_x), int(y0 - start_y)) + else: + painter.drawLine(int(x0 - start_x), int(y0 - start_y), int(x1 - start_x), int(y1 - start_y)) + painter.end() + + return stroke_image, (start_x, start_y) + + def setPaintType(self, paint_type: str) -> None: + Logger.warning(f"TODO: Implement paint-types ({paint_type}).") + pass # FIXME: ... and also please call `self._brush_pen = self._createBrushPen()` (see other funcs). + + def setBrushSize(self, brush_size: float) -> None: + if brush_size != self._brush_size: + self._brush_size = int(brush_size) + self._brush_pen = self._createBrushPen() + + def setBrushColor(self, brush_color: str) -> None: + if brush_color != self._brush_color: + self._brush_color = brush_color + self._brush_pen = self._createBrushPen() + + def setBrushShape(self, brush_shape: str) -> None: + if brush_shape != self._brush_shape: + self._brush_shape = brush_shape + self._brush_pen = self._createBrushPen() + + def undoStackAction(self, redo_instead: bool) -> bool: + paintview = Application.getInstance().getController().getActiveView() + if paintview is None or paintview.getPluginId() != "PaintTool": + return False + paintview = cast(PaintView, paintview) + if redo_instead: + paintview.redoStroke() + else: + paintview.undoStroke() + nodes = Selection.getAllSelectedObjects() + if len(nodes) > 0: + Application.getInstance().getController().getScene().sceneChanged.emit(nodes[0]) + return True + + @staticmethod + 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 unit vectors of directions of lines A and B + udir_a = a - pt + udir_a /= numpy.linalg.norm(udir_a) + udir_b = b - c + udir_b /= numpy.linalg.norm(udir_b) + + # find unit direction vector for line C, which is perpendicular to lines A and B + udir_res = numpy.cross(udir_b, udir_a) + udir_res /= numpy.linalg.norm(udir_res) + + # solve system of equations + rhs = b - a + lhs = numpy.array([udir_a, -udir_b, udir_res]).T + solved = numpy.linalg.solve(lhs, rhs) + + # get the ratio + intersect = ((a + solved[0] * udir_a) + (b + solved[1] * udir_b)) * 0.5 + return numpy.linalg.norm(pt - intersect) / numpy.linalg.norm(a - intersect) + + def _nodeTransformChanged(self, *args) -> None: + self._cache_dirty = True + + def _getTexCoordsFromClick(self, node: SceneNode, x: int, y: int) -> Optional[Tuple[float, float]]: + face_id = self._selection_pass.getFaceIdAtPosition(x, y) + if face_id < 0 or face_id >= node.getMeshData().getFaceCount(): + return None + + pt = self._picking_pass.getPickedPosition(x, y).getData() + + va, vb, vc = self._mesh_transformed_cache.getFaceNodes(face_id) + ta, tb, tc = node.getMeshData().getFaceUvCoords(face_id) + + # 'Weight' of each vertex that would produce point pt, so we can generate the texture coordinates from the uv ones of the vertices. + # See (also) https://mathworld.wolfram.com/BarycentricCoordinates.html + wa = PaintTool._get_intersect_ratio_via_pt(va, pt, vb, vc) + wb = PaintTool._get_intersect_ratio_via_pt(vb, pt, vc, va) + wc = PaintTool._get_intersect_ratio_via_pt(vc, pt, va, vb) + wt = wa + wb + wc + wa /= wt + wb /= wt + wc /= wt + texcoords = wa * ta + wb * tb + wc * tc + return texcoords + + def event(self, event: Event) -> bool: + """Handle mouse and keyboard events. + + :param event: The event to handle. + :return: Whether this event has been caught by this tool (True) or should + be passed on (False). + """ + super().event(event) + + controller = Application.getInstance().getController() + nodes = Selection.getAllSelectedObjects() + if len(nodes) <= 0: + return False + node = nodes[0] + + # Make sure the displayed values are updated if the bounding box of the selected mesh(es) changes + if event.type == Event.ToolActivateEvent: + controller.setActiveStage("PrepareStage") + controller.setActiveView("PaintTool") # Because that's the plugin-name, and the view is registered to it. + return True + + if event.type == Event.ToolDeactivateEvent: + controller.setActiveStage("PrepareStage") + controller.setActiveView("SolidView") + return True + + if event.type == Event.KeyPressEvent: + evt = cast(KeyEvent, event) + if evt.key == KeyEvent.ControlKey: + self._ctrl_held = True + return True + if evt.key == KeyEvent.ShiftKey: + self._shift_held = True + return True + return False + + if event.type == Event.KeyReleaseEvent: + evt = cast(KeyEvent, event) + if evt.key == KeyEvent.ControlKey: + self._ctrl_held = False + return True + if evt.key == KeyEvent.ShiftKey: + self._shift_held = False + return True + if evt.key == Qt.Key.Key_L and self._ctrl_held: + # NOTE: Ctrl-L is used here instead of Ctrl-Z, as the latter is the application-wide one that takes precedence. + return self.undoStackAction(self._shift_held) + return False + + if event.type == Event.MouseReleaseEvent and self._controller.getToolsEnabled(): + if MouseEvent.LeftButton not in cast(MouseEvent, event).buttons: + return False + self._mouse_held = False + self._last_text_coords = None + return True + + 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 + + evt = cast(MouseEvent, event) + if is_pressed: + if MouseEvent.LeftButton not in evt.buttons: + return False + else: + self._mouse_held = True + + paintview = controller.getActiveView() + if paintview is None or paintview.getPluginId() != "PaintTool": + return False + paintview = cast(PaintView, paintview) + + if not self._selection_pass: + return False + + camera = self._controller.getScene().getActiveCamera() + if not camera: + return False + + if node != self._node_cache: + if self._node_cache is not None: + self._node_cache.transformationChanged.disconnect(self._nodeTransformChanged) + self._node_cache = node + self._node_cache.transformationChanged.connect(self._nodeTransformChanged) + if self._cache_dirty: + self._cache_dirty = False + self._mesh_transformed_cache = self._node_cache.getMeshDataTransformed() + if not self._mesh_transformed_cache: + return False + + evt = cast(MouseEvent, event) + + if not self._picking_pass: + self._picking_pass = PickingPass(camera.getViewportWidth(), camera.getViewportHeight()) + self._picking_pass.render() + + self._selection_pass.renderFacesMode() + + texcoords = self._getTexCoordsFromClick(node, evt.x, evt.y) + if texcoords is None: + return False + if self._last_text_coords is None: + self._last_text_coords = texcoords + + w, h = paintview.getUvTexDimensions() + sub_image, (start_x, start_y) = self._createStrokeImage( + self._last_text_coords[0] * w, + self._last_text_coords[1] * h, + texcoords[0] * w, + texcoords[1] * h + ) + paintview.addStroke(sub_image, start_x, start_y) + + self._last_text_coords = texcoords + Application.getInstance().getController().getScene().sceneChanged.emit(node) + return True + + return False diff --git a/plugins/PaintTool/PaintTool.qml b/plugins/PaintTool/PaintTool.qml new file mode 100644 index 0000000000..a1fac9c3a3 --- /dev/null +++ b/plugins/PaintTool/PaintTool.qml @@ -0,0 +1,215 @@ +// Copyright (c) 2025 UltiMaker +// Cura is released under the terms of the LGPLv3 or higher. + +import QtQuick +import QtQuick.Layouts + +import UM 1.7 as UM + +Item +{ + id: base + width: childrenRect.width + height: childrenRect.height + UM.I18nCatalog { id: catalog; name: "cura"} + + ColumnLayout + { + RowLayout + { + UM.ToolbarButton + { + id: paintTypeA + + text: catalog.i18nc("@action:button", "Paint Type A") + toolItem: UM.ColorImage + { + source: UM.Theme.getIcon("Buildplate") + color: UM.Theme.getColor("icon") + } + property bool needBorder: true + + z: 2 + + onClicked: UM.Controller.triggerActionWithData("setPaintType", "A") + } + + UM.ToolbarButton + { + id: paintTypeB + + text: catalog.i18nc("@action:button", "Paint Type B") + toolItem: UM.ColorImage + { + source: UM.Theme.getIcon("BlackMagic") + color: UM.Theme.getColor("icon") + } + property bool needBorder: true + + z: 2 + + onClicked: UM.Controller.triggerActionWithData("setPaintType", "B") + } + } + + RowLayout + { + UM.ToolbarButton + { + id: colorButtonA + + text: catalog.i18nc("@action:button", "Color A") + toolItem: UM.ColorImage + { + source: UM.Theme.getIcon("Eye") + color: "purple" + } + property bool needBorder: true + + z: 2 + + onClicked: UM.Controller.triggerActionWithData("setBrushColor", "A") + } + + UM.ToolbarButton + { + id: colorButtonB + + text: catalog.i18nc("@action:button", "Color B") + toolItem: UM.ColorImage + { + source: UM.Theme.getIcon("Eye") + color: "orange" + } + property bool needBorder: true + + z: 2 + + onClicked: UM.Controller.triggerActionWithData("setBrushColor", "B") + } + + UM.ToolbarButton + { + id: colorButtonC + + text: catalog.i18nc("@action:button", "Color C") + toolItem: UM.ColorImage + { + source: UM.Theme.getIcon("Eye") + color: "green" + } + property bool needBorder: true + + z: 2 + + onClicked: UM.Controller.triggerActionWithData("setBrushColor", "C") + } + + UM.ToolbarButton + { + id: colorButtonD + + text: catalog.i18nc("@action:button", "Color D") + toolItem: UM.ColorImage + { + source: UM.Theme.getIcon("Eye") + color: "ghostwhite" + } + property bool needBorder: true + + z: 2 + + onClicked: UM.Controller.triggerActionWithData("setBrushColor", "D") + } + } + + RowLayout + { + UM.ToolbarButton + { + id: shapeSquareButton + + text: catalog.i18nc("@action:button", "Square Brush") + toolItem: UM.ColorImage + { + source: UM.Theme.getIcon("MeshTypeNormal") + color: UM.Theme.getColor("icon") + } + property bool needBorder: true + + z: 2 + + onClicked: UM.Controller.triggerActionWithData("setBrushShape", "A") + } + + UM.ToolbarButton + { + id: shapeCircleButton + + text: catalog.i18nc("@action:button", "Round Brush") + toolItem: UM.ColorImage + { + source: UM.Theme.getIcon("CircleOutline") + color: UM.Theme.getColor("icon") + } + property bool needBorder: true + + z: 2 + + onClicked: UM.Controller.triggerActionWithData("setBrushShape", "B") + } + + UM.Slider + { + id: shapeSizeSlider + + from: 1 + to: 40 + value: 10 + + onPressedChanged: function(pressed) + { + if(! pressed) + { + UM.Controller.triggerActionWithData("setBrushSize", shapeSizeSlider.value) + } + } + } + } + + RowLayout + { + UM.ToolbarButton + { + id: undoButton + + text: catalog.i18nc("@action:button", "Undo Stroke") + toolItem: UM.ColorImage + { + source: UM.Theme.getIcon("ArrowReset") + } + property bool needBorder: true + + z: 2 + + onClicked: UM.Controller.triggerActionWithData("undoStackAction", false) + } + + UM.ToolbarButton + { + id: redoButton + + text: catalog.i18nc("@action:button", "Redo Stroke") + toolItem: UM.ColorImage + { + source: UM.Theme.getIcon("ArrowDoubleCircleRight") + } + property bool needBorder: true + + z: 2 + + onClicked: UM.Controller.triggerActionWithData("undoStackAction", true) + } + } + } +} diff --git a/plugins/PaintTool/PaintView.py b/plugins/PaintTool/PaintView.py new file mode 100644 index 0000000000..080cdd3b41 --- /dev/null +++ b/plugins/PaintTool/PaintView.py @@ -0,0 +1,98 @@ +# Copyright (c) 2025 UltiMaker +# Cura is released under the terms of the LGPLv3 or higher. + +import os +from typing import Optional, List, Tuple + +from PyQt6.QtGui import QImage, QColor, QPainter + +from UM.PluginRegistry import PluginRegistry +from UM.View.GL.ShaderProgram import ShaderProgram +from UM.View.GL.Texture import Texture +from UM.View.View import View +from UM.Scene.Selection import Selection +from UM.View.GL.OpenGL import OpenGL +from UM.i18n import i18nCatalog + +catalog = i18nCatalog("cura") + + +class PaintView(View): + """View for model-painting.""" + + UNDO_STACK_SIZE = 1024 + + def __init__(self) -> None: + super().__init__() + self._paint_shader: Optional[ShaderProgram] = None + self._current_paint_texture: Optional[Texture] = None + + self._stroke_undo_stack: List[Tuple[QImage, int, int]] = [] + self._stroke_redo_stack: List[Tuple[QImage, int, int]] = [] + + self._force_opaque_mask = QImage(2, 2, QImage.Format.Format_Mono) + self._force_opaque_mask.fill(1) + + def _checkSetup(self): + if not self._paint_shader: + shader_filename = os.path.join(PluginRegistry.getInstance().getPluginPath("PaintTool"), "paint.shader") + self._paint_shader = OpenGL.getInstance().createShaderProgram(shader_filename) + + def _forceOpaqueDeepCopy(self, image: QImage): + res = QImage(image.width(), image.height(), QImage.Format.Format_RGBA8888) + res.fill(QColor(255, 255, 255, 255)) + painter = QPainter(res) + painter.setRenderHint(QPainter.RenderHint.Antialiasing, False) + painter.setCompositionMode(QPainter.CompositionMode.CompositionMode_SourceOver) + painter.drawImage(0, 0, image) + painter.end() + res.setAlphaChannel(self._force_opaque_mask.scaled(image.width(), image.height())) + return res + + def addStroke(self, stroke_image: QImage, start_x: int, start_y: int) -> None: + if self._current_paint_texture is None: + return + + self._stroke_redo_stack.clear() + if len(self._stroke_undo_stack) >= PaintView.UNDO_STACK_SIZE: + self._stroke_undo_stack.pop(0) + undo_image = self._forceOpaqueDeepCopy(self._current_paint_texture.setSubImage(stroke_image, start_x, start_y)) + if undo_image is not None: + self._stroke_undo_stack.append((undo_image, start_x, start_y)) + + def _applyUndoStacksAction(self, from_stack: List[Tuple[QImage, int, int]], to_stack: List[Tuple[QImage, int, int]]) -> bool: + if len(from_stack) <= 0 or self._current_paint_texture is None: + return False + from_image, x, y = from_stack.pop() + to_image = self._forceOpaqueDeepCopy(self._current_paint_texture.setSubImage(from_image, x, y)) + if to_image is None: + return False + if len(to_stack) >= PaintView.UNDO_STACK_SIZE: + to_stack.pop(0) + to_stack.append((to_image, x, y)) + return True + + def undoStroke(self) -> bool: + return self._applyUndoStacksAction(self._stroke_undo_stack, self._stroke_redo_stack) + + def redoStroke(self) -> bool: + return self._applyUndoStacksAction(self._stroke_redo_stack, self._stroke_undo_stack) + + def getUvTexDimensions(self): + if self._current_paint_texture is not None: + return self._current_paint_texture.getWidth(), self._current_paint_texture.getHeight() + return 0, 0 + + def beginRendering(self) -> None: + renderer = self.getRenderer() + self._checkSetup() + paint_batch = renderer.createRenderBatch(shader=self._paint_shader) + renderer.addRenderBatch(paint_batch) + + node = Selection.getAllSelectedObjects()[0] + if node is None: + return + + self._current_paint_texture = node.callDecoration("getPaintTexture") + self._paint_shader.setTexture(0, self._current_paint_texture) + paint_batch.addItem(node.getWorldTransformation(copy=False), node.getMeshData(), normal_transformation=node.getCachedNormalMatrix()) diff --git a/plugins/PaintTool/__init__.py b/plugins/PaintTool/__init__.py new file mode 100644 index 0000000000..301bc49e0d --- /dev/null +++ b/plugins/PaintTool/__init__.py @@ -0,0 +1,30 @@ +# Copyright (c) 2025 UltiMaker +# Cura is released under the terms of the LGPLv3 or higher. + +from . import PaintTool +from . import PaintView + +from UM.i18n import i18nCatalog +i18n_catalog = i18nCatalog("cura") + +def getMetaData(): + return { + "tool": { + "name": i18n_catalog.i18nc("@action:button", "Paint"), + "description": i18n_catalog.i18nc("@info:tooltip", "Paint Model"), + "icon": "Visual", + "tool_panel": "PaintTool.qml", + "weight": 0 + }, + "view": { + "name": i18n_catalog.i18nc("@item:inmenu", "Paint view"), + "weight": 0, + "visible": False + } + } + +def register(app): + return { + "tool": PaintTool.PaintTool(), + "view": PaintView.PaintView() + } diff --git a/plugins/PaintTool/paint.shader b/plugins/PaintTool/paint.shader new file mode 100644 index 0000000000..83682c7222 --- /dev/null +++ b/plugins/PaintTool/paint.shader @@ -0,0 +1,142 @@ +[shaders] +vertex = + uniform highp mat4 u_modelMatrix; + uniform highp mat4 u_viewMatrix; + uniform highp mat4 u_projectionMatrix; + + uniform highp mat4 u_normalMatrix; + + attribute highp vec4 a_vertex; + attribute highp vec4 a_normal; + attribute highp vec2 a_uvs; + + varying highp vec3 v_vertex; + varying highp vec3 v_normal; + varying highp vec2 v_uvs; + + void main() + { + vec4 world_space_vert = u_modelMatrix * a_vertex; + gl_Position = u_projectionMatrix * u_viewMatrix * world_space_vert; + + v_vertex = world_space_vert.xyz; + v_normal = (u_normalMatrix * normalize(a_normal)).xyz; + + v_uvs = a_uvs; + } + +fragment = + uniform mediump vec4 u_ambientColor; + uniform mediump vec4 u_diffuseColor; + uniform highp vec3 u_lightPosition; + uniform highp vec3 u_viewPosition; + uniform mediump float u_opacity; + uniform sampler2D u_texture; + + varying highp vec3 v_vertex; + varying highp vec3 v_normal; + varying highp vec2 v_uvs; + + void main() + { + mediump vec4 final_color = vec4(0.0); + + /* Ambient Component */ + final_color += u_ambientColor; + + highp vec3 normal = normalize(v_normal); + highp vec3 light_dir = normalize(u_lightPosition - v_vertex); + + /* Diffuse Component */ + highp float n_dot_l = clamp(dot(normal, light_dir), 0.0, 1.0); + final_color += (n_dot_l * u_diffuseColor); + + final_color.a = u_opacity; + + lowp vec4 texture = texture2D(u_texture, v_uvs); + final_color = mix(final_color, texture, texture.a); + + gl_FragColor = final_color; + } + +vertex41core = + #version 410 + uniform highp mat4 u_modelMatrix; + uniform highp mat4 u_viewMatrix; + uniform highp mat4 u_projectionMatrix; + + uniform highp mat4 u_normalMatrix; + + in highp vec4 a_vertex; + in highp vec4 a_normal; + in highp vec2 a_uvs; + + out highp vec3 v_vertex; + out highp vec3 v_normal; + out highp vec2 v_uvs; + + void main() + { + vec4 world_space_vert = u_modelMatrix * a_vertex; + gl_Position = u_projectionMatrix * u_viewMatrix * world_space_vert; + + v_vertex = world_space_vert.xyz; + v_normal = (u_normalMatrix * normalize(a_normal)).xyz; + + v_uvs = a_uvs; + } + +fragment41core = + #version 410 + uniform mediump vec4 u_ambientColor; + uniform mediump vec4 u_diffuseColor; + uniform highp vec3 u_lightPosition; + uniform highp vec3 u_viewPosition; + uniform mediump float u_opacity; + uniform sampler2D u_texture; + + in highp vec3 v_vertex; + in highp vec3 v_normal; + in highp vec2 v_uvs; + out vec4 frag_color; + + void main() + { + mediump vec4 final_color = vec4(0.0); + + /* Ambient Component */ + final_color += u_ambientColor; + + highp vec3 normal = normalize(v_normal); + highp vec3 light_dir = normalize(u_lightPosition - v_vertex); + + /* Diffuse Component */ + highp float n_dot_l = clamp(dot(normal, light_dir), 0.0, 1.0); + final_color += (n_dot_l * u_diffuseColor); + + 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; + } + +[defaults] +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_texture = 0 + +[bindings] +u_modelMatrix = model_matrix +u_viewMatrix = view_matrix +u_projectionMatrix = projection_matrix +u_normalMatrix = normal_matrix +u_lightPosition = light_0_position +u_viewPosition = camera_position + +[attributes] +a_vertex = vertex +a_normal = normal +a_uvs = uv0 diff --git a/plugins/PaintTool/plugin.json b/plugins/PaintTool/plugin.json new file mode 100644 index 0000000000..2a55d677d2 --- /dev/null +++ b/plugins/PaintTool/plugin.json @@ -0,0 +1,8 @@ +{ + "name": "Paint Tools", + "author": "UltiMaker", + "version": "1.0.0", + "description": "Provides the paint tools.", + "api": 8, + "i18n-catalog": "cura" +} diff --git a/plugins/SimulationView/SimulationPass.py b/plugins/SimulationView/SimulationPass.py index 436d5b8723..a7411a2ed0 100644 --- a/plugins/SimulationView/SimulationPass.py +++ b/plugins/SimulationView/SimulationPass.py @@ -203,9 +203,9 @@ class SimulationPass(RenderPass): self._layer_shader.setUniformValue("u_next_vertex", not_a_vector) self._layer_shader.setUniformValue("u_last_line_ratio", 1.0) - # The first line does not have a previous line: add a MoveCombingType in front for start detection + # The first line does not have a previous line: add a MoveUnretractedType in front for start detection # this way the first start of the layer can also be drawn - prev_line_types = numpy.concatenate([numpy.asarray([LayerPolygon.MoveCombingType], dtype = numpy.float32), layer_data._attributes["line_types"]["value"]]) + prev_line_types = numpy.concatenate([numpy.asarray([LayerPolygon.MoveUnretractedType], dtype = numpy.float32), layer_data._attributes["line_types"]["value"]]) # Remove the last element prev_line_types = prev_line_types[0:layer_data._attributes["line_types"]["value"].size] layer_data._attributes["prev_line_types"] = {'opengl_type': 'float', 'value': prev_line_types, 'opengl_name': 'a_prev_line_type'} diff --git a/plugins/SimulationView/SimulationView.py b/plugins/SimulationView/SimulationView.py index 10861acfd0..083fc73bf1 100644 --- a/plugins/SimulationView/SimulationView.py +++ b/plugins/SimulationView/SimulationView.py @@ -608,8 +608,10 @@ class SimulationView(CuraView): visible_line_types.append(LayerPolygon.SupportInterfaceType) visible_line_types_with_extrusion = visible_line_types.copy() # Copy before travel moves are added if self.getShowTravelMoves(): - visible_line_types.append(LayerPolygon.MoveCombingType) - visible_line_types.append(LayerPolygon.MoveRetractionType) + visible_line_types.append(LayerPolygon.MoveUnretractedType) + visible_line_types.append(LayerPolygon.MoveRetractedType) + visible_line_types.append(LayerPolygon.MoveWhileRetractingType) + visible_line_types.append(LayerPolygon.MoveWhileUnretractingType) for node in DepthFirstIterator(self.getController().getScene().getRoot()): layer_data = node.callDecoration("getLayerData") diff --git a/plugins/SimulationView/SimulationViewMenuComponent.qml b/plugins/SimulationView/SimulationViewMenuComponent.qml index d434d883eb..dcd2c7d178 100644 --- a/plugins/SimulationView/SimulationViewMenuComponent.qml +++ b/plugins/SimulationView/SimulationViewMenuComponent.qml @@ -227,29 +227,52 @@ Cura.ExpandableComponent id: typesLegendModel Component.onCompleted: { + const travelsTypesModel = [ + { + label: catalog.i18nc("@label", "Unretracted"), + colorId: "layerview_move_combing" + }, + { + label: catalog.i18nc("@label", "Retracted"), + colorId: "layerview_move_retraction" + }, + { + label: catalog.i18nc("@label", "Retracting"), + colorId: "layerview_move_while_retracting" + }, + { + label: catalog.i18nc("@label", "Unretracting"), + colorId: "layerview_move_while_unretracting" + } + ]; + typesLegendModel.append({ label: catalog.i18nc("@label", "Travels"), initialValue: viewSettings.show_travel_moves, preference: "layerview/show_travel_moves", - colorId: "layerview_move_combing" + colorId: "layerview_move_combing", + subTypesModel: travelsTypesModel }); typesLegendModel.append({ label: catalog.i18nc("@label", "Helpers"), initialValue: viewSettings.show_helpers, preference: "layerview/show_helpers", - colorId: "layerview_support" + colorId: "layerview_support", + subTypesModel: [] }); typesLegendModel.append({ label: catalog.i18nc("@label", "Shell"), initialValue: viewSettings.show_skin, preference: "layerview/show_skin", - colorId: "layerview_inset_0" + colorId: "layerview_inset_0", + subTypesModel: [] }); typesLegendModel.append({ label: catalog.i18nc("@label", "Infill"), initialValue: viewSettings.show_infill, preference: "layerview/show_infill", - colorId: "layerview_infill" + colorId: "layerview_infill", + subTypesModel: [] }); if (! UM.SimulationView.compatibilityMode) { @@ -257,7 +280,8 @@ Cura.ExpandableComponent label: catalog.i18nc("@label", "Starts"), initialValue: viewSettings.show_starts, preference: "layerview/show_starts", - colorId: "layerview_starts" + colorId: "layerview_starts", + subTypesModel: [] }); } } @@ -273,6 +297,7 @@ Cura.ExpandableComponent Rectangle { + id: rectangleColor anchors.verticalCenter: parent.verticalCenter anchors.right: legendModelCheckBox.right width: UM.Theme.getSize("layerview_legend_size").width @@ -281,6 +306,58 @@ Cura.ExpandableComponent border.width: UM.Theme.getSize("default_lining").width border.color: UM.Theme.getColor("lining") visible: viewSettings.show_legend + + MouseArea + { + anchors.fill: parent + hoverEnabled: true + acceptedButtons: Qt.NoButton + enabled: subTypesModel.count > 0 + + onEntered: tooltip.show() + onExited: tooltip.hide() + + UM.ToolTip + { + id: tooltip + delay: 0 + width: subTypesColumn.implicitWidth + 2 * UM.Theme.getSize("thin_margin").width + height: subTypesColumn.implicitHeight + 2 * UM.Theme.getSize("thin_margin").width + + contentItem: Column + { + id: subTypesColumn + padding: 0 + spacing: UM.Theme.getSize("layerview_row_spacing").height + + Repeater + { + model: subTypesModel + UM.Label + { + text: label + + height: UM.Theme.getSize("layerview_row").height + UM.Theme.getSize("default_lining").height + width: UM.Theme.getSize("layerview_menu_size").width + color: UM.Theme.getColor("setting_control_text") + Rectangle + { + anchors.verticalCenter: parent.verticalCenter + anchors.right: parent.right + + width: UM.Theme.getSize("layerview_legend_size").width + height: UM.Theme.getSize("layerview_legend_size").height + + color: UM.Theme.getColor(model.colorId) + + border.width: UM.Theme.getSize("default_lining").width + border.color: UM.Theme.getColor("lining") + } + } + } + } + } + } } UM.Label diff --git a/plugins/SimulationView/layers.shader b/plugins/SimulationView/layers.shader index e6210c2b65..d5079fd82b 100644 --- a/plugins/SimulationView/layers.shader +++ b/plugins/SimulationView/layers.shader @@ -22,8 +22,8 @@ vertex = gl_Position = u_projectionMatrix * u_viewMatrix * u_modelMatrix * a_vertex; // shade the color depending on the extruder index v_color = a_color; - // 8 and 9 are travel moves - if ((a_line_type != 8.0) && (a_line_type != 9.0)) { + // 8, 9, 12 and 13 are travel moves + if ((a_line_type != 8.0) && (a_line_type != 9.0) && (a_line_type != 12.0) && (a_line_type != 13.0)) { v_color = (a_extruder == u_active_extruder) ? v_color : vec4(u_shade_factor * v_color.rgb, v_color.a); } @@ -48,7 +48,9 @@ fragment = void main() { - if ((u_show_travel_moves == 0) && (v_line_type >= 7.5) && (v_line_type <= 9.5)) { // actually, 8 and 9 + // travel moves: 8, 9, 12, 13 + if ((u_show_travel_moves == 0) && (((v_line_type >= 7.5) && (v_line_type <= 9.5)) || + ((v_line_type >= 11.5) && (v_line_type <= 13.5)))) { // discard movements discard; } @@ -100,7 +102,7 @@ vertex41core = { gl_Position = u_projectionMatrix * u_viewMatrix * u_modelMatrix * a_vertex; v_color = a_color; - if ((a_line_type != 8) && (a_line_type != 9)) { + if ((a_line_type != 8) && (a_line_type != 9) && (a_line_type != 12) && (a_line_type != 13)) { v_color = (a_extruder == u_active_extruder) ? v_color : vec4(u_shade_factor * v_color.rgb, v_color.a); } @@ -120,7 +122,9 @@ fragment41core = void main() { - if ((u_show_travel_moves == 0) && (v_line_type >= 7.5) && (v_line_type <= 9.5)) { // actually, 8 and 9 + // travel moves: 8, 9, 12, 13 + if ((u_show_travel_moves == 0) && (((v_line_type >= 7.5) && (v_line_type <= 9.5)) || + ((v_line_type >= 11.5) && (v_line_type <= 13.5)))) { // discard movements discard; } diff --git a/plugins/SimulationView/layers3d.shader b/plugins/SimulationView/layers3d.shader index 494a07083d..e2f57823f3 100644 --- a/plugins/SimulationView/layers3d.shader +++ b/plugins/SimulationView/layers3d.shader @@ -228,22 +228,26 @@ geometry41core = { highp mat4 viewProjectionMatrix = u_projectionMatrix * u_viewMatrix; - vec4 g_vertex_delta; - vec3 g_vertex_normal_horz; // horizontal and vertical in respect to layers - vec4 g_vertex_offset_horz; // vec4 to match gl_in[x].gl_Position + // Vertices are declared as vec4 so that they can be used for calculations with gl_in[x].gl_Position + vec3 g_vertex_delta; + vec3 g_vertex_normal_horz; + vec4 g_vertex_offset_horz; vec3 g_vertex_normal_vert; vec4 g_vertex_offset_vert; vec3 g_vertex_normal_horz_head; vec4 g_vertex_offset_horz_head; + vec3 g_axial_plan_vector; + vec3 g_radial_plan_vector; float size_x; float size_y; - if ((v_extruder_opacity[0][int(mod(v_extruder[0], 4))][v_extruder[0] / 4] == 0.0) && (v_line_type[0] != 8) && (v_line_type[0] != 9)) { + if ((v_extruder_opacity[0][int(mod(v_extruder[0], 4))][v_extruder[0] / 4] == 0.0) && + (v_line_type[0] != 8) && (v_line_type[0] != 9) && (v_line_type[0] != 12) && (v_line_type[0] != 13)) { return; } - // See LayerPolygon; 8 is MoveCombingType, 9 is RetractionType - if ((u_show_travel_moves == 0) && ((v_line_type[0] == 8) || (v_line_type[0] == 9))) { + // See LayerPolygon; 8 is MoveUnretractedType, 9 is RetractionType, 12 is MoveWhileRetractingType, 13 is MoveWhileUnretractingType + if ((u_show_travel_moves == 0) && ((v_line_type[0] == 8) || (v_line_type[0] == 9) || (v_line_type[0] == 12) || (v_line_type[0] == 13))) { return; } if ((u_show_helpers == 0) && ((v_line_type[0] == 4) || (v_line_type[0] == 5) || (v_line_type[0] == 7) || (v_line_type[0] == 10) || v_line_type[0] == 11)) { @@ -256,7 +260,7 @@ geometry41core = return; } - if ((v_line_type[0] == 8) || (v_line_type[0] == 9)) { + if ((v_line_type[0] == 8) || (v_line_type[0] == 9) || (v_line_type[0] == 12) || (v_line_type[0] == 13)) { // fixed size for movements size_x = 0.05; } else { @@ -264,26 +268,47 @@ geometry41core = } size_y = v_line_dim[1].y / 2 + 0.01; - g_vertex_delta = gl_in[1].gl_Position - gl_in[0].gl_Position; //Actual movement exhibited by the line. - g_vertex_normal_horz_head = normalize(vec3(-g_vertex_delta.x, -g_vertex_delta.y, -g_vertex_delta.z)); //Lengthwise normal vector pointing backwards. - g_vertex_offset_horz_head = vec4(g_vertex_normal_horz_head * size_x, 0.0); //Lengthwise offset vector pointing backwards. + g_vertex_delta = (gl_in[1].gl_Position - gl_in[0].gl_Position).xyz; //Actual movement exhibited by the line. - g_vertex_normal_horz = normalize(vec3(g_vertex_delta.z, g_vertex_delta.y, -g_vertex_delta.x)); //Normal vector pointing right. + if (g_vertex_delta == vec3(0.0)) { + return; + } + + if (g_vertex_delta.y == 0.0) + { + // vector is in the horizontal plan, radial vector is a simple rotation around Y axis + g_radial_plan_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) + { + // 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); + } + else + { + // 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_radial_plan_vector = cross(g_vertex_delta, g_axial_plan_vector); // Radial vector in the horizontal plan, pointing right. + } + + 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_normal_horz = normalize(g_radial_plan_vector); //Normal 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_offset_vert = vec4(g_vertex_normal_vert * size_y, 0.0); //Upwards offset vector. Goes up by half the layer thickness. - if ((v_line_type[0] == 8) || (v_line_type[0] == 9)) { //Travel or retraction moves. - vec4 va_head = viewProjectionMatrix * (gl_in[0].gl_Position + g_vertex_offset_horz_head + g_vertex_offset_vert); + if ((v_line_type[0] == 8) || (v_line_type[0] == 9) || (v_line_type[0] == 12) || (v_line_type[0] == 13)) { //Travel or retraction moves. + vec4 va_head = viewProjectionMatrix * (gl_in[0].gl_Position - g_vertex_offset_horz_head + g_vertex_offset_vert); vec4 va_up = viewProjectionMatrix * (gl_in[0].gl_Position + g_vertex_offset_horz + g_vertex_offset_vert); vec4 va_down = viewProjectionMatrix * (gl_in[0].gl_Position - g_vertex_offset_horz + g_vertex_offset_vert); - vec4 vb_head = viewProjectionMatrix * (gl_in[1].gl_Position - g_vertex_offset_horz_head + g_vertex_offset_vert); + vec4 vb_head = viewProjectionMatrix * (gl_in[1].gl_Position + g_vertex_offset_horz_head + g_vertex_offset_vert); vec4 vb_down = viewProjectionMatrix * (gl_in[1].gl_Position - g_vertex_offset_horz + g_vertex_offset_vert); vec4 vb_up = viewProjectionMatrix * (gl_in[1].gl_Position + g_vertex_offset_horz + g_vertex_offset_vert); // Travels: flat plane with pointy ends - myEmitVertex(v_vertex[0], v_color[1], g_vertex_normal_vert, va_up); myEmitVertex(v_vertex[0], v_color[1], g_vertex_normal_vert, va_head); myEmitVertex(v_vertex[0], v_color[1], g_vertex_normal_vert, va_down); myEmitVertex(v_vertex[0], v_color[1], g_vertex_normal_vert, va_up); @@ -308,8 +333,8 @@ geometry41core = vec4 vb_p_horz = viewProjectionMatrix * (gl_in[1].gl_Position + g_vertex_offset_horz); //Line end, right vertex. vec4 va_m_vert = viewProjectionMatrix * (gl_in[0].gl_Position - g_vertex_offset_vert); //Line start, bottom vertex. vec4 vb_m_vert = viewProjectionMatrix * (gl_in[1].gl_Position - g_vertex_offset_vert); //Line end, bottom vertex. - vec4 va_head = viewProjectionMatrix * (gl_in[0].gl_Position + g_vertex_offset_horz_head); //Line start, tip. - vec4 vb_head = viewProjectionMatrix * (gl_in[1].gl_Position - g_vertex_offset_horz_head); //Line end, tip. + vec4 va_head = viewProjectionMatrix * (gl_in[0].gl_Position - g_vertex_offset_horz_head); //Line start, tip. + vec4 vb_head = viewProjectionMatrix * (gl_in[1].gl_Position + g_vertex_offset_horz_head); //Line end, tip. // All normal lines are rendered as 3d tubes. myEmitVertex(v_vertex[0], v_color[1], -g_vertex_normal_horz, va_m_horz); @@ -328,14 +353,14 @@ geometry41core = // left side myEmitVertex(v_vertex[0], v_color[1], -g_vertex_normal_horz, va_m_horz); myEmitVertex(v_vertex[0], v_color[1], g_vertex_normal_vert, va_p_vert); - myEmitVertex(v_vertex[0], v_color[1], g_vertex_normal_horz_head, va_head); + myEmitVertex(v_vertex[0], v_color[1], -g_vertex_normal_horz_head, va_head); myEmitVertex(v_vertex[0], v_color[1], g_vertex_normal_horz, va_p_horz); EndPrimitive(); myEmitVertex(v_vertex[0], v_color[1], g_vertex_normal_horz, va_p_horz); myEmitVertex(v_vertex[0], v_color[1], -g_vertex_normal_vert, va_m_vert); - myEmitVertex(v_vertex[0], v_color[1], g_vertex_normal_horz_head, va_head); + myEmitVertex(v_vertex[0], v_color[1], -g_vertex_normal_horz_head, va_head); myEmitVertex(v_vertex[0], v_color[1], -g_vertex_normal_horz, va_m_horz); EndPrimitive(); @@ -343,14 +368,14 @@ geometry41core = // right side myEmitVertex(v_vertex[1], v_color[1], g_vertex_normal_horz, vb_p_horz); myEmitVertex(v_vertex[1], v_color[1], g_vertex_normal_vert, vb_p_vert); - myEmitVertex(v_vertex[1], v_color[1], -g_vertex_normal_horz_head, vb_head); + myEmitVertex(v_vertex[1], v_color[1], g_vertex_normal_horz_head, vb_head); myEmitVertex(v_vertex[1], v_color[1], -g_vertex_normal_horz, vb_m_horz); EndPrimitive(); myEmitVertex(v_vertex[1], v_color[1], -g_vertex_normal_horz, vb_m_horz); myEmitVertex(v_vertex[1], v_color[1], -g_vertex_normal_vert, vb_m_vert); - myEmitVertex(v_vertex[1], v_color[1], -g_vertex_normal_horz_head, vb_head); + myEmitVertex(v_vertex[1], v_color[1], g_vertex_normal_horz_head, vb_head); myEmitVertex(v_vertex[1], v_color[1], g_vertex_normal_horz, vb_p_horz); EndPrimitive(); diff --git a/plugins/SimulationView/layers3d_shadow.shader b/plugins/SimulationView/layers3d_shadow.shader index 88268938c9..47637cfb20 100644 --- a/plugins/SimulationView/layers3d_shadow.shader +++ b/plugins/SimulationView/layers3d_shadow.shader @@ -95,22 +95,26 @@ geometry41core = { highp mat4 viewProjectionMatrix = u_projectionMatrix * u_viewMatrix; - vec4 g_vertex_delta; - vec3 g_vertex_normal_horz; // horizontal and vertical in respect to layers - vec4 g_vertex_offset_horz; // vec4 to match gl_in[x].gl_Position + // Vertices are declared as vec4 so that they can be used for calculations with gl_in[x].gl_Position + vec3 g_vertex_delta; + vec3 g_vertex_normal_horz; + vec4 g_vertex_offset_horz; vec3 g_vertex_normal_vert; vec4 g_vertex_offset_vert; vec3 g_vertex_normal_horz_head; vec4 g_vertex_offset_horz_head; + vec3 g_axial_plan_vector; + vec3 g_radial_plan_vector; float size_x; float size_y; - if ((v_extruder_opacity[0][int(mod(v_extruder[0], 4))][v_extruder[0] / 4] == 0.0) && (v_line_type[0] != 8) && (v_line_type[0] != 9)) { + if ((v_extruder_opacity[0][int(mod(v_extruder[0], 4))][v_extruder[0] / 4] == 0.0) && + (v_line_type[0] != 8) && (v_line_type[0] != 9) && (v_line_type[0] != 12) && (v_line_type[0] != 13)) { return; } - // See LayerPolygon; 8 is MoveCombingType, 9 is RetractionType - if ((u_show_travel_moves == 0) && ((v_line_type[0] == 8) || (v_line_type[0] == 9))) { + // See LayerPolygon; 8 is MoveUnretractedType, 9 is RetractionType, 12 is MoveWhileRetractingType, 13 is MoveWhileUnretractingType + if ((u_show_travel_moves == 0) && ((v_line_type[0] == 8) || (v_line_type[0] == 9) || (v_line_type[0] == 12) || (v_line_type[0] == 13))) { return; } if ((u_show_helpers == 0) && ((v_line_type[0] == 4) || (v_line_type[0] == 5) || (v_line_type[0] == 7) || (v_line_type[0] == 10))) { @@ -123,7 +127,7 @@ geometry41core = return; } - if ((v_line_type[0] == 8) || (v_line_type[0] == 9)) { + if ((v_line_type[0] == 8) || (v_line_type[0] == 9) || (v_line_type[0] == 12) || (v_line_type[0] == 13)) { // fixed size for movements size_x = 0.05; } else { @@ -131,93 +135,114 @@ geometry41core = } size_y = v_line_dim[1].y / 2 + 0.01; - g_vertex_delta = gl_in[1].gl_Position - gl_in[0].gl_Position; - g_vertex_normal_horz_head = normalize(vec3(-g_vertex_delta.x, -g_vertex_delta.y, -g_vertex_delta.z)); - g_vertex_offset_horz_head = vec4(g_vertex_normal_horz_head * size_x, 0.0); + g_vertex_delta = (gl_in[1].gl_Position - gl_in[0].gl_Position).xyz; //Actual movement exhibited by the line. - g_vertex_normal_horz = normalize(vec3(g_vertex_delta.z, g_vertex_delta.y, -g_vertex_delta.x)); + if (g_vertex_delta == vec3(0.0)) { + return; + } - g_vertex_offset_horz = vec4(g_vertex_normal_horz * size_x, 0.0); //size * g_vertex_normal_horz; - g_vertex_normal_vert = vec3(0.0, 1.0, 0.0); - g_vertex_offset_vert = vec4(g_vertex_normal_vert * size_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 + g_radial_plan_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) + { + // 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); + } + else + { + // 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_radial_plan_vector = cross(g_vertex_delta, g_axial_plan_vector); // Radial vector in the horizontal plan, pointing right. + } - if ((v_line_type[0] == 8) || (v_line_type[0] == 9)) { - vec4 va_head = viewProjectionMatrix * (gl_in[0].gl_Position + g_vertex_offset_horz_head + g_vertex_offset_vert); + 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_normal_horz = normalize(g_radial_plan_vector); //Normal 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_offset_vert = vec4(g_vertex_normal_vert * size_y, 0.0); //Upwards offset vector. Goes up by half the layer thickness. + + if ((v_line_type[0] == 8) || (v_line_type[0] == 9) || (v_line_type[0] == 12) || (v_line_type[0] == 13)) { + vec4 va_head = viewProjectionMatrix * (gl_in[0].gl_Position - g_vertex_offset_horz_head + g_vertex_offset_vert); vec4 va_up = viewProjectionMatrix * (gl_in[0].gl_Position + g_vertex_offset_horz + g_vertex_offset_vert); vec4 va_down = viewProjectionMatrix * (gl_in[0].gl_Position - g_vertex_offset_horz + g_vertex_offset_vert); - vec4 vb_head = viewProjectionMatrix * (gl_in[1].gl_Position - g_vertex_offset_horz_head + g_vertex_offset_vert); + vec4 vb_head = viewProjectionMatrix * (gl_in[1].gl_Position + g_vertex_offset_horz_head + g_vertex_offset_vert); vec4 vb_down = viewProjectionMatrix * (gl_in[1].gl_Position - g_vertex_offset_horz + g_vertex_offset_vert); vec4 vb_up = viewProjectionMatrix * (gl_in[1].gl_Position + g_vertex_offset_horz + g_vertex_offset_vert); // Travels: flat plane with pointy ends - myEmitVertex(v_vertex[0], v_color[0], g_vertex_normal_vert, va_up); - myEmitVertex(v_vertex[0], v_color[0], g_vertex_normal_vert, va_head); - myEmitVertex(v_vertex[0], v_color[0], g_vertex_normal_vert, va_down); - myEmitVertex(v_vertex[0], v_color[0], g_vertex_normal_vert, va_up); + myEmitVertex(v_vertex[0], v_color[1], g_vertex_normal_vert, va_head); + myEmitVertex(v_vertex[0], v_color[1], g_vertex_normal_vert, va_down); + myEmitVertex(v_vertex[0], v_color[1], g_vertex_normal_vert, va_up); myEmitVertex(v_vertex[1], v_color[1], g_vertex_normal_vert, vb_down); myEmitVertex(v_vertex[1], v_color[1], g_vertex_normal_vert, vb_up); myEmitVertex(v_vertex[1], v_color[1], g_vertex_normal_vert, vb_head); //And reverse so that the line is also visible from the back side. myEmitVertex(v_vertex[1], v_color[1], g_vertex_normal_vert, vb_up); myEmitVertex(v_vertex[1], v_color[1], g_vertex_normal_vert, vb_down); - myEmitVertex(v_vertex[0], v_color[0], g_vertex_normal_vert, va_up); - myEmitVertex(v_vertex[0], v_color[0], g_vertex_normal_vert, va_down); - myEmitVertex(v_vertex[0], v_color[0], g_vertex_normal_vert, va_head); - myEmitVertex(v_vertex[0], v_color[0], g_vertex_normal_vert, va_up); + myEmitVertex(v_vertex[0], v_color[1], g_vertex_normal_vert, va_up); + myEmitVertex(v_vertex[0], v_color[1], g_vertex_normal_vert, va_down); + myEmitVertex(v_vertex[0], v_color[1], g_vertex_normal_vert, va_head); + myEmitVertex(v_vertex[0], v_color[1], g_vertex_normal_vert, va_up); EndPrimitive(); } else { - vec4 va_m_horz = viewProjectionMatrix * (gl_in[0].gl_Position - g_vertex_offset_horz); - vec4 vb_m_horz = viewProjectionMatrix * (gl_in[1].gl_Position - g_vertex_offset_horz); - vec4 va_p_vert = viewProjectionMatrix * (gl_in[0].gl_Position + g_vertex_offset_vert); - vec4 vb_p_vert = viewProjectionMatrix * (gl_in[1].gl_Position + g_vertex_offset_vert); - vec4 va_p_horz = viewProjectionMatrix * (gl_in[0].gl_Position + g_vertex_offset_horz); - vec4 vb_p_horz = viewProjectionMatrix * (gl_in[1].gl_Position + g_vertex_offset_horz); - vec4 va_m_vert = viewProjectionMatrix * (gl_in[0].gl_Position - g_vertex_offset_vert); - vec4 vb_m_vert = viewProjectionMatrix * (gl_in[1].gl_Position - g_vertex_offset_vert); - vec4 va_head = viewProjectionMatrix * (gl_in[0].gl_Position + g_vertex_offset_horz_head); - vec4 vb_head = viewProjectionMatrix * (gl_in[1].gl_Position - g_vertex_offset_horz_head); + vec4 va_m_horz = viewProjectionMatrix * (gl_in[0].gl_Position - g_vertex_offset_horz); //Line start, left vertex. + vec4 vb_m_horz = viewProjectionMatrix * (gl_in[1].gl_Position - g_vertex_offset_horz); //Line end, left vertex. + vec4 va_p_vert = viewProjectionMatrix * (gl_in[0].gl_Position + g_vertex_offset_vert); //Line start, top vertex. + vec4 vb_p_vert = viewProjectionMatrix * (gl_in[1].gl_Position + g_vertex_offset_vert); //Line end, top vertex. + vec4 va_p_horz = viewProjectionMatrix * (gl_in[0].gl_Position + g_vertex_offset_horz); //Line start, right vertex. + vec4 vb_p_horz = viewProjectionMatrix * (gl_in[1].gl_Position + g_vertex_offset_horz); //Line end, right vertex. + vec4 va_m_vert = viewProjectionMatrix * (gl_in[0].gl_Position - g_vertex_offset_vert); //Line start, bottom vertex. + vec4 vb_m_vert = viewProjectionMatrix * (gl_in[1].gl_Position - g_vertex_offset_vert); //Line end, bottom vertex. + vec4 va_head = viewProjectionMatrix * (gl_in[0].gl_Position - g_vertex_offset_horz_head); //Line start, tip. + vec4 vb_head = viewProjectionMatrix * (gl_in[1].gl_Position + g_vertex_offset_horz_head); //Line end, tip. // All normal lines are rendered as 3d tubes. - myEmitVertex(v_vertex[0], v_color[0], -g_vertex_normal_horz, va_m_horz); + myEmitVertex(v_vertex[0], v_color[1], -g_vertex_normal_horz, va_m_horz); myEmitVertex(v_vertex[1], v_color[1], -g_vertex_normal_horz, vb_m_horz); - myEmitVertex(v_vertex[0], v_color[0], g_vertex_normal_vert, va_p_vert); + myEmitVertex(v_vertex[0], v_color[1], g_vertex_normal_vert, va_p_vert); myEmitVertex(v_vertex[1], v_color[1], g_vertex_normal_vert, vb_p_vert); - myEmitVertex(v_vertex[0], v_color[0], g_vertex_normal_horz, va_p_horz); + myEmitVertex(v_vertex[0], v_color[1], g_vertex_normal_horz, va_p_horz); myEmitVertex(v_vertex[1], v_color[1], g_vertex_normal_horz, vb_p_horz); - myEmitVertex(v_vertex[0], v_color[0], -g_vertex_normal_vert, va_m_vert); + myEmitVertex(v_vertex[0], v_color[1], -g_vertex_normal_vert, va_m_vert); myEmitVertex(v_vertex[1], v_color[1], -g_vertex_normal_vert, vb_m_vert); - myEmitVertex(v_vertex[0], v_color[0], -g_vertex_normal_horz, va_m_horz); + myEmitVertex(v_vertex[0], v_color[1], -g_vertex_normal_horz, va_m_horz); myEmitVertex(v_vertex[1], v_color[1], -g_vertex_normal_horz, vb_m_horz); EndPrimitive(); // left side - myEmitVertex(v_vertex[0], v_color[0], -g_vertex_normal_horz, va_m_horz); - myEmitVertex(v_vertex[0], v_color[0], g_vertex_normal_vert, va_p_vert); - myEmitVertex(v_vertex[0], v_color[0], g_vertex_normal_horz_head, va_head); - myEmitVertex(v_vertex[0], v_color[0], g_vertex_normal_horz, va_p_horz); + myEmitVertex(v_vertex[0], v_color[1], -g_vertex_normal_horz, va_m_horz); + myEmitVertex(v_vertex[0], v_color[1], g_vertex_normal_vert, va_p_vert); + myEmitVertex(v_vertex[0], v_color[1], -g_vertex_normal_horz_head, va_head); + myEmitVertex(v_vertex[0], v_color[1], g_vertex_normal_horz, va_p_horz); EndPrimitive(); - myEmitVertex(v_vertex[0], v_color[0], g_vertex_normal_horz, va_p_horz); - myEmitVertex(v_vertex[0], v_color[0], -g_vertex_normal_vert, va_m_vert); - myEmitVertex(v_vertex[0], v_color[0], g_vertex_normal_horz_head, va_head); - myEmitVertex(v_vertex[0], v_color[0], -g_vertex_normal_horz, va_m_horz); + myEmitVertex(v_vertex[0], v_color[1], g_vertex_normal_horz, va_p_horz); + myEmitVertex(v_vertex[0], v_color[1], -g_vertex_normal_vert, va_m_vert); + myEmitVertex(v_vertex[0], v_color[1], -g_vertex_normal_horz_head, va_head); + myEmitVertex(v_vertex[0], v_color[1], -g_vertex_normal_horz, va_m_horz); EndPrimitive(); // right side myEmitVertex(v_vertex[1], v_color[1], g_vertex_normal_horz, vb_p_horz); myEmitVertex(v_vertex[1], v_color[1], g_vertex_normal_vert, vb_p_vert); - myEmitVertex(v_vertex[1], v_color[1], -g_vertex_normal_horz_head, vb_head); + myEmitVertex(v_vertex[1], v_color[1], g_vertex_normal_horz_head, vb_head); myEmitVertex(v_vertex[1], v_color[1], -g_vertex_normal_horz, vb_m_horz); EndPrimitive(); myEmitVertex(v_vertex[1], v_color[1], -g_vertex_normal_horz, vb_m_horz); myEmitVertex(v_vertex[1], v_color[1], -g_vertex_normal_vert, vb_m_vert); - myEmitVertex(v_vertex[1], v_color[1], -g_vertex_normal_horz_head, vb_head); + myEmitVertex(v_vertex[1], v_color[1], g_vertex_normal_horz_head, vb_head); myEmitVertex(v_vertex[1], v_color[1], g_vertex_normal_horz, vb_p_horz); EndPrimitive(); diff --git a/plugins/SimulationView/layers_shadow.shader b/plugins/SimulationView/layers_shadow.shader index 4bc2de3d0b..73278914b7 100644 --- a/plugins/SimulationView/layers_shadow.shader +++ b/plugins/SimulationView/layers_shadow.shader @@ -48,8 +48,10 @@ fragment = void main() { - if ((u_show_travel_moves == 0) && (v_line_type >= 7.5) && (v_line_type <= 9.5)) - { // actually, 8 and 9 + // travel moves: 8, 9, 12, 13 + if ((u_show_travel_moves == 0) && (((v_line_type >= 7.5) && (v_line_type <= 9.5)) || + ((v_line_type >= 11.5) && (v_line_type <= 13.5)))) { + { // discard movements discard; } @@ -124,7 +126,9 @@ fragment41core = void main() { - if ((u_show_travel_moves == 0) && (v_line_type >= 7.5) && (v_line_type <= 9.5)) { // actually, 8 and 9 + // travel moves: 8, 9, 12, 13 + if ((u_show_travel_moves == 0) && (((v_line_type >= 7.5) && (v_line_type <= 9.5)) || + ((v_line_type >= 11.5) && (v_line_type <= 13.5)))) { // discard movements discard; } diff --git a/plugins/SolidView/SolidView.py b/plugins/SolidView/SolidView.py index 7f32b0df7f..e115267720 100644 --- a/plugins/SolidView/SolidView.py +++ b/plugins/SolidView/SolidView.py @@ -1,13 +1,12 @@ # Copyright (c) 2021 Ultimaker B.V. # Cura is released under the terms of the LGPLv3 or higher. -import os.path from UM.View.View import View from UM.Scene.Iterator.DepthFirstIterator import DepthFirstIterator from UM.Scene.Selection import Selection from UM.Resources import Resources -from PyQt6.QtGui import QOpenGLContext, QDesktopServices, QImage -from PyQt6.QtCore import QSize, QUrl +from PyQt6.QtGui import QDesktopServices, QImage +from PyQt6.QtCore import QUrl import numpy as np import time @@ -36,11 +35,13 @@ class SolidView(View): """Standard view for mesh models.""" _show_xray_warning_preference = "view/show_xray_warning" + _show_overhang_preference = "view/show_overhang" + _paint_active_preference = "view/paint_active" def __init__(self): super().__init__() application = Application.getInstance() - application.getPreferences().addPreference("view/show_overhang", True) + application.getPreferences().addPreference(self._show_overhang_preference, True) application.globalContainerStackChanged.connect(self._onGlobalContainerChanged) self._enabled_shader = None self._disabled_shader = None @@ -212,7 +213,7 @@ class SolidView(View): global_container_stack = Application.getInstance().getGlobalContainerStack() if global_container_stack: - if Application.getInstance().getPreferences().getValue("view/show_overhang"): + if Application.getInstance().getPreferences().getValue(self._show_overhang_preference): # Make sure the overhang angle is valid before passing it to the shader if self._support_angle >= 0 and self._support_angle <= 90: self._enabled_shader.setUniformValue("u_overhangAngle", math.cos(math.radians(90 - self._support_angle))) diff --git a/resources/definitions/fdmprinter.def.json b/resources/definitions/fdmprinter.def.json index 6710d0f0bf..3ad11933e6 100644 --- a/resources/definitions/fdmprinter.def.json +++ b/resources/definitions/fdmprinter.def.json @@ -9311,6 +9311,32 @@ "default_value": true, "settable_per_mesh": true }, + "retraction_during_travel_ratio": + { + "label": "Retraction During Travel Move", + "description": "The ratio of retraction performed during the travel move, with the remainder completed while the nozzle is stationary, before traveling", + "unit": "%", + "type": "float", + "default_value": 0, + "minimum_value": 0, + "maximum_value": 100, + "enabled": "retraction_enable and not machine_firmware_retract and machine_gcode_flavor != \"UltiGCode\" and machine_gcode_flavor != \"BFB\"", + "settable_per_mesh": false, + "settable_per_extruder": true + }, + "prime_during_travel_ratio": + { + "label": "Prime During Travel Move", + "description": "The ratio of priming performed during the travel move, with the remainder completed while the nozzle is stationary, after traveling", + "unit": "%", + "type": "float", + "default_value": 0, + "minimum_value": 0, + "maximum_value": 100, + "enabled": "retraction_enable and not machine_firmware_retract and machine_gcode_flavor != \"UltiGCode\" and machine_gcode_flavor != \"BFB\"", + "settable_per_mesh": false, + "settable_per_extruder": true + }, "scarf_joint_seam_length": { "label": "Scarf Seam Length", diff --git a/resources/themes/cura-dark-colorblind/theme.json b/resources/themes/cura-dark-colorblind/theme.json index 4a006ee836..4443111b60 100644 --- a/resources/themes/cura-dark-colorblind/theme.json +++ b/resources/themes/cura-dark-colorblind/theme.json @@ -1,26 +1 @@ -{ - "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] - } -} +{"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]}} \ No newline at end of file diff --git a/resources/themes/cura-dark/theme.json b/resources/themes/cura-dark/theme.json index 1517b22eb9..29be47e697 100644 --- a/resources/themes/cura-dark/theme.json +++ b/resources/themes/cura-dark/theme.json @@ -1,212 +1 @@ -{ - "metadata": { - "name": "UltiMaker Dark", - "inherits": "cura-light" - }, - - "base_colors": - { - "background_1": [31, 31, 32, 255], - "background_2": [57, 57, 58, 255], - "background_3": [85, 85, 87, 255], - "background_4": [23, 23, 23, 255], - - "accent_1": [25, 110, 240, 255], - "accent_2": [16, 70, 156, 255], - "border_main": [118, 118, 119, 255], - "border_accent_1": [255, 255, 255, 255], - "border_accent_2": [243, 243, 243, 255], - "border_field": [57, 57, 58, 255], - - "text_default": [255, 255, 255, 255], - "text_disabled": [118, 118, 118, 255], - "text_primary_button": [255, 255, 255, 255], - "text_secondary_button": [255, 255, 255, 255], - "text_link_hover": [156, 195, 255, 255], - "text_lighter": [243, 243, 243, 255], - - "um_green_1": [233, 245, 237, 255], - "um_green_5": [36, 162, 73, 255], - "um_green_9": [31, 44, 36, 255], - "um_red_1": [251, 232, 233, 255], - "um_red_5": [218, 30, 40, 255], - "um_red_9": [59, 31, 33, 255], - "um_orange_1": [255, 235, 221, 255], - "um_orange_5": [252, 123, 30, 255], - "um_orange_9": [64, 45, 32, 255], - "um_yellow_1": [255, 248, 225, 255], - "um_yellow_5": [253, 209, 58, 255], - "um_yellow_9": [64, 58, 36, 255] - }, - - "colors": { - "main_background": "background_1", - "detail_background": "background_2", - "message_background": "background_1", - "wide_lining": [31, 36, 39, 255], - "thick_lining": [255, 255, 255, 60], - "lining": "border_main", - "viewport_overlay": "background_1", - - "primary_text": "text_default", - "secondary": [95, 95, 95, 255], - - "expandable_active": "background_2", - "expandable_hover": "background_2", - - "secondary_button": "background_1", - "secondary_button_hover": "background_3", - "secondary_button_text": "text_secondary_button", - - "icon": "text_default", - "toolbar_background": "background_1", - "toolbar_button_active": "background_3", - "toolbar_button_hover": "background_3", - "toolbar_button_active_hover": "background_3", - - "main_window_header_button_background_inactive": "background_4", - "main_window_header_button_text_inactive": "text_primary_button", - "main_window_header_button_text_active": "background_4", - "main_window_header_background": "background_4", - "main_window_header_background_gradient": "background_4", - "main_window_header_button_background_hovered": [46, 46, 46, 255], - - "account_sync_state_icon": [255, 255, 255, 204], - - "machine_selector_printer_icon": [204, 204, 204, 255], - - "text": "text_default", - "text_detail": [255, 255, 255, 172], - "text_link": "accent_1", - "text_inactive": [118, 118, 118, 255], - "text_hover": [255, 255, 255, 255], - "text_scene": [250, 250, 250, 255], - "text_scene_hover": [255, 255, 255, 255], - - "printer_type_label_background": [95, 95, 95, 255], - - "error": [212, 31, 53, 255], - "disabled": [32, 32, 32, 255], - - "button": [39, 44, 48, 255], - "button_hover": [39, 44, 48, 255], - "button_text": "text_default", - "button_disabled": [39, 44, 48, 255], - "button_disabled_text": [255, 255, 255, 101], - - "small_button_text": [255, 255, 255, 197], - "small_button_text_hover": [255, 255, 255, 255], - - "button_tooltip": [39, 44, 48, 255], - - "tab_checked": [39, 44, 48, 255], - "tab_checked_border": [255, 255, 255, 30], - "tab_checked_text": [255, 255, 255, 255], - "tab_unchecked": [39, 44, 48, 255], - "tab_unchecked_border": [255, 255, 255, 30], - "tab_unchecked_text": [255, 255, 255, 101], - "tab_hovered": [39, 44, 48, 255], - "tab_hovered_border": [255, 255, 255, 30], - "tab_hovered_text": [255, 255, 255, 255], - "tab_active": [39, 44, 48, 255], - "tab_active_border": [255, 255, 255, 30], - "tab_active_text": [255, 255, 255, 255], - "tab_background": [39, 44, 48, 255], - - "action_button": "background_1", - "action_button_text": [255, 255, 255, 200], - "action_button_border": "border_main", - "action_button_hovered": [79, 85, 89, 255], - "action_button_hovered_text": "text_default", - "action_button_hovered_border": "border_main", - "action_button_active": [39, 44, 48, 30], - "action_button_active_text": "text_default", - "action_button_active_border": [255, 255, 255, 100], - "action_button_disabled": "background_3", - "action_button_disabled_text": "text_disabled", - "action_button_disabled_border": [255, 255, 255, 30], - - "scrollbar_background": [39, 44, 48, 0], - "scrollbar_handle": [255, 255, 255, 105], - "scrollbar_handle_hover": [255, 255, 255, 255], - "scrollbar_handle_down": [255, 255, 255, 255], - - "setting_category_disabled": [75, 80, 83, 255], - "setting_category_disabled_text": [255, 255, 255, 101], - - "setting_control": "background_2", - "setting_control_selected": [34, 39, 42, 38], - "setting_control_highlight": "background_3", - "setting_control_border": [255, 255, 255, 38], - "setting_control_border_highlight": [12, 169, 227, 255], - "setting_control_text": "text_default", - "setting_control_button": [255, 255, 255, 127], - "setting_control_button_hover": [255, 255, 255, 204], - "setting_control_disabled": [34, 39, 42, 255], - "setting_control_disabled_text": [255, 255, 255, 101], - "setting_control_disabled_border": [255, 255, 255, 101], - "setting_unit": [255, 255, 255, 127], - "setting_validation_error_background": "um_red_9", - "setting_validation_warning_background": "um_yellow_9", - "setting_validation_ok": "background_2", - - "progressbar_background": [255, 255, 255, 48], - "progressbar_control": [255, 255, 255, 197], - - "slider_groove": [127, 127, 127, 255], - "slider_groove_border": [127, 127, 127, 255], - "slider_groove_fill": [245, 245, 245, 255], - "slider_handle": [255, 255, 255, 255], - "slider_handle_active": [68, 192, 255, 255], - - "category_background": "background_3", - - "tooltip": "background_2", - "tooltip_text": "text_default", - - "tool_panel_background": "background_1", - - "viewport_background": "background_1", - "volume_outline": [12, 169, 227, 128], - "buildplate": [169, 169, 169, 255], - "buildplate_grid_minor": [154, 154, 155, 255], - - "disallowed_area": [0, 0, 0, 52], - - "model_selection_outline": [12, 169, 227, 255], - - "material_compatibility_warning": [255, 255, 255, 255], - - "core_compatibility_warning": [255, 255, 255, 255], - - "quality_slider_available": [255, 255, 255, 255], - - "monitor_printer_family_tag": [86, 86, 106, 255], - "monitor_text_disabled": [102, 102, 102, 255], - "monitor_icon_primary": [229, 229, 229, 255], - "monitor_icon_accent": [51, 53, 54, 255], - "monitor_icon_disabled": [102, 102, 102, 255], - - "monitor_secondary_button_hover": [80, 80, 80, 255], - "monitor_card_border": [102, 102, 102, 255], - "monitor_card_background": [51, 53, 54, 255], - "monitor_card_hover": [84, 89, 95, 255], - - "monitor_stage_background": "background_1", - "monitor_stage_background_fade": "background_1", - - "monitor_progress_bar_deactive": [102, 102, 102, 255], - "monitor_progress_bar_empty": [67, 67, 67, 255], - - "monitor_tooltip_text": [229, 229, 229, 255], - "monitor_context_menu": [67, 67, 67, 255], - "monitor_context_menu_hover": [30, 102, 215, 255], - - "monitor_skeleton_loading": [102, 102, 102, 255], - "monitor_placeholder_image": [102, 102, 102, 255], - "monitor_shadow": [4, 10, 13, 255], - - "monitor_carousel_dot": [119, 119, 119, 255], - "monitor_carousel_dot_current": [216, 216, 216, 255] - } -} +{"metadata": {"name": "UltiMaker Dark", "inherits": "cura-light"}, "base_colors": {"background_1": [31, 31, 32, 255], "background_2": [57, 57, 58, 255], "background_3": [85, 85, 87, 255], "background_4": [23, 23, 23, 255], "accent_1": [25, 110, 240, 255], "accent_2": [16, 70, 156, 255], "border_main": [118, 118, 119, 255], "border_accent_1": [255, 255, 255, 255], "border_accent_2": [243, 243, 243, 255], "border_field": [57, 57, 58, 255], "text_default": [255, 255, 255, 255], "text_disabled": [118, 118, 118, 255], "text_primary_button": [255, 255, 255, 255], "text_secondary_button": [255, 255, 255, 255], "text_link_hover": [156, 195, 255, 255], "text_lighter": [243, 243, 243, 255], "um_green_1": [233, 245, 237, 255], "um_green_5": [36, 162, 73, 255], "um_green_9": [31, 44, 36, 255], "um_red_1": [251, 232, 233, 255], "um_red_5": [218, 30, 40, 255], "um_red_9": [59, 31, 33, 255], "um_orange_1": [255, 235, 221, 255], "um_orange_5": [252, 123, 30, 255], "um_orange_9": [64, 45, 32, 255], "um_yellow_1": [255, 248, 225, 255], "um_yellow_5": [253, 209, 58, 255], "um_yellow_9": [64, 58, 36, 255]}, "colors": {"main_background": "background_1", "detail_background": "background_2", "message_background": "background_1", "wide_lining": [31, 36, 39, 255], "thick_lining": [255, 255, 255, 60], "lining": "border_main", "viewport_overlay": "background_1", "primary_text": "text_default", "secondary": [95, 95, 95, 255], "expandable_active": "background_2", "expandable_hover": "background_2", "secondary_button": "background_1", "secondary_button_hover": "background_3", "secondary_button_text": "text_secondary_button", "icon": "text_default", "toolbar_background": "background_1", "toolbar_button_active": "background_3", "toolbar_button_hover": "background_3", "toolbar_button_active_hover": "background_3", "main_window_header_button_background_inactive": "background_4", "main_window_header_button_text_inactive": "text_primary_button", "main_window_header_button_text_active": "background_4", "main_window_header_background": [192, 199, 65, 255], "main_window_header_background_gradient": "background_4", "main_window_header_button_background_hovered": [46, 46, 46, 255], "account_sync_state_icon": [255, 255, 255, 204], "machine_selector_printer_icon": [204, 204, 204, 255], "text": "text_default", "text_detail": [255, 255, 255, 172], "text_link": "accent_1", "text_inactive": [118, 118, 118, 255], "text_hover": [255, 255, 255, 255], "text_scene": [250, 250, 250, 255], "text_scene_hover": [255, 255, 255, 255], "printer_type_label_background": [95, 95, 95, 255], "error": [212, 31, 53, 255], "disabled": [32, 32, 32, 255], "button": [39, 44, 48, 255], "button_hover": [39, 44, 48, 255], "button_text": "text_default", "button_disabled": [39, 44, 48, 255], "button_disabled_text": [255, 255, 255, 101], "small_button_text": [255, 255, 255, 197], "small_button_text_hover": [255, 255, 255, 255], "button_tooltip": [39, 44, 48, 255], "tab_checked": [39, 44, 48, 255], "tab_checked_border": [255, 255, 255, 30], "tab_checked_text": [255, 255, 255, 255], "tab_unchecked": [39, 44, 48, 255], "tab_unchecked_border": [255, 255, 255, 30], "tab_unchecked_text": [255, 255, 255, 101], "tab_hovered": [39, 44, 48, 255], "tab_hovered_border": [255, 255, 255, 30], "tab_hovered_text": [255, 255, 255, 255], "tab_active": [39, 44, 48, 255], "tab_active_border": [255, 255, 255, 30], "tab_active_text": [255, 255, 255, 255], "tab_background": [39, 44, 48, 255], "action_button": "background_1", "action_button_text": [255, 255, 255, 200], "action_button_border": "border_main", "action_button_hovered": [79, 85, 89, 255], "action_button_hovered_text": "text_default", "action_button_hovered_border": "border_main", "action_button_active": [39, 44, 48, 30], "action_button_active_text": "text_default", "action_button_active_border": [255, 255, 255, 100], "action_button_disabled": "background_3", "action_button_disabled_text": "text_disabled", "action_button_disabled_border": [255, 255, 255, 30], "scrollbar_background": [39, 44, 48, 0], "scrollbar_handle": [255, 255, 255, 105], "scrollbar_handle_hover": [255, 255, 255, 255], "scrollbar_handle_down": [255, 255, 255, 255], "setting_category_disabled": [75, 80, 83, 255], "setting_category_disabled_text": [255, 255, 255, 101], "setting_control": "background_2", "setting_control_selected": [34, 39, 42, 38], "setting_control_highlight": "background_3", "setting_control_border": [255, 255, 255, 38], "setting_control_border_highlight": [12, 169, 227, 255], "setting_control_text": "text_default", "setting_control_button": [255, 255, 255, 127], "setting_control_button_hover": [255, 255, 255, 204], "setting_control_disabled": [34, 39, 42, 255], "setting_control_disabled_text": [255, 255, 255, 101], "setting_control_disabled_border": [255, 255, 255, 101], "setting_unit": [255, 255, 255, 127], "setting_validation_error_background": "um_red_9", "setting_validation_warning_background": "um_yellow_9", "setting_validation_ok": "background_2", "progressbar_background": [255, 255, 255, 48], "progressbar_control": [255, 255, 255, 197], "slider_groove": [127, 127, 127, 255], "slider_groove_border": [127, 127, 127, 255], "slider_groove_fill": [245, 245, 245, 255], "slider_handle": [255, 255, 255, 255], "slider_handle_active": [68, 192, 255, 255], "category_background": "background_3", "tooltip": "background_2", "tooltip_text": "text_default", "tool_panel_background": "background_1", "viewport_background": "background_1", "volume_outline": [12, 169, 227, 128], "buildplate": [169, 169, 169, 255], "buildplate_grid_minor": [154, 154, 155, 255], "disallowed_area": [0, 0, 0, 52], "model_selection_outline": [12, 169, 227, 255], "material_compatibility_warning": [255, 255, 255, 255], "core_compatibility_warning": [255, 255, 255, 255], "quality_slider_available": [255, 255, 255, 255], "monitor_printer_family_tag": [86, 86, 106, 255], "monitor_text_disabled": [102, 102, 102, 255], "monitor_icon_primary": [229, 229, 229, 255], "monitor_icon_accent": [51, 53, 54, 255], "monitor_icon_disabled": [102, 102, 102, 255], "monitor_secondary_button_hover": [80, 80, 80, 255], "monitor_card_border": [102, 102, 102, 255], "monitor_card_background": [51, 53, 54, 255], "monitor_card_hover": [84, 89, 95, 255], "monitor_stage_background": "background_1", "monitor_stage_background_fade": "background_1", "monitor_progress_bar_deactive": [102, 102, 102, 255], "monitor_progress_bar_empty": [67, 67, 67, 255], "monitor_tooltip_text": [229, 229, 229, 255], "monitor_context_menu": [67, 67, 67, 255], "monitor_context_menu_hover": [30, 102, 215, 255], "monitor_skeleton_loading": [102, 102, 102, 255], "monitor_placeholder_image": [102, 102, 102, 255], "monitor_shadow": [4, 10, 13, 255], "monitor_carousel_dot": [119, 119, 119, 255], "monitor_carousel_dot_current": [216, 216, 216, 255]}} \ No newline at end of file diff --git a/resources/themes/cura-light-colorblind/theme.json b/resources/themes/cura-light-colorblind/theme.json index 740bf977b2..cc7ed5dfba 100644 --- a/resources/themes/cura-light-colorblind/theme.json +++ b/resources/themes/cura-light-colorblind/theme.json @@ -1,29 +1 @@ -{ - "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] - } -} +{"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]}} \ No newline at end of file diff --git a/resources/themes/cura-light/theme.json b/resources/themes/cura-light/theme.json index 1ae316f96c..2362155944 100644 --- a/resources/themes/cura-light/theme.json +++ b/resources/themes/cura-light/theme.json @@ -1,687 +1 @@ -{ - "metadata": { - "name": "UltiMaker" - }, - - "fonts": { - "large": { - "size": 1.35, - "weight": 400, - "family": "Noto Sans" - }, - "large_ja_JP": { - "size": 1.35, - "weight": 400, - "family": "Noto Sans" - }, - "large_zh_CN": { - "size": 1.35, - "weight": 400, - "family": "Noto Sans" - }, - "large_zh_TW": { - "size": 1.35, - "weight": 400, - "family": "Noto Sans" - }, - "large_bold": { - "size": 1.35, - "weight": 600, - "family": "Noto Sans" - }, - "huge": { - "size": 1.8, - "weight": 400, - "family": "Noto Sans" - }, - "huge_bold": { - "size": 1.8, - "weight": 600, - "family": "Noto Sans" - }, - "medium": { - "size": 1.16, - "weight": 400, - "family": "Noto Sans" - }, - "medium_ja_JP": { - "size": 1.16, - "weight": 400, - "family": "Noto Sans" - }, - "medium_zh_CN": { - "size": 1.16, - "weight": 400, - "family": "Noto Sans" - }, - "medium_zh_TW": { - "size": 1.16, - "weight": 400, - "family": "Noto Sans" - }, - "medium_bold": { - "size": 1.16, - "weight": 600, - "family": "Noto Sans" - }, - "default": { - "size": 0.95, - "weight": 400, - "family": "Noto Sans" - }, - "default_ja_JP": { - "size": 1.0, - "weight": 400, - "family": "Noto Sans" - }, - "default_zh_CN": { - "size": 1.0, - "weight": 400, - "family": "Noto Sans" - }, - "default_zh_TW": { - "size": 1.0, - "weight": 400, - "family": "Noto Sans" - }, - "default_bold": { - "size": 0.95, - "weight": 600, - "family": "Noto Sans" - }, - "default_bold_ja_JP": { - "size": 1.0, - "weight": 600, - "family": "Noto Sans" - }, - "default_bold_zh_CN": { - "size": 1.0, - "weight": 600, - "family": "Noto Sans" - }, - "default_bold_zh_TW": { - "size": 1.0, - "weight": 600, - "family": "Noto Sans" - }, - "default_italic": { - "size": 0.95, - "weight": 400, - "italic": true, - "family": "Noto Sans" - }, - "medium_italic": { - "size": 1.16, - "weight": 400, - "italic": true, - "family": "Noto Sans" - }, - "default_italic_ja_JP": { - "size": 1.0, - "weight": 400, - "italic": true, - "family": "Noto Sans" - }, - "default_italic_zh_CN": { - "size": 1.0, - "weight": 400, - "italic": true, - "family": "Noto Sans" - }, - "default_italic_zh_TW": { - "size": 1.0, - "weight": 400, - "italic": true, - "family": "Noto Sans" - }, - "small": { - "size": 0.9, - "weight": 400, - "family": "Noto Sans" - }, - "small_bold": { - "size": 0.9, - "weight": 700, - "family": "Noto Sans" - }, - "small_ja_JP": { - "size": 0.9, - "weight": 400, - "family": "Noto Sans" - }, - "small_zh_CN": { - "size": 0.9, - "weight": 400, - "family": "Noto Sans" - }, - "small_zh_TW": { - "size": 0.9, - "weight": 400, - "family": "Noto Sans" - }, - "small_emphasis": { - "size": 0.9, - "weight": 700, - "family": "Noto Sans" - }, - "small_emphasis_ja_JP": { - "size": 0.9, - "weight": 700, - "family": "Noto Sans" - }, - "small_emphasis_zh_CN": { - "size": 0.9, - "weight": 700, - "family": "Noto Sans" - }, - "small_emphasis_zh_TW": { - "size": 0.9, - "weight": 700, - "family": "Noto Sans" - }, - "tiny_emphasis": { - "size": 0.7, - "weight": 700, - "family": "Noto Sans" - }, - "tiny_emphasis_ja_JP": { - "size": 0.7, - "weight": 700, - "family": "Noto Sans" - }, - "tiny_emphasis_zh_CN": { - "size": 0.7, - "weight": 700, - "family": "Noto Sans" - }, - "tiny_emphasis_zh_TW": { - "size": 0.7, - "weight": 700, - "family": "Noto Sans" - } - }, - - "base_colors": { - "background_1": [255, 255, 255, 255], - "background_2": [243, 243, 243, 255], - "background_3": [232, 240, 253, 255], - "background_4": [3, 12, 66, 255], - - "accent_1": [25, 110, 240, 255], - "accent_2": [16, 70, 156, 255], - "border_main": [212, 212, 212, 255], - "border_accent_1": [25, 110, 240, 255], - "border_accent_2": [16, 70, 156, 255], - "border_field": [180, 180, 180, 255], - - "text_default": [0, 14, 26, 255], - "text_disabled": [180, 180, 180, 255], - "text_primary_button": [255, 255, 255, 255], - "text_secondary_button": [25, 110, 240, 255], - "text_link_hover": [16, 70, 156, 255], - "text_lighter": [108, 108, 108, 255], - - "um_green_1": [233, 245, 237, 255], - "um_green_5": [36, 162, 73, 255], - "um_green_9": [31, 44, 36, 255], - "um_red_1": [251, 232, 233, 255], - "um_red_5": [218, 30, 40, 255], - "um_red_9": [59, 31, 33, 255], - "um_orange_1": [255, 235, 221, 255], - "um_orange_5": [252, 123, 30, 255], - "um_orange_9": [64, 45, 32, 255], - "um_yellow_1": [255, 248, 225, 255], - "um_yellow_5": [253, 209, 58, 255], - "um_yellow_9": [64, 58, 36, 255] - }, - - "colors": { - - "main_background": "background_1", - "detail_background": "background_2", - "wide_lining": [245, 245, 245, 255], - "thick_lining": [180, 180, 180, 255], - "lining": [192, 193, 194, 255], - "viewport_overlay": [246, 246, 246, 255], - - "primary": "accent_1", - "primary_hover": [48, 182, 231, 255], - "primary_text": [255, 255, 255, 255], - "text_selection": [156, 195, 255, 127], - "border": [127, 127, 127, 255], - "border_field": [180, 180, 180, 255], - "secondary": [240, 240, 240, 255], - - "expandable_active": [240, 240, 240, 255], - "expandable_hover": [232, 242, 252, 255], - - "icon": [8, 7, 63, 255], - - "primary_button": "accent_1", - "primary_button_hover": [16, 70, 156, 255], - "primary_button_text": [255, 255, 255, 255], - - "secondary_button": "background_1", - "secondary_button_shadow": [216, 216, 216, 255], - "secondary_button_hover": [232, 240, 253, 255], - "secondary_button_text": "accent_1", - - "main_window_header_background": [8, 7, 63, 255], - "main_window_header_background_gradient": [25, 23, 91, 255], - "main_window_header_button_text_active": [8, 7, 63, 255], - "main_window_header_button_text_inactive": [255, 255, 255, 255], - "main_window_header_button_text_hovered": [255, 255, 255, 255], - "main_window_header_button_background_active": [255, 255, 255, 255], - "main_window_header_button_background_inactive": [255, 255, 255, 0], - "main_window_header_button_background_hovered": [117, 114, 159, 255], - - "account_widget_outline_active": [70, 66, 126, 255], - "account_sync_state_icon": [25, 25, 25, 255], - - "machine_selector_printer_icon": [8, 7, 63, 255], - - "action_panel_secondary": "accent_1", - - "first_run_shadow": [50, 50, 50, 255], - - "toolbar_background": [255, 255, 255, 255], - - "notification_icon": [255, 0, 0, 255], - - "printer_type_label_background": [228, 228, 242, 255], - - "window_disabled_background": [0, 0, 0, 255], - - "text": [25, 25, 25, 255], - "text_disabled": [180, 180, 180, 255], - "text_detail": [174, 174, 174, 128], - "text_link": "accent_1", - "text_inactive": [174, 174, 174, 255], - "text_medium": [128, 128, 128, 255], - "text_scene": [102, 102, 102, 255], - "text_scene_hover": [123, 123, 113, 255], - - "error": [218, 30, 40, 255], - "warning": [253, 209, 58, 255], - "success": [36, 162, 73, 255], - "disabled": [229, 229, 229, 255], - - "toolbar_button_hover": [232, 242, 252, 255], - "toolbar_button_active": [232, 242, 252, 255], - "toolbar_button_active_hover": [232, 242, 252, 255], - - "button_text": [255, 255, 255, 255], - - "small_button_text": [102, 102, 102, 255], - "small_button_text_hover": [8, 7, 63, 255], - - "button_tooltip": [31, 36, 39, 255], - - "extruder_disabled": [255, 255, 255, 102], - - "action_button": [255, 255, 255, 255], - "action_button_hovered": [232, 242, 252, 255], - "action_button_disabled": [245, 245, 245, 255], - "action_button_disabled_text": [196, 196, 196, 255], - "action_button_shadow": [223, 223, 223, 255], - - "scrollbar_background": [255, 255, 255, 255], - "scrollbar_handle": [10, 8, 80, 255], - "scrollbar_handle_hover": [50, 130, 255, 255], - "scrollbar_handle_down": [50, 130, 255, 255], - - "setting_category": "background_1", - "setting_category_disabled": [255, 255, 255, 255], - "setting_category_hover": "background_2", - "setting_category_text": "text_default", - "setting_category_disabled_text": [24, 41, 77, 101], - "setting_category_active_text": "text_default", - - "setting_control": "background_2", - "setting_control_highlight": "background_3", - "setting_control_border": [199, 199, 199, 255], - "setting_control_border_highlight": [50, 130, 255, 255], - "setting_control_text": [35, 35, 35, 255], - "setting_control_button": [102, 102, 102, 255], - "setting_control_button_hover": [8, 7, 63, 255], - "setting_control_disabled": "background_2", - "setting_control_disabled_text": [127, 127, 127, 255], - "setting_control_disabled_border": [127, 127, 127, 255], - "setting_unit": [127, 127, 127, 255], - "setting_validation_error_background": "um_red_1", - "setting_validation_error": "um_red_5", - "setting_validation_warning_background": "um_yellow_1", - "setting_validation_warning": "um_yellow_5", - "setting_validation_ok": "background_2", - - "material_compatibility_warning": [243, 166, 59, 255], - "core_compatibility_warning": [243, 166, 59, 255], - - "progressbar_background": [245, 245, 245, 255], - "progressbar_control": [50, 130, 255, 255], - - "slider_groove": [223, 223, 223, 255], - "slider_groove_fill": [8, 7, 63, 255], - "slider_handle": [8, 7, 63, 255], - "slider_handle_active": [50, 130, 255, 255], - "slider_text_background": [255, 255, 255, 255], - - "quality_slider_unavailable": [179, 179, 179, 255], - "quality_slider_available": [0, 0, 0, 255], - - "checkbox": "background_1", - "checkbox_hover": "background_1", - "checkbox_disabled": "background_2", - "checkbox_border": [180, 180, 180, 255], - "checkbox_border_hover": "border_main", - "checkbox_border_disabled": "text_disabled", - "checkbox_mark": "text_default", - "checkbox_mark_disabled": "text_disabled", - "checkbox_square": [180, 180, 180, 255], - "checkbox_text": "text_default", - "checkbox_text_disabled": "text_disabled", - - "switch": "background_1", - "switch_state_checked": "accent_1", - "switch_state_unchecked": "text_disabled", - - "radio": "background_1", - "radio_disabled": "background_2", - "radio_selected": "accent_1", - "radio_selected_disabled": "text_disabled", - "radio_border": [180, 180, 180, 255], - "radio_border_hover": "border_main", - "radio_border_disabled": "text_disabled", - "radio_dot": "background_1", - "radio_dot_disabled": "background_2", - "radio_text": "text_default", - "radio_text_disabled": "text_disabled", - - "text_field": "background_1", - "text_field_border": [180, 180, 180, 255], - "text_field_border_hovered": "border_main", - "text_field_border_active": "border_accent_2", - "text_field_border_disabled": "background_2", - "text_field_text": "text_default", - "text_field_text_disabled": "text_disabled", - - "category_background": "background_2", - - "tooltip": [25, 25, 25, 255], - "tooltip_text": [255, 255, 255, 255], - - "message_background": [255, 255, 255, 255], - "message_border": [192, 193, 194, 255], - "message_close": [102, 102, 102, 255], - "message_close_hover": [8, 7, 63, 255], - "message_progressbar_background": [245, 245, 245, 255], - "message_progressbar_control": [50, 130, 255, 255], - "message_success_icon": [255, 255, 255, 255], - "message_warning_icon": [0, 0, 0, 255], - "message_error_icon": [255, 255, 255, 255], - - "tool_panel_background": [255, 255, 255, 255], - - "status_offline": [0, 0, 0, 255], - "status_ready": [0, 205, 0, 255], - "status_busy": [50, 130, 255, 255], - "status_paused": [255, 140, 0, 255], - "status_stopped": [236, 82, 80, 255], - - "disabled_axis": [127, 127, 127, 255], - "x_axis": [218, 30, 40, 255], - "y_axis": [25, 110, 240, 255], - "z_axis": [36, 162, 73, 255], - "all_axis": [255, 255, 255, 255], - - "viewport_background": [250, 250, 250, 255], - "volume_outline": [50, 130, 255, 255], - "buildplate": [244, 244, 244, 255], - "buildplate_grid": [180, 180, 180, 255], - "buildplate_grid_minor": [228, 228, 228, 255], - - "convex_hull": [35, 35, 35, 127], - "disallowed_area": [0, 0, 0, 40], - "error_area": [255, 0, 0, 127], - - "model_overhang": [255, 0, 0, 255], - "model_unslicable": [122, 122, 122, 255], - "model_unslicable_alt": [172, 172, 127, 255], - "model_selection_outline": [50, 130, 255, 255], - "model_non_printing": [122, 122, 122, 255], - - "xray": [26, 26, 62, 255], - - "layerview_ghost": [31, 31, 31, 95], - "layerview_none": [255, 255, 255, 255], - "layerview_inset_0": [230, 0, 0, 255], - "layerview_inset_x": [0, 230, 0, 255], - "layerview_skin": [230, 230, 0, 255], - "layerview_support": [0, 230, 230, 127], - "layerview_skirt": [0, 230, 230, 255], - "layerview_infill": [230, 115, 0, 255], - "layerview_support_infill": [0, 230, 230, 127], - "layerview_move_combing": [0, 0, 255, 255], - "layerview_move_retraction": [128, 127, 255, 255], - "layerview_support_interface": [63, 127, 255, 127], - "layerview_prime_tower": [0, 255, 255, 255], - "layerview_nozzle": [224, 192, 16, 64], - "layerview_starts": [255, 255, 255, 255], - - - "monitor_printer_family_tag": [228, 228, 242, 255], - "monitor_text_disabled": [238, 238, 238, 255], - "monitor_icon_primary": [10, 8, 80, 255], - "monitor_icon_accent": [255, 255, 255, 255], - "monitor_icon_disabled": [238, 238, 238, 255], - - "monitor_card_border": [192, 193, 194, 255], - "monitor_card_background": [255, 255, 255, 255], - "monitor_card_hover": [232, 242, 252, 255], - - "monitor_stage_background": [246, 246, 246, 255], - "monitor_stage_background_fade": [246, 246, 246, 102], - - "monitor_tooltip": [25, 25, 25, 255], - "monitor_tooltip_text": [255, 255, 255, 255], - "monitor_context_menu": [255, 255, 255, 255], - "monitor_context_menu_hover": [245, 245, 245, 255], - - "monitor_skeleton_loading": [238, 238, 238, 255], - "monitor_placeholder_image": [230, 230, 230, 255], - "monitor_image_overlay": [0, 0, 0, 255], - "monitor_shadow": [200, 200, 200, 255], - - "monitor_carousel_dot": [216, 216, 216, 255], - "monitor_carousel_dot_current": [119, 119, 119, 255], - - "cloud_unavailable": [153, 153, 153, 255], - "connection_badge_background": [255, 255, 255, 255], - "warning_badge_background": [0, 0, 0, 255], - "error_badge_background": [255, 255, 255, 255], - - "border_field_light": [180, 180, 180, 255], - "border_main_light": [212, 212, 212, 255] - }, - - "sizes": { - "window_minimum_size": [80, 48], - "popup_dialog": [40, 36], - "small_popup_dialog": [36, 12], - - "main_window_header": [0.0, 4.0], - - "stage_menu": [0.0, 4.0], - - "account_button": [12, 2.5], - - "print_setup_widget": [38.0, 30.0], - "print_setup_extruder_box": [0.0, 6.0], - "slider_widget_groove": [0.16, 0.16], - "slider_widget_handle": [1.3, 1.3], - "slider_widget_tickmarks": [0.5, 0.5], - "print_setup_big_item": [28, 2.5], - "print_setup_icon": [1.2, 1.2], - "drag_icon": [1.416, 0.25], - - "application_switcher_item": [8, 9], - "application_switcher_icon": [3.75, 3.75], - - "expandable_component_content_header": [0.0, 3.0], - - "configuration_selector": [35.0, 4.0], - - "action_panel_widget": [26.0, 0.0], - "action_panel_information_widget": [20.0, 0.0], - - "machine_selector_widget": [20.0, 4.0], - "machine_selector_widget_content": [25.0, 32.0], - "machine_selector_icon": [2.5, 2.5], - - "views_selector": [16.0, 4.0], - - "printer_type_label": [3.5, 1.5], - - "default_radius": [0.25, 0.25], - - "wide_lining": [0.5, 0.5], - "thick_lining": [0.2, 0.2], - "default_lining": [0.08, 0.08], - - "default_arrow": [0.8, 0.8], - "logo": [16, 2], - - "wide_margin": [2.0, 2.0], - "thick_margin": [1.71, 1.43], - "default_margin": [1.0, 1.0], - "thin_margin": [0.71, 0.71], - "narrow_margin": [0.5, 0.5], - - "extruder_icon": [2.5, 2.5], - - "section": [0.0, 2], - "section_header": [0.0, 2.5], - - "section_control": [0, 1], - "section_icon": [1.5, 1.5], - "section_icon_column": [2.5, 2.5], - - "setting": [25.0, 1.8], - "setting_control": [9.0, 2.0], - "setting_control_radius": [0.15, 0.15], - "setting_control_depth_margin": [1.4, 0.0], - "setting_unit_margin": [0.5, 0.5], - - "standard_list_lineheight": [1.5, 1.5], - "standard_arrow": [1.0, 1.0], - - "card": [25.0, 10], - "card_icon": [6.0, 6.0], - "card_tiny_icon": [1.5, 1.5], - - "button": [4, 4], - "button_icon": [2.5, 2.5], - - "action_button": [15.0, 2.5], - "action_button_icon": [1.5, 1.5], - "action_button_icon_small": [1.0, 1.0], - "action_button_radius": [0.15, 0.15], - - "radio_button": [1.3, 1.3], - - "small_button": [2, 2], - "small_button_icon": [1.5, 1.5], - - "medium_button": [2.5, 2.5], - "medium_button_icon": [2, 2], - - "large_button": [3.0, 3.0], - "large_button_icon": [2.8, 2.8], - - "context_menu": [20, 2], - - "icon_indicator": [1, 1], - - "printer_status_icon": [1.0, 1.0], - - "button_tooltip": [1.0, 1.3], - "button_tooltip_arrow": [0.25, 0.25], - - "progressbar": [26.0, 0.75], - "progressbar_radius": [0.15, 0.15], - - "scrollbar": [0.75, 0.5], - - "slider_groove": [0.5, 0.5], - "slider_groove_radius": [0.15, 0.15], - "slider_handle": [1.5, 1.5], - "slider_layerview_size": [1.0, 34.0], - - "layerview_menu_size": [16.0, 4.0], - "layerview_legend_size": [1.0, 1.0], - "layerview_row": [11.0, 1.5], - "layerview_row_spacing": [0.0, 0.5], - - "checkbox": [1.33, 1.33], - "checkbox_mark": [1, 1], - "checkbox_radius": [0.25, 0.25], - - "spinbox": [6.0, 3.0], - "combobox": [14, 2], - "combobox_wide": [22, 2], - - "tooltip": [20.0, 10.0], - "tooltip_margins": [1.0, 1.0], - "tooltip_arrow_margins": [2.0, 2.0], - - "save_button_save_to_button": [0.3, 2.7], - "save_button_specs_icons": [1.4, 1.4], - - "first_run_shadow_radius": [1.2, 1.2], - - "monitor_preheat_temperature_control": [4.5, 2.0], - - "welcome_wizard_window": [46, 50], - "modal_window_minimum": [60.0, 50.0], - "wizard_progress": [10.0, 0.0], - - "message": [30.0, 5.0], - "message_close": [2, 2], - "message_radius": [0.25, 0.25], - "message_action_button": [0, 2.5], - "message_image": [15.0, 10.0], - "message_type_icon": [2, 2], - "menu": [18, 2], - - "jobspecs_line": [2.0, 2.0], - - "objects_menu_size": [15, 15], - - "notification_icon": [1.5, 1.5], - - "avatar_image": [6.8, 6.8], - - "monitor_shadow_radius": [0.4, 0.4], - "monitor_empty_state_offset": [5.6, 5.6], - "monitor_empty_state_size": [35.0, 25.0], - "monitor_column": [18.0, 1.0], - "monitor_progress_bar": [16.5, 1.0], - - "table_row": [2.0, 2.0], - - "welcome_wizard_content_image_big": [18, 15], - "welcome_wizard_cloud_content_image": [4, 4], - - "banner_icon_size": [2.0, 2.0], - - "marketplace_large_icon": [4.0, 4.0], - - "preferences_page_list_item": [8.0, 2.0], - - "recommended_button_icon": [1.7, 1.7], - - "recommended_section_setting_item": [14.0, 2.0], - - "reset_profile_icon": [1, 1] - } -} +{"metadata": {"name": "UltiMaker"}, "fonts": {"large": {"size": 1.35, "weight": 400, "family": "Noto Sans"}, "large_ja_JP": {"size": 1.35, "weight": 400, "family": "Noto Sans"}, "large_zh_CN": {"size": 1.35, "weight": 400, "family": "Noto Sans"}, "large_zh_TW": {"size": 1.35, "weight": 400, "family": "Noto Sans"}, "large_bold": {"size": 1.35, "weight": 600, "family": "Noto Sans"}, "huge": {"size": 1.8, "weight": 400, "family": "Noto Sans"}, "huge_bold": {"size": 1.8, "weight": 600, "family": "Noto Sans"}, "medium": {"size": 1.16, "weight": 400, "family": "Noto Sans"}, "medium_ja_JP": {"size": 1.16, "weight": 400, "family": "Noto Sans"}, "medium_zh_CN": {"size": 1.16, "weight": 400, "family": "Noto Sans"}, "medium_zh_TW": {"size": 1.16, "weight": 400, "family": "Noto Sans"}, "medium_bold": {"size": 1.16, "weight": 600, "family": "Noto Sans"}, "default": {"size": 0.95, "weight": 400, "family": "Noto Sans"}, "default_ja_JP": {"size": 1.0, "weight": 400, "family": "Noto Sans"}, "default_zh_CN": {"size": 1.0, "weight": 400, "family": "Noto Sans"}, "default_zh_TW": {"size": 1.0, "weight": 400, "family": "Noto Sans"}, "default_bold": {"size": 0.95, "weight": 600, "family": "Noto Sans"}, "default_bold_ja_JP": {"size": 1.0, "weight": 600, "family": "Noto Sans"}, "default_bold_zh_CN": {"size": 1.0, "weight": 600, "family": "Noto Sans"}, "default_bold_zh_TW": {"size": 1.0, "weight": 600, "family": "Noto Sans"}, "default_italic": {"size": 0.95, "weight": 400, "italic": true, "family": "Noto Sans"}, "medium_italic": {"size": 1.16, "weight": 400, "italic": true, "family": "Noto Sans"}, "default_italic_ja_JP": {"size": 1.0, "weight": 400, "italic": true, "family": "Noto Sans"}, "default_italic_zh_CN": {"size": 1.0, "weight": 400, "italic": true, "family": "Noto Sans"}, "default_italic_zh_TW": {"size": 1.0, "weight": 400, "italic": true, "family": "Noto Sans"}, "small": {"size": 0.9, "weight": 400, "family": "Noto Sans"}, "small_bold": {"size": 0.9, "weight": 700, "family": "Noto Sans"}, "small_ja_JP": {"size": 0.9, "weight": 400, "family": "Noto Sans"}, "small_zh_CN": {"size": 0.9, "weight": 400, "family": "Noto Sans"}, "small_zh_TW": {"size": 0.9, "weight": 400, "family": "Noto Sans"}, "small_emphasis": {"size": 0.9, "weight": 700, "family": "Noto Sans"}, "small_emphasis_ja_JP": {"size": 0.9, "weight": 700, "family": "Noto Sans"}, "small_emphasis_zh_CN": {"size": 0.9, "weight": 700, "family": "Noto Sans"}, "small_emphasis_zh_TW": {"size": 0.9, "weight": 700, "family": "Noto Sans"}, "tiny_emphasis": {"size": 0.7, "weight": 700, "family": "Noto Sans"}, "tiny_emphasis_ja_JP": {"size": 0.7, "weight": 700, "family": "Noto Sans"}, "tiny_emphasis_zh_CN": {"size": 0.7, "weight": 700, "family": "Noto Sans"}, "tiny_emphasis_zh_TW": {"size": 0.7, "weight": 700, "family": "Noto Sans"}}, "base_colors": {"background_1": [255, 255, 255, 255], "background_2": [243, 243, 243, 255], "background_3": [232, 240, 253, 255], "background_4": [3, 12, 66, 255], "accent_1": [25, 110, 240, 255], "accent_2": [16, 70, 156, 255], "border_main": [212, 212, 212, 255], "border_accent_1": [25, 110, 240, 255], "border_accent_2": [16, 70, 156, 255], "border_field": [180, 180, 180, 255], "text_default": [0, 14, 26, 255], "text_disabled": [180, 180, 180, 255], "text_primary_button": [255, 255, 255, 255], "text_secondary_button": [25, 110, 240, 255], "text_link_hover": [16, 70, 156, 255], "text_lighter": [108, 108, 108, 255], "um_green_1": [233, 245, 237, 255], "um_green_5": [36, 162, 73, 255], "um_green_9": [31, 44, 36, 255], "um_red_1": [251, 232, 233, 255], "um_red_5": [218, 30, 40, 255], "um_red_9": [59, 31, 33, 255], "um_orange_1": [255, 235, 221, 255], "um_orange_5": [252, 123, 30, 255], "um_orange_9": [64, 45, 32, 255], "um_yellow_1": [255, 248, 225, 255], "um_yellow_5": [253, 209, 58, 255], "um_yellow_9": [64, 58, 36, 255]}, "colors": {"main_background": "background_1", "detail_background": "background_2", "wide_lining": [245, 245, 245, 255], "thick_lining": [180, 180, 180, 255], "lining": [192, 193, 194, 255], "viewport_overlay": [246, 246, 246, 255], "primary": "accent_1", "primary_hover": [48, 182, 231, 255], "primary_text": [255, 255, 255, 255], "text_selection": [156, 195, 255, 127], "border": [127, 127, 127, 255], "border_field": [180, 180, 180, 255], "secondary": [240, 240, 240, 255], "expandable_active": [240, 240, 240, 255], "expandable_hover": [232, 242, 252, 255], "icon": [8, 7, 63, 255], "primary_button": "accent_1", "primary_button_hover": [16, 70, 156, 255], "primary_button_text": [255, 255, 255, 255], "secondary_button": "background_1", "secondary_button_shadow": [216, 216, 216, 255], "secondary_button_hover": [232, 240, 253, 255], "secondary_button_text": "accent_1", "main_window_header_background": [192, 199, 65, 255], "main_window_header_background_gradient": [25, 23, 91, 255], "main_window_header_button_text_active": [8, 7, 63, 255], "main_window_header_button_text_inactive": [255, 255, 255, 255], "main_window_header_button_text_hovered": [255, 255, 255, 255], "main_window_header_button_background_active": [255, 255, 255, 255], "main_window_header_button_background_inactive": [255, 255, 255, 0], "main_window_header_button_background_hovered": [117, 114, 159, 255], "account_widget_outline_active": [70, 66, 126, 255], "account_sync_state_icon": [25, 25, 25, 255], "machine_selector_printer_icon": [8, 7, 63, 255], "action_panel_secondary": "accent_1", "first_run_shadow": [50, 50, 50, 255], "toolbar_background": [255, 255, 255, 255], "notification_icon": [255, 0, 0, 255], "printer_type_label_background": [228, 228, 242, 255], "window_disabled_background": [0, 0, 0, 255], "text": [25, 25, 25, 255], "text_disabled": [180, 180, 180, 255], "text_detail": [174, 174, 174, 128], "text_link": "accent_1", "text_inactive": [174, 174, 174, 255], "text_medium": [128, 128, 128, 255], "text_scene": [102, 102, 102, 255], "text_scene_hover": [123, 123, 113, 255], "error": [218, 30, 40, 255], "warning": [253, 209, 58, 255], "success": [36, 162, 73, 255], "disabled": [229, 229, 229, 255], "toolbar_button_hover": [232, 242, 252, 255], "toolbar_button_active": [232, 242, 252, 255], "toolbar_button_active_hover": [232, 242, 252, 255], "button_text": [255, 255, 255, 255], "small_button_text": [102, 102, 102, 255], "small_button_text_hover": [8, 7, 63, 255], "button_tooltip": [31, 36, 39, 255], "extruder_disabled": [255, 255, 255, 102], "action_button": [255, 255, 255, 255], "action_button_hovered": [232, 242, 252, 255], "action_button_disabled": [245, 245, 245, 255], "action_button_disabled_text": [196, 196, 196, 255], "action_button_shadow": [223, 223, 223, 255], "scrollbar_background": [255, 255, 255, 255], "scrollbar_handle": [10, 8, 80, 255], "scrollbar_handle_hover": [50, 130, 255, 255], "scrollbar_handle_down": [50, 130, 255, 255], "setting_category": "background_1", "setting_category_disabled": [255, 255, 255, 255], "setting_category_hover": "background_2", "setting_category_text": "text_default", "setting_category_disabled_text": [24, 41, 77, 101], "setting_category_active_text": "text_default", "setting_control": "background_2", "setting_control_highlight": "background_3", "setting_control_border": [199, 199, 199, 255], "setting_control_border_highlight": [50, 130, 255, 255], "setting_control_text": [35, 35, 35, 255], "setting_control_button": [102, 102, 102, 255], "setting_control_button_hover": [8, 7, 63, 255], "setting_control_disabled": "background_2", "setting_control_disabled_text": [127, 127, 127, 255], "setting_control_disabled_border": [127, 127, 127, 255], "setting_unit": [127, 127, 127, 255], "setting_validation_error_background": "um_red_1", "setting_validation_error": "um_red_5", "setting_validation_warning_background": "um_yellow_1", "setting_validation_warning": "um_yellow_5", "setting_validation_ok": "background_2", "material_compatibility_warning": [243, 166, 59, 255], "core_compatibility_warning": [243, 166, 59, 255], "progressbar_background": [245, 245, 245, 255], "progressbar_control": [50, 130, 255, 255], "slider_groove": [223, 223, 223, 255], "slider_groove_fill": [8, 7, 63, 255], "slider_handle": [8, 7, 63, 255], "slider_handle_active": [50, 130, 255, 255], "slider_text_background": [255, 255, 255, 255], "quality_slider_unavailable": [179, 179, 179, 255], "quality_slider_available": [0, 0, 0, 255], "checkbox": "background_1", "checkbox_hover": "background_1", "checkbox_disabled": "background_2", "checkbox_border": [180, 180, 180, 255], "checkbox_border_hover": "border_main", "checkbox_border_disabled": "text_disabled", "checkbox_mark": "text_default", "checkbox_mark_disabled": "text_disabled", "checkbox_square": [180, 180, 180, 255], "checkbox_text": "text_default", "checkbox_text_disabled": "text_disabled", "switch": "background_1", "switch_state_checked": "accent_1", "switch_state_unchecked": "text_disabled", "radio": "background_1", "radio_disabled": "background_2", "radio_selected": "accent_1", "radio_selected_disabled": "text_disabled", "radio_border": [180, 180, 180, 255], "radio_border_hover": "border_main", "radio_border_disabled": "text_disabled", "radio_dot": "background_1", "radio_dot_disabled": "background_2", "radio_text": "text_default", "radio_text_disabled": "text_disabled", "text_field": "background_1", "text_field_border": [180, 180, 180, 255], "text_field_border_hovered": "border_main", "text_field_border_active": "border_accent_2", "text_field_border_disabled": "background_2", "text_field_text": "text_default", "text_field_text_disabled": "text_disabled", "category_background": "background_2", "tooltip": [25, 25, 25, 255], "tooltip_text": [255, 255, 255, 255], "message_background": [255, 255, 255, 255], "message_border": [192, 193, 194, 255], "message_close": [102, 102, 102, 255], "message_close_hover": [8, 7, 63, 255], "message_progressbar_background": [245, 245, 245, 255], "message_progressbar_control": [50, 130, 255, 255], "message_success_icon": [255, 255, 255, 255], "message_warning_icon": [0, 0, 0, 255], "message_error_icon": [255, 255, 255, 255], "tool_panel_background": [255, 255, 255, 255], "status_offline": [0, 0, 0, 255], "status_ready": [0, 205, 0, 255], "status_busy": [50, 130, 255, 255], "status_paused": [255, 140, 0, 255], "status_stopped": [236, 82, 80, 255], "disabled_axis": [127, 127, 127, 255], "x_axis": [218, 30, 40, 255], "y_axis": [25, 110, 240, 255], "z_axis": [36, 162, 73, 255], "all_axis": [255, 255, 255, 255], "viewport_background": [250, 250, 250, 255], "volume_outline": [50, 130, 255, 255], "buildplate": [244, 244, 244, 255], "buildplate_grid": [180, 180, 180, 255], "buildplate_grid_minor": [228, 228, 228, 255], "convex_hull": [35, 35, 35, 127], "disallowed_area": [0, 0, 0, 40], "error_area": [255, 0, 0, 127], "model_overhang": [255, 0, 0, 255], "model_unslicable": [122, 122, 122, 255], "model_unslicable_alt": [172, 172, 127, 255], "model_selection_outline": [50, 130, 255, 255], "model_non_printing": [122, 122, 122, 255], "xray": [26, 26, 62, 255], "layerview_ghost": [31, 31, 31, 95], "layerview_none": [255, 255, 255, 255], "layerview_inset_0": [230, 0, 0, 255], "layerview_inset_x": [0, 230, 0, 255], "layerview_skin": [230, 230, 0, 255], "layerview_support": [0, 230, 230, 127], "layerview_skirt": [0, 230, 230, 255], "layerview_infill": [230, 115, 0, 255], "layerview_support_infill": [0, 230, 230, 127], "layerview_move_combing": [0, 0, 255, 255], "layerview_move_retraction": [128, 127, 255, 255], "layerview_move_while_retracting": [127, 255, 255, 255], "layerview_move_while_unretracting": [255, 127, 255, 255], "layerview_support_interface": [63, 127, 255, 127], "layerview_prime_tower": [0, 255, 255, 255], "layerview_nozzle": [224, 192, 16, 64], "layerview_starts": [255, 255, 255, 255], "monitor_printer_family_tag": [228, 228, 242, 255], "monitor_text_disabled": [238, 238, 238, 255], "monitor_icon_primary": [10, 8, 80, 255], "monitor_icon_accent": [255, 255, 255, 255], "monitor_icon_disabled": [238, 238, 238, 255], "monitor_card_border": [192, 193, 194, 255], "monitor_card_background": [255, 255, 255, 255], "monitor_card_hover": [232, 242, 252, 255], "monitor_stage_background": [246, 246, 246, 255], "monitor_stage_background_fade": [246, 246, 246, 102], "monitor_tooltip": [25, 25, 25, 255], "monitor_tooltip_text": [255, 255, 255, 255], "monitor_context_menu": [255, 255, 255, 255], "monitor_context_menu_hover": [245, 245, 245, 255], "monitor_skeleton_loading": [238, 238, 238, 255], "monitor_placeholder_image": [230, 230, 230, 255], "monitor_image_overlay": [0, 0, 0, 255], "monitor_shadow": [200, 200, 200, 255], "monitor_carousel_dot": [216, 216, 216, 255], "monitor_carousel_dot_current": [119, 119, 119, 255], "cloud_unavailable": [153, 153, 153, 255], "connection_badge_background": [255, 255, 255, 255], "warning_badge_background": [0, 0, 0, 255], "error_badge_background": [255, 255, 255, 255], "border_field_light": [180, 180, 180, 255], "border_main_light": [212, 212, 212, 255]}, "sizes": {"window_minimum_size": [80, 48], "popup_dialog": [40, 36], "small_popup_dialog": [36, 12], "main_window_header": [0.0, 4.0], "stage_menu": [0.0, 4.0], "account_button": [12, 2.5], "print_setup_widget": [38.0, 30.0], "print_setup_extruder_box": [0.0, 6.0], "slider_widget_groove": [0.16, 0.16], "slider_widget_handle": [1.3, 1.3], "slider_widget_tickmarks": [0.5, 0.5], "print_setup_big_item": [28, 2.5], "print_setup_icon": [1.2, 1.2], "drag_icon": [1.416, 0.25], "application_switcher_item": [8, 9], "application_switcher_icon": [3.75, 3.75], "expandable_component_content_header": [0.0, 3.0], "configuration_selector": [35.0, 4.0], "action_panel_widget": [26.0, 0.0], "action_panel_information_widget": [20.0, 0.0], "machine_selector_widget": [20.0, 4.0], "machine_selector_widget_content": [25.0, 32.0], "machine_selector_icon": [2.5, 2.5], "views_selector": [16.0, 4.0], "printer_type_label": [3.5, 1.5], "default_radius": [0.25, 0.25], "wide_lining": [0.5, 0.5], "thick_lining": [0.2, 0.2], "default_lining": [0.08, 0.08], "default_arrow": [0.8, 0.8], "logo": [16, 2], "wide_margin": [2.0, 2.0], "thick_margin": [1.71, 1.43], "default_margin": [1.0, 1.0], "thin_margin": [0.71, 0.71], "narrow_margin": [0.5, 0.5], "extruder_icon": [2.5, 2.5], "section": [0.0, 2], "section_header": [0.0, 2.5], "section_control": [0, 1], "section_icon": [1.5, 1.5], "section_icon_column": [2.5, 2.5], "setting": [25.0, 1.8], "setting_control": [9.0, 2.0], "setting_control_radius": [0.15, 0.15], "setting_control_depth_margin": [1.4, 0.0], "setting_unit_margin": [0.5, 0.5], "standard_list_lineheight": [1.5, 1.5], "standard_arrow": [1.0, 1.0], "card": [25.0, 10], "card_icon": [6.0, 6.0], "card_tiny_icon": [1.5, 1.5], "button": [4, 4], "button_icon": [2.5, 2.5], "action_button": [15.0, 2.5], "action_button_icon": [1.5, 1.5], "action_button_icon_small": [1.0, 1.0], "action_button_radius": [0.15, 0.15], "radio_button": [1.3, 1.3], "small_button": [2, 2], "small_button_icon": [1.5, 1.5], "medium_button": [2.5, 2.5], "medium_button_icon": [2, 2], "large_button": [3.0, 3.0], "large_button_icon": [2.8, 2.8], "context_menu": [20, 2], "icon_indicator": [1, 1], "printer_status_icon": [1.0, 1.0], "button_tooltip": [1.0, 1.3], "button_tooltip_arrow": [0.25, 0.25], "progressbar": [26.0, 0.75], "progressbar_radius": [0.15, 0.15], "scrollbar": [0.75, 0.5], "slider_groove": [0.5, 0.5], "slider_groove_radius": [0.15, 0.15], "slider_handle": [1.5, 1.5], "slider_layerview_size": [1.0, 34.0], "layerview_menu_size": [16.0, 4.0], "layerview_legend_size": [1.0, 1.0], "layerview_row": [11.0, 1.5], "layerview_row_spacing": [0.0, 0.5], "checkbox": [1.33, 1.33], "checkbox_mark": [1, 1], "checkbox_radius": [0.25, 0.25], "spinbox": [6.0, 3.0], "combobox": [14, 2], "combobox_wide": [22, 2], "tooltip": [20.0, 10.0], "tooltip_margins": [1.0, 1.0], "tooltip_arrow_margins": [2.0, 2.0], "save_button_save_to_button": [0.3, 2.7], "save_button_specs_icons": [1.4, 1.4], "first_run_shadow_radius": [1.2, 1.2], "monitor_preheat_temperature_control": [4.5, 2.0], "welcome_wizard_window": [46, 50], "modal_window_minimum": [60.0, 50.0], "wizard_progress": [10.0, 0.0], "message": [30.0, 5.0], "message_close": [2, 2], "message_radius": [0.25, 0.25], "message_action_button": [0, 2.5], "message_image": [15.0, 10.0], "message_type_icon": [2, 2], "menu": [18, 2], "jobspecs_line": [2.0, 2.0], "objects_menu_size": [15, 15], "notification_icon": [1.5, 1.5], "avatar_image": [6.8, 6.8], "monitor_shadow_radius": [0.4, 0.4], "monitor_empty_state_offset": [5.6, 5.6], "monitor_empty_state_size": [35.0, 25.0], "monitor_column": [18.0, 1.0], "monitor_progress_bar": [16.5, 1.0], "table_row": [2.0, 2.0], "welcome_wizard_content_image_big": [18, 15], "welcome_wizard_cloud_content_image": [4, 4], "banner_icon_size": [2.0, 2.0], "marketplace_large_icon": [4.0, 4.0], "preferences_page_list_item": [8.0, 2.0], "recommended_button_icon": [1.7, 1.7], "recommended_section_setting_item": [14.0, 2.0], "reset_profile_icon": [1, 1]}} \ No newline at end of file diff --git a/resources/themes/daily_test_colors.json b/resources/themes/daily_test_colors.json deleted file mode 100644 index 1cfa2baa74..0000000000 --- a/resources/themes/daily_test_colors.json +++ /dev/null @@ -1,16 +0,0 @@ -[ - [ 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] -]