Merge branch 'master' into fix_version_upgrade_returning_none

This commit is contained in:
Aleksei S 2018-11-22 11:17:44 +01:00
commit c765615f1a
104 changed files with 13958 additions and 52759 deletions

View file

@ -17,6 +17,7 @@ if(CURA_DEBUGMODE)
set(_cura_debugmode "ON")
endif()
set(CURA_APP_DISPLAY_NAME "Ultimaker Cura" CACHE STRING "Display name of Cura")
set(CURA_VERSION "master" CACHE STRING "Version name of Cura")
set(CURA_BUILDTYPE "" CACHE STRING "Build type of Cura, eg. 'PPA'")
set(CURA_SDK_VERSION "" CACHE STRING "SDK version of Cura")

43
Jenkinsfile vendored
View file

@ -38,20 +38,9 @@ parallel_nodes(['linux && cura', 'windows && cura'])
{
if (isUnix())
{
// For Linux to show everything
def branch = env.BRANCH_NAME
if(!fileExists("${env.CURA_ENVIRONMENT_PATH}/${branch}"))
{
branch = "master"
}
def uranium_dir = get_workspace_dir("Ultimaker/Uranium/${branch}")
// For Linux
try {
sh """
cd ..
export PYTHONPATH=.:"${uranium_dir}"
${env.CURA_ENVIRONMENT_PATH}/${branch}/bin/pytest -x --verbose --full-trace --capture=no ./tests
"""
sh 'make CTEST_OUTPUT_ON_FAILURE=TRUE test'
} catch(e)
{
currentBuild.result = "UNSTABLE"
@ -70,34 +59,6 @@ parallel_nodes(['linux && cura', 'windows && cura'])
}
}
}
stage('Code Style')
{
if (isUnix())
{
// For Linux to show everything.
// CMake also runs this test, but if it fails then the test just shows "failed" without details of what exactly failed.
def branch = env.BRANCH_NAME
if(!fileExists("${env.CURA_ENVIRONMENT_PATH}/${branch}"))
{
branch = "master"
}
def uranium_dir = get_workspace_dir("Ultimaker/Uranium/${branch}")
try
{
sh """
cd ..
export PYTHONPATH=.:"${uranium_dir}"
${env.CURA_ENVIRONMENT_PATH}/${branch}/bin/python3 run_mypy.py
"""
}
catch(e)
{
currentBuild.result = "UNSTABLE"
}
}
}
}
}

View file

@ -6,6 +6,8 @@ include(CMakeParseArguments)
find_package(PythonInterp 3.5.0 REQUIRED)
add_custom_target(test-verbose COMMAND ${CMAKE_CTEST_COMMAND} --verbose)
function(cura_add_test)
set(_single_args NAME DIRECTORY PYTHONPATH)
cmake_parse_arguments("" "" "${_single_args}" "" ${ARGN})

View file

@ -3,7 +3,6 @@
from typing import TYPE_CHECKING
from UM.PluginRegistry import PluginRegistry
from cura.API.Interface.Settings import Settings
if TYPE_CHECKING:
@ -23,9 +22,6 @@ if TYPE_CHECKING:
class Interface:
# For now we use the same API version to be consistent.
VERSION = PluginRegistry.APIVersion
def __init__(self, application: "CuraApplication") -> None:
# API methods specific to the settings portion of the UI
self.settings = Settings(application)

View file

@ -4,7 +4,6 @@ from typing import Optional, TYPE_CHECKING
from PyQt5.QtCore import QObject, pyqtProperty
from UM.PluginRegistry import PluginRegistry
from cura.API.Backups import Backups
from cura.API.Interface import Interface
from cura.API.Account import Account
@ -22,7 +21,6 @@ if TYPE_CHECKING:
class CuraAPI(QObject):
# For now we use the same API version to be consistent.
VERSION = PluginRegistry.APIVersion
__instance = None # type: "CuraAPI"
_application = None # type: CuraApplication
@ -62,4 +60,4 @@ class CuraAPI(QObject):
@property
def interface(self) -> "Interface":
return self._interface
return self._interface

View file

@ -489,7 +489,9 @@ class BuildVolume(SceneNode):
def _updateRaftThickness(self):
old_raft_thickness = self._raft_thickness
self._adhesion_type = self._global_container_stack.getProperty("adhesion_type", "value")
if self._global_container_stack.extruders:
# This might be called before the extruder stacks have initialised, in which case getting the adhesion_type fails
self._adhesion_type = self._global_container_stack.getProperty("adhesion_type", "value")
self._raft_thickness = 0.0
if self._adhesion_type == "raft":
self._raft_thickness = (

View file

@ -128,12 +128,13 @@ if TYPE_CHECKING:
numpy.seterr(all = "ignore")
try:
from cura.CuraVersion import CuraVersion, CuraBuildType, CuraDebugMode, CuraSDKVersion # type: ignore
from cura.CuraVersion import CuraAppDisplayName, CuraVersion, CuraBuildType, CuraDebugMode, CuraSDKVersion # type: ignore
except ImportError:
CuraAppDisplayName = "Ultimaker Cura"
CuraVersion = "master" # [CodeStyle: Reflecting imported value]
CuraBuildType = ""
CuraDebugMode = False
CuraSDKVersion = ""
CuraSDKVersion = "5.0.0"
class CuraApplication(QtApplication):
@ -161,7 +162,9 @@ class CuraApplication(QtApplication):
def __init__(self, *args, **kwargs):
super().__init__(name = "cura",
app_display_name = CuraAppDisplayName,
version = CuraVersion,
api_version = CuraSDKVersion,
buildtype = CuraBuildType,
is_debug_mode = CuraDebugMode,
tray_icon_name = "cura-icon-32.png",
@ -429,34 +432,30 @@ class CuraApplication(QtApplication):
self.setRequiredPlugins([
# Misc.:
"ConsoleLogger",
"CuraEngineBackend",
"UserAgreement",
"FileLogger",
"XmlMaterialProfile",
"Toolbox",
"PrepareStage",
"MonitorStage",
"LocalFileOutputDevice",
"LocalContainerProvider",
"ConsoleLogger", #You want to be able to read the log if something goes wrong.
"CuraEngineBackend", #Cura is useless without this one since you can't slice.
"UserAgreement", #Our lawyers want every user to see this at least once.
"FileLogger", #You want to be able to read the log if something goes wrong.
"XmlMaterialProfile", #Cura crashes without this one.
"Toolbox", #This contains the interface to enable/disable plug-ins, so if you disable it you can't enable it back.
"PrepareStage", #Cura is useless without this one since you can't load models.
"MonitorStage", #Major part of Cura's functionality.
"LocalFileOutputDevice", #Major part of Cura's functionality.
"LocalContainerProvider", #Cura is useless without any profiles or setting definitions.
# Views:
"SimpleView",
"SimulationView",
"SolidView",
"SimpleView", #Dependency of SolidView.
"SolidView", #Displays models. Cura is useless without it.
# Readers & Writers:
"GCodeWriter",
"STLReader",
"3MFWriter",
"GCodeWriter", #Cura is useless if it can't write its output.
"STLReader", #Most common model format, so disabling this makes Cura 90% useless.
"3MFWriter", #Required for writing project files.
# Tools:
"CameraTool",
"MirrorTool",
"RotateTool",
"ScaleTool",
"SelectionTool",
"TranslateTool",
"CameraTool", #Needed to see the scene. Cura is useless without it.
"SelectionTool", #Dependency of the rest of the tools.
"TranslateTool", #You'll need this for almost every print.
])
self._i18n_catalog = i18nCatalog("cura")

View file

@ -1,6 +1,7 @@
# Copyright (c) 2015 Ultimaker B.V.
# Copyright (c) 2018 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
CuraAppDisplayName = "@CURA_APP_DISPLAY_NAME@"
CuraVersion = "@CURA_VERSION@"
CuraBuildType = "@CURA_BUILDTYPE@"
CuraDebugMode = True if "@_cura_debugmode@" == "ON" else False

View file

@ -644,8 +644,11 @@ class MaterialManager(QObject):
machine_manager = self._application.getMachineManager()
extruder_stack = machine_manager.activeStack
machine_definition = self._application.getGlobalContainerStack().definition
preferred_material = machine_definition.getMetaDataEntry("preferred_material")
approximate_diameter = str(extruder_stack.approximateMaterialDiameter)
root_material_id = "generic_pla"
root_material_id = preferred_material if preferred_material else "generic_pla"
root_material_id = self.getRootMaterialIDForDiameter(root_material_id, approximate_diameter)
material_group = self.getMaterialGroup(root_material_id)

View file

@ -16,7 +16,7 @@ from .QualityGroup import QualityGroup
from .QualityNode import QualityNode
if TYPE_CHECKING:
from UM.Settings.DefinitionContainer import DefinitionContainer
from UM.Settings.Interfaces import DefinitionContainerInterface
from cura.Settings.GlobalStack import GlobalStack
from .QualityChangesGroup import QualityChangesGroup
from cura.CuraApplication import CuraApplication
@ -538,7 +538,7 @@ class QualityManager(QObject):
# Example: for an Ultimaker 3 Extended, it has "quality_definition = ultimaker3". This means Ultimaker 3 Extended
# shares the same set of qualities profiles as Ultimaker 3.
#
def getMachineDefinitionIDForQualitySearch(machine_definition: "DefinitionContainer",
def getMachineDefinitionIDForQualitySearch(machine_definition: "DefinitionContainerInterface",
default_definition_id: str = "fdmprinter") -> str:
machine_definition_id = default_definition_id
if parseBool(machine_definition.getMetaDataEntry("has_machine_quality", False)):

View file

@ -120,7 +120,7 @@ class AuthorizationService:
"redirect_uri": self._settings.CALLBACK_URL,
"scope": self._settings.CLIENT_SCOPES,
"response_type": "code",
"state": "CuraDriveIsAwesome",
"state": "(.Y.)",
"code_challenge": challenge_code,
"code_challenge_method": "S512"
})

View file

@ -272,7 +272,7 @@ class ConvexHullDecorator(SceneNodeDecorator):
head_and_fans = self._getHeadAndFans().intersectionConvexHulls(mirrored)
# Min head hull is used for the push free
convex_hull = self._compute2DConvexHeadFull()
convex_hull = self._compute2DConvexHull()
if convex_hull:
return convex_hull.getMinkowskiHull(head_and_fans)
return None

View file

@ -419,13 +419,13 @@ class ContainerManager(QObject):
self._container_name_filters[name_filter] = entry
## Import single profile, file_url does not have to end with curaprofile
@pyqtSlot(QUrl, result="QVariantMap")
def importProfile(self, file_url: QUrl):
@pyqtSlot(QUrl, result = "QVariantMap")
def importProfile(self, file_url: QUrl) -> Dict[str, str]:
if not file_url.isValid():
return
return {"status": "error", "message": catalog.i18nc("@info:status", "Invalid file URL:") + " " + str(file_url)}
path = file_url.toLocalFile()
if not path:
return
return {"status": "error", "message": catalog.i18nc("@info:status", "Invalid file URL:") + " " + str(file_url)}
return self._container_registry.importProfile(path)
@pyqtSlot(QObject, QUrl, str)

View file

@ -5,12 +5,12 @@ import os
import re
import configparser
from typing import cast, Optional
from typing import cast, Dict, Optional
from PyQt5.QtWidgets import QMessageBox
from UM.Decorators import override
from UM.Settings.ContainerFormatError import ContainerFormatError
from UM.Settings.Interfaces import ContainerInterface
from UM.Settings.ContainerRegistry import ContainerRegistry
from UM.Settings.ContainerStack import ContainerStack
from UM.Settings.InstanceContainer import InstanceContainer
@ -28,7 +28,7 @@ from . import GlobalStack
import cura.CuraApplication
from cura.Machines.QualityManager import getMachineDefinitionIDForQualitySearch
from cura.ReaderWriters.ProfileReader import NoProfileException
from cura.ReaderWriters.ProfileReader import NoProfileException, ProfileReader
from UM.i18n import i18nCatalog
catalog = i18nCatalog("cura")
@ -161,20 +161,20 @@ class CuraContainerRegistry(ContainerRegistry):
## Imports a profile from a file
#
# \param file_name \type{str} the full path and filename of the profile to import
# \return \type{Dict} dict with a 'status' key containing the string 'ok' or 'error', and a 'message' key
# containing a message for the user
def importProfile(self, file_name):
# \param file_name The full path and filename of the profile to import.
# \return Dict with a 'status' key containing the string 'ok' or 'error',
# and a 'message' key containing a message for the user.
def importProfile(self, file_name: str) -> Dict[str, str]:
Logger.log("d", "Attempting to import profile %s", file_name)
if not file_name:
return { "status": "error", "message": catalog.i18nc("@info:status Don't translate the XML tags <filename> or <message>!", "Failed to import profile from <filename>{0}</filename>: <message>{1}</message>", file_name, "Invalid path")}
return { "status": "error", "message": catalog.i18nc("@info:status Don't translate the XML tags <filename>!", "Failed to import profile from <filename>{0}</filename>: {1}", file_name, "Invalid path")}
plugin_registry = PluginRegistry.getInstance()
extension = file_name.split(".")[-1]
global_stack = Application.getInstance().getGlobalContainerStack()
if not global_stack:
return
return {"status": "error", "message": catalog.i18nc("@info:status Don't translate the XML tags <filename>!", "Can't import profile from <filename>{0}</filename> before a printer is added.", file_name)}
machine_extruders = []
for position in sorted(global_stack.extruders):
@ -183,7 +183,7 @@ class CuraContainerRegistry(ContainerRegistry):
for plugin_id, meta_data in self._getIOPlugins("profile_reader"):
if meta_data["profile_reader"][0]["extension"] != extension:
continue
profile_reader = plugin_registry.getPluginObject(plugin_id)
profile_reader = cast(ProfileReader, plugin_registry.getPluginObject(plugin_id))
try:
profile_or_list = profile_reader.read(file_name) # Try to open the file with the profile reader.
except NoProfileException:
@ -221,13 +221,13 @@ class CuraContainerRegistry(ContainerRegistry):
# Make sure we have a profile_definition in the file:
if profile_definition is None:
break
machine_definition = self.findDefinitionContainers(id = profile_definition)
if not machine_definition:
machine_definitions = self.findDefinitionContainers(id = profile_definition)
if not machine_definitions:
Logger.log("e", "Incorrect profile [%s]. Unknown machine type [%s]", file_name, profile_definition)
return {"status": "error",
"message": catalog.i18nc("@info:status Don't translate the XML tags <filename>!", "This profile <filename>{0}</filename> contains incorrect data, could not import it.", file_name)
}
machine_definition = machine_definition[0]
machine_definition = machine_definitions[0]
# Get the expected machine definition.
# i.e.: We expect gcode for a UM2 Extended to be defined as normal UM2 gcode...
@ -274,11 +274,12 @@ class CuraContainerRegistry(ContainerRegistry):
setting_value = global_profile.getProperty(qc_setting_key, "value")
setting_definition = global_stack.getSettingDefinition(qc_setting_key)
new_instance = SettingInstance(setting_definition, profile)
new_instance.setProperty("value", setting_value)
new_instance.resetState() # Ensure that the state is not seen as a user state.
profile.addInstance(new_instance)
profile.setDirty(True)
if setting_definition is not None:
new_instance = SettingInstance(setting_definition, profile)
new_instance.setProperty("value", setting_value)
new_instance.resetState() # Ensure that the state is not seen as a user state.
profile.addInstance(new_instance)
profile.setDirty(True)
global_profile.removeInstance(qc_setting_key, postpone_emit=True)
extruder_profiles.append(profile)
@ -290,7 +291,7 @@ class CuraContainerRegistry(ContainerRegistry):
for profile_index, profile in enumerate(profile_or_list):
if profile_index == 0:
# This is assumed to be the global profile
profile_id = (global_stack.getBottom().getId() + "_" + name_seed).lower().replace(" ", "_")
profile_id = (cast(ContainerInterface, global_stack.getBottom()).getId() + "_" + name_seed).lower().replace(" ", "_")
elif profile_index < len(machine_extruders) + 1:
# This is assumed to be an extruder profile

View file

@ -5,6 +5,7 @@ from typing import Any, List, Optional, TYPE_CHECKING
from UM.Settings.PropertyEvaluationContext import PropertyEvaluationContext
from UM.Settings.SettingFunction import SettingFunction
from UM.Logger import Logger
if TYPE_CHECKING:
from cura.CuraApplication import CuraApplication
@ -38,7 +39,11 @@ class CuraFormulaFunctions:
extruder_position = int(machine_manager.defaultExtruderPosition)
global_stack = machine_manager.activeMachine
extruder_stack = global_stack.extruders[str(extruder_position)]
try:
extruder_stack = global_stack.extruders[str(extruder_position)]
except KeyError:
Logger.log("w", "Value for %s of extruder %s was requested, but that extruder is not available" % (property_key, extruder_position))
return None
value = extruder_stack.getRawProperty(property_key, "value", context = context)
if isinstance(value, SettingFunction):

View file

@ -1,156 +0,0 @@
!ifndef VERSION
!define VERSION '15.09.80'
!endif
; The name of the installer
Name "Cura ${VERSION}"
; The file to write
OutFile "Cura_${VERSION}.exe"
; The default installation directory
InstallDir $PROGRAMFILES\Cura_${VERSION}
; Registry key to check for directory (so if you install again, it will
; overwrite the old one automatically)
InstallDirRegKey HKLM "Software\Cura_${VERSION}" "Install_Dir"
; Request application privileges for Windows Vista
RequestExecutionLevel admin
; Set the LZMA compressor to reduce size.
SetCompressor /SOLID lzma
;--------------------------------
!include "MUI2.nsh"
!include "Library.nsh"
; !define MUI_ICON "dist/resources/cura.ico"
!define MUI_BGCOLOR FFFFFF
; Directory page defines
!define MUI_DIRECTORYPAGE_VERIFYONLEAVE
; Header
; Don't show the component description box
!define MUI_COMPONENTSPAGE_NODESC
;Do not leave (Un)Installer page automaticly
!define MUI_FINISHPAGE_NOAUTOCLOSE
!define MUI_UNFINISHPAGE_NOAUTOCLOSE
;Run Cura after installing
!define MUI_FINISHPAGE_RUN
!define MUI_FINISHPAGE_RUN_TEXT "Start Cura ${VERSION}"
!define MUI_FINISHPAGE_RUN_FUNCTION "LaunchLink"
;Add an option to show release notes
!define MUI_FINISHPAGE_SHOWREADME "$INSTDIR\plugins\ChangeLogPlugin\changelog.txt"
; Pages
;!insertmacro MUI_PAGE_WELCOME
!insertmacro MUI_PAGE_DIRECTORY
!insertmacro MUI_PAGE_COMPONENTS
!insertmacro MUI_PAGE_INSTFILES
!insertmacro MUI_PAGE_FINISH
!insertmacro MUI_UNPAGE_CONFIRM
!insertmacro MUI_UNPAGE_INSTFILES
!insertmacro MUI_UNPAGE_FINISH
; Languages
!insertmacro MUI_LANGUAGE "English"
; Reserve Files
!insertmacro MUI_RESERVEFILE_LANGDLL
ReserveFile '${NSISDIR}\Plugins\InstallOptions.dll'
;--------------------------------
; The stuff to install
Section "Cura ${VERSION}"
SectionIn RO
; Set output path to the installation directory.
SetOutPath $INSTDIR
; Put file there
File /r "dist\"
; Write the installation path into the registry
WriteRegStr HKLM "SOFTWARE\Cura_${VERSION}" "Install_Dir" "$INSTDIR"
; Write the uninstall keys for Windows
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Cura_${VERSION}" "DisplayName" "Cura ${VERSION}"
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Cura_${VERSION}" "UninstallString" '"$INSTDIR\uninstall.exe"'
WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Cura_${VERSION}" "NoModify" 1
WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Cura_${VERSION}" "NoRepair" 1
WriteUninstaller "uninstall.exe"
; Write start menu entries for all users
SetShellVarContext all
CreateDirectory "$SMPROGRAMS\Cura ${VERSION}"
CreateShortCut "$SMPROGRAMS\Cura ${VERSION}\Uninstall Cura ${VERSION}.lnk" "$INSTDIR\uninstall.exe" "" "$INSTDIR\uninstall.exe" 0
CreateShortCut "$SMPROGRAMS\Cura ${VERSION}\Cura ${VERSION}.lnk" "$INSTDIR\Cura.exe" '' "$INSTDIR\Cura.exe" 0
SectionEnd
Function LaunchLink
; Write start menu entries for all users
SetShellVarContext all
Exec '"$WINDIR\explorer.exe" "$SMPROGRAMS\Cura ${VERSION}\Cura ${VERSION}.lnk"'
FunctionEnd
Section "Install Visual Studio 2010 Redistributable"
SetOutPath "$INSTDIR"
File "vcredist_2010_20110908_x86.exe"
IfSilent +2
ExecWait '"$INSTDIR\vcredist_2010_20110908_x86.exe" /q /norestart'
SectionEnd
Section "Install Arduino Drivers"
; Set output path to the driver directory.
SetOutPath "$INSTDIR\drivers\"
File /r "drivers\"
${If} ${RunningX64}
IfSilent +2
ExecWait '"$INSTDIR\drivers\dpinst64.exe" /lm'
${Else}
IfSilent +2
ExecWait '"$INSTDIR\drivers\dpinst32.exe" /lm'
${EndIf}
SectionEnd
Section "Open STL files with Cura"
${registerExtension} "$INSTDIR\Cura.exe" ".stl" "STL_File"
SectionEnd
Section /o "Open OBJ files with Cura"
WriteRegStr HKCR .obj "" "Cura OBJ model file"
DeleteRegValue HKCR .obj "Content Type"
WriteRegStr HKCR "Cura OBJ model file\DefaultIcon" "" "$INSTDIR\Cura.exe,0"
WriteRegStr HKCR "Cura OBJ model file\shell" "" "open"
WriteRegStr HKCR "Cura OBJ model file\shell\open\command" "" '"$INSTDIR\Cura.exe" "%1"'
SectionEnd
;--------------------------------
; Uninstaller
Section "Uninstall"
; Remove registry keys
DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Cura_${VERSION}"
DeleteRegKey HKLM "SOFTWARE\Cura_${VERSION}"
; Write start menu entries for all users
SetShellVarContext all
; Remove directories used
RMDir /r "$SMPROGRAMS\Cura ${VERSION}"
RMDir /r "$INSTDIR"
SectionEnd

View file

@ -1,4 +1,4 @@
# Copyright (c) 2015 Ultimaker B.V.
# Copyright (c) 2018 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
from UM.i18n import i18nCatalog
@ -29,6 +29,7 @@ class ChangeLog(Extension, QObject,):
self._change_logs = None
Application.getInstance().engineCreatedSignal.connect(self._onEngineCreated)
Application.getInstance().getPreferences().addPreference("general/latest_version_changelog_shown", "2.0.0") #First version of CURA with uranium
self.setMenuName(catalog.i18nc("@item:inmenu", "Changelog"))
self.addMenuItem(catalog.i18nc("@item:inmenu", "Show Changelog"), self.showChangelog)
def getChangeLogs(self):

View file

@ -1,6 +1,6 @@
{
"source_version": "15.04",
"target_version": 3,
"target_version": "4.5",
"translation": {
"machine_nozzle_size": "nozzle_size",

View file

@ -1,4 +1,4 @@
# Copyright (c) 2017 Ultimaker B.V.
# Copyright (c) 2018 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
import configparser # For reading the legacy profile INI files.
@ -6,6 +6,7 @@ import io
import json # For reading the Dictionary of Doom.
import math # For mathematical operations included in the Dictionary of Doom.
import os.path # For concatenating the path to the plugin and the relative path to the Dictionary of Doom.
from typing import Dict
from UM.Application import Application # To get the machine manager to create the new profile in.
from UM.Logger import Logger # Logging errors.
@ -33,10 +34,11 @@ class LegacyProfileReader(ProfileReader):
# \param json The JSON file to load the default setting values from. This
# should not be a URL but a pre-loaded JSON handle.
# \return A dictionary of the default values of the legacy Cura version.
def prepareDefaults(self, json):
def prepareDefaults(self, json: Dict[str, Dict[str, str]]) -> Dict[str, str]:
defaults = {}
for key in json["defaults"]: # We have to copy over all defaults from the JSON handle to a normal dict.
defaults[key] = json["defaults"][key]
if "defaults" in json:
for key in json["defaults"]: # We have to copy over all defaults from the JSON handle to a normal dict.
defaults[key] = json["defaults"][key]
return defaults
## Prepares the local variables that can be used in evaluation of computing
@ -80,11 +82,10 @@ class LegacyProfileReader(ProfileReader):
Logger.log("i", "Importing legacy profile from file " + file_name + ".")
container_registry = ContainerRegistry.getInstance()
profile_id = container_registry.uniqueName("Imported Legacy Profile")
profile = InstanceContainer(profile_id) # Create an empty profile.
parser = configparser.ConfigParser(interpolation = None)
input_parser = configparser.ConfigParser(interpolation = None)
try:
parser.read([file_name]) # Parse the INI file.
input_parser.read([file_name]) # Parse the INI file.
except Exception as e:
Logger.log("e", "Unable to open legacy profile %s: %s", file_name, str(e))
return None
@ -92,7 +93,7 @@ class LegacyProfileReader(ProfileReader):
# Legacy Cura saved the profile under the section "profile_N" where N is the ID of a machine, except when you export in which case it saves it in the section "profile".
# Since importing multiple machine profiles is out of scope, just import the first section we find.
section = ""
for found_section in parser.sections():
for found_section in input_parser.sections():
if found_section.startswith("profile"):
section = found_section
break
@ -110,15 +111,13 @@ class LegacyProfileReader(ProfileReader):
return None
defaults = self.prepareDefaults(dict_of_doom)
legacy_settings = self.prepareLocals(parser, section, defaults) #Gets the settings from the legacy profile.
legacy_settings = self.prepareLocals(input_parser, section, defaults) #Gets the settings from the legacy profile.
#Check the target version in the Dictionary of Doom with this application version.
if "target_version" not in dict_of_doom:
Logger.log("e", "Dictionary of Doom has no target version. Is it the correct JSON file?")
return None
if InstanceContainer.Version != dict_of_doom["target_version"]:
Logger.log("e", "Dictionary of Doom of legacy profile reader (version %s) is not in sync with the current instance container version (version %s)!", dict_of_doom["target_version"], str(InstanceContainer.Version))
return None
# Serialised format into version 4.5. Do NOT upgrade this, let the version upgrader handle it.
output_parser = configparser.ConfigParser(interpolation = None)
output_parser.add_section("general")
output_parser.add_section("metadata")
output_parser.add_section("values")
if "translation" not in dict_of_doom:
Logger.log("e", "Dictionary of Doom has no translation. Is it the correct JSON file?")
@ -127,7 +126,7 @@ class LegacyProfileReader(ProfileReader):
quality_definition = current_printer_definition.getMetaDataEntry("quality_definition")
if not quality_definition:
quality_definition = current_printer_definition.getId()
profile.setDefinition(quality_definition)
output_parser["general"]["definition"] = quality_definition
for new_setting in dict_of_doom["translation"]: # Evaluate all new settings that would get a value from the translations.
old_setting_expression = dict_of_doom["translation"][new_setting]
compiled = compile(old_setting_expression, new_setting, "eval")
@ -140,37 +139,34 @@ class LegacyProfileReader(ProfileReader):
definitions = current_printer_definition.findDefinitions(key = new_setting)
if definitions:
if new_value != value_using_defaults and definitions[0].default_value != new_value: # Not equal to the default in the new Cura OR the default in the legacy Cura.
profile.setProperty(new_setting, "value", new_value) # Store the setting in the profile!
output_parser["values"][new_setting] = str(new_value) # Store the setting in the profile!
if len(profile.getAllKeys()) == 0:
if len(output_parser["values"]) == 0:
Logger.log("i", "A legacy profile was imported but everything evaluates to the defaults, creating an empty profile.")
profile.setMetaDataEntry("type", "profile")
# don't know what quality_type it is based on, so use "normal" by default
profile.setMetaDataEntry("quality_type", "normal")
profile.setName(profile_id)
profile.setDirty(True)
output_parser["general"]["version"] = "4"
output_parser["general"]["name"] = profile_id
output_parser["metadata"]["type"] = "quality_changes"
output_parser["metadata"]["quality_type"] = "normal" # Don't know what quality_type it is based on, so use "normal" by default.
output_parser["metadata"]["position"] = "0" # We only support single extrusion.
output_parser["metadata"]["setting_version"] = "5" # What the dictionary of doom is made for.
#Serialise and deserialise in order to perform the version upgrade.
parser = configparser.ConfigParser(interpolation = None)
data = profile.serialize()
parser.read_string(data)
parser["general"]["version"] = "1"
if parser.has_section("values"):
parser["settings"] = parser["values"]
del parser["values"]
# Serialise in order to perform the version upgrade.
stream = io.StringIO()
parser.write(stream)
output_parser.write(stream)
data = stream.getvalue()
profile.deserialize(data)
# The definition can get reset to fdmprinter during the deserialization's upgrade. Here we set the definition
# again.
profile.setDefinition(quality_definition)
profile = InstanceContainer(profile_id)
profile.deserialize(data) # Also performs the version upgrade.
profile.setDirty(True)
#We need to return one extruder stack and one global stack.
global_container_id = container_registry.uniqueName("Global Imported Legacy Profile")
# We duplicate the extruder profile into the global stack.
# This may introduce some settings that are global in the extruder stack and some settings that are per-extruder in the global stack.
# We don't care about that. The engine will ignore them anyway.
global_profile = profile.duplicate(new_id = global_container_id, new_name = profile_id) #Needs to have the same name as the extruder profile.
del global_profile.getMetaData()["position"] # Has no position because it's global.
global_profile.setDirty(True)
profile_definition = "fdmprinter"

View file

@ -0,0 +1,190 @@
# Copyright (c) 2018 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
import configparser # An input for some functions we're testing.
import os.path # To find the integration test .ini files.
import pytest # To register tests with.
import unittest.mock # To mock the application, plug-in and container registry out.
import UM.Application # To mock the application out.
import UM.PluginRegistry # To mock the plug-in registry out.
import UM.Settings.ContainerRegistry # To mock the container registry out.
import UM.Settings.InstanceContainer # To intercept the serialised data from the read() function.
import LegacyProfileReader as LegacyProfileReaderModule # To get the directory of the module.
from LegacyProfileReader import LegacyProfileReader # The module we're testing.
@pytest.fixture
def legacy_profile_reader():
return LegacyProfileReader()
test_prepareDefaultsData = [
{
"defaults":
{
"foo": "bar"
},
"cheese": "delicious"
},
{
"cat": "fluffy",
"dog": "floofy"
}
]
@pytest.mark.parametrize("input", test_prepareDefaultsData)
def test_prepareDefaults(legacy_profile_reader, input):
output = legacy_profile_reader.prepareDefaults(input)
if "defaults" in input:
assert input["defaults"] == output
else:
assert output == {}
test_prepareLocalsData = [
( # Ordinary case.
{ # Parser data.
"profile":
{
"layer_height": "0.2",
"infill_density": "30"
}
},
{ # Defaults.
"layer_height": "0.1",
"infill_density": "20",
"line_width": "0.4"
}
),
( # Empty data.
{ # Parser data.
"profile":
{
}
},
{ # Defaults.
}
),
( # All defaults.
{ # Parser data.
"profile":
{
}
},
{ # Defaults.
"foo": "bar",
"boo": "far"
}
),
( # Multiple config sections.
{ # Parser data.
"some_other_name":
{
"foo": "bar"
},
"profile":
{
"foo": "baz" #Not the same as in some_other_name
}
},
{ # Defaults.
"foo": "bla"
}
)
]
@pytest.mark.parametrize("parser_data, defaults", test_prepareLocalsData)
def test_prepareLocals(legacy_profile_reader, parser_data, defaults):
parser = configparser.ConfigParser()
parser.read_dict(parser_data)
output = legacy_profile_reader.prepareLocals(parser, "profile", defaults)
assert set(defaults.keys()) <= set(output.keys()) # All defaults must be in there.
assert set(parser_data["profile"]) <= set(output.keys()) # All overwritten values must be in there.
for key in output:
if key in parser_data["profile"]:
assert output[key] == parser_data["profile"][key] # If overwritten, must be the overwritten value.
else:
assert output[key] == defaults[key] # Otherwise must be equal to the default.
test_prepareLocalsNoSectionErrorData = [
( # Section does not exist.
{ # Parser data.
"some_other_name":
{
"foo": "bar"
},
},
{ # Defaults.
"foo": "baz"
}
)
]
## Test cases where a key error is expected.
@pytest.mark.parametrize("parser_data, defaults", test_prepareLocalsNoSectionErrorData)
def test_prepareLocalsNoSectionError(legacy_profile_reader, parser_data, defaults):
parser = configparser.ConfigParser()
parser.read_dict(parser_data)
with pytest.raises(configparser.NoSectionError):
legacy_profile_reader.prepareLocals(parser, "profile", defaults)
intercepted_data = ""
@pytest.mark.parametrize("file_name", ["normal_case.ini"])
def test_read(legacy_profile_reader, file_name):
# Mock out all dependencies. Quite a lot!
global_stack = unittest.mock.MagicMock()
global_stack.getProperty = unittest.mock.MagicMock(return_value = 1) # For machine_extruder_count setting.
def getMetaDataEntry(key, default_value = ""):
if key == "quality_definition":
return "mocked_quality_definition"
if key == "has_machine_quality":
return "True"
global_stack.definition.getMetaDataEntry = getMetaDataEntry
global_stack.definition.getId = unittest.mock.MagicMock(return_value = "mocked_global_definition")
application = unittest.mock.MagicMock()
application.getGlobalContainerStack = unittest.mock.MagicMock(return_value = global_stack)
application_getInstance = unittest.mock.MagicMock(return_value = application)
container_registry = unittest.mock.MagicMock()
container_registry_getInstance = unittest.mock.MagicMock(return_value = container_registry)
container_registry.uniqueName = unittest.mock.MagicMock(return_value = "Imported Legacy Profile")
container_registry.findDefinitionContainers = unittest.mock.MagicMock(return_value = [global_stack.definition])
UM.Settings.InstanceContainer.setContainerRegistry(container_registry)
plugin_registry = unittest.mock.MagicMock()
plugin_registry_getInstance = unittest.mock.MagicMock(return_value = plugin_registry)
plugin_registry.getPluginPath = unittest.mock.MagicMock(return_value = os.path.dirname(LegacyProfileReaderModule.__file__))
# Mock out the resulting InstanceContainer so that we can intercept the data before it's passed through the version upgrader.
def deserialize(self, data): # Intercepts the serialised data that we'd perform the version upgrade from when deserializing.
global intercepted_data
intercepted_data = data
parser = configparser.ConfigParser()
parser.read_string(data)
self._metadata["position"] = parser["metadata"]["position"]
def duplicate(self, new_id, new_name):
self._metadata["id"] = new_id
self._metadata["name"] = new_name
return self
with unittest.mock.patch.object(UM.Application.Application, "getInstance", application_getInstance):
with unittest.mock.patch.object(UM.Settings.ContainerRegistry.ContainerRegistry, "getInstance", container_registry_getInstance):
with unittest.mock.patch.object(UM.PluginRegistry.PluginRegistry, "getInstance", plugin_registry_getInstance):
with unittest.mock.patch.object(UM.Settings.InstanceContainer.InstanceContainer, "deserialize", deserialize):
with unittest.mock.patch.object(UM.Settings.InstanceContainer.InstanceContainer, "duplicate", duplicate):
result = legacy_profile_reader.read(os.path.join(os.path.dirname(__file__), file_name))
assert len(result) == 1
# Let's see what's inside the actual output file that we generated.
parser = configparser.ConfigParser()
parser.read_string(intercepted_data)
assert parser["general"]["definition"] == "mocked_quality_definition"
assert parser["general"]["version"] == "4" # Yes, before we upgraded.
assert parser["general"]["name"] == "Imported Legacy Profile" # Because we overwrote uniqueName.
assert parser["metadata"]["type"] == "quality_changes"
assert parser["metadata"]["quality_type"] == "normal"
assert parser["metadata"]["position"] == "0"
assert parser["metadata"]["setting_version"] == "5" # Yes, before we upgraded.

View file

@ -0,0 +1,7 @@
[profile]
foo = bar
boo = far
fill_overlap = 3
[alterations]
some = values

View file

@ -32,7 +32,8 @@ class PostProcessingPlugin(QObject, Extension):
def __init__(self, parent = None) -> None:
QObject.__init__(self, parent)
Extension.__init__(self)
self.addMenuItem(i18n_catalog.i18n("Modify G-Code"), self.showPopup)
self.setMenuName(i18n_catalog.i18nc("@item:inmenu", "Post Processing"))
self.addMenuItem(i18n_catalog.i18nc("@item:inmenu", "Modify G-Code"), self.showPopup)
self._view = None
# Loaded scripts are all scripts that can be used

View file

@ -187,7 +187,8 @@ Item
var result = ""
if (base.technicalDataSheetUrl !== undefined)
{
result += "<a href='%1'>%2</a>".arg(base.technicalDataSheetUrl).arg("Technical Data Sheet")
var tds_name = catalog.i18nc("@action:label", "Technical Data Sheet")
result += "<a href='%1'>%2</a>".arg(base.technicalDataSheetUrl).arg(tds_name)
}
if (base.safetyDataSheetUrl !== undefined)
{
@ -195,7 +196,8 @@ Item
{
result += "<br/>"
}
result += "<a href='%1'>%2</a>".arg(base.safetyDataSheetUrl).arg("Safety Data Sheet")
var sds_name = catalog.i18nc("@action:label", "Safety Data Sheet")
result += "<a href='%1'>%2</a>".arg(base.safetyDataSheetUrl).arg(sds_name)
}
if (base.printingGuidelinesUrl !== undefined)
{
@ -203,7 +205,8 @@ Item
{
result += "<br/>"
}
result += "<a href='%1'>%2</a>".arg(base.printingGuidelinesUrl).arg("Printing Guidelines")
var pg_name = catalog.i18nc("@action:label", "Printing Guidelines")
result += "<a href='%1'>%2</a>".arg(base.printingGuidelinesUrl).arg(pg_name)
}
return result
}

View file

@ -12,7 +12,7 @@ from UM.Qt.ListModel import ListModel
from .ConfigsModel import ConfigsModel
## Model that holds cura packages. By setting the filter property the instances held by this model can be changed.
## Model that holds Cura packages. By setting the filter property the instances held by this model can be changed.
class PackagesModel(ListModel):
def __init__(self, parent = None):
super().__init__(parent)
@ -70,7 +70,7 @@ class PackagesModel(ListModel):
# Links is a list of dictionaries with "title" and "url". Convert this list into a dict so it's easier
# to process.
link_list = package['data']['links'] if 'links' in package['data'] else []
link_list = package["data"]["links"] if "links" in package["data"] else []
links_dict = {d["title"]: d["url"] for d in link_list}
if "author_id" not in package["author"] or "display_name" not in package["author"]:

View file

@ -172,18 +172,18 @@ class Toolbox(QObject, Extension):
self._cloud_api_version = self._getCloudAPIVersion()
self._cloud_api_root = self._getCloudAPIRoot()
self._api_url = "{cloud_api_root}/cura-packages/v{cloud_api_version}/cura/v{sdk_version}".format(
cloud_api_root=self._cloud_api_root,
cloud_api_version=self._cloud_api_version,
sdk_version=self._sdk_version
cloud_api_root = self._cloud_api_root,
cloud_api_version = self._cloud_api_version,
sdk_version = self._sdk_version
)
self._request_urls = {
"authors": QUrl("{base_url}/authors".format(base_url=self._api_url)),
"packages": QUrl("{base_url}/packages".format(base_url=self._api_url)),
"plugins_showcase": QUrl("{base_url}/showcase".format(base_url=self._api_url)),
"plugins_available": QUrl("{base_url}/packages?package_type=plugin".format(base_url=self._api_url)),
"materials_showcase": QUrl("{base_url}/showcase".format(base_url=self._api_url)),
"materials_available": QUrl("{base_url}/packages?package_type=material".format(base_url=self._api_url)),
"materials_generic": QUrl("{base_url}/packages?package_type=material&tags=generic".format(base_url=self._api_url))
"authors": QUrl("{base_url}/authors".format(base_url = self._api_url)),
"packages": QUrl("{base_url}/packages".format(base_url = self._api_url)),
"plugins_showcase": QUrl("{base_url}/showcase".format(base_url = self._api_url)),
"plugins_available": QUrl("{base_url}/packages?package_type=plugin".format(base_url = self._api_url)),
"materials_showcase": QUrl("{base_url}/showcase".format(base_url = self._api_url)),
"materials_available": QUrl("{base_url}/packages?package_type=material".format(base_url = self._api_url)),
"materials_generic": QUrl("{base_url}/packages?package_type=material&tags=generic".format(base_url = self._api_url))
}
# Get the API root for the packages API depending on Cura version settings.
@ -209,11 +209,11 @@ class Toolbox(QObject, Extension):
# Get the packages version depending on Cura version settings.
def _getSDKVersion(self) -> Union[int, str]:
if not hasattr(cura, "CuraVersion"):
return self._plugin_registry.APIVersion
return self._application.getAPIVersion().getMajor()
if not hasattr(cura.CuraVersion, "CuraSDKVersion"): # type: ignore
return self._plugin_registry.APIVersion
return self._application.getAPIVersion().getMajor()
if not cura.CuraVersion.CuraSDKVersion: # type: ignore
return self._plugin_registry.APIVersion
return self._application.getAPIVersion().getMajor()
return cura.CuraVersion.CuraSDKVersion # type: ignore
@pyqtSlot()
@ -299,7 +299,7 @@ class Toolbox(QObject, Extension):
for plugin_id in old_plugin_ids:
# Neither the installed packages nor the packages that are scheduled to remove are old plugins
if plugin_id not in installed_package_ids and plugin_id not in scheduled_to_remove_package_ids:
Logger.log('i', 'Found a plugin that was installed with the old plugin browser: %s', plugin_id)
Logger.log("i", "Found a plugin that was installed with the old plugin browser: %s", plugin_id)
old_metadata = self._plugin_registry.getMetaData(plugin_id)
new_metadata = self._convertPluginMetadata(old_metadata)
@ -511,7 +511,10 @@ class Toolbox(QObject, Extension):
# version, we also need to check if the current one has a lower SDK version. If so, this package should also
# be upgradable.
elif remote_version == local_version:
can_upgrade = local_package.get("sdk_version", 0) < remote_package.get("sdk_version", 0)
# First read sdk_version_semver. If that doesn't exist, read just sdk_version (old version system).
remote_sdk_version = Version(remote_package.get("sdk_version_semver", remote_package.get("sdk_version", 0)))
local_sdk_version = Version(local_package.get("sdk_version_semver", local_package.get("sdk_version", 0)))
can_upgrade = local_sdk_version < remote_sdk_version
return can_upgrade

View file

@ -590,13 +590,27 @@ class ClusterUM3OutputDevice(NetworkedPrinterOutputDevice):
origin_name=change["origin_name"]))
return result
def _createMaterialOutputModel(self, material_data) -> MaterialOutputModel:
containers = ContainerRegistry.getInstance().findInstanceContainers(type="material", GUID=material_data["guid"])
if containers:
color = containers[0].getMetaDataEntry("color_code")
brand = containers[0].getMetaDataEntry("brand")
material_type = containers[0].getMetaDataEntry("material")
name = containers[0].getName()
def _createMaterialOutputModel(self, material_data: Dict[str, Any]) -> "MaterialOutputModel":
material_manager = CuraApplication.getInstance().getMaterialManager()
material_group_list = material_manager.getMaterialGroupListByGUID(material_data["guid"])
# Sort the material groups by "is_read_only = True" first, and then the name alphabetically.
read_only_material_group_list = list(filter(lambda x: x.is_read_only, material_group_list))
non_read_only_material_group_list = list(filter(lambda x: not x.is_read_only, material_group_list))
material_group = None
if read_only_material_group_list:
read_only_material_group_list = sorted(read_only_material_group_list, key = lambda x: x.name)
material_group = read_only_material_group_list[0]
elif non_read_only_material_group_list:
non_read_only_material_group_list = sorted(non_read_only_material_group_list, key = lambda x: x.name)
material_group = non_read_only_material_group_list[0]
if material_group:
container = material_group.root_material_node.getContainer()
color = container.getMetaDataEntry("color_code")
brand = container.getMetaDataEntry("brand")
material_type = container.getMetaDataEntry("material")
name = container.getName()
else:
Logger.log("w",
"Unable to find material with guid {guid}. Using data as provided by cluster".format(

View file

@ -7,7 +7,6 @@
"author": "3Dator GmbH",
"manufacturer": "3Dator GmbH",
"file_formats": "text/x-gcode",
"icon": "icon_ultimaker2",
"supports_usb_connection": true,
"platform": "3dator_platform.stl",
"machine_extruder_trains":

View file

@ -8,7 +8,6 @@
"author": "TheTobby",
"manufacturer": "Anycubic",
"file_formats": "text/x-gcode",
"icon": "icon_ultimaker2",
"platform": "anycubic_i3_mega_platform.stl",
"has_materials": false,
"has_machine_quality": true,

View file

@ -8,7 +8,6 @@
"manufacturer": "Deltacomb 3D",
"category": "Other",
"file_formats": "text/x-gcode",
"icon": "icon_ultimaker2",
"platform": "deltacomb.stl",
"has_machine_quality": true,
"machine_extruder_trains":

View file

@ -9,7 +9,6 @@
"category": "Other",
"file_formats": "text/x-gcode",
"platform": "fabtotum_platform.stl",
"icon": "fabtotum_platform.png",
"has_machine_quality": true,
"has_variants": true,
"variants_name": "Head",

View file

@ -78,7 +78,7 @@
"machine_extruder_start_code":
{
"label": "Extruder Start G-Code",
"description": "Start g-code to execute whenever turning the extruder on.",
"description": "Start g-code to execute when switching to this extruder.",
"type": "str",
"default_value": "",
"settable_per_mesh": false,
@ -124,7 +124,7 @@
"machine_extruder_end_code":
{
"label": "Extruder End G-Code",
"description": "End g-code to execute whenever turning the extruder off.",
"description": "End g-code to execute when switching away from this extruder.",
"type": "str",
"default_value": "",
"settable_per_mesh": false,

View file

@ -2406,7 +2406,7 @@
"switch_extruder_retraction_amount":
{
"label": "Nozzle Switch Retraction Distance",
"description": "The amount of retraction: Set at 0 for no retraction at all. This should generally be the same as the length of the heat zone.",
"description": "The amount of retraction when switching extruders. Set to 0 for no retraction at all. This should generally be the same as the length of the heat zone.",
"type": "float",
"unit": "mm",
"enabled": "retraction_enable",
@ -4139,6 +4139,20 @@
"limit_to_extruder": "support_infill_extruder_nr",
"settable_per_mesh": false
},
"minimum_support_area":
{
"label": "Minimum Support Area",
"description": "Minimum area size for support polygons. Polygons which have an area smaller than this value will not be generated.",
"unit": "mm²",
"type": "float",
"default_value": 0.0,
"minimum_value": "0",
"enabled": "support_enable",
"limit_to_extruder": "support_infill_extruder_nr",
"settable_per_mesh": true,
"fabricate_enabled": true,
"intermediate_enabled": true
},
"support_interface_enable":
{
"label": "Enable Support Interface",
@ -4378,6 +4392,94 @@
}
}
},
"minimum_interface_area":
{
"label": "Minimum Support Interface Area",
"description": "Minimum area size for support interface polygons. Polygons which have an area smaller than this value will not be generated.",
"unit": "mm²",
"type": "float",
"default_value": 1.0,
"minimum_value": "0",
"minimum_value_warning": "minimum_support_area",
"limit_to_extruder": "support_interface_extruder_nr",
"enabled": "support_interface_enable and support_enable",
"settable_per_mesh": true,
"children":
{
"minimum_roof_area":
{
"label": "Minimum Support Roof Area",
"description": "Minimum area size for the roofs of the support. Polygons which have an area smaller than this value will not be generated.",
"unit": "mm²",
"type": "float",
"default_value": 1.0,
"value": "extruderValue(support_roof_extruder_nr, 'minimum_interface_area')",
"minimum_value": "0",
"minimum_value_warning": "minimum_support_area",
"limit_to_extruder": "support_roof_extruder_nr",
"enabled": "support_roof_enable and support_enable",
"settable_per_mesh": true
},
"minimum_bottom_area":
{
"label": "Minimum Support Floor Area",
"description": "Minimum area size for the floors of the support. Polygons which have an area smaller than this value will not be generated.",
"unit": "mm²",
"type": "float",
"default_value": 1.0,
"value": "extruderValue(support_bottom_extruder_nr, 'minimum_interface_area')",
"minimum_value": "0",
"minimum_value_warning": "minimum_support_area",
"limit_to_extruder": "support_bottom_extruder_nr",
"enabled": "support_bottom_enable and support_enable",
"settable_per_mesh": true
}
}
},
"support_interface_offset":
{
"label": "Support Interface Horizontal Expansion",
"description": "Amount of offset applied to the support interface polygons.",
"unit": "mm",
"type": "float",
"default_value": 0.0,
"maximum_value": "extruderValue(support_extruder_nr, 'support_offset')",
"limit_to_extruder": "support_interface_extruder_nr",
"enabled": "support_interface_enable and (support_enable or support_tree_enable)",
"settable_per_mesh": false,
"settable_per_extruder": true,
"children":
{
"support_roof_offset":
{
"label": "Support Roof Horizontal Expansion",
"description": "Amount of offset applied to the roofs of the support.",
"unit": "mm",
"type": "float",
"default_value": 0.0,
"value": "extruderValue(support_roof_extruder_nr, 'support_interface_offset')",
"maximum_value": "extruderValue(support_extruder_nr, 'support_offset')",
"limit_to_extruder": "support_roof_extruder_nr",
"enabled": "support_roof_enable and (support_enable or support_tree_enable)",
"settable_per_mesh": false,
"settable_per_extruder": true
},
"support_bottom_offset":
{
"label": "Support Floor Horizontal Expansion",
"description": "Amount of offset applied to the floors of the support.",
"unit": "mm",
"type": "float",
"default_value": 0.0,
"value": "extruderValue(support_bottom_extruder_nr, 'support_interface_offset')",
"maximum_value": "extruderValue(support_extruder_nr, 'support_offset')",
"limit_to_extruder": "support_bottom_extruder_nr",
"enabled": "support_bottom_enable and (support_enable or support_tree_enable)",
"settable_per_mesh": false,
"settable_per_extruder": true
}
}
},
"support_fan_enable":
{
"label": "Fan Speed Override",

View file

@ -7,7 +7,6 @@
"author": "Simon Cor",
"manufacturer": "German RepRap",
"file_formats": "text/x-gcode",
"icon": "icon_ultimaker.png",
"platform": "grr_neo_platform.stl",
"machine_extruder_trains":
{

View file

@ -7,7 +7,6 @@
"author": "Claudio Sampaio (Patola)",
"manufacturer": "Other",
"file_formats": "text/x-gcode",
"icon": "icon_ultimaker2",
"platform": "kossel_platform.stl",
"platform_offset": [0, -0.25, 0],
"machine_extruder_trains":

View file

@ -7,7 +7,6 @@
"author": "Chris Petersen",
"manufacturer": "OpenBeam",
"file_formats": "text/x-gcode",
"icon": "icon_ultimaker2",
"platform": "kossel_pro_build_platform.stl",
"platform_offset": [0, -0.25, 0],
"machine_extruder_trains":

View file

@ -7,7 +7,6 @@
"author": "makeR",
"manufacturer": "makeR",
"file_formats": "text/x-gcode",
"icon": "icon_ultimaker2",
"platform": "makeR_pegasus_platform.stl",
"platform_offset": [-200, -10, 200],
"machine_extruder_trains":

View file

@ -7,7 +7,6 @@
"author": "makeR",
"manufacturer": "makeR",
"file_formats": "text/x-gcode",
"icon": "icon_ultimaker2",
"platform": "makeR_prusa_tairona_i3_platform.stl",
"platform_offset": [-2, 0, 0],
"machine_extruder_trains":

View file

@ -7,7 +7,6 @@
"author": "tvlgiao",
"manufacturer": "3DMaker",
"file_formats": "text/x-gcode;application/x-stl-ascii;application/x-stl-binary;application/x-wavefront-obj",
"icon": "icon_ultimaker2.png",
"platform": "makerstarter_platform.stl",
"preferred_quality_type": "draft",
"machine_extruder_trains":

View file

@ -7,7 +7,6 @@
"author": "Quillford",
"manufacturer": "Prusajr",
"file_formats": "text/x-gcode",
"icon": "icon_ultimaker2",
"platform": "prusai3_platform.stl",
"machine_extruder_trains":
{

View file

@ -7,7 +7,6 @@
"author": "Apsu, Nounours2099",
"manufacturer": "Prusa Research",
"file_formats": "text/x-gcode",
"icon": "icon_ultimaker2",
"platform": "prusai3_platform.stl",
"has_materials": true,
"machine_extruder_trains":

View file

@ -7,7 +7,6 @@
"author": "guigashm",
"manufacturer": "Prusajr",
"file_formats": "text/x-gcode",
"icon": "icon_ultimaker2.png",
"platform": "prusai3_xl_platform.stl",
"machine_extruder_trains":
{

View file

@ -7,7 +7,6 @@
"author": "PouncingIguana, JJ",
"manufacturer": "SeeMeCNC",
"file_formats": "text/x-gcode",
"icon": "icon_ultimaker2",
"platform": "artemis_platform.stl",
"has_materials": true,
"machine_extruder_trains":

View file

@ -7,7 +7,6 @@
"author": "PouncingIguana, JJ",
"manufacturer": "SeeMeCNC",
"file_formats": "text/x-gcode",
"icon": "icon_ultimaker2",
"platform": "rostock_platform.stl",
"has_materials": true,
"machine_extruder_trains":

View file

@ -7,7 +7,6 @@
"author": "TheTobby",
"manufacturer": "Tevo",
"file_formats": "text/x-gcode",
"icon": "icon_ultimaker2",
"has_materials": false,
"has_machine_quality": true,
"platform": "tevo_blackwidow.stl",

View file

@ -8,7 +8,6 @@
"author": "TheAssassin",
"manufacturer": "Tevo",
"file_formats": "text/x-gcode",
"icon": "icon_ultimaker2",
"platform": "prusai3_platform.stl",
"machine_extruder_trains":
{

View file

@ -7,7 +7,6 @@
"author": "nean",
"manufacturer": "Tevo",
"file_formats": "text/x-gcode",
"icon": "icon_ultimaker2.png",
"has_materials": true,
"machine_extruder_trains": {
"0": "tevo_tornado_extruder_0"

View file

@ -9,7 +9,6 @@
"manufacturer": "uBuild-3D",
"category": "Other",
"file_formats": "text/x-gcode",
"icon": "icon_uBuild-3D",
"platform": "mr_bot_280_platform.stl",
"has_materials": true,
"preferred_quality_type": "draft",

View file

@ -8,7 +8,6 @@
"manufacturer": "Ultimaker B.V.",
"weight": 3,
"file_formats": "text/x-gcode",
"icon": "icon_ultimaker2.png",
"platform": "ultimaker2_platform.obj",
"platform_texture": "Ultimaker2backplate.png",
"platform_offset": [9, 0, 0],

View file

@ -8,7 +8,6 @@
"quality_definition": "ultimaker2",
"weight": 3,
"file_formats": "text/x-gcode",
"icon": "icon_ultimaker2.png",
"platform": "ultimaker2_platform.obj",
"platform_texture": "Ultimaker2Extendedbackplate.png",
"machine_extruder_trains":

View file

@ -8,7 +8,6 @@
"quality_definition": "ultimaker2",
"weight": 3,
"file_formats": "text/x-gcode",
"icon": "icon_ultimaker2.png",
"platform": "ultimaker2go_platform.obj",
"platform_texture": "Ultimaker2Gobackplate.png",
"platform_offset": [0, 0, 0],

View file

@ -8,7 +8,6 @@
"manufacturer": "Ultimaker B.V.",
"weight": 4,
"file_formats": "text/x-gcode",
"icon": "icon_ultimaker.png",
"platform": "ultimaker_platform.stl",
"has_materials": true,
"has_machine_quality": true,

View file

@ -8,7 +8,6 @@
"manufacturer": "Ultimaker B.V.",
"weight": 4,
"file_formats": "text/x-gcode",
"icon": "icon_ultimaker.png",
"platform": "ultimaker_platform.stl",
"has_materials": true,
"has_machine_quality": true,

View file

@ -7,7 +7,6 @@
"manufacturer": "Ultimaker B.V.",
"weight": 4,
"file_formats": "text/x-gcode",
"icon": "icon_ultimaker.png",
"platform": "ultimaker2_platform.obj",
"platform_texture": "UltimakerPlusbackplate.png",
"quality_definition": "ultimaker_original",

View file

@ -6,7 +6,6 @@
"author": "Unimatech",
"manufacturer": "Unimatech",
"file_formats": "text/x-gcode",
"icon": "icon_ultimaker2.png",
"machine_extruder_trains":
{
"0": "uniqbot_one_extruder_0"

View file

@ -6,7 +6,6 @@
"visible": true,
"manufacturer": "Velleman",
"file_formats": "text/x-gcode",
"icon": "icon_ultimaker2",
"platform": "Vertex_build_panel.stl",
"platform_offset": [0, -3, 0],
"supports_usb_connection": true,

View file

@ -6,7 +6,6 @@
"visible": true,
"manufacturer": "Velleman",
"file_formats": "text/x-gcode",
"icon": "icon_ultimaker2",
"platform": "Vertex_build_panel.stl",
"platform_offset": [0, -3, 0],
"machine_extruder_trains": {

View file

@ -7,7 +7,6 @@
"author": "Ricardo Snoek",
"manufacturer": "Wanhao",
"file_formats": "text/x-gcode",
"icon": "wanhao-icon.png",
"has_materials": true,
"platform": "wanhao_225_145_platform.obj",
"platform_texture": "Wanhaobackplate.png",

View file

@ -7,7 +7,6 @@
"author": "Ricardo Snoek",
"manufacturer": "Wanhao",
"file_formats": "text/x-gcode",
"icon": "wanhao-icon.png",
"has_materials": true,
"platform": "wanhao_200_200_platform.obj",
"platform_texture": "Wanhaobackplate.png",

View file

@ -7,7 +7,6 @@
"author": "Ricardo Snoek",
"manufacturer": "Wanhao",
"file_formats": "text/x-gcode",
"icon": "wanhao-icon.png",
"has_materials": true,
"platform": "wanhao_200_200_platform.obj",
"platform_texture": "Wanhaobackplate.png",

View file

@ -7,7 +7,6 @@
"author": "Ricardo Snoek",
"manufacturer": "Wanhao",
"file_formats": "text/x-gcode",
"icon": "wanhao-icon.png",
"has_materials": true,
"platform": "wanhao_300_200_platform.obj",
"platform_texture": "Wanhaobackplate.png",

View file

@ -7,7 +7,6 @@
"author": "Ricardo Snoek",
"manufacturer": "Wanhao",
"file_formats": "text/x-gcode",
"icon": "wanhao-icon.png",
"has_materials": true,
"platform": "wanhao_300_200_platform.obj",
"platform_texture": "Wanhaobackplate.png",

View file

@ -7,7 +7,6 @@
"author": "Ricardo Snoek",
"manufacturer": "Wanhao",
"file_formats": "text/x-gcode",
"icon": "wanhao-icon.png",
"has_materials": true,
"platform": "wanhao_200_200_platform.obj",
"platform_texture": "Wanhaobackplate.png",

View file

@ -7,7 +7,6 @@
"author": "Ricardo Snoek",
"manufacturer": "Wanhao",
"file_formats": "text/x-gcode",
"icon": "wanhao-icon.png",
"has_materials": true,
"platform": "wanhao_110_110_platform.obj",
"platform_texture": "Wanhaobackplate.png",

View file

@ -7,7 +7,6 @@
"author": "Ricardo Snoek",
"manufacturer": "Wanhao",
"file_formats": "text/x-gcode",
"icon": "wanhao-icon.png",
"has_materials": true,
"platform": "wanhao_200_200_platform.obj",
"platform_texture": "Wanhaobackplate.png",

File diff suppressed because it is too large Load diff

Binary file not shown.

Binary file not shown.

View file

@ -168,6 +168,7 @@ Item
id: manageMaterialsAction
text: catalog.i18nc("@action:inmenu", "Manage Materials...")
iconName: "configure"
shortcut: "Ctrl+K"
}
Action
@ -182,7 +183,7 @@ Item
{
id: resetProfileAction;
enabled: Cura.MachineManager.hasUserSettings
text: catalog.i18nc("@action:inmenu menubar:profile","&Discard current changes");
text: catalog.i18nc("@action:inmenu menubar:profile", "&Discard current changes");
onTriggered:
{
forceActiveFocus();
@ -194,20 +195,21 @@ Item
{
id: addProfileAction;
enabled: !Cura.MachineManager.stacksHaveErrors && Cura.MachineManager.hasUserSettings
text: catalog.i18nc("@action:inmenu menubar:profile","&Create profile from current settings/overrides...");
text: catalog.i18nc("@action:inmenu menubar:profile", "&Create profile from current settings/overrides...");
}
Action
{
id: manageProfilesAction;
text: catalog.i18nc("@action:inmenu menubar:profile","Manage Profiles...");
iconName: "configure";
id: manageProfilesAction
text: catalog.i18nc("@action:inmenu menubar:profile", "Manage Profiles...")
iconName: "configure"
shortcut: "Ctrl+J"
}
Action
{
id: documentationAction;
text: catalog.i18nc("@action:inmenu menubar:help","Show Online &Documentation");
text: catalog.i18nc("@action:inmenu menubar:help", "Show Online &Documentation");
iconName: "help-contents";
shortcut: StandardKey.Help;
onTriggered: CuraActions.openDocumentation();
@ -215,7 +217,7 @@ Item
Action {
id: reportBugAction;
text: catalog.i18nc("@action:inmenu menubar:help","Report a &Bug");
text: catalog.i18nc("@action:inmenu menubar:help", "Report a &Bug");
iconName: "tools-report-bug";
onTriggered: CuraActions.openBugReportPage();
}
@ -223,7 +225,7 @@ Item
Action
{
id: aboutAction;
text: catalog.i18nc("@action:inmenu menubar:help","About...");
text: catalog.i18nc("@action:inmenu menubar:help", "About...");
iconName: "help-about";
}

View file

@ -25,7 +25,8 @@ UM.Dialog
width: minimumWidth
height: minimumHeight
flags: {
flags:
{
var window_flags = Qt.Dialog | Qt.CustomizeWindowHint | Qt.WindowTitleHint;
if (Cura.MachineManager.activeDefinitionId !== "") //Disallow closing the window if we have no active printer yet. You MUST add a printer.
{
@ -45,10 +46,52 @@ UM.Dialog
}
signal machineAdded(string id)
function getMachineName()
{
var name = machineList.model.getItem(machineList.currentIndex) != undefined ? machineList.model.getItem(machineList.currentIndex).name : ""
return name
if (machineList.model.getItem(machineList.currentIndex) != undefined)
{
return machineList.model.getItem(machineList.currentIndex).name;
}
return "";
}
function getMachineMetaDataEntry(key)
{
if (machineList.model.getItem(machineList.currentIndex) != undefined)
{
return machineList.model.getItem(machineList.currentIndex).metadata[key];
}
return "";
}
Label
{
id: titleLabel
anchors
{
top: parent.top
left: parent.left
topMargin: UM.Theme.getSize("default_margin").height
}
text: catalog.i18nc("@title:tab", "Add a printer to Cura")
font.pointSize: 18
}
Label
{
id: captionLabel
anchors
{
left: parent.left
top: titleLabel.bottom
topMargin: UM.Theme.getSize("default_margin").height
}
text: catalog.i18nc("@title:tab", "Select the printer you want to use from the list below.\n\nIf your printer is not in the list, use the \"Custom FFF Printer\" from the \"Custom\" category and adjust the settings to match your printer in the next dialog.")
width: parent.width
wrapMode: Text.WordWrap
}
ScrollView
@ -57,13 +100,22 @@ UM.Dialog
anchors
{
left: parent.left;
top: parent.top;
right: parent.right;
bottom: machineNameRow.top;
top: captionLabel.visible ? captionLabel.bottom : parent.top;
topMargin: captionLabel.visible ? UM.Theme.getSize("default_margin").height : 0;
bottom: addPrinterButton.top;
bottomMargin: UM.Theme.getSize("default_margin").height
}
width: Math.round(parent.width * 0.45)
frameVisible: true;
Rectangle
{
parent: viewport
anchors.fill: parent
color: palette.light
}
ListView
{
id: machineList
@ -115,11 +167,14 @@ UM.Dialog
onClicked:
{
base.activeCategory = section;
if (machineList.model.getItem(machineList.currentIndex).section != section) {
if (machineList.model.getItem(machineList.currentIndex).section != section)
{
// Find the first machine from this section
for(var i = 0; i < machineList.model.rowCount(); i++) {
for(var i = 0; i < machineList.model.rowCount(); i++)
{
var item = machineList.model.getItem(i);
if (item.section == section) {
if (item.section == section)
{
machineList.currentIndex = i;
break;
}
@ -184,32 +239,76 @@ UM.Dialog
}
}
Row
Column
{
id: machineNameRow
anchors.bottom:parent.bottom
spacing: UM.Theme.getSize("default_margin").width
Label
anchors
{
text: catalog.i18nc("@label", "Printer Name:")
anchors.verticalCenter: machineName.verticalCenter
top: machinesHolder.top
left: machinesHolder.right
right: parent.right
leftMargin: UM.Theme.getSize("default_margin").width
}
TextField
spacing: UM.Theme.getSize("default_margin").height
Label
{
id: machineName
width: parent.width
wrapMode: Text.WordWrap
text: getMachineName()
implicitWidth: UM.Theme.getSize("standard_list_input").width
maximumLength: 40
//validator: Cura.MachineNameValidator { } //TODO: Gives a segfault in PyQt5.6. For now, we must use a signal on text changed.
validator: RegExpValidator
font.pointSize: 16
elide: Text.ElideRight
}
Grid
{
width: parent.width
columns: 2
rowSpacing: UM.Theme.getSize("default_lining").height
columnSpacing: UM.Theme.getSize("default_margin").width
verticalItemAlignment: Grid.AlignVCenter
Label
{
regExp: {
machineName.machine_name_validator.machineNameRegex
}
wrapMode: Text.WordWrap
text: catalog.i18nc("@label", "Manufacturer")
}
Label
{
width: Math.floor(parent.width * 0.65)
wrapMode: Text.WordWrap
text: getMachineMetaDataEntry("manufacturer")
}
Label
{
wrapMode: Text.WordWrap
text: catalog.i18nc("@label", "Author")
}
Label
{
width: Math.floor(parent.width * 0.75)
wrapMode: Text.WordWrap
text: getMachineMetaDataEntry("author")
}
Label
{
wrapMode: Text.WordWrap
text: catalog.i18nc("@label", "Printer Name")
}
TextField
{
id: machineName
text: getMachineName()
width: Math.floor(parent.width * 0.75)
implicitWidth: UM.Theme.getSize("standard_list_input").width
maximumLength: 40
//validator: Cura.MachineNameValidator { } //TODO: Gives a segfault in PyQt5.6. For now, we must use a signal on text changed.
validator: RegExpValidator
{
regExp: {
machineName.machine_name_validator.machineNameRegex
}
}
property var machine_name_validator: Cura.MachineNameValidator { }
}
property var machine_name_validator: Cura.MachineNameValidator { }
}
}

View file

@ -152,7 +152,7 @@ SettingItem
maximumLength: (definition.type == "str" || definition.type == "[int]") ? -1 : 10;
clip: true; //Hide any text that exceeds the width of the text box.
validator: RegExpValidator { regExp: (definition.type == "[int]") ? /^\[?(\s*-?[0-9]{0,9}\s*,)*(\s*-?[0-9]{0,9})\s*\]?$/ : (definition.type == "int") ? /^-?[0-9]{0,10}$/ : (definition.type == "float") ? /^-?[0-9]{0,9}[.,]?[0-9]{0,10}$/ : /^.*$/ } // definition.type property from parent loader used to disallow fractional number entry
validator: RegExpValidator { regExp: (definition.type == "[int]") ? /^\[?(\s*-?[0-9]{0,9}\s*,)*(\s*-?[0-9]{0,9})\s*\]?$/ : (definition.type == "int") ? /^-?[0-9]{0,10}$/ : (definition.type == "float") ? /^-?[0-9]{0,9}[.,]?[0-9]{0,3}$/ : /^.*$/ } // definition.type property from parent loader used to disallow fractional number entry
Binding
{

View file

@ -489,7 +489,7 @@ Column
Label
{
id: bulidplateLabel
id: buildplateLabel
text: catalog.i18nc("@label", "Build plate");
width: Math.floor(parent.width * 0.45 - UM.Theme.getSize("default_margin").width)
height: parent.height

View file

@ -8,7 +8,7 @@ setting_version = 5
type = quality
quality_type = fast
weight = -1
material = fabtotum_abs
material = generic_abs
[values]
adhesion_type = raft

View file

@ -8,7 +8,7 @@ setting_version = 5
type = quality
quality_type = high
weight = 1
material = fabtotum_abs
material = generic_abs
[values]
adhesion_type = raft

View file

@ -8,7 +8,7 @@ setting_version = 5
type = quality
quality_type = normal
weight = 0
material = fabtotum_abs
material = generic_abs
[values]
adhesion_type = raft

View file

@ -8,7 +8,7 @@ setting_version = 5
type = quality
quality_type = fast
weight = -1
material = fabtotum_nylon
material = generic_nylon
[values]
adhesion_type = raft

View file

@ -8,7 +8,7 @@ setting_version = 5
type = quality
quality_type = high
weight = 1
material = fabtotum_nylon
material = generic_nylon
[values]
adhesion_type = raft

View file

@ -8,7 +8,7 @@ setting_version = 5
type = quality
quality_type = normal
weight = 0
material = fabtotum_nylon
material = generic_nylon
[values]
adhesion_type = raft

View file

@ -8,7 +8,7 @@ setting_version = 5
type = quality
quality_type = fast
weight = -1
material = fabtotum_pla
material = generic_pla
[values]
adhesion_type = skirt

View file

@ -8,7 +8,7 @@ setting_version = 5
type = quality
quality_type = high
weight = 1
material = fabtotum_pla
material = generic_pla
[values]
adhesion_type = skirt

View file

@ -8,7 +8,7 @@ setting_version = 5
type = quality
quality_type = normal
weight = 0
material = fabtotum_pla
material = generic_pla
[values]
adhesion_type = skirt

View file

@ -6,7 +6,7 @@ name = Fast Quality
[metadata]
type = quality
setting_version = 5
material = fabtotum_tpu
material = generic_tpu
quality_type = fast
weight = -1

View file

@ -6,7 +6,7 @@ name = High Quality
[metadata]
type = quality
setting_version = 5
material = fabtotum_tpu
material = generic_tpu
quality_type = high
weight = 1

View file

@ -6,7 +6,7 @@ name = Normal Quality
[metadata]
type = quality
setting_version = 5
material = fabtotum_TPU
material = generic_tpu
quality_type = normal
weight = 0

View file

@ -31,11 +31,11 @@ line_width = =machine_nozzle_size * 0.95
machine_min_cool_heat_time_window = 15
machine_nozzle_cool_down_speed = 0.5
machine_nozzle_heat_up_speed = 2.5
material_final_print_temperature = =material_print_temperature - 21
material_final_print_temperature = =material_print_temperature
material_flow = 106
material_initial_print_temperature = =material_print_temperature - 16
material_initial_print_temperature = =material_print_temperature
material_print_temperature = =default_material_print_temperature + 2
material_print_temperature_layer_0 = =default_material_print_temperature + 2
material_print_temperature_layer_0 = =material_print_temperature + 15
material_standby_temperature = 100
multiple_mesh_overlap = 0
prime_tower_wipe_enabled = True

View file

@ -31,11 +31,11 @@ line_width = =machine_nozzle_size * 0.95
machine_min_cool_heat_time_window = 15
machine_nozzle_cool_down_speed = 0.5
machine_nozzle_heat_up_speed = 2.5
material_final_print_temperature = =material_print_temperature - 21
material_final_print_temperature = =material_print_temperature
material_flow = 106
material_initial_print_temperature = =material_print_temperature - 16
material_initial_print_temperature = =material_print_temperature
material_print_temperature = =default_material_print_temperature + 2
material_print_temperature_layer_0 = =default_material_print_temperature + 2
material_print_temperature_layer_0 = =material_print_temperature + 15
material_standby_temperature = 100
multiple_mesh_overlap = 0
prime_tower_wipe_enabled = True

View file

@ -30,10 +30,10 @@ line_width = =machine_nozzle_size * 0.95
machine_min_cool_heat_time_window = 15
machine_nozzle_cool_down_speed = 0.5
machine_nozzle_heat_up_speed = 2.5
material_final_print_temperature = =material_print_temperature - 21
material_final_print_temperature = =material_print_temperature
material_flow = 106
material_initial_print_temperature = =material_print_temperature - 16
material_print_temperature_layer_0 = =default_material_print_temperature
material_initial_print_temperature = =material_print_temperature
material_print_temperature_layer_0 = =material_print_temperature + 17
material_standby_temperature = 100
multiple_mesh_overlap = 0
prime_tower_wipe_enabled = True

View file

@ -25,11 +25,11 @@ jerk_support = =math.ceil(jerk_print * 25 / 25)
jerk_wall_0 = =math.ceil(jerk_wall * 15 / 25)
machine_nozzle_cool_down_speed = 0.5
machine_nozzle_heat_up_speed = 2.5
material_final_print_temperature = =material_print_temperature - 21
material_final_print_temperature = =material_print_temperature
material_flow = 105
material_initial_print_temperature = =material_print_temperature - 16
material_initial_print_temperature = =material_print_temperature
material_print_temperature = =default_material_print_temperature - 2
material_print_temperature_layer_0 = =material_print_temperature + 4
material_print_temperature_layer_0 = =material_print_temperature + 19
material_standby_temperature = 100
multiple_mesh_overlap = 0.2
prime_tower_enable = True

View file

@ -26,11 +26,11 @@ jerk_wall_0 = =math.ceil(jerk_wall * 15 / 25)
layer_height = 0.4
machine_nozzle_cool_down_speed = 0.5
machine_nozzle_heat_up_speed = 2.5
material_final_print_temperature = =material_print_temperature - 21
material_final_print_temperature = =material_print_temperature
material_flow = 105
material_initial_print_temperature = =material_print_temperature - 16
material_initial_print_temperature = =material_print_temperature
material_print_temperature = =default_material_print_temperature + 2
material_print_temperature_layer_0 = =material_print_temperature
material_print_temperature_layer_0 = =material_print_temperature +15
material_standby_temperature = 100
multiple_mesh_overlap = 0.2
prime_tower_enable = True

View file

@ -26,10 +26,10 @@ jerk_wall_0 = =math.ceil(jerk_wall * 15 / 25)
layer_height = 0.3
machine_nozzle_cool_down_speed = 0.5
machine_nozzle_heat_up_speed = 2.5
material_final_print_temperature = =material_print_temperature - 21
material_final_print_temperature = =material_print_temperature
material_flow = 105
material_initial_print_temperature = =material_print_temperature - 16
material_print_temperature_layer_0 = =material_print_temperature + 2
material_initial_print_temperature = =material_print_temperature
material_print_temperature_layer_0 = =material_print_temperature + 17
material_standby_temperature = 100
multiple_mesh_overlap = 0.2
prime_tower_enable = True

View file

@ -30,11 +30,11 @@ line_width = =machine_nozzle_size * 0.95
machine_min_cool_heat_time_window = 15
machine_nozzle_cool_down_speed = 0.5
machine_nozzle_heat_up_speed = 2.5
material_final_print_temperature = =material_print_temperature - 21
material_final_print_temperature = =material_print_temperature
material_flow = 106
material_initial_print_temperature = =material_print_temperature - 16
material_initial_print_temperature = =material_print_temperature
material_print_temperature = =default_material_print_temperature + 2
material_print_temperature_layer_0 = =default_material_print_temperature + 2
material_print_temperature_layer_0 = =material_print_temperature + 15
material_standby_temperature = 100
multiple_mesh_overlap = 0
prime_tower_wipe_enabled = True

View file

@ -30,11 +30,11 @@ line_width = =machine_nozzle_size * 0.95
machine_min_cool_heat_time_window = 15
machine_nozzle_cool_down_speed = 0.5
machine_nozzle_heat_up_speed = 2.5
material_final_print_temperature = =material_print_temperature - 21
material_final_print_temperature = =material_print_temperature
material_flow = 106
material_initial_print_temperature = =material_print_temperature - 16
material_initial_print_temperature = =material_print_temperature
material_print_temperature = =default_material_print_temperature + 2
material_print_temperature_layer_0 = =default_material_print_temperature + 2
material_print_temperature_layer_0 = =material_print_temperature + 15
material_standby_temperature = 100
multiple_mesh_overlap = 0
prime_tower_wipe_enabled = True

View file

@ -30,10 +30,10 @@ line_width = =machine_nozzle_size * 0.95
machine_min_cool_heat_time_window = 15
machine_nozzle_cool_down_speed = 0.5
machine_nozzle_heat_up_speed = 2.5
material_final_print_temperature = =material_print_temperature - 21
material_final_print_temperature = =material_print_temperature
material_flow = 106
material_initial_print_temperature = =material_print_temperature - 16
material_print_temperature_layer_0 = =default_material_print_temperature
material_initial_print_temperature = =material_print_temperature
material_print_temperature_layer_0 = =material_print_temperature + 17
material_standby_temperature = 100
multiple_mesh_overlap = 0
prime_tower_wipe_enabled = True

View file

@ -23,11 +23,11 @@ jerk_support = =math.ceil(jerk_print * 25 / 25)
jerk_wall_0 = =math.ceil(jerk_wall * 15 / 25)
machine_nozzle_cool_down_speed = 0.5
machine_nozzle_heat_up_speed = 2.5
material_final_print_temperature = =material_print_temperature - 21
material_final_print_temperature = =material_print_temperature
material_flow = 105
material_initial_print_temperature = =material_print_temperature - 16
material_initial_print_temperature = =material_print_temperature
material_print_temperature = =default_material_print_temperature - 2
material_print_temperature_layer_0 = =material_print_temperature + 4
material_print_temperature_layer_0 = =material_print_temperature + 19
material_standby_temperature = 100
multiple_mesh_overlap = 0.2
prime_tower_enable = True

View file

@ -24,11 +24,11 @@ jerk_support = =math.ceil(jerk_print * 25 / 25)
jerk_wall_0 = =math.ceil(jerk_wall * 15 / 25)
machine_nozzle_cool_down_speed = 0.5
machine_nozzle_heat_up_speed = 2.5
material_final_print_temperature = =material_print_temperature - 21
material_final_print_temperature = =material_print_temperature
material_flow = 105
material_initial_print_temperature = =material_print_temperature - 16
material_initial_print_temperature = =material_print_temperature
material_print_temperature = =default_material_print_temperature + 2
material_print_temperature_layer_0 = =material_print_temperature
material_print_temperature_layer_0 = =material_print_temperature + 15
material_standby_temperature = 100
multiple_mesh_overlap = 0.2
prime_tower_enable = True

View file

@ -24,10 +24,10 @@ jerk_support = =math.ceil(jerk_print * 25 / 25)
jerk_wall_0 = =math.ceil(jerk_wall * 15 / 25)
machine_nozzle_cool_down_speed = 0.5
machine_nozzle_heat_up_speed = 2.5
material_final_print_temperature = =material_print_temperature - 21
material_final_print_temperature = =material_print_temperature
material_flow = 105
material_initial_print_temperature = =material_print_temperature - 16
material_print_temperature_layer_0 = =material_print_temperature + 2
material_initial_print_temperature = =material_print_temperature
material_print_temperature_layer_0 = =material_print_temperature + 17
material_standby_temperature = 100
multiple_mesh_overlap = 0.2
prime_tower_enable = True

View file

@ -8,7 +8,7 @@ setting_version = 5
type = quality
quality_type = fast
weight = 1
material = zyyx_pro_flex
material = generic_tpu
[values]
layer_height = 0.3

View file

@ -8,7 +8,7 @@ setting_version = 5
type = quality
quality_type = fine
weight = 3
material = zyyx_pro_flex
material = generic_tpu
[values]
layer_height = 0.12

View file

@ -8,7 +8,7 @@ setting_version = 5
type = quality
quality_type = normal
weight = 2
material = zyyx_pro_flex
material = generic_tpu
[values]
layer_height = 0.2

Some files were not shown because too many files have changed in this diff Show more