SupportEraser.py 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. # Copyright (c) 2018 Ultimaker B.V.
  2. # Cura is released under the terms of the LGPLv3 or higher.
  3. from UM.Math.Vector import Vector
  4. from UM.Tool import Tool
  5. from PyQt5.QtCore import Qt, QUrl
  6. from UM.Application import Application
  7. from UM.Event import Event, MouseEvent
  8. from UM.Mesh.MeshBuilder import MeshBuilder
  9. from UM.Operations.AddSceneNodeOperation import AddSceneNodeOperation
  10. from UM.Operations.RemoveSceneNodeOperation import RemoveSceneNodeOperation
  11. from UM.Settings.SettingInstance import SettingInstance
  12. from cura.Scene.CuraSceneNode import CuraSceneNode
  13. from cura.Scene.SliceableObjectDecorator import SliceableObjectDecorator
  14. from cura.Scene.BuildPlateDecorator import BuildPlateDecorator
  15. from UM.Scene.Iterator.BreadthFirstIterator import BreadthFirstIterator
  16. from cura.Settings.SettingOverrideDecorator import SettingOverrideDecorator
  17. from cura.PickingPass import PickingPass
  18. import os
  19. import os.path
  20. class SupportEraser(Tool):
  21. def __init__(self):
  22. super().__init__()
  23. self._shortcut_key = Qt.Key_G
  24. self._controller = Application.getInstance().getController()
  25. self._selection_pass = None
  26. Application.getInstance().globalContainerStackChanged.connect(self._updateEnabled)
  27. def event(self, event):
  28. super().event(event)
  29. if event.type == Event.MousePressEvent and self._controller.getToolsEnabled():
  30. if self._selection_pass is None:
  31. # The selection renderpass is used to identify objects in the current view
  32. self._selection_pass = Application.getInstance().getRenderer().getRenderPass("selection")
  33. picked_node = self._controller.getScene().findObject(self._selection_pass.getIdAtPosition(event.x, event.y))
  34. node_stack = picked_node.callDecoration("getStack")
  35. if node_stack:
  36. if node_stack.getProperty("anti_overhang_mesh", "value"):
  37. self._removeEraserMesh(picked_node)
  38. return
  39. elif node_stack.getProperty("support_mesh", "value") or node_stack.getProperty("infill_mesh", "value") or node_stack.getProperty("cutting_mesh", "value"):
  40. return
  41. # Create a pass for picking a world-space location from the mouse location
  42. active_camera = self._controller.getScene().getActiveCamera()
  43. picking_pass = PickingPass(active_camera.getViewportWidth(), active_camera.getViewportHeight())
  44. picking_pass.render()
  45. picked_position = picking_pass.getPickedPosition(event.x, event.y)
  46. # Add the anti_overhang_mesh cube at the picked location
  47. self._createEraserMesh(picked_node, picked_position)
  48. def _createEraserMesh(self, parent: CuraSceneNode, position: Vector):
  49. node = CuraSceneNode()
  50. node.setName("Eraser")
  51. node.setSelectable(True)
  52. mesh = MeshBuilder()
  53. mesh.addCube(10,10,10)
  54. node.setMeshData(mesh.build())
  55. node.setPosition(position)
  56. active_build_plate = Application.getInstance().getMultiBuildPlateModel().activeBuildPlate
  57. node.addDecorator(SettingOverrideDecorator())
  58. node.addDecorator(BuildPlateDecorator(active_build_plate))
  59. node.addDecorator(SliceableObjectDecorator())
  60. stack = node.callDecoration("getStack") #Don't try to get the active extruder since it may be None anyway.
  61. if not stack:
  62. node.addDecorator(SettingOverrideDecorator())
  63. stack = node.callDecoration("getStack")
  64. settings = stack.getTop()
  65. if not (settings.getInstance("anti_overhang_mesh") and settings.getProperty("anti_overhang_mesh", "value")):
  66. definition = stack.getSettingDefinition("anti_overhang_mesh")
  67. new_instance = SettingInstance(definition, settings)
  68. new_instance.setProperty("value", True)
  69. new_instance.resetState() # Ensure that the state is not seen as a user state.
  70. settings.addInstance(new_instance)
  71. scene = self._controller.getScene()
  72. op = AddSceneNodeOperation(node, scene.getRoot())
  73. op.push()
  74. Application.getInstance().getController().getScene().sceneChanged.emit(node)
  75. def _removeEraserMesh(self, node: CuraSceneNode):
  76. op = RemoveSceneNodeOperation(node)
  77. op.push()
  78. Application.getInstance().getController().getScene().sceneChanged.emit(node)
  79. def _updateEnabled(self):
  80. plugin_enabled = False
  81. global_container_stack = Application.getInstance().getGlobalContainerStack()
  82. if global_container_stack:
  83. plugin_enabled = global_container_stack.getProperty("anti_overhang_mesh", "enabled")
  84. Application.getInstance().getController().toolEnabledChanged.emit(self._plugin_id, plugin_enabled)