def test_getSelectedObject(self): node_1 = SceneNode() node_2 = SceneNode() Selection.add(node_1) Selection.add(node_2) assert Selection.getSelectedObject(0) == node_1 assert Selection.getSelectedObject(1) == node_2 assert Selection.getSelectedObject(3) is None
def setZ(self, z): obj = Selection.getSelectedObject(0) if obj: new_position = obj.getWorldPosition() selected_node = Selection.getSelectedObject(0) center = selected_node.getBoundingBox().center bottom = selected_node.getBoundingBox().bottom # Note; The switching of z & y is intentional. We display z as up for the user, # But store the data in openGL space. new_position.setY(float(z) + (center.y - bottom)) Selection.applyOperation(TranslateOperation, new_position, set_position=True) self.operationStopped.emit(self)
def getObjectDepth(self): if Selection.hasSelection(): return round( float(Selection.getSelectedObject(0).getBoundingBox().depth), 1) return 0.0
def getObjectHeight(self): if Selection.hasSelection(): return round( float(Selection.getSelectedObject(0).getBoundingBox().height), 1) return 0.0
def run(self): status_message = Message(i18n_catalog.i18nc( "@info:status", "Multiplying and placing objects"), lifetime=0, dismissable=False, progress=0) status_message.show() scene = Application.getInstance().getController().getScene() node = scene.findObject(self._object_id) if not node and self._object_id != 0: # Workaround for tool handles overlapping the selected object node = Selection.getSelectedObject(0) # If object is part of a group, multiply group current_node = node while current_node.getParent() and current_node.getParent( ).callDecoration("isGroup"): current_node = current_node.getParent() root = scene.getRoot() arranger = Arrange.create(scene_root=root) node_too_big = False if node.getBoundingBox().width < 300 or node.getBoundingBox( ).depth < 300: offset_shape_arr, hull_shape_arr = ShapeArray.fromNode( current_node, min_offset=self._min_offset) else: node_too_big = True nodes = [] found_solution_for_all = True for i in range(self._count): # We do place the nodes one by one, as we want to yield in between. if not node_too_big: node, solution_found = arranger.findNodePlacement( current_node, offset_shape_arr, hull_shape_arr) if node_too_big or not solution_found: found_solution_for_all = False new_location = node.getPosition() new_location = new_location.set(z=100 - i * 20) node.setPosition(new_location) nodes.append(node) Job.yieldThread() status_message.setProgress((i + 1) / self._count * 100) if nodes: op = GroupedOperation() for new_node in nodes: op.addOperation( AddSceneNodeOperation(new_node, current_node.getParent())) op.push() status_message.hide() if not found_solution_for_all: no_full_solution_message = Message( i18n_catalog.i18nc( "@info:status", "Unable to find a location within the build volume for all objects" )) no_full_solution_message.show()
def multiplyObject(self, object_id, count): node = self.getController().getScene().findObject(object_id) if not node and object_id != 0: #Workaround for tool handles overlapping the selected object node = Selection.getSelectedObject(0) if node: op = GroupedOperation() for i in range(count): if node.getParent() and node.getParent().callDecoration( "isGroup"): new_node = copy.deepcopy( node.getParent()) #Copy the group node. new_node.callDecoration("setConvexHull", None) op.addOperation( AddSceneNodeOperation(new_node, node.getParent().getParent())) else: new_node = copy.deepcopy(node) new_node.callDecoration("setConvexHull", None) op.addOperation( AddSceneNodeOperation(new_node, node.getParent())) op.push()
def getScaleZ(self): if Selection.hasSelection(): ## Ensure that the returned value is positive (mirror causes scale to be negative) return abs( round(float(Selection.getSelectedObject(0).getScale().z), 4)) return 1.0
def setMeshType(self, mesh_type): selected_object = Selection.getSelectedObject(0) stack = selected_object.callDecoration( "getStack" ) #Don't try to get the active extruder since it may be None anyway. if not stack: selected_object.addDecorator(SettingOverrideDecorator()) stack = selected_object.callDecoration("getStack") settings = stack.getTop() for property_key in [ "infill_mesh", "cutting_mesh", "support_mesh", "anti_overhang_mesh" ]: if property_key != mesh_type: if settings.getInstance(property_key): settings.removeInstance(property_key) else: if not (settings.getInstance(property_key) and settings.getProperty(property_key, "value")): definition = stack.getSettingDefinition(property_key) new_instance = SettingInstance(definition, settings) new_instance.setProperty("value", True) new_instance.resetState( ) # Ensure that the state is not seen as a user state. settings.addInstance(new_instance)
def getContainerID(self): selected_object = Selection.getSelectedObject(0) if selected_object.getParent().callDecoration("isGroup"): selected_object = selected_object.getParent() try: return selected_object.callDecoration("getStack").getId() except AttributeError: return ""
def getSelectedActiveExtruder(self): """Gets the active extruder of the currently selected object. :return: The active extruder of the currently selected object. """ selected_object = Selection.getSelectedObject(0) return selected_object.callDecoration("getActiveExtruder")
def getContainerID(self): selected_object = Selection.getSelectedObject(0) if selected_object.getParent().callDecoration("isGroup"): selected_object = selected_object.getParent() try: return selected_object.callDecoration("getStack").getId() except AttributeError: return ""
def setSelectedActiveExtruder(self, extruder_stack_id): selected_object = Selection.getSelectedObject(0) stack = selected_object.callDecoration( "getStack" ) #Don't try to get the active extruder since it may be None anyway. if not stack: selected_object.addDecorator(SettingOverrideDecorator()) selected_object.callDecoration("setActiveExtruder", extruder_stack_id)
def _onToolOperationStopped(self, event): if self._center_after_select: self._center_after_select = False self._camera_animation.setStart( self.getController().getTool("CameraTool").getOrigin()) self._camera_animation.setTarget( Selection.getSelectedObject(0).getWorldPosition()) self._camera_animation.start()
def event(self, event): super().event(event) if event.type == Event.MousePressEvent and self._controller.getToolsEnabled(): # Initialise a mirror operation if MouseEvent.LeftButton not in event.buttons: return False id = self._selection_pass.getIdAtPosition(event.x, event.y) if not id: return False if ToolHandle.isAxis(id): self.setLockedAxis(id) self._operation_started = True self.operationStarted.emit(self) return True if event.type == Event.MouseReleaseEvent: if self._operation_started: self._operation_started = False self.operationStopped.emit(self) # Perform a mirror operation if self.getLockedAxis(): op = None if Selection.getCount() == 1: node = Selection.getSelectedObject(0) if self.getLockedAxis() == ToolHandle.XAxis: mirror = Vector(-1, 1, 1) elif self.getLockedAxis() == ToolHandle.YAxis: mirror = Vector(1, -1, 1) elif self.getLockedAxis() == ToolHandle.ZAxis: mirror = Vector(1, 1, -1) else: mirror = Vector(1, 1, 1) op = MirrorOperation(node, mirror, mirror_around_center = True) else: op = GroupedOperation() for node in Selection.getAllSelectedObjects(): if self.getLockedAxis() == ToolHandle.XAxis: mirror = Vector(-1, 1, 1) elif self.getLockedAxis() == ToolHandle.YAxis: mirror = Vector(1, -1, 1) elif self.getLockedAxis() == ToolHandle.ZAxis: mirror = Vector(1, 1, -1) else: mirror = Vector(1, 1, 1) op.addOperation(MirrorOperation(node, mirror, mirror_around_center = True)) op.push() self.setLockedAxis(None) return True return False
def centerObject(self, object_id): node = self.getController().getScene().findObject(object_id) if not node and object_id != 0: #Workaround for tool handles overlapping the selected object node = Selection.getSelectedObject(0) if node: op = SetTransformOperation(node, Vector()) op.push()
def deleteObject(self, object_id): object = self.getController().getScene().findObject(object_id) if not object and object_id != 0: #Workaround for tool handles overlapping the selected object object = Selection.getSelectedObject(0) if object: op = RemoveSceneNodeOperation(object) op.push()
def getSelectedObjectId(self): try: selected_object = Selection.getSelectedObject(0) if selected_object.getParent().callDecoration("isGroup"): selected_object = selected_object.getParent() except: selected_object = None selected_object_id = id(selected_object) return selected_object_id
def _pixelHover(self, event): if Selection.getFaceSelectMode(): face_id = self._selection_pass.getFaceIdAtPosition(event.x, event.y) if face_id >= 0: Selection.hoverFace(Selection.getSelectedObject(0), face_id) else: Selection.clearFace() return True return False
def requestWriteSelectionToDevice(self, device_id, file_name, kwargs): if not Selection.hasSelection(): return filter_by_machine = kwargs.get("filter_by_machine", False) # On Windows, calling requestWrite() on LocalFileOutputDevice crashes when called from a signal # handler attached to a QML MenuItem. So instead, defer the call to the next run of the event # loop, since that does work. Application.getInstance().callLater(self._writeToDevice, Selection.getSelectedObject(0), device_id, file_name, filter_by_machine)
def getSelectedObjectId(self): try: selected_object = Selection.getSelectedObject(0) if selected_object.getParent().callDecoration("isGroup"): selected_object = selected_object.getParent() except: selected_object = None selected_object_id = id(selected_object) return selected_object_id
def centerObject(self, object_id): node = self.getController().getScene().findObject(object_id) if not node and object_id != 0: #Workaround for tool handles overlapping the selected object node = Selection.getSelectedObject(0) if node: op = SetTransformOperation(node, Vector()) op.push()
def requestWriteSelectionToDevice(self, device_id, file_name): if not Selection.hasSelection(): return # On Windows, calling requestWrite() on LocalFileOutputDevice crashes when called from a signal # handler attached to a QML MenuItem. So instead, defer the call to the next run of the event # loop, since that does work. event = CallFunctionEvent(self._writeToDevice, [Selection.getSelectedObject(0), device_id, file_name], {}) Application.getInstance().functionEvent(event)
def setX(self, x): obj = Selection.getSelectedObject(0) if obj: new_position = obj.getWorldPosition() new_position.setX(x) Selection.applyOperation(TranslateOperation, new_position, set_position=True) self.operationStopped.emit(self)
def event(self, event): super().event(event) if event.type == Event.MousePressEvent and self._controller.getToolsEnabled(): # Initialise a mirror operation if MouseEvent.LeftButton not in event.buttons: return False id = self._selection_pass.getIdAtPosition(event.x, event.y) if not id: return False if self._handle.isAxis(id): self.setLockedAxis(id) self._operation_started = True self.operationStarted.emit(self) return True if event.type == Event.MouseReleaseEvent: if self._operation_started: self._operation_started = False self.operationStopped.emit(self) # Perform a mirror operation if self.getLockedAxis() != ToolHandle.NoAxis: if Selection.getCount() == 1: node = Selection.getSelectedObject(0) if self.getLockedAxis() == ToolHandle.XAxis: mirror = Vector(-1, 1, 1) elif self.getLockedAxis() == ToolHandle.YAxis: mirror = Vector(1, -1, 1) elif self.getLockedAxis() == ToolHandle.ZAxis: mirror = Vector(1, 1, -1) else: mirror = Vector(1, 1, 1) op = MirrorOperation(node, mirror, mirror_around_center = True) else: op = GroupedOperation() for node in self._getSelectedObjectsWithoutSelectedAncestors(): if self.getLockedAxis() == ToolHandle.XAxis: mirror = Vector(-1, 1, 1) elif self.getLockedAxis() == ToolHandle.YAxis: mirror = Vector(1, -1, 1) elif self.getLockedAxis() == ToolHandle.ZAxis: mirror = Vector(1, 1, -1) else: mirror = Vector(1, 1, 1) op.addOperation(MirrorOperation(node, mirror, mirror_around_center = True)) op.push() self.setLockedAxis(ToolHandle.NoAxis) return True return False
def setMeshType(self, mesh_type: str) -> bool: old_mesh_type = self.getMeshType() if old_mesh_type == mesh_type: return False selected_object = Selection.getSelectedObject(0) if selected_object is None: Logger.log( "w", "Tried setting the mesh type of the selected object, but no object was selected" ) return False stack = selected_object.callDecoration( "getStack" ) #Don't try to get the active extruder since it may be None anyway. if not stack: selected_object.addDecorator(SettingOverrideDecorator()) stack = selected_object.callDecoration("getStack") settings = stack.getTop() for property_key in [ "infill_mesh", "cutting_mesh", "support_mesh", "anti_overhang_mesh" ]: if property_key != mesh_type: if settings.getInstance(property_key): settings.removeInstance(property_key) else: if not (settings.getInstance(property_key) and settings.getProperty(property_key, "value")): definition = stack.getSettingDefinition(property_key) new_instance = SettingInstance(definition, settings) new_instance.setProperty("value", True) new_instance.resetState( ) # Ensure that the state is not seen as a user state. settings.addInstance(new_instance) for property_key in ["top_bottom_thickness", "wall_thickness"]: if mesh_type == "infill_mesh": if settings.getInstance(property_key) is None: definition = stack.getSettingDefinition(property_key) new_instance = SettingInstance(definition, settings) new_instance.setProperty("value", 0) new_instance.resetState( ) # Ensure that the state is not seen as a user state. settings.addInstance(new_instance) visible = self.visibility_handler.getVisible() visible.add(property_key) self.visibility_handler.setVisible(visible) elif old_mesh_type == "infill_mesh" and settings.getInstance( property_key) and settings.getProperty( property_key, "value") == 0: settings.removeInstance(property_key) self.propertyChanged.emit() return True
def getScaleY(self): if Selection.hasSelection(): ## Ensure that the returned value is positive (mirror causes scale to be negative) return abs( round( float( self._getScaleInWorldCoordinates( Selection.getSelectedObject(0)).y), 4)) return 1.0
def getObjectWidth(self): """Get the width of the bounding box of the selected object(s) :return: width type(float) Width in mm """ if Selection.hasSelection(): return float(Selection.getSelectedObject(0).getBoundingBox().width) return 0.0
def getSelectedIndex(self): try: selected_object = Selection.getSelectedObject(0) if selected_object.getParent().callDecoration("isGroup"): selected_object = selected_object.getParent() except: selected_object = None selected_object_id = id(selected_object) index = self.getModel().find("id", selected_object_id) return index
def getObjectHeight(self): """Get the height of the bounding box of the selected object(s) :return: height type(float) height in mm """ if Selection.hasSelection(): return float(Selection.getSelectedObject(0).getBoundingBox().height) return 0.0
def getObjectDepth(self): """Get the depth of the bounding box of the first selected object :return: depth type(float) depth in mm """ if Selection.hasSelection(): return float(Selection.getSelectedObject(0).getBoundingBox().depth) return 0.0
def getScaleZ(self): if Selection.hasSelection(): ## Ensure that the returned value is positive (mirror causes scale to be negative) obj = Selection.getSelectedObject(0) return abs( round( float(self.getObjectDepth() / obj.getMeshData().getExtents().depth), 4)) return 1.0
def unsubscribeForSettingValidation(self, setting_name): selected_object = Selection.getSelectedObject(0) stack = selected_object.callDecoration("getStack") # Don't try to get the active extruder since it may be None anyway. if not stack: return "" settings = stack.getTop() setting_instance = settings.getInstance(setting_name) if setting_instance: setting_instance.propertyChanged.disconnect(self._onPropertyChanged)
def getSelectedIndex(self): try: selected_object = Selection.getSelectedObject(0) if selected_object.getParent().callDecoration("isGroup"): selected_object = selected_object.getParent() except: selected_object = None selected_object_id = id(selected_object) index = self.getModel().find("id", selected_object_id) return index
def subdivide(self): if Selection.getCount() != 2: Logger.log( "w", i18n_catalog.i18n( "Cannot subdivide: number of selected objects is not equal 2. Plane and object need to be selected. Current selected objects: %i" ) % Selection.getCount()) return object1 = Selection.getSelectedObject(0) object2 = Selection.getSelectedObject(1) if type(object1) is SceneNode and type(object2) is Plane: obj = object1 plane = object2 elif type(object2) is SceneNode and type(object1) is Plane: obj = object2 plane = object1 else: Logger.log( "w", i18n_catalog.i18n( "Cannot subdivide: object and plane need to be selected. Current selection: %s and %s" ) % (str(object1), str(object2))) return result = self._subdivide(obj, plane) if type(result) is tuple: operation = GroupedOperation() operation.addOperation(RemoveSceneNodeOperation(plane)) operation.addOperation(RemoveSceneNodeOperation(obj)) operation.addOperation( AddSceneNodeOperation(result[0], obj.getParent())) operation.addOperation( TranslateOperation(result[0], obj.getPosition())) if len(result) == 2: operation.addOperation( AddSceneNodeOperation(result[1], obj.getParent())) operation.addOperation( TranslateOperation(result[1], obj.getPosition())) operation.push() else: Logger.log("w", i18n_catalog.i18n("Cannot subdivide: Internal error"))
def getScaleZ(self): """Get the z-axis scale of the of the first selected object :return: scale type(float) scale factor (1.0 = normal scale) """ if Selection.hasSelection(): ## Ensure that the returned value is positive (mirror causes scale to be negative) return abs(round(float(self._getScaleInWorldCoordinates(Selection.getSelectedObject(0)).z), 4)) return 1.0
def setScaleX(self, scale): obj = Selection.getSelectedObject(0) if obj: obj_scale = self._getScaleInWorldCoordinates(obj) if round(float(obj_scale.x), 4) != scale: scale_factor = abs(scale / obj_scale.x) if self._non_uniform_scale: scale_vector = Vector(scale_factor, 1, 1) else: scale_vector = Vector(scale_factor, scale_factor, scale_factor) Selection.applyOperation(ScaleOperation, scale_vector, scale_around_point = obj.getWorldPosition())
def setScaleZ(self, scale): obj = Selection.getSelectedObject(0) if obj: obj_scale = self._getScaleInWorldCoordinates(obj) if round(float(obj_scale.z), 4) != scale: scale_factor = abs(scale / obj_scale.z) if self._non_uniform_scale: scale_vector = Vector(1, 1, scale_factor) else: scale_vector = Vector(scale_factor, scale_factor, scale_factor) Selection.applyOperation(ScaleOperation, scale_vector)
def setScaleX(self, scale): obj = Selection.getSelectedObject(0) if obj: obj_scale = self._getScaleInWorldCoordinates(obj) if round(float(obj_scale.x), 4) != scale: scale_factor = abs(scale / obj_scale.x) if self._non_uniform_scale: scale_vector = Vector(scale_factor, 1, 1) else: scale_vector = Vector(scale_factor, scale_factor, scale_factor) Selection.applyOperation(ScaleOperation, scale_vector)
def onSelectionChanged(self): if Selection.hasSelection(): if not self.getController().getActiveTool(): self.getController().setActiveTool("TranslateTool") self._camera_animation.setStart(self.getController().getTool("CameraTool").getOrigin()) self._camera_animation.setTarget(Selection.getSelectedObject(0).getWorldPosition()) self._camera_animation.start() else: if self.getController().getActiveTool(): self.getController().setActiveTool(None)
def setScaleZ(self, scale): obj = Selection.getSelectedObject(0) if obj: obj_scale = self._getScaleInWorldCoordinates(obj) if round(float(obj_scale.z), 4) != scale: scale_factor = abs(scale / obj_scale.z) if self._non_uniform_scale: scale_vector = Vector(1, 1, scale_factor) else: scale_vector = Vector(scale_factor, scale_factor, scale_factor) Selection.applyOperation(ScaleOperation, scale_vector, scale_around_point = obj.getWorldPosition())
def setScaleZ(self, scale): obj = Selection.getSelectedObject(0) if obj: obj_scale = obj.getScale() if obj_scale.z != scale: obj_scale.setZ(scale) if not self._non_uniform_scale: obj_scale.setY(scale) obj_scale.setX(scale) operation = SetTransformOperation(obj, None, None, obj_scale) operation.push()
def setScaleZ(self, scale): obj = Selection.getSelectedObject(0) if obj: obj_scale = obj.getScale() if round(float(obj_scale.z), 4) != scale: scale_factor = abs(scale / obj_scale.z) if self._non_uniform_scale: scale_vector = Vector(1, 1, scale_factor) else: scale_vector = Vector(scale_factor, scale_factor, scale_factor) self._scaleSelectedNodes(scale_vector)
def getMeshType(self): selected_object = Selection.getSelectedObject(0) stack = selected_object.callDecoration("getStack") #Don't try to get the active extruder since it may be None anyway. if not stack: return "" settings = stack.getTop() for property_key in ["infill_mesh", "cutting_mesh", "support_mesh", "anti_overhang_mesh"]: if settings.getInstance(property_key) and settings.getProperty(property_key, "value"): return property_key return ""
def setObjectWidth(self, width): obj = Selection.getSelectedObject(0) if obj: width = float(width) obj_width = obj.getBoundingBox().width if not Float.fuzzyCompare(obj_width, width, DIMENSION_TOLERANCE): scale_factor = width / obj_width if self._non_uniform_scale: scale_vector = Vector(scale_factor, 1, 1) else: scale_vector = Vector(scale_factor, scale_factor, scale_factor) Selection.applyOperation(ScaleOperation, scale_vector, scale_around_point = obj.getWorldPosition())
def setObjectDepth(self, depth): obj = Selection.getSelectedObject(0) if obj: depth = float(depth) obj_depth = obj.getBoundingBox().depth if not Float.fuzzyCompare(obj_depth, depth, DIMENSION_TOLERANCE): scale_factor = depth / obj_depth if self._non_uniform_scale: scale_vector = Vector(1, 1, scale_factor) else: scale_vector = Vector(scale_factor, scale_factor, scale_factor) Selection.applyOperation(ScaleOperation, scale_vector)
def setObjectHeight(self, height): obj = Selection.getSelectedObject(0) if obj: height = float(height) obj_height = obj.getBoundingBox().height if not Float.fuzzyCompare(obj_height, height, DIMENSION_TOLERANCE): scale_factor = height / obj_height if self._non_uniform_scale: scale_vector = Vector(1, scale_factor, 1) else: scale_vector = Vector(scale_factor, scale_factor, scale_factor) Selection.applyOperation(ScaleOperation, scale_vector)
def getContainerID(self): try: selected_object = Selection.getSelectedObject(0) if selected_object.getParent().callDecoration("isGroup"): selected_object = selected_object.getParent() try: return selected_object.callDecoration("getStack").getId() except: print(":(") return except: print(":((") return
def setObjectWidth(self, width): obj = Selection.getSelectedObject(0) if obj: width = float(width) obj_width = obj.getBoundingBox().width if not Float.fuzzyCompare(obj_width, width, DIMENSION_TOLERANCE): scale_factor = width / obj_width if self._non_uniform_scale: scale_vector = Vector(scale_factor, 1, 1) else: scale_vector = Vector(scale_factor, scale_factor, scale_factor) self._scaleSelectedNodes(scale_vector)
def setObjectHeight(self, height): obj = Selection.getSelectedObject(0) if obj: obj_scale = obj.getScale() obj_height = obj.getBoundingBox().height / obj_scale.y target_scale = float(height) / obj_height if obj_scale.y != target_scale: obj_scale.setY(target_scale) if not self._non_uniform_scale: obj_scale.setX(target_scale) obj_scale.setZ(target_scale) operation = SetTransformOperation(obj, None, None, obj_scale) operation.push()
def setObjectDepth(self, depth): obj = Selection.getSelectedObject(0) if obj: obj_scale = obj.getScale() obj_depth = obj.getBoundingBox().depth / obj_scale.z target_scale = float(depth) / obj_depth if obj_scale.z != target_scale: obj_scale.setZ(target_scale) if not self._non_uniform_scale: obj_scale.setY(target_scale) obj_scale.setX(target_scale) operation = SetTransformOperation(obj, None, None, obj_scale) operation.push()
def event(self, event): super().event(event) if event.type == Event.MousePressEvent: if MouseEvent.LeftButton not in event.buttons: return False id = self._selection_pass.getIdAtPosition(event.x, event.y) if not id: return False if ToolHandle.isAxis(id): self.setLockedAxis(id) return True if event.type == Event.MouseReleaseEvent: if self.getLockedAxis(): op = None if Selection.getCount() == 1: node = Selection.getSelectedObject(0) mirror = node.getMirror() if self.getLockedAxis() == ToolHandle.XAxis: mirror.setX(-mirror.x) elif self.getLockedAxis() == ToolHandle.YAxis: mirror.setY(-mirror.y) elif self.getLockedAxis() == ToolHandle.ZAxis: mirror.setZ(-mirror.z) op = MirrorOperation(node, mirror, set_mirror=True) else: op = GroupedOperation() for node in Selection.getAllSelectedObjects(): mirror = node.getMirror() if self.getLockedAxis() == ToolHandle.XAxis: mirror.setX(-mirror.x) elif self.getLockedAxis() == ToolHandle.YAxis: mirror.setY(-mirror.y) elif self.getLockedAxis() == ToolHandle.ZAxis: mirror.setZ(-mirror.z) op.addOperation(MirrorOperation(node, mirror, set_mirror = True)) op.push() self.setLockedAxis(None) return True return False
def event(self, event): super().event(event) if event.type == Event.MousePressEvent: if MouseEvent.LeftButton not in event.buttons: return False id = self._renderer.getIdAtCoordinate(event.x, event.y) if not id: return False if ToolHandle.isAxis(id): self.setLockedAxis(id) return True if event.type == Event.MouseReleaseEvent: if self.getLockedAxis(): op = None if Selection.getCount() == 1: node = Selection.getSelectedObject(0) scale = node.getScale() if self.getLockedAxis() == ToolHandle.XAxis: scale.setX(-scale.x) elif self.getLockedAxis() == ToolHandle.YAxis: scale.setY(-scale.y) elif self.getLockedAxis() == ToolHandle.ZAxis: scale.setZ(-scale.z) op = ScaleOperation(node, scale, set_scale=True) else: op = GroupedOperation() for node in Selection.getAllSelectedObjects(): scale = node.getScale() if self.getLockedAxis() == ToolHandle.XAxis: scale.setX(-scale.x) elif self.getLockedAxis() == ToolHandle.YAxis: scale.setY(-scale.y) elif self.getLockedAxis() == ToolHandle.ZAxis: scale.setZ(-scale.z) op.addOperation(ScaleOperation(node, scale, set_scale = True)) op.push() self.setLockedAxis(None) return True return False
def run(self): status_message = Message(i18n_catalog.i18nc("@info:status", "Multiplying and placing objects"), lifetime=0, dismissable=False, progress=0) status_message.show() scene = Application.getInstance().getController().getScene() node = scene.findObject(self._object_id) if not node and self._object_id != 0: # Workaround for tool handles overlapping the selected object node = Selection.getSelectedObject(0) # If object is part of a group, multiply group current_node = node while current_node.getParent() and current_node.getParent().callDecoration("isGroup"): current_node = current_node.getParent() root = scene.getRoot() arranger = Arrange.create(scene_root=root) node_too_big = False if node.getBoundingBox().width < 300 or node.getBoundingBox().depth < 300: offset_shape_arr, hull_shape_arr = ShapeArray.fromNode(current_node, min_offset=self._min_offset) else: node_too_big = True nodes = [] found_solution_for_all = True for i in range(self._count): # We do place the nodes one by one, as we want to yield in between. if not node_too_big: node, solution_found = arranger.findNodePlacement(current_node, offset_shape_arr, hull_shape_arr) if node_too_big or not solution_found: found_solution_for_all = False new_location = node.getPosition() new_location = new_location.set(z = 100 - i * 20) node.setPosition(new_location) nodes.append(node) Job.yieldThread() status_message.setProgress((i + 1) / self._count * 100) if nodes: op = GroupedOperation() for new_node in nodes: op.addOperation(AddSceneNodeOperation(new_node, current_node.getParent())) op.push() status_message.hide() if not found_solution_for_all: no_full_solution_message = Message(i18n_catalog.i18nc("@info:status", "Unable to find a location within the build volume for all objects")) no_full_solution_message.show()
def deleteObject(self, object_id): object = self.getController().getScene().findObject(object_id) if not object and object_id != 0: #Workaround for tool handles overlapping the selected object object = Selection.getSelectedObject(0) if object: if object.getParent(): group_node = object.getParent() if not group_node.callDecoration("isGroup"): op = RemoveSceneNodeOperation(object) else: while group_node.getParent().callDecoration("isGroup"): group_node = group_node.getParent() op = RemoveSceneNodeOperation(group_node) op.push()
def multiplyObject(self, object_id, count): node = self.getController().getScene().findObject(object_id) if not node and object_id != 0: #Workaround for tool handles overlapping the selected object node = Selection.getSelectedObject(0) if node: op = GroupedOperation() for i in range(count): new_node = SceneNode() new_node.setMeshData(node.getMeshData()) new_node.setScale(node.getScale()) new_node.translate(Vector((i + 1) * node.getBoundingBox().width, 0, 0)) new_node.setSelectable(True) op.addOperation(AddSceneNodeOperation(new_node, node.getParent())) op.push()
def multiplyObject(self, object_id, count): node = self.getController().getScene().findObject(object_id) if not node and object_id != 0: # Workaround for tool handles overlapping the selected object node = Selection.getSelectedObject(0) if node: current_node = node # Find the topmost group while current_node.getParent() and current_node.getParent().callDecoration("isGroup"): current_node = current_node.getParent() op = GroupedOperation() for _ in range(count): new_node = copy.deepcopy(current_node) op.addOperation(AddSceneNodeOperation(new_node, current_node.getParent())) op.push()
def onSelectionChanged(self): if Selection.hasSelection(): if not self.getController().getActiveTool(): if self._previous_active_tool: self.getController().setActiveTool(self._previous_active_tool) self._previous_active_tool = None else: self.getController().setActiveTool("TranslateTool") if Preferences.getInstance().getValue("view/center_on_select"): self._camera_animation.setStart(self.getController().getTool("CameraTool").getOrigin()) self._camera_animation.setTarget(Selection.getSelectedObject(0).getWorldPosition()) self._camera_animation.start() else: if self.getController().getActiveTool(): self._previous_active_tool = self.getController().getActiveTool().getPluginId() self.getController().setActiveTool(None) else: self._previous_active_tool = None
def deleteObject(self, object_id): if not self.getController().getToolsEnabled(): return node = self.getController().getScene().findObject(object_id) if not node and object_id != 0: # Workaround for tool handles overlapping the selected object node = Selection.getSelectedObject(0) if node: if node.getParent(): group_node = node.getParent() if not group_node.callDecoration("isGroup"): op = RemoveSceneNodeOperation(node) else: while group_node.getParent().callDecoration("isGroup"): group_node = group_node.getParent() op = RemoveSceneNodeOperation(group_node) op.push()