mirror of
https://github.com/Ultimaker/Cura.git
synced 2025-07-06 22:47:29 -06:00
Merge branch '3.4'
This commit is contained in:
commit
c6ac344ed5
8 changed files with 46 additions and 23 deletions
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
from UM.Scene.Iterator.DepthFirstIterator import DepthFirstIterator
|
from UM.Scene.Iterator.DepthFirstIterator import DepthFirstIterator
|
||||||
from UM.Logger import Logger
|
from UM.Logger import Logger
|
||||||
|
from UM.Math.Polygon import Polygon
|
||||||
from UM.Math.Vector import Vector
|
from UM.Math.Vector import Vector
|
||||||
from cura.Arranging.ShapeArray import ShapeArray
|
from cura.Arranging.ShapeArray import ShapeArray
|
||||||
from cura.Scene import ZOffsetDecorator
|
from cura.Scene import ZOffsetDecorator
|
||||||
|
@ -45,7 +46,7 @@ class Arrange:
|
||||||
# \param scene_root Root for finding all scene nodes
|
# \param scene_root Root for finding all scene nodes
|
||||||
# \param fixed_nodes Scene nodes to be placed
|
# \param fixed_nodes Scene nodes to be placed
|
||||||
@classmethod
|
@classmethod
|
||||||
def create(cls, scene_root = None, fixed_nodes = None, scale = 0.5, x = 350, y = 250):
|
def create(cls, scene_root = None, fixed_nodes = None, scale = 0.5, x = 350, y = 250, min_offset = 8):
|
||||||
arranger = Arrange(x, y, x // 2, y // 2, scale = scale)
|
arranger = Arrange(x, y, x // 2, y // 2, scale = scale)
|
||||||
arranger.centerFirst()
|
arranger.centerFirst()
|
||||||
|
|
||||||
|
@ -58,9 +59,10 @@ class Arrange:
|
||||||
|
|
||||||
# Place all objects fixed nodes
|
# Place all objects fixed nodes
|
||||||
for fixed_node in fixed_nodes:
|
for fixed_node in fixed_nodes:
|
||||||
vertices = fixed_node.callDecoration("getConvexHull")
|
vertices = fixed_node.callDecoration("getConvexHullHead") or fixed_node.callDecoration("getConvexHull")
|
||||||
if not vertices:
|
if not vertices:
|
||||||
continue
|
continue
|
||||||
|
vertices = vertices.getMinkowskiHull(Polygon.approximatedCircle(min_offset))
|
||||||
points = copy.deepcopy(vertices._points)
|
points = copy.deepcopy(vertices._points)
|
||||||
shape_arr = ShapeArray.fromPolygon(points, scale = scale)
|
shape_arr = ShapeArray.fromPolygon(points, scale = scale)
|
||||||
arranger.place(0, 0, shape_arr)
|
arranger.place(0, 0, shape_arr)
|
||||||
|
@ -81,12 +83,12 @@ class Arrange:
|
||||||
## Find placement for a node (using offset shape) and place it (using hull shape)
|
## Find placement for a node (using offset shape) and place it (using hull shape)
|
||||||
# return the nodes that should be placed
|
# return the nodes that should be placed
|
||||||
# \param node
|
# \param node
|
||||||
# \param offset_shape_arr ShapeArray with offset, used to find location
|
# \param offset_shape_arr ShapeArray with offset, for placing the shape
|
||||||
# \param hull_shape_arr ShapeArray without offset, for placing the shape
|
# \param hull_shape_arr ShapeArray without offset, used to find location
|
||||||
def findNodePlacement(self, node, offset_shape_arr, hull_shape_arr, step = 1):
|
def findNodePlacement(self, node, offset_shape_arr, hull_shape_arr, step = 1):
|
||||||
new_node = copy.deepcopy(node)
|
new_node = copy.deepcopy(node)
|
||||||
best_spot = self.bestSpot(
|
best_spot = self.bestSpot(
|
||||||
offset_shape_arr, start_prio = self._last_priority, step = step)
|
hull_shape_arr, start_prio = self._last_priority, step = step)
|
||||||
x, y = best_spot.x, best_spot.y
|
x, y = best_spot.x, best_spot.y
|
||||||
|
|
||||||
# Save the last priority.
|
# Save the last priority.
|
||||||
|
@ -102,7 +104,7 @@ class Arrange:
|
||||||
if x is not None: # We could find a place
|
if x is not None: # We could find a place
|
||||||
new_node.setPosition(Vector(x, center_y, y))
|
new_node.setPosition(Vector(x, center_y, y))
|
||||||
found_spot = True
|
found_spot = True
|
||||||
self.place(x, y, hull_shape_arr) # place the object in arranger
|
self.place(x, y, offset_shape_arr) # place the object in arranger
|
||||||
else:
|
else:
|
||||||
Logger.log("d", "Could not find spot!"),
|
Logger.log("d", "Could not find spot!"),
|
||||||
found_spot = False
|
found_spot = False
|
||||||
|
|
|
@ -37,7 +37,7 @@ class ArrangeObjectsJob(Job):
|
||||||
machine_width = global_container_stack.getProperty("machine_width", "value")
|
machine_width = global_container_stack.getProperty("machine_width", "value")
|
||||||
machine_depth = global_container_stack.getProperty("machine_depth", "value")
|
machine_depth = global_container_stack.getProperty("machine_depth", "value")
|
||||||
|
|
||||||
arranger = Arrange.create(x = machine_width, y = machine_depth, fixed_nodes = self._fixed_nodes)
|
arranger = Arrange.create(x = machine_width, y = machine_depth, fixed_nodes = self._fixed_nodes, min_offset = self._min_offset)
|
||||||
|
|
||||||
# Collect nodes to be placed
|
# Collect nodes to be placed
|
||||||
nodes_arr = [] # fill with (size, node, offset_shape_arr, hull_shape_arr)
|
nodes_arr = [] # fill with (size, node, offset_shape_arr, hull_shape_arr)
|
||||||
|
@ -66,7 +66,7 @@ class ArrangeObjectsJob(Job):
|
||||||
start_priority = last_priority
|
start_priority = last_priority
|
||||||
else:
|
else:
|
||||||
start_priority = 0
|
start_priority = 0
|
||||||
best_spot = arranger.bestSpot(offset_shape_arr, start_prio=start_priority)
|
best_spot = arranger.bestSpot(hull_shape_arr, start_prio = start_priority)
|
||||||
x, y = best_spot.x, best_spot.y
|
x, y = best_spot.x, best_spot.y
|
||||||
node.removeDecorator(ZOffsetDecorator)
|
node.removeDecorator(ZOffsetDecorator)
|
||||||
if node.getBoundingBox():
|
if node.getBoundingBox():
|
||||||
|
@ -77,7 +77,7 @@ class ArrangeObjectsJob(Job):
|
||||||
last_size = size
|
last_size = size
|
||||||
last_priority = best_spot.priority
|
last_priority = best_spot.priority
|
||||||
|
|
||||||
arranger.place(x, y, hull_shape_arr) # take place before the next one
|
arranger.place(x, y, offset_shape_arr) # take place before the next one
|
||||||
grouped_operation.addOperation(TranslateOperation(node, Vector(x, center_y, y), set_position = True))
|
grouped_operation.addOperation(TranslateOperation(node, Vector(x, center_y, y), set_position = True))
|
||||||
else:
|
else:
|
||||||
Logger.log("d", "Arrange all: could not find spot!")
|
Logger.log("d", "Arrange all: could not find spot!")
|
||||||
|
|
|
@ -158,14 +158,17 @@ class CuraPackageManager(QObject):
|
||||||
# Add bundled plugins
|
# Add bundled plugins
|
||||||
if package_id in self._bundled_package_dict:
|
if package_id in self._bundled_package_dict:
|
||||||
package_info = self._bundled_package_dict[package_id]["package_info"]
|
package_info = self._bundled_package_dict[package_id]["package_info"]
|
||||||
|
package_info["is_installed"] = True
|
||||||
|
|
||||||
# Add installed plugins
|
# Add installed plugins
|
||||||
if package_id in self._installed_package_dict:
|
if package_id in self._installed_package_dict:
|
||||||
package_info = self._installed_package_dict[package_id]["package_info"]
|
package_info = self._installed_package_dict[package_id]["package_info"]
|
||||||
|
package_info["is_installed"] = True
|
||||||
|
|
||||||
# Add to install plugins
|
# Add to install plugins
|
||||||
if package_id in self._to_install_package_dict:
|
if package_id in self._to_install_package_dict:
|
||||||
package_info = self._to_install_package_dict[package_id]["package_info"]
|
package_info = self._to_install_package_dict[package_id]["package_info"]
|
||||||
|
package_info["is_installed"] = False
|
||||||
|
|
||||||
if package_info is None:
|
if package_info is None:
|
||||||
continue
|
continue
|
||||||
|
|
|
@ -38,7 +38,7 @@ class MultiplyObjectsJob(Job):
|
||||||
|
|
||||||
root = scene.getRoot()
|
root = scene.getRoot()
|
||||||
scale = 0.5
|
scale = 0.5
|
||||||
arranger = Arrange.create(x = machine_width, y = machine_depth, scene_root = root, scale = scale)
|
arranger = Arrange.create(x = machine_width, y = machine_depth, scene_root = root, scale = scale, min_offset = self._min_offset)
|
||||||
processed_nodes = []
|
processed_nodes = []
|
||||||
nodes = []
|
nodes = []
|
||||||
|
|
||||||
|
|
|
@ -15,7 +15,6 @@ from UM.Math.Vector import Vector
|
||||||
from UM.Mesh.MeshBuilder import MeshBuilder
|
from UM.Mesh.MeshBuilder import MeshBuilder
|
||||||
from UM.Mesh.MeshReader import MeshReader
|
from UM.Mesh.MeshReader import MeshReader
|
||||||
from UM.Scene.GroupDecorator import GroupDecorator
|
from UM.Scene.GroupDecorator import GroupDecorator
|
||||||
from UM.MimeTypeDatabase import MimeTypeDatabase, MimeType
|
|
||||||
|
|
||||||
from cura.Settings.ExtruderManager import ExtruderManager
|
from cura.Settings.ExtruderManager import ExtruderManager
|
||||||
from cura.Scene.CuraSceneNode import CuraSceneNode
|
from cura.Scene.CuraSceneNode import CuraSceneNode
|
||||||
|
@ -26,15 +25,6 @@ from cura.Machines.QualityManager import getMachineDefinitionIDForQualitySearch
|
||||||
|
|
||||||
MYPY = False
|
MYPY = False
|
||||||
|
|
||||||
|
|
||||||
MimeTypeDatabase.addMimeType(
|
|
||||||
MimeType(
|
|
||||||
name = "application/x-cura-project-file",
|
|
||||||
comment = "Cura Project File",
|
|
||||||
suffixes = ["curaproject.3mf"]
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
if not MYPY:
|
if not MYPY:
|
||||||
import xml.etree.cElementTree as ET
|
import xml.etree.cElementTree as ET
|
||||||
|
|
|
@ -13,8 +13,24 @@ from . import ThreeMFWorkspaceReader
|
||||||
|
|
||||||
from UM.i18n import i18nCatalog
|
from UM.i18n import i18nCatalog
|
||||||
from UM.Platform import Platform
|
from UM.Platform import Platform
|
||||||
|
from UM.MimeTypeDatabase import MimeTypeDatabase, MimeType
|
||||||
catalog = i18nCatalog("cura")
|
catalog = i18nCatalog("cura")
|
||||||
|
|
||||||
|
MimeTypeDatabase.addMimeType(
|
||||||
|
MimeType(
|
||||||
|
name = "application/x-cura-project-file",
|
||||||
|
comment = "Cura Project File",
|
||||||
|
suffixes = ["curaproject.3mf"]
|
||||||
|
)
|
||||||
|
)
|
||||||
|
MimeTypeDatabase.addMimeType(
|
||||||
|
MimeType(
|
||||||
|
name = "application/x-cura-project-file",
|
||||||
|
comment = "Cura Project File",
|
||||||
|
suffixes = ["3mf"]
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
def getMetaData() -> Dict:
|
def getMetaData() -> Dict:
|
||||||
# Workarround for osx not supporting double file extensions correctly.
|
# Workarround for osx not supporting double file extensions correctly.
|
||||||
if Platform.isOSX():
|
if Platform.isOSX():
|
||||||
|
|
|
@ -13,6 +13,16 @@ Column
|
||||||
width: UM.Theme.getSize("toolbox_action_button").width
|
width: UM.Theme.getSize("toolbox_action_button").width
|
||||||
spacing: UM.Theme.getSize("narrow_margin").height
|
spacing: UM.Theme.getSize("narrow_margin").height
|
||||||
|
|
||||||
|
Label
|
||||||
|
{
|
||||||
|
visible: !model.is_installed
|
||||||
|
text: catalog.i18nc("@label", "Will install upon restarting")
|
||||||
|
color: UM.Theme.getColor("lining")
|
||||||
|
font: UM.Theme.getFont("default")
|
||||||
|
wrapMode: Text.WordWrap
|
||||||
|
width: parent.width
|
||||||
|
}
|
||||||
|
|
||||||
ToolboxProgressButton
|
ToolboxProgressButton
|
||||||
{
|
{
|
||||||
id: updateButton
|
id: updateButton
|
||||||
|
@ -39,7 +49,7 @@ Column
|
||||||
{
|
{
|
||||||
id: removeButton
|
id: removeButton
|
||||||
text: canDowngrade ? catalog.i18nc("@action:button", "Downgrade") : catalog.i18nc("@action:button", "Uninstall")
|
text: canDowngrade ? catalog.i18nc("@action:button", "Downgrade") : catalog.i18nc("@action:button", "Uninstall")
|
||||||
visible: !model.is_bundled
|
visible: !model.is_bundled && model.is_installed
|
||||||
enabled: !toolbox.isDownloading
|
enabled: !toolbox.isDownloading
|
||||||
style: ButtonStyle
|
style: ButtonStyle
|
||||||
{
|
{
|
||||||
|
|
|
@ -29,8 +29,9 @@ class PackagesModel(ListModel):
|
||||||
self.addRoleName(Qt.UserRole + 12, "last_updated")
|
self.addRoleName(Qt.UserRole + 12, "last_updated")
|
||||||
self.addRoleName(Qt.UserRole + 13, "is_bundled")
|
self.addRoleName(Qt.UserRole + 13, "is_bundled")
|
||||||
self.addRoleName(Qt.UserRole + 14, "is_enabled")
|
self.addRoleName(Qt.UserRole + 14, "is_enabled")
|
||||||
self.addRoleName(Qt.UserRole + 15, "has_configs")
|
self.addRoleName(Qt.UserRole + 15, "is_installed") # Scheduled pkgs are included in the model but should not be marked as actually installed
|
||||||
self.addRoleName(Qt.UserRole + 16, "supported_configs")
|
self.addRoleName(Qt.UserRole + 16, "has_configs")
|
||||||
|
self.addRoleName(Qt.UserRole + 17, "supported_configs")
|
||||||
|
|
||||||
# List of filters for queries. The result is the union of the each list of results.
|
# List of filters for queries. The result is the union of the each list of results.
|
||||||
self._filter = {} # type: Dict[str, str]
|
self._filter = {} # type: Dict[str, str]
|
||||||
|
@ -73,6 +74,7 @@ class PackagesModel(ListModel):
|
||||||
"last_updated": package["last_updated"] if "last_updated" in package else None,
|
"last_updated": package["last_updated"] if "last_updated" in package else None,
|
||||||
"is_bundled": package["is_bundled"] if "is_bundled" in package else False,
|
"is_bundled": package["is_bundled"] if "is_bundled" in package else False,
|
||||||
"is_enabled": package["is_enabled"] if "is_enabled" in package else False,
|
"is_enabled": package["is_enabled"] if "is_enabled" in package else False,
|
||||||
|
"is_installed": package["is_installed"] if "is_installed" in package else False,
|
||||||
"has_configs": has_configs,
|
"has_configs": has_configs,
|
||||||
"supported_configs": configs_model
|
"supported_configs": configs_model
|
||||||
})
|
})
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue