mirror of
https://github.com/Ultimaker/Cura.git
synced 2025-08-09 06:45:09 -06:00
Merge branch 'Ultimaker:main' into Cura_ankermake_august
This commit is contained in:
commit
da4e3f3082
493 changed files with 7854 additions and 824 deletions
8
.github/ISSUE_TEMPLATE/SlicingCrash.yaml
vendored
8
.github/ISSUE_TEMPLATE/SlicingCrash.yaml
vendored
|
@ -5,6 +5,13 @@ body:
|
|||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
### 💥 Slicing Crash Analysis Tool 💥
|
||||
We are taking steps to analyze an increase in reported crashes more systematically. We'll need some help with that. 😇
|
||||
Before filling out the report below, we want you to try a special Cura 5.7 Alpha.
|
||||
This version of Cura has an updated slicing engine that will automatically send a report to the Cura Team for analysis.
|
||||
#### [You can find the downloads here](https://github.com/Ultimaker/Cura/discussions/18080) ####
|
||||
If you still encounter a crash you are still welcome to report the issue so we can use your model as a test case, you can find instructions on how to do that below.
|
||||
|
||||
### Project File
|
||||
**⚠️ Before you continue, we need your project file to troubleshoot a slicing crash.**
|
||||
It contains the printer and settings we need for troubleshooting.
|
||||
|
@ -68,4 +75,3 @@ body:
|
|||
description: You can add the zip file and additional information that is relevant to the issue in the comments below.
|
||||
validations:
|
||||
required: true
|
||||
|
||||
|
|
16
.github/workflows/conan-package.yml
vendored
16
.github/workflows/conan-package.yml
vendored
|
@ -20,12 +20,8 @@ on:
|
|||
- 'main'
|
||||
- 'CURA-*'
|
||||
- 'PP-*'
|
||||
- '[0-9].[0-9]'
|
||||
- '[0-9].[0-9][0-9]'
|
||||
tags:
|
||||
- '[0-9].[0-9].[0-9]*'
|
||||
- '[0-9].[0-9].[0-9]'
|
||||
- '[0-9].[0-9][0-9].[0-9]*'
|
||||
- '[0-9].[0-9]*'
|
||||
- '[0-9].[0-9][0-9]*'
|
||||
|
||||
env:
|
||||
CONAN_LOGIN_USERNAME_CURA: ${{ secrets.CONAN_USER }}
|
||||
|
@ -44,3 +40,11 @@ jobs:
|
|||
recipe_id_full: ${{ needs.conan-recipe-version.outputs.recipe_id_full }}
|
||||
recipe_id_latest: ${{ needs.conan-recipe-version.outputs.recipe_id_latest }}
|
||||
secrets: inherit
|
||||
|
||||
conan-package-create:
|
||||
needs: [ conan-recipe-version, conan-package-export ]
|
||||
uses: ultimaker/cura-workflows/.github/workflows/conan-package-create-linux.yml@main
|
||||
with:
|
||||
recipe_id_full: ${{ needs.conan-recipe-version.outputs.recipe_id_full }}
|
||||
conan_extra_args: "-o cura:enable_i18n=True"
|
||||
secrets: inherit
|
2
.github/workflows/installers.yml
vendored
2
.github/workflows/installers.yml
vendored
|
@ -58,7 +58,7 @@ jobs:
|
|||
enterprise: ${{ github.event.inputs.enterprise == 'true' }}
|
||||
staging: ${{ github.event.inputs.staging == 'true' }}
|
||||
architecture: X64
|
||||
operating_system: windows-2022
|
||||
operating_system: self-hosted-Windows-X64
|
||||
secrets: inherit
|
||||
|
||||
linux-installer:
|
||||
|
|
11
.github/workflows/linux.yml
vendored
11
.github/workflows/linux.yml
vendored
|
@ -39,19 +39,14 @@ on:
|
|||
options:
|
||||
- ubuntu-22.04
|
||||
|
||||
env:
|
||||
CONAN_ARGS: ${{ inputs.conan_args || '' }}
|
||||
ENTERPRISE: ${{ inputs.enterprise || false }}
|
||||
STAGING: ${{ inputs.staging || false }}
|
||||
|
||||
jobs:
|
||||
windows-installer:
|
||||
linux-installer:
|
||||
uses: ultimaker/cura-workflows/.github/workflows/cura-installer-linux.yml@main
|
||||
with:
|
||||
cura_conan_version: ${{ inputs.cura_conan_version }}
|
||||
conan_args: ${{ inputs.conan_args }}
|
||||
enterprise: ${{ inputs.enterprise == 'true' }}
|
||||
staging: ${{ inputs.staging == 'true' }}
|
||||
enterprise: ${{ inputs.enterprise }}
|
||||
staging: ${{ inputs.staging }}
|
||||
architecture: ${{ inputs.architecture }}
|
||||
operating_system: ${{ inputs.operating_system }}
|
||||
secrets: inherit
|
11
.github/workflows/macos.yml
vendored
11
.github/workflows/macos.yml
vendored
|
@ -43,19 +43,14 @@ on:
|
|||
- macos-11
|
||||
- macos-12
|
||||
|
||||
env:
|
||||
CONAN_ARGS: ${{ inputs.conan_args || '' }}
|
||||
ENTERPRISE: ${{ inputs.enterprise || false }}
|
||||
STAGING: ${{ inputs.staging || false }}
|
||||
|
||||
jobs:
|
||||
windows-installer:
|
||||
macos-installer:
|
||||
uses: ultimaker/cura-workflows/.github/workflows/cura-installer-macos.yml@main
|
||||
with:
|
||||
cura_conan_version: ${{ inputs.cura_conan_version }}
|
||||
conan_args: ${{ inputs.conan_args }}
|
||||
enterprise: ${{ inputs.enterprise == 'true' }}
|
||||
staging: ${{ inputs.staging == 'true' }}
|
||||
enterprise: ${{ inputs.enterprise }}
|
||||
staging: ${{ inputs.staging }}
|
||||
architecture: ${{ inputs.architecture }}
|
||||
operating_system: ${{ inputs.operating_system }}
|
||||
secrets: inherit
|
1
.github/workflows/unit-test-post.yml
vendored
1
.github/workflows/unit-test-post.yml
vendored
|
@ -11,3 +11,4 @@ jobs:
|
|||
with:
|
||||
event: ${{ github.event.workflow_run.event }}
|
||||
conclusion: ${{ github.event.workflow_run.conclusion }}
|
||||
secrets: inherit
|
||||
|
|
3
.github/workflows/unit-test.yml
vendored
3
.github/workflows/unit-test.yml
vendored
|
@ -58,4 +58,5 @@ jobs:
|
|||
conan_extra_args: '-g VirtualPythonEnv -o cura:devtools=True -c tools.build:skip_test=False'
|
||||
unit_test_cmd: 'pytest --junitxml=junit_cura.xml'
|
||||
unit_test_dir: 'tests'
|
||||
conan_generator_dir: './venv/bin'
|
||||
conan_generator_dir: './venv/bin'
|
||||
secrets: inherit
|
12
.github/workflows/windows.yml
vendored
12
.github/workflows/windows.yml
vendored
|
@ -34,24 +34,20 @@ on:
|
|||
operating_system:
|
||||
description: 'OS'
|
||||
required: true
|
||||
default: 'windows-2022'
|
||||
default: 'self-hosted-Windows-X64'
|
||||
type: choice
|
||||
options:
|
||||
- self-hosted-Windows-X64
|
||||
- windows-2022
|
||||
|
||||
env:
|
||||
CONAN_ARGS: ${{ inputs.conan_args || '' }}
|
||||
ENTERPRISE: ${{ inputs.enterprise || false }}
|
||||
STAGING: ${{ inputs.staging || false }}
|
||||
|
||||
jobs:
|
||||
windows-installer:
|
||||
uses: ultimaker/cura-workflows/.github/workflows/cura-installer-windows.yml@main
|
||||
with:
|
||||
cura_conan_version: ${{ inputs.cura_conan_version }}
|
||||
conan_args: ${{ inputs.conan_args }}
|
||||
enterprise: ${{ inputs.enterprise == 'true' }}
|
||||
staging: ${{ inputs.staging == 'true' }}
|
||||
enterprise: ${{ inputs.enterprise }}
|
||||
staging: ${{ inputs.staging }}
|
||||
architecture: ${{ inputs.architecture }}
|
||||
operating_system: ${{ inputs.operating_system }}
|
||||
secrets: inherit
|
|
@ -266,6 +266,10 @@ app = UMBUNDLE(
|
|||
'CFBundlePackageType': 'APPL',
|
||||
'CFBundleVersionString': {{ version }},
|
||||
'CFBundleShortVersionString': {{ short_version }},
|
||||
'CFBundleURLTypes': [{
|
||||
'CFBundleURLName': '{{ display_name }}',
|
||||
'CFBundleURLSchemes': ['cura', 'slicer'],
|
||||
}],
|
||||
'CFBundleDocumentTypes': [{
|
||||
'CFBundleTypeRole': 'Viewer',
|
||||
'CFBundleTypeExtensions': ['*'],
|
||||
|
|
|
@ -1,12 +1,11 @@
|
|||
version: "5.7.0-alpha.0"
|
||||
version: "5.7.0-alpha.1"
|
||||
requirements:
|
||||
- "uranium/(latest)@ultimaker/testing"
|
||||
- "curaengine/(latest)@ultimaker/testing"
|
||||
- "cura_binary_data/(latest)@ultimaker/testing"
|
||||
- "fdm_materials/(latest)@ultimaker/testing"
|
||||
- "curaengine_plugin_gradual_flow/(latest)@ultimaker/stable"
|
||||
- "dulcificum/(latest)@ultimaker/testing"
|
||||
- "pyarcus/5.3.0"
|
||||
- "curaengine_plugin_gradual_flow/0.1.0-beta.2"
|
||||
- "dulcificum/latest@ultimaker/testing"
|
||||
- "pysavitar/5.3.0"
|
||||
- "pynest2d/5.3.0"
|
||||
- "curaengine_grpc_definitions/(latest)@ultimaker/testing"
|
||||
|
|
28
conanfile.py
28
conanfile.py
|
@ -1,4 +1,5 @@
|
|||
import os
|
||||
from io import StringIO
|
||||
from pathlib import Path
|
||||
|
||||
from jinja2 import Template
|
||||
|
@ -150,6 +151,7 @@ class CuraConan(ConanFile):
|
|||
return "None"
|
||||
|
||||
def _conan_installs(self):
|
||||
self.output.info("Collecting conan installs")
|
||||
conan_installs = {}
|
||||
|
||||
# list of conan installs
|
||||
|
@ -161,13 +163,22 @@ class CuraConan(ConanFile):
|
|||
return conan_installs
|
||||
|
||||
def _python_installs(self):
|
||||
self.output.info("Collecting python installs")
|
||||
python_installs = {}
|
||||
|
||||
# list of python installs
|
||||
python_ins_cmd = f"python -c \"import pkg_resources; print(';'.join([(s.key+','+ s.version) for s in pkg_resources.working_set]))\""
|
||||
from six import StringIO
|
||||
run_env = VirtualRunEnv(self)
|
||||
env = run_env.environment()
|
||||
env.prepend_path("PYTHONPATH", str(self._site_packages.as_posix()))
|
||||
venv_vars = env.vars(self, scope = "run")
|
||||
|
||||
outer = '"' if self.settings.os == "Windows" else "'"
|
||||
inner = "'" if self.settings.os == "Windows" else '"'
|
||||
buffer = StringIO()
|
||||
self.run(python_ins_cmd, run_environment= True, env = "conanrun", output=buffer)
|
||||
with venv_vars.apply():
|
||||
self.run(f"""python -c {outer}import pkg_resources; print({inner};{inner}.join([(s.key+{inner},{inner}+ s.version) for s in pkg_resources.working_set])){outer}""",
|
||||
env = "conanrun",
|
||||
output = buffer)
|
||||
|
||||
packages = str(buffer.getvalue()).split("-----------------\n")
|
||||
packages = packages[1].strip('\r\n').split(";")
|
||||
|
@ -320,6 +331,8 @@ class CuraConan(ConanFile):
|
|||
self.options["openssl"].shared = True
|
||||
if self.conf.get("user.curaengine:sentry_url", "", check_type=str) != "":
|
||||
self.options["curaengine"].enable_sentry = True
|
||||
self.options["arcus"].enable_sentry = True
|
||||
self.options["clipper"].enable_sentry = True
|
||||
|
||||
def validate(self):
|
||||
version = self.conf.get("user.cura:version", default = self.version, check_type = str)
|
||||
|
@ -335,6 +348,7 @@ class CuraConan(ConanFile):
|
|||
for req in self.conan_data["requirements_internal"]:
|
||||
self.requires(req)
|
||||
self.requires("cpython/3.10.4@ultimaker/stable")
|
||||
self.requires("clipper/6.4.2@ultimaker/stable")
|
||||
self.requires("openssl/3.2.0")
|
||||
self.requires("boost/1.82.0")
|
||||
self.requires("spdlog/1.12.0")
|
||||
|
@ -417,7 +431,6 @@ class CuraConan(ConanFile):
|
|||
)
|
||||
|
||||
if self.options.get_safe("enable_i18n", False) and self._i18n_options["extract"]:
|
||||
# Update the po and pot files
|
||||
vb = VirtualBuildEnv(self)
|
||||
vb.generate()
|
||||
|
||||
|
@ -502,10 +515,14 @@ echo "CURA_APP_NAME={{ cura_app_name }}" >> ${{ env_prefix }}GITHUB_ENV
|
|||
|
||||
if self.in_local_cache:
|
||||
self.runenv_info.append_path("PYTHONPATH", os.path.join(self.package_folder, "site-packages"))
|
||||
self.env_info.PYTHONPATH.append(os.path.join(self.package_folder, "site-packages"))
|
||||
self.runenv_info.append_path("PYTHONPATH", os.path.join(self.package_folder, "plugins"))
|
||||
self.env_info.PYTHONPATH.append(os.path.join(self.package_folder, "plugins"))
|
||||
else:
|
||||
self.runenv_info.append_path("PYTHONPATH", self.source_folder)
|
||||
self.env_info.PYTHONPATH.append(self.source_folder)
|
||||
self.runenv_info.append_path("PYTHONPATH", os.path.join(self.source_folder, "plugins"))
|
||||
self.env_info.PYTHONPATH.append(os.path.join(self.source_folder, "plugins"))
|
||||
|
||||
def package_id(self):
|
||||
self.info.clear()
|
||||
|
@ -518,7 +535,8 @@ echo "CURA_APP_NAME={{ cura_app_name }}" >> ${{ env_prefix }}GITHUB_ENV
|
|||
del self.info.options.cloud_api_version
|
||||
del self.info.options.display_name
|
||||
del self.info.options.cura_debug_mode
|
||||
self.options.rm_safe("enable_i18n")
|
||||
if self.options.get_safe("enable_i18n", False):
|
||||
del self.info.options.enable_i18n
|
||||
|
||||
# TODO: Use the hash of requirements.txt and requirements-ultimaker.txt, Because changing these will actually result in a different
|
||||
# Cura. This is needed because the requirements.txt aren't managed by Conan and therefor not resolved in the package_id. This isn't
|
||||
|
|
|
@ -3,10 +3,11 @@
|
|||
|
||||
from typing import List, cast
|
||||
|
||||
from PyQt6.QtCore import QObject, QUrl, QMimeData
|
||||
from PyQt6.QtCore import QObject, QUrl, pyqtSignal, pyqtProperty
|
||||
from PyQt6.QtGui import QDesktopServices
|
||||
from PyQt6.QtWidgets import QApplication
|
||||
|
||||
from UM.Application import Application
|
||||
from UM.Event import CallFunctionEvent
|
||||
from UM.FlameProfiler import pyqtSlot
|
||||
from UM.Math.Vector import Vector
|
||||
|
@ -37,6 +38,10 @@ class CuraActions(QObject):
|
|||
def __init__(self, parent: QObject = None) -> None:
|
||||
super().__init__(parent)
|
||||
|
||||
self._operation_stack = Application.getInstance().getOperationStack()
|
||||
self._operation_stack.changed.connect(self._onUndoStackChanged)
|
||||
|
||||
undoStackChanged = pyqtSignal()
|
||||
@pyqtSlot()
|
||||
def openDocumentation(self) -> None:
|
||||
# Starting a web browser from a signal handler connected to a menu will crash on windows.
|
||||
|
@ -45,6 +50,25 @@ class CuraActions(QObject):
|
|||
event = CallFunctionEvent(self._openUrl, [QUrl("https://ultimaker.com/en/resources/manuals/software?utm_source=cura&utm_medium=software&utm_campaign=dropdown-documentation")], {})
|
||||
cura.CuraApplication.CuraApplication.getInstance().functionEvent(event)
|
||||
|
||||
@pyqtProperty(bool, notify=undoStackChanged)
|
||||
def canUndo(self):
|
||||
return self._operation_stack.canUndo()
|
||||
|
||||
@pyqtProperty(bool, notify=undoStackChanged)
|
||||
def canRedo(self):
|
||||
return self._operation_stack.canRedo()
|
||||
|
||||
@pyqtSlot()
|
||||
def undo(self):
|
||||
self._operation_stack.undo()
|
||||
|
||||
@pyqtSlot()
|
||||
def redo(self):
|
||||
self._operation_stack.redo()
|
||||
|
||||
def _onUndoStackChanged(self):
|
||||
self.undoStackChanged.emit()
|
||||
|
||||
@pyqtSlot()
|
||||
def openBugReportPage(self) -> None:
|
||||
event = CallFunctionEvent(self._openUrl, [QUrl("https://github.com/Ultimaker/Cura/issues/new/choose")], {})
|
||||
|
|
|
@ -2,23 +2,26 @@
|
|||
# Cura is released under the terms of the LGPLv3 or higher.
|
||||
import enum
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
import tempfile
|
||||
import time
|
||||
import platform
|
||||
from pathlib import Path
|
||||
from typing import cast, TYPE_CHECKING, Optional, Callable, List, Any, Dict
|
||||
import requests
|
||||
|
||||
import numpy
|
||||
from PyQt6.QtCore import QObject, QTimer, QUrl, pyqtSignal, pyqtProperty, QEvent, pyqtEnum, QCoreApplication
|
||||
from PyQt6.QtCore import QObject, QTimer, QUrl, QUrlQuery, pyqtSignal, pyqtProperty, QEvent, pyqtEnum, QCoreApplication, \
|
||||
QByteArray
|
||||
from PyQt6.QtGui import QColor, QIcon
|
||||
from PyQt6.QtQml import qmlRegisterUncreatableType, qmlRegisterUncreatableMetaObject, qmlRegisterSingletonType, qmlRegisterType
|
||||
from PyQt6.QtQml import qmlRegisterUncreatableMetaObject, qmlRegisterSingletonType, qmlRegisterType
|
||||
from PyQt6.QtWidgets import QMessageBox
|
||||
|
||||
import UM.Util
|
||||
import cura.Settings.cura_empty_instance_containers
|
||||
from UM.Application import Application
|
||||
from UM.Decorators import override
|
||||
from UM.Decorators import override, deprecated
|
||||
from UM.FlameProfiler import pyqtSlot
|
||||
from UM.Logger import Logger
|
||||
from UM.Math.AxisAlignedBox import AxisAlignedBox
|
||||
|
@ -179,6 +182,7 @@ class CuraApplication(QtApplication):
|
|||
self._use_single_instance = False
|
||||
|
||||
self._single_instance = None
|
||||
self._open_project_mode: Optional[str] = None
|
||||
|
||||
self._cura_formula_functions = None # type: Optional[CuraFormulaFunctions]
|
||||
|
||||
|
@ -187,7 +191,7 @@ class CuraApplication(QtApplication):
|
|||
self.empty_container = None # type: EmptyInstanceContainer
|
||||
self.empty_definition_changes_container = None # type: EmptyInstanceContainer
|
||||
self.empty_variant_container = None # type: EmptyInstanceContainer
|
||||
self.empty_intent_container = None # type: EmptyInstanceContainer
|
||||
self.empty_intent_container = None # type: EmptyInstanceContainer
|
||||
self.empty_material_container = None # type: EmptyInstanceContainer
|
||||
self.empty_quality_container = None # type: EmptyInstanceContainer
|
||||
self.empty_quality_changes_container = None # type: EmptyInstanceContainer
|
||||
|
@ -249,7 +253,7 @@ class CuraApplication(QtApplication):
|
|||
self._additional_components = {} # Components to add to certain areas in the interface
|
||||
|
||||
self._open_file_queue = [] # A list of files to open (after the application has started)
|
||||
|
||||
self._open_url_queue = [] # A list of urls to open (after the application has started)
|
||||
self._update_platform_activity_timer = None
|
||||
|
||||
self._sidebar_custom_menu_items = [] # type: list # Keeps list of custom menu items for the side bar
|
||||
|
@ -273,6 +277,8 @@ class CuraApplication(QtApplication):
|
|||
self._conan_installs = ApplicationMetadata.CONAN_INSTALLS
|
||||
self._python_installs = ApplicationMetadata.PYTHON_INSTALLS
|
||||
|
||||
self._supported_url_schemes: List[str] = ["cura", "slicer"]
|
||||
|
||||
@pyqtProperty(str, constant=True)
|
||||
def ultimakerCloudApiRootUrl(self) -> str:
|
||||
return UltimakerCloudConstants.CuraCloudAPIRoot
|
||||
|
@ -325,7 +331,11 @@ class CuraApplication(QtApplication):
|
|||
assert not "This crash is triggered by the trigger_early_crash command line argument."
|
||||
|
||||
for filename in self._cli_args.file:
|
||||
self._files_to_open.append(os.path.abspath(filename))
|
||||
url = QUrl(filename)
|
||||
if url.scheme() in self._supported_url_schemes:
|
||||
self._open_url_queue.append(url)
|
||||
else:
|
||||
self._files_to_open.append(os.path.abspath(filename))
|
||||
|
||||
def initialize(self) -> None:
|
||||
self.__addExpectedResourceDirsAndSearchPaths() # Must be added before init of super
|
||||
|
@ -946,6 +956,8 @@ class CuraApplication(QtApplication):
|
|||
self.callLater(self._openFile, file_name)
|
||||
for file_name in self._open_file_queue: # Open all the files that were queued up while plug-ins were loading.
|
||||
self.callLater(self._openFile, file_name)
|
||||
for url in self._open_url_queue:
|
||||
self.callLater(self._openUrl, url)
|
||||
|
||||
initializationFinished = pyqtSignal()
|
||||
showAddPrintersUncancellableDialog = pyqtSignal() # Used to show the add printers dialog with a greyed background
|
||||
|
@ -1126,6 +1138,10 @@ class CuraApplication(QtApplication):
|
|||
|
||||
return cast(MachineActionManager.MachineActionManager, self._machine_action_manager)
|
||||
|
||||
@pyqtSlot(result = QObject)
|
||||
def getMachineActionManagerQml(self)-> MachineActionManager.MachineActionManager:
|
||||
return cast(QObject, self._machine_action_manager)
|
||||
|
||||
@pyqtSlot(result = QObject)
|
||||
def getMaterialManagementModel(self) -> MaterialManagementModel:
|
||||
if not self._material_management_model:
|
||||
|
@ -1138,7 +1154,8 @@ class CuraApplication(QtApplication):
|
|||
self._quality_management_model = QualityManagementModel(parent = self)
|
||||
return self._quality_management_model
|
||||
|
||||
def getSimpleModeSettingsManager(self, *args):
|
||||
@pyqtSlot(result=QObject)
|
||||
def getSimpleModeSettingsManager(self)-> SimpleModeSettingsManager:
|
||||
if self._simple_mode_settings_manager is None:
|
||||
self._simple_mode_settings_manager = SimpleModeSettingsManager()
|
||||
return self._simple_mode_settings_manager
|
||||
|
@ -1155,9 +1172,15 @@ class CuraApplication(QtApplication):
|
|||
|
||||
if event.type() == QEvent.Type.FileOpen:
|
||||
if self._plugins_loaded:
|
||||
self._openFile(event.file())
|
||||
if event.file():
|
||||
self._openFile(event.file())
|
||||
if event.url():
|
||||
self._openUrl(event.url())
|
||||
else:
|
||||
self._open_file_queue.append(event.file())
|
||||
if event.file():
|
||||
self._open_file_queue.append(event.file())
|
||||
if event.url():
|
||||
self._open_url_queue.append(event.url())
|
||||
|
||||
if int(event.type()) == 20: # 'QEvent.Type.Quit' enum isn't there, even though it should be according to docs.
|
||||
# Once we're at this point, everything should have been flushed already (past OnExitCallbackManager).
|
||||
|
@ -1175,16 +1198,43 @@ class CuraApplication(QtApplication):
|
|||
|
||||
return self._print_information
|
||||
|
||||
def getQualityProfilesDropDownMenuModel(self, *args, **kwargs):
|
||||
@pyqtSlot(result=QObject)
|
||||
def getQualityProfilesDropDownMenuModel(self, *args, **kwargs)-> QualityProfilesDropDownMenuModel:
|
||||
if self._quality_profile_drop_down_menu_model is None:
|
||||
self._quality_profile_drop_down_menu_model = QualityProfilesDropDownMenuModel(self)
|
||||
return self._quality_profile_drop_down_menu_model
|
||||
|
||||
def getCustomQualityProfilesDropDownMenuModel(self, *args, **kwargs):
|
||||
@pyqtSlot(result=QObject)
|
||||
def getCustomQualityProfilesDropDownMenuModel(self, *args, **kwargs)->CustomQualityProfilesDropDownMenuModel:
|
||||
if self._custom_quality_profile_drop_down_menu_model is None:
|
||||
self._custom_quality_profile_drop_down_menu_model = CustomQualityProfilesDropDownMenuModel(self)
|
||||
return self._custom_quality_profile_drop_down_menu_model
|
||||
|
||||
@deprecated("SimpleModeSettingsManager is deprecated and will be removed in major SDK release, Use getSimpleModeSettingsManager() instead", since = "5.7.0")
|
||||
def getSimpleModeSettingsManagerWrapper(self, *args, **kwargs):
|
||||
return self.getSimpleModeSettingsManager()
|
||||
|
||||
@deprecated("MachineActionManager is deprecated and will be removed in major SDK release, Use getMachineActionManager() instead", since="5.7.0")
|
||||
def getMachineActionManagerWrapper(self, *args, **kwargs):
|
||||
return self.getMachineActionManager()
|
||||
|
||||
@deprecated("QualityManagementModel is deprecated and will be removed in major SDK release, Use getQualityManagementModel() instead", since="5.7.0")
|
||||
def getQualityManagementModelWrapper(self, *args, **kwargs):
|
||||
return self.getQualityManagementModel()
|
||||
|
||||
@deprecated("MaterialManagementModel is deprecated and will be removed in major SDK release, Use getMaterialManagementModel() instead", since = "5.7.0")
|
||||
def getMaterialManagementModelWrapper(self, *args, **kwargs):
|
||||
return self.getMaterialManagementModel()
|
||||
|
||||
@deprecated("QualityProfilesDropDownMenuModel is deprecated and will be removed in major SDK release, Use getQualityProfilesDropDownMenuModel() instead", since = "5.7.0")
|
||||
def getQualityProfilesDropDownMenuModelWrapper(self, *args, **kwargs):
|
||||
return self.getQualityProfilesDropDownMenuModel()
|
||||
|
||||
@deprecated("CustomQualityProfilesDropDownMenuModel is deprecated and will be removed in major SDK release, Use getCustomQualityProfilesDropDownMenuModel() instead", since = "5.7.0")
|
||||
def getCustomQualityProfilesDropDownMenuModelWrapper(self, *args, **kwargs):
|
||||
return self.getCustomQualityProfilesDropDownMenuModel()
|
||||
|
||||
|
||||
def getCuraAPI(self, *args, **kwargs) -> "CuraAPI":
|
||||
return self._cura_API
|
||||
|
||||
|
@ -1213,8 +1263,8 @@ class CuraApplication(QtApplication):
|
|||
qmlRegisterSingletonType(MachineManager, "Cura", 1, 0, self.getMachineManager, "MachineManager")
|
||||
qmlRegisterSingletonType(IntentManager, "Cura", 1, 6, self.getIntentManager, "IntentManager")
|
||||
qmlRegisterSingletonType(SettingInheritanceManager, "Cura", 1, 0, self.getSettingInheritanceManager, "SettingInheritanceManager")
|
||||
qmlRegisterSingletonType(SimpleModeSettingsManager, "Cura", 1, 0, self.getSimpleModeSettingsManager, "SimpleModeSettingsManager")
|
||||
qmlRegisterSingletonType(MachineActionManager.MachineActionManager, "Cura", 1, 0, self.getMachineActionManager, "MachineActionManager")
|
||||
qmlRegisterSingletonType(SimpleModeSettingsManager, "Cura", 1, 0, self.getSimpleModeSettingsManagerWrapper, "SimpleModeSettingsManager")
|
||||
qmlRegisterSingletonType(MachineActionManager.MachineActionManager, "Cura", 1, 0, self.getMachineActionManagerWrapper, "MachineActionManager")
|
||||
|
||||
self.processEvents()
|
||||
qmlRegisterType(NetworkingUtil, "Cura", 1, 5, "NetworkingUtil")
|
||||
|
@ -1239,16 +1289,14 @@ class CuraApplication(QtApplication):
|
|||
qmlRegisterType(FavoriteMaterialsModel, "Cura", 1, 0, "FavoriteMaterialsModel")
|
||||
qmlRegisterType(GenericMaterialsModel, "Cura", 1, 0, "GenericMaterialsModel")
|
||||
qmlRegisterType(MaterialBrandsModel, "Cura", 1, 0, "MaterialBrandsModel")
|
||||
qmlRegisterSingletonType(QualityManagementModel, "Cura", 1, 0, self.getQualityManagementModel, "QualityManagementModel")
|
||||
qmlRegisterSingletonType(MaterialManagementModel, "Cura", 1, 5, self.getMaterialManagementModel, "MaterialManagementModel")
|
||||
qmlRegisterSingletonType(QualityManagementModel, "Cura", 1, 0, self.getQualityManagementModelWrapper,"QualityManagementModel")
|
||||
qmlRegisterSingletonType(MaterialManagementModel, "Cura", 1, 5, self.getMaterialManagementModelWrapper,"MaterialManagementModel")
|
||||
|
||||
self.processEvents()
|
||||
qmlRegisterType(DiscoveredPrintersModel, "Cura", 1, 0, "DiscoveredPrintersModel")
|
||||
qmlRegisterType(DiscoveredCloudPrintersModel, "Cura", 1, 7, "DiscoveredCloudPrintersModel")
|
||||
qmlRegisterSingletonType(QualityProfilesDropDownMenuModel, "Cura", 1, 0,
|
||||
self.getQualityProfilesDropDownMenuModel, "QualityProfilesDropDownMenuModel")
|
||||
qmlRegisterSingletonType(CustomQualityProfilesDropDownMenuModel, "Cura", 1, 0,
|
||||
self.getCustomQualityProfilesDropDownMenuModel, "CustomQualityProfilesDropDownMenuModel")
|
||||
qmlRegisterSingletonType(QualityProfilesDropDownMenuModel, "Cura", 1, 0, self.getQualityProfilesDropDownMenuModelWrapper, "QualityProfilesDropDownMenuModel")
|
||||
qmlRegisterSingletonType(CustomQualityProfilesDropDownMenuModel, "Cura", 1, 0, self.getCustomQualityProfilesDropDownMenuModelWrapper, "CustomQualityProfilesDropDownMenuModel")
|
||||
qmlRegisterType(NozzleModel, "Cura", 1, 0, "NozzleModel")
|
||||
qmlRegisterType(IntentModel, "Cura", 1, 6, "IntentModel")
|
||||
qmlRegisterType(IntentCategoryModel, "Cura", 1, 6, "IntentCategoryModel")
|
||||
|
@ -1541,7 +1589,7 @@ class CuraApplication(QtApplication):
|
|||
if not nodes:
|
||||
return
|
||||
|
||||
objects_in_filename = {} # type: Dict[str, List[CuraSceneNode]]
|
||||
objects_in_filename: Dict[str, List[CuraSceneNode]] = {}
|
||||
for node in nodes:
|
||||
mesh_data = node.getMeshData()
|
||||
if mesh_data:
|
||||
|
@ -1782,6 +1830,58 @@ class CuraApplication(QtApplication):
|
|||
def _openFile(self, filename):
|
||||
self.readLocalFile(QUrl.fromLocalFile(filename))
|
||||
|
||||
def _openUrl(self, url: QUrl) -> None:
|
||||
if url.scheme() not in self._supported_url_schemes:
|
||||
# only handle cura:// and slicer:// urls schemes
|
||||
return
|
||||
|
||||
match url.host() + url.path():
|
||||
case "open" | "open/":
|
||||
query = QUrlQuery(url.query())
|
||||
model_url = QUrl(query.queryItemValue("file", options=QUrl.ComponentFormattingOption.FullyDecoded))
|
||||
|
||||
def on_finish(response):
|
||||
content_disposition_header_key = QByteArray("content-disposition".encode())
|
||||
|
||||
if not response.hasRawHeader(content_disposition_header_key):
|
||||
Logger.log("w", "Could not find Content-Disposition header in response from {0}".format(
|
||||
model_url.url()))
|
||||
# Use the last part of the url as the filename, and assume it is an STL file
|
||||
filename = model_url.path().split("/")[-1] + ".stl"
|
||||
else:
|
||||
# content_disposition is in the format
|
||||
# ```
|
||||
# content_disposition attachment; "filename=[FILENAME]"
|
||||
# ```
|
||||
# Use a regex to extract the filename
|
||||
content_disposition = str(response.rawHeader(content_disposition_header_key).data(),
|
||||
encoding='utf-8')
|
||||
content_disposition_match = re.match(r'attachment; filename="(?P<filename>.*)"',
|
||||
content_disposition)
|
||||
assert content_disposition_match is not None
|
||||
filename = content_disposition_match.group("filename")
|
||||
|
||||
tmp = tempfile.NamedTemporaryFile(suffix=filename, delete=False)
|
||||
with open(tmp.name, "wb") as f:
|
||||
f.write(response.readAll())
|
||||
|
||||
self.readLocalFile(QUrl.fromLocalFile(tmp.name), add_to_recent_files=False)
|
||||
|
||||
def on_error(*args, **kwargs):
|
||||
Logger.log("w", "Could not download file from {0}".format(model_url.url()))
|
||||
Message("Could not download file: " + str(model_url.url()),
|
||||
title= "Loading Model failed",
|
||||
message_type=Message.MessageType.ERROR).show()
|
||||
return
|
||||
|
||||
self.getHttpRequestManager().get(
|
||||
model_url.url(),
|
||||
callback=on_finish,
|
||||
error_callback=on_error,
|
||||
)
|
||||
case path:
|
||||
Logger.log("w", "Unsupported url scheme path: {0}".format(path))
|
||||
|
||||
def _addProfileReader(self, profile_reader):
|
||||
# TODO: Add the profile reader to the list of plug-ins that can be used when importing profiles.
|
||||
pass
|
||||
|
@ -1845,7 +1945,7 @@ class CuraApplication(QtApplication):
|
|||
Logger.log("i", "Attempting to read file %s", file.toString())
|
||||
if not file.isValid():
|
||||
return
|
||||
|
||||
self._open_project_mode = project_mode
|
||||
scene = self.getController().getScene()
|
||||
|
||||
for node in DepthFirstIterator(scene.getRoot()):
|
||||
|
@ -1855,16 +1955,16 @@ class CuraApplication(QtApplication):
|
|||
|
||||
is_project_file = self.checkIsValidProjectFile(file)
|
||||
|
||||
if project_mode is None:
|
||||
project_mode = self.getPreferences().getValue("cura/choice_on_open_project")
|
||||
if self._open_project_mode is None:
|
||||
self._open_project_mode = self.getPreferences().getValue("cura/choice_on_open_project")
|
||||
|
||||
if is_project_file and project_mode == "open_as_project":
|
||||
if is_project_file and self._open_project_mode == "open_as_project":
|
||||
# open as project immediately without presenting a dialog
|
||||
workspace_handler = self.getWorkspaceFileHandler()
|
||||
workspace_handler.readLocalFile(file, add_to_recent_files_hint = add_to_recent_files)
|
||||
return
|
||||
|
||||
if is_project_file and project_mode == "always_ask":
|
||||
if is_project_file and self._open_project_mode == "always_ask":
|
||||
# present a dialog asking to open as project or import models
|
||||
self.callLater(self.openProjectFile.emit, file, add_to_recent_files)
|
||||
return
|
||||
|
@ -1999,8 +2099,11 @@ class CuraApplication(QtApplication):
|
|||
center_y = 0
|
||||
|
||||
node.translate(Vector(0, center_y, 0))
|
||||
|
||||
nodes_to_arrange.append(node)
|
||||
# If the file is a project,and models are to be loaded from a that project,
|
||||
# models inside file should be arranged in buildplate.
|
||||
elif self._open_project_mode == "open_as_model":
|
||||
nodes_to_arrange.append(node)
|
||||
|
||||
# This node is deep copied from some other node which already has a BuildPlateDecorator, but the deepcopy
|
||||
# of BuildPlateDecorator produces one that's associated with build plate -1. So, here we need to check if
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
# Copyright (c) 2019 Ultimaker B.V.
|
||||
# Cura is released under the terms of the LGPLv3 or higher.
|
||||
import math
|
||||
import numpy
|
||||
|
||||
from typing import Optional, cast
|
||||
|
@ -66,7 +67,7 @@ class LayerPolygon:
|
|||
# Buffering the colors shouldn't be necessary as it is not
|
||||
# re-used and can save a lot of memory usage.
|
||||
self._color_map = LayerPolygon.getColorMap()
|
||||
self._colors = self._color_map[self._types] # type: numpy.ndarray
|
||||
self._colors: numpy.ndarray = self._color_map[self._types]
|
||||
|
||||
# When type is used as index returns true if type == LayerPolygon.InfillType
|
||||
# or type == LayerPolygon.SkinType
|
||||
|
@ -74,8 +75,8 @@ class LayerPolygon:
|
|||
# Should be generated in better way, not hardcoded.
|
||||
self._is_infill_or_skin_type_map = numpy.array([0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0], dtype=bool)
|
||||
|
||||
self._build_cache_line_mesh_mask = None # type: Optional[numpy.ndarray]
|
||||
self._build_cache_needed_points = None # type: Optional[numpy.ndarray]
|
||||
self._build_cache_line_mesh_mask: Optional[numpy.ndarray] = None
|
||||
self._build_cache_needed_points: Optional[numpy.ndarray] = None
|
||||
|
||||
def buildCache(self) -> None:
|
||||
# For the line mesh we do not draw Infill or Jumps. Therefore those lines are filtered out.
|
||||
|
@ -186,6 +187,11 @@ class LayerPolygon:
|
|||
def types(self):
|
||||
return self._types
|
||||
|
||||
@property
|
||||
def lineLengths(self):
|
||||
data_array = numpy.array(self._data)
|
||||
return numpy.linalg.norm(data_array[1:] - data_array[:-1], axis=1)
|
||||
|
||||
@property
|
||||
def data(self):
|
||||
return self._data
|
||||
|
|
|
@ -227,7 +227,7 @@ class ExtrudersModel(ListModel):
|
|||
"material_brand": "",
|
||||
"color_name": "",
|
||||
"material_type": "",
|
||||
"material_label": ""
|
||||
"material_name": ""
|
||||
}
|
||||
items.append(item)
|
||||
if self._items != items:
|
||||
|
|
|
@ -40,6 +40,7 @@ class AuthorizationHelpers:
|
|||
"""
|
||||
data = {
|
||||
"client_id": self._settings.CLIENT_ID if self._settings.CLIENT_ID is not None else "",
|
||||
"client_secret": self._settings.CLIENT_SECRET if self._settings.CLIENT_SECRET is not None else "",
|
||||
"redirect_uri": self._settings.CALLBACK_URL if self._settings.CALLBACK_URL is not None else "",
|
||||
"grant_type": "authorization_code",
|
||||
"code": authorization_code,
|
||||
|
@ -64,6 +65,7 @@ class AuthorizationHelpers:
|
|||
Logger.log("d", "Refreshing the access token for [%s]", self._settings.OAUTH_SERVER_URL)
|
||||
data = {
|
||||
"client_id": self._settings.CLIENT_ID if self._settings.CLIENT_ID is not None else "",
|
||||
"client_secret": self._settings.CLIENT_SECRET if self._settings.CLIENT_SECRET is not None else "",
|
||||
"redirect_uri": self._settings.CALLBACK_URL if self._settings.CALLBACK_URL is not None else "",
|
||||
"grant_type": "refresh_token",
|
||||
"refresh_token": refresh_token,
|
||||
|
|
|
@ -31,20 +31,24 @@ class AuthorizationService:
|
|||
account information.
|
||||
"""
|
||||
|
||||
# Emit signal when authentication is completed.
|
||||
onAuthStateChanged = Signal()
|
||||
def __init__(self,
|
||||
settings: "OAuth2Settings",
|
||||
preferences: Optional["Preferences"] = None,
|
||||
get_user_profile: bool = True) -> None:
|
||||
# Emit signal when authentication is completed.
|
||||
self.onAuthStateChanged = Signal()
|
||||
|
||||
# Emit signal when authentication failed.
|
||||
onAuthenticationError = Signal()
|
||||
# Emit signal when authentication failed.
|
||||
self.onAuthenticationError = Signal()
|
||||
|
||||
accessTokenChanged = Signal()
|
||||
self.accessTokenChanged = Signal()
|
||||
|
||||
def __init__(self, settings: "OAuth2Settings", preferences: Optional["Preferences"] = None) -> None:
|
||||
self._settings = settings
|
||||
self._auth_helpers = AuthorizationHelpers(settings)
|
||||
self._auth_url = "{}/authorize".format(self._settings.OAUTH_SERVER_URL)
|
||||
self._auth_data: Optional[AuthenticationResponse] = None
|
||||
self._user_profile: Optional["UserProfile"] = None
|
||||
self._get_user_profile: bool = get_user_profile
|
||||
self._preferences = preferences
|
||||
self._server = LocalAuthorizationServer(self._auth_helpers, self._onAuthStateChanged, daemon=True)
|
||||
self._currently_refreshing_token = False # Whether we are currently in the process of refreshing auth. Don't make new requests while busy.
|
||||
|
@ -294,7 +298,8 @@ class AuthorizationService:
|
|||
self._auth_data = auth_data
|
||||
self._currently_refreshing_token = False
|
||||
if auth_data:
|
||||
self.getUserProfile()
|
||||
if self._get_user_profile:
|
||||
self.getUserProfile()
|
||||
self._preferences.setValue(self._settings.AUTH_DATA_PREFERENCE_KEY, json.dumps(auth_data.dump()))
|
||||
else:
|
||||
Logger.log("d", "Clearing the user profile")
|
||||
|
|
|
@ -16,6 +16,7 @@ class OAuth2Settings(BaseModel):
|
|||
CALLBACK_PORT = None # type: Optional[int]
|
||||
OAUTH_SERVER_URL = None # type: Optional[str]
|
||||
CLIENT_ID = None # type: Optional[str]
|
||||
CLIENT_SECRET = None # type: Optional[str]
|
||||
CLIENT_SCOPES = None # type: Optional[str]
|
||||
CALLBACK_URL = None # type: Optional[str]
|
||||
AUTH_DATA_PREFERENCE_KEY = "" # type: str
|
||||
|
|
|
@ -316,7 +316,13 @@ class ExtruderManager(QObject):
|
|||
# Starts with the adhesion extruder.
|
||||
adhesion_type = global_stack.getProperty("adhesion_type", "value")
|
||||
if adhesion_type in {"skirt", "brim"}:
|
||||
return max(0, int(global_stack.getProperty("skirt_brim_extruder_nr", "value"))) # optional skirt/brim extruder defaults to zero
|
||||
skirt_brim_extruder_nr = global_stack.getProperty("skirt_brim_extruder_nr", "value")
|
||||
# if the skirt_brim_extruder_nr is -1, then we use the first used extruder
|
||||
if skirt_brim_extruder_nr == -1:
|
||||
used_extruders = self.getUsedExtruderStacks()
|
||||
return used_extruders[0].position
|
||||
else:
|
||||
return skirt_brim_extruder_nr
|
||||
if adhesion_type == "raft":
|
||||
return global_stack.getProperty("raft_base_extruder_nr", "value")
|
||||
|
||||
|
|
|
@ -49,7 +49,7 @@ class Snapshot:
|
|||
"""
|
||||
|
||||
if node is None:
|
||||
root = Application.getInstance().getController().getScene().getRoot()
|
||||
node = Application.getInstance().getController().getScene().getRoot()
|
||||
|
||||
# the direction the camera is looking at to create the isometric view
|
||||
iso_view_dir = Vector(-1, -1, -1).normalized()
|
||||
|
|
|
@ -15,6 +15,10 @@ if "" in sys.path:
|
|||
import argparse
|
||||
import faulthandler
|
||||
import os
|
||||
|
||||
# set the environment variable QT_QUICK_FLICKABLE_WHEEL_DECELERATION to 5000 as mentioned in qt6.6 update log to overcome scroll related issues
|
||||
os.environ["QT_QUICK_FLICKABLE_WHEEL_DECELERATION"] = str(int(os.environ.get("QT_QUICK_FLICKABLE_WHEEL_DECELERATION", "5000")))
|
||||
|
||||
if sys.platform != "linux": # Turns out the Linux build _does_ use this, but we're not making an Enterprise release for that system anyway.
|
||||
os.environ["QT_PLUGIN_PATH"] = "" # Security workaround: Don't need it, and introduces an attack vector, so set to nul.
|
||||
os.environ["QML2_IMPORT_PATH"] = "" # Security workaround: Don't need it, and introduces an attack vector, so set to nul.
|
||||
|
|
|
@ -38,6 +38,7 @@ AppDir:
|
|||
- usr/share/doc/*/changelog.*
|
||||
- usr/share/doc/*/NEWS.*
|
||||
- usr/share/doc/*/TODO.*
|
||||
- usr/lib/x86_64-linux-gnu/libssl.so*
|
||||
runtime:
|
||||
env:
|
||||
APPDIR_LIBRARY_PATH: "$APPDIR:$APPDIR/runtime/compat/:$APPDIR/usr/lib/x86_64-linux-gnu:$APPDIR/lib/x86_64-linux-gnu:$APPDIR/usr/lib:$APPDIR/usr/lib/x86_64-linux-gnu/gdk-pixbuf-2.0/2.10.0/loaders"
|
||||
|
|
|
@ -144,6 +144,23 @@ SectionEnd
|
|||
|
||||
######################################################################
|
||||
|
||||
Section UrlProtocol
|
||||
|
||||
WriteRegStr HKCR "cura" "" "URL:cura"
|
||||
WriteRegStr HKCR "cura" "URL Protocol" ""
|
||||
WriteRegStr HKCR "cura\DefaultIcon" "" "$INSTDIR\${MAIN_APP_EXE},1"
|
||||
WriteRegStr HKCR "cura\shell" "" "open"
|
||||
WriteRegStr HKCR "cura\shell\open\command" "" '"$INSTDIR\${MAIN_APP_EXE}" "%1"'
|
||||
|
||||
WriteRegStr HKCR "slicer" "" "URL:slicer"
|
||||
WriteRegStr HKCR "slicer" "URL Protocol" ""
|
||||
WriteRegStr HKCR "slicer\DefaultIcon" "" "$INSTDIR\${MAIN_APP_EXE},1"
|
||||
WriteRegStr HKCR "slicer\shell" "" "open"
|
||||
WriteRegStr HKCR "slicer\shell\open\command" "" '"$INSTDIR\${MAIN_APP_EXE}" "%1"'
|
||||
|
||||
SectionEnd
|
||||
######################################################################
|
||||
|
||||
Section Uninstall
|
||||
${INSTALL_TYPE}{% for files in mapped_out_paths.values() %}{% for file in files %}
|
||||
Delete "{{ file[1] }}"{% endfor %}{% endfor %}{% for rem_dir in rmdir_paths %}
|
||||
|
@ -187,8 +204,13 @@ RmDir "$SMPROGRAMS\{{ app_name }}"
|
|||
!insertmacro APP_UNASSOCIATE "stl" "Cura.model"
|
||||
!insertmacro APP_UNASSOCIATE "3mf" "Cura.project"
|
||||
|
||||
; Unassociate file associations for 'cura' protocol
|
||||
DeleteRegKey HKCR "cura"
|
||||
|
||||
; Unassociate file associations for 'slicer' protocol
|
||||
DeleteRegKey HKCR "slicer"
|
||||
|
||||
DeleteRegKey ${REG_ROOT} "${REG_APP_PATH}"
|
||||
DeleteRegKey ${REG_ROOT} "${UNINSTALL_PATH}"
|
||||
SectionEnd
|
||||
|
||||
######################################################################
|
||||
|
|
|
@ -33,6 +33,21 @@
|
|||
/>
|
||||
</Upgrade>
|
||||
|
||||
<Property Id="ASSOCIATE_URL_PROTOCOLS">
|
||||
<RegistrySearch Id="CheckCuraProtocolHandler"
|
||||
Type="raw"
|
||||
Root="HKCR"
|
||||
Key="cura"
|
||||
Name="URL Protocol"
|
||||
/>
|
||||
<RegistrySearch Id="CheckSlicerProtocolHandler"
|
||||
Type="raw"
|
||||
Root="HKCR"
|
||||
Key="slicer"
|
||||
Name="URL Protocol"
|
||||
/>
|
||||
</Property>
|
||||
|
||||
{% if "Enterprise" in app_name %}
|
||||
<Property Id="PREVIOUS_413_INSTALLED" Secure="yes" />
|
||||
<Upgrade Id="53C603BB-2B17-4206-A609-29C2E0D0B0AE">
|
||||
|
@ -144,11 +159,32 @@
|
|||
</Component>
|
||||
</DirectoryRef>
|
||||
|
||||
<!--Url Scheme-->
|
||||
<Component Id="CuraRegistration" Guid="*" Directory="APPLICATIONFOLDER">
|
||||
<RegistryKey Root="HKCR" Key="cura">
|
||||
<RegistryValue Type="string" Value="URL:Cura Protocol"/>
|
||||
<RegistryValue Type="string" Name="URL Protocol" Value=""/>
|
||||
<RegistryValue Type="string" Key="DefaultIcon" Value="[APPLICATIONFOLDER]\{{ main_app }},1"/>
|
||||
<RegistryValue Type="string" Key="shell\open\command" Value=""[APPLICATIONFOLDER]\{{ main_app }}" "%1""/>
|
||||
</RegistryKey>
|
||||
</Component>
|
||||
|
||||
<Component Id="SlicerRegistration" Guid="*" Directory="APPLICATIONFOLDER">
|
||||
<RegistryKey Root="HKCR" Key="slicer">
|
||||
<RegistryValue Type="string" Value="URL:Slicer Protocol"/>
|
||||
<RegistryValue Type="string" Name="URL Protocol" Value=""/>
|
||||
<RegistryValue Type="string" Key="DefaultIcon" Value="[APPLICATIONFOLDER]\{{ main_app }},1"/>
|
||||
<RegistryValue Type="string" Key="shell\open\command" Value=""[APPLICATIONFOLDER]\{{ main_app }}" "%1""/>
|
||||
</RegistryKey>
|
||||
</Component>
|
||||
|
||||
<Feature Id="ProductFeature" Title="{{ app_name }}" Level="1" ConfigurableDirectory="APPLICATIONFOLDER">
|
||||
<ComponentRef Id="CMP_UltiMaker_Cura_exe" />
|
||||
<ComponentRef Id="CMP_CuraEngine_exe" />
|
||||
<ComponentGroupRef Id="NewFilesGroup" />
|
||||
<ComponentRef Id="CMP_Shortcuts" />
|
||||
<ComponentRef Id="CuraRegistration"/>
|
||||
<ComponentRef Id="SlicerRegistration"/>
|
||||
</Feature>
|
||||
<Feature Id="UninstallOlderVersionFeature" Title="Uninstall previous versions" Level="{{ 1 if "Enterprise" in app_name else 0 }}" Description="..."/>
|
||||
</Product>
|
||||
|
|
|
@ -10,11 +10,8 @@ from UM.Math.Vector import Vector
|
|||
from UM.Logger import Logger
|
||||
from UM.Math.Matrix import Matrix
|
||||
from UM.Application import Application
|
||||
from UM.Message import Message
|
||||
from UM.Resources import Resources
|
||||
from UM.Scene.SceneNode import SceneNode
|
||||
from UM.Settings.ContainerRegistry import ContainerRegistry
|
||||
from UM.Settings.EmptyInstanceContainer import EmptyInstanceContainer
|
||||
|
||||
from cura.CuraApplication import CuraApplication
|
||||
from cura.CuraPackageManager import CuraPackageManager
|
||||
|
|
|
@ -33,6 +33,10 @@ message Slice
|
|||
repeated Extruder extruders = 3; // The settings sent to each extruder object
|
||||
repeated SettingExtruder limit_to_extruder = 4; // From which stack the setting would inherit if not defined per object
|
||||
repeated EnginePlugin engine_plugins = 5;
|
||||
string sentry_id = 6; // The anonymized Sentry user id that requested the slice
|
||||
string cura_version = 7; // The version of Cura that requested the slice
|
||||
optional string project_name = 8; // The name of the project that requested the slice
|
||||
optional string user_name = 9; // The Digital Factory account name of the user that requested the slice
|
||||
}
|
||||
|
||||
message Extruder
|
||||
|
|
|
@ -164,6 +164,7 @@ class CuraEngineBackend(QObject, Backend):
|
|||
|
||||
application.getPreferences().addPreference("general/auto_slice", False)
|
||||
application.getPreferences().addPreference("info/send_engine_crash", True)
|
||||
application.getPreferences().addPreference("info/anonymous_engine_crash_report", True)
|
||||
|
||||
self._use_timer: bool = False
|
||||
|
||||
|
@ -1094,14 +1095,14 @@ class CuraEngineBackend(QObject, Backend):
|
|||
self._change_timer.timeout.disconnect(self.slice)
|
||||
|
||||
def _onPreferencesChanged(self, preference: str) -> None:
|
||||
if preference != "general/auto_slice" and preference != "info/send_engine_crash":
|
||||
if preference != "general/auto_slice" and preference != "info/send_engine_crash" and preference != "info/anonymous_engine_crash_report":
|
||||
return
|
||||
if preference == "general/auto_slice":
|
||||
auto_slice = self.determineAutoSlicing()
|
||||
if auto_slice:
|
||||
self._change_timer.start()
|
||||
elif preference == "info/send_engine_crash":
|
||||
os.environ["use_sentry"] = "1" if CuraApplication.getInstance().getPreferences().getValue("info/send_engine_crash") else "0"
|
||||
os.environ["USE_SENTRY"] = "1" if CuraApplication.getInstance().getPreferences().getValue("info/send_engine_crash") else "0"
|
||||
|
||||
def tickle(self) -> None:
|
||||
"""Tickle the backend so in case of auto slicing, it starts the timer."""
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
# Copyright (c) 2023 UltiMaker
|
||||
# Copyright (c) 2024 UltiMaker
|
||||
# Cura is released under the terms of the LGPLv3 or higher.
|
||||
import uuid
|
||||
|
||||
import os
|
||||
|
||||
import numpy
|
||||
|
@ -30,6 +32,7 @@ from cura.CuraApplication import CuraApplication
|
|||
from cura.Scene.CuraSceneNode import CuraSceneNode
|
||||
from cura.OneAtATimeIterator import OneAtATimeIterator
|
||||
from cura.Settings.ExtruderManager import ExtruderManager
|
||||
from cura.CuraVersion import CuraVersion
|
||||
|
||||
|
||||
NON_PRINTING_MESH_SETTINGS = ["anti_overhang_mesh", "infill_mesh", "cutting_mesh"]
|
||||
|
@ -60,13 +63,12 @@ class GcodeStartEndFormatter(Formatter):
|
|||
# will be used. Alternatively, if the expression is formatted as "{[expression], [extruder_nr]}",
|
||||
# then the expression will be evaluated with the extruder stack of the specified extruder_nr.
|
||||
|
||||
_extruder_regex = re.compile(r"^\s*(?P<expression>.*)\s*,\s*(?P<extruder_nr>\d+)\s*$")
|
||||
_extruder_regex = re.compile(r"^\s*(?P<expression>.*)\s*,\s*(?P<extruder_nr_expr>.*)\s*$")
|
||||
|
||||
def __init__(self, default_extruder_nr: int = -1, *,
|
||||
additional_per_extruder_settings: Optional[Dict[str, Dict[str, any]]] = None) -> None:
|
||||
def __init__(self, all_extruder_settings: Dict[str, Any], default_extruder_nr: int = -1) -> None:
|
||||
super().__init__()
|
||||
self._all_extruder_settings: Dict[str, Any] = all_extruder_settings
|
||||
self._default_extruder_nr: int = default_extruder_nr
|
||||
self._additional_per_extruder_settings: Optional[Dict[str, Dict[str, any]]] = additional_per_extruder_settings
|
||||
|
||||
def get_field(self, field_name, args: [str], kwargs: dict) -> Tuple[str, str]:
|
||||
# get_field method parses all fields in the format-string and parses them individually to the get_value method.
|
||||
|
@ -85,22 +87,32 @@ class GcodeStartEndFormatter(Formatter):
|
|||
if expression in post_slice_data_variables:
|
||||
return f"{{{expression}}}"
|
||||
|
||||
extruder_nr = self._default_extruder_nr
|
||||
extruder_nr = str(self._default_extruder_nr)
|
||||
|
||||
# The settings may specify a specific extruder to use. This is done by
|
||||
# formatting the expression as "{expression}, {extruder_nr}". If the
|
||||
# formatting the expression as "{expression}, {extruder_nr_expr}". If the
|
||||
# expression is formatted like this, we extract the extruder_nr and use
|
||||
# it to get the value from the correct extruder stack.
|
||||
match = self._extruder_regex.match(expression)
|
||||
if match:
|
||||
expression = match.group("expression")
|
||||
extruder_nr = int(match.group("extruder_nr"))
|
||||
extruder_nr_expr = match.group("extruder_nr_expr")
|
||||
|
||||
if self._additional_per_extruder_settings is not None and str(
|
||||
extruder_nr) in self._additional_per_extruder_settings:
|
||||
additional_variables = self._additional_per_extruder_settings[str(extruder_nr)]
|
||||
if extruder_nr_expr.isdigit():
|
||||
extruder_nr = extruder_nr_expr
|
||||
else:
|
||||
# We get the value of the extruder_nr_expr from `_all_extruder_settings` dictionary
|
||||
# rather than the global container stack. The `_all_extruder_settings["-1"]` is a
|
||||
# dict-representation of the global container stack, with additional properties such
|
||||
# as `initial_extruder_nr`. As users may enter such expressions we can't use the
|
||||
# global container stack.
|
||||
extruder_nr = str(self._all_extruder_settings["-1"].get(extruder_nr_expr, "-1"))
|
||||
|
||||
if extruder_nr in self._all_extruder_settings:
|
||||
additional_variables = self._all_extruder_settings[extruder_nr].copy()
|
||||
else:
|
||||
additional_variables = dict()
|
||||
Logger.warning(f"Extruder {extruder_nr} does not exist, using global settings")
|
||||
additional_variables = self._all_extruder_settings["-1"].copy()
|
||||
|
||||
# Add the arguments and keyword arguments to the additional settings. These
|
||||
# are currently _not_ used, but they are added for consistency with the
|
||||
|
@ -110,15 +122,17 @@ class GcodeStartEndFormatter(Formatter):
|
|||
for key, value in kwargs.items():
|
||||
additional_variables[key] = value
|
||||
|
||||
if extruder_nr == -1:
|
||||
if extruder_nr == "-1":
|
||||
container_stack = CuraApplication.getInstance().getGlobalContainerStack()
|
||||
else:
|
||||
container_stack = ExtruderManager.getInstance().getExtruderStack(extruder_nr)
|
||||
if not container_stack:
|
||||
Logger.warning(f"Extruder {extruder_nr} does not exist, using global settings")
|
||||
container_stack = CuraApplication.getInstance().getGlobalContainerStack()
|
||||
|
||||
setting_function = SettingFunction(expression)
|
||||
value = setting_function(container_stack, additional_variables=additional_variables)
|
||||
|
||||
|
||||
return value
|
||||
|
||||
|
||||
|
@ -128,12 +142,13 @@ class StartSliceJob(Job):
|
|||
def __init__(self, slice_message: Arcus.PythonMessage) -> None:
|
||||
super().__init__()
|
||||
|
||||
self._scene = CuraApplication.getInstance().getController().getScene() #type: Scene
|
||||
self._scene: Scene = CuraApplication.getInstance().getController().getScene()
|
||||
self._slice_message: Arcus.PythonMessage = slice_message
|
||||
self._is_cancelled = False #type: bool
|
||||
self._build_plate_number = None #type: Optional[int]
|
||||
self._is_cancelled: bool = False
|
||||
self._build_plate_number: Optional[int] = None
|
||||
|
||||
self._all_extruders_settings = None #type: Optional[Dict[str, Any]] # cache for all setting values from all stacks (global & extruder) for the current machine
|
||||
# cache for all setting values from all stacks (global & extruder) for the current machine
|
||||
self._all_extruders_settings: Optional[Dict[str, Any]] = None
|
||||
|
||||
def getSliceMessage(self) -> Arcus.PythonMessage:
|
||||
return self._slice_message
|
||||
|
@ -332,6 +347,17 @@ class StartSliceJob(Job):
|
|||
self._buildGlobalSettingsMessage(stack)
|
||||
self._buildGlobalInheritsStackMessage(stack)
|
||||
|
||||
user_id = uuid.getnode() # On all of Cura's supported platforms, this returns the MAC address which is pseudonymical information (!= anonymous).
|
||||
user_id %= 2 ** 16 # So to make it anonymous, apply a bitmask selecting only the last 16 bits. This prevents it from being traceable to a specific user but still gives somewhat of an idea of whether it's just the same user hitting the same crash over and over again, or if it's widespread.
|
||||
self._slice_message.sentry_id = f"{user_id}"
|
||||
self._slice_message.cura_version = CuraVersion
|
||||
|
||||
# Add the project name to the message if the user allows for non-anonymous crash data collection.
|
||||
account = CuraApplication.getInstance().getCuraAPI().account
|
||||
if account and account.isLoggedIn and not CuraApplication.getInstance().getPreferences().getValue("info/anonymous_engine_crash_report"):
|
||||
self._slice_message.project_name = CuraApplication.getInstance().getPrintInformation().baseName
|
||||
self._slice_message.user_name = account.userName
|
||||
|
||||
# Build messages for extruder stacks
|
||||
for extruder_stack in global_stack.extruderList:
|
||||
self._buildExtruderMessage(extruder_stack)
|
||||
|
@ -463,10 +489,7 @@ class StartSliceJob(Job):
|
|||
# Get "replacement-keys" for the extruders. In the formatter the settings stack is used to get the
|
||||
# replacement values for the setting-keys. However, the values for `material_id`, `material_type`,
|
||||
# etc are not in the settings stack.
|
||||
additional_per_extruder_settings = self._all_extruders_settings.copy()
|
||||
additional_per_extruder_settings["default_extruder_nr"] = default_extruder_nr
|
||||
fmt = GcodeStartEndFormatter(default_extruder_nr=default_extruder_nr,
|
||||
additional_per_extruder_settings=additional_per_extruder_settings)
|
||||
fmt = GcodeStartEndFormatter(self._all_extruders_settings, default_extruder_nr=default_extruder_nr)
|
||||
return str(fmt.format(value))
|
||||
except:
|
||||
Logger.logException("w", "Unable to do token replacement on start/end g-code")
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
# Copyright (c) 2021 Ultimaker B.V.
|
||||
# Cura is released under the terms of the LGPLv3 or higher.
|
||||
|
||||
from UM.MimeTypeDatabase import MimeType, MimeTypeDatabase
|
||||
from .src import DigitalFactoryFileProvider, DigitalFactoryOutputDevicePlugin, DigitalFactoryController
|
||||
|
||||
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
|
||||
import json
|
||||
from json import JSONDecodeError
|
||||
import re
|
||||
from time import time
|
||||
from typing import List, Any, Optional, Union, Type, Tuple, Dict, cast, TypeVar, Callable
|
||||
|
||||
|
|
|
@ -4,7 +4,6 @@ from typing import List, Optional
|
|||
|
||||
from PyQt6.QtCore import Qt, pyqtSignal
|
||||
|
||||
from UM.Logger import Logger
|
||||
from UM.Qt.ListModel import ListModel
|
||||
from .DigitalFactoryProjectResponse import DigitalFactoryProjectResponse
|
||||
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
# Cura is released under the terms of the LGPLv3 or higher.
|
||||
|
||||
from UM.i18n import i18nCatalog
|
||||
from UM.Platform import Platform
|
||||
|
||||
from . import GCodeGzWriter
|
||||
|
||||
|
|
|
@ -11,7 +11,6 @@ from UM.Settings.InstanceContainer import InstanceContainer
|
|||
from cura.Machines.ContainerTree import ContainerTree
|
||||
|
||||
from UM.i18n import i18nCatalog
|
||||
from cura.Settings.CuraStackBuilder import CuraStackBuilder
|
||||
|
||||
catalog = i18nCatalog("cura")
|
||||
|
||||
|
|
|
@ -3,12 +3,10 @@
|
|||
|
||||
from typing import Optional, TYPE_CHECKING, Dict, List
|
||||
|
||||
from .Constants import PACKAGES_URL
|
||||
from .PackageModel import PackageModel
|
||||
from .RemotePackageList import RemotePackageList
|
||||
from PyQt6.QtCore import pyqtSignal, QObject, pyqtProperty, QCoreApplication
|
||||
|
||||
from UM.TaskManagement.HttpRequestManager import HttpRequestManager # To request the package list from the API.
|
||||
from UM.i18n import i18nCatalog
|
||||
|
||||
if TYPE_CHECKING:
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
# Cura is released under the terms of the LGPLv3 or higher.
|
||||
|
||||
import re
|
||||
from enum import Enum
|
||||
from typing import Any, cast, Dict, List, Optional
|
||||
|
||||
from PyQt6.QtCore import pyqtProperty, QObject, pyqtSignal, pyqtSlot
|
||||
|
@ -12,7 +11,6 @@ from cura.CuraApplication import CuraApplication
|
|||
from cura.CuraPackageManager import CuraPackageManager
|
||||
from cura.Settings.CuraContainerRegistry import CuraContainerRegistry # To get names of materials we're compatible with.
|
||||
from UM.i18n import i18nCatalog # To translate placeholder names if data is not present.
|
||||
from UM.Logger import Logger
|
||||
from UM.PluginRegistry import PluginRegistry
|
||||
|
||||
catalog = i18nCatalog("cura")
|
||||
|
|
|
@ -25,7 +25,7 @@ UM.TooltipArea
|
|||
onClicked:
|
||||
{
|
||||
addedSettingsModel.setVisible(model.key, checked);
|
||||
UM.ActiveTool.forceUpdate();
|
||||
UM.Controller.forceUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -11,7 +11,7 @@ from UM.Settings.SettingInstance import SettingInstance
|
|||
from UM.Logger import Logger
|
||||
import UM.Settings.Models.SettingVisibilityHandler
|
||||
|
||||
from cura.Settings.ExtruderManager import ExtruderManager #To get global-inherits-stack setting values from different extruders.
|
||||
from cura.Settings.ExtruderManager import ExtruderManager # To get global-inherits-stack setting values from different extruders.
|
||||
from cura.Settings.SettingOverrideDecorator import SettingOverrideDecorator
|
||||
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@ Item
|
|||
readonly property string infillMeshType: "infill_mesh"
|
||||
readonly property string antiOverhangMeshType: "anti_overhang_mesh"
|
||||
|
||||
property var currentMeshType: UM.ActiveTool.properties.getValue("MeshType")
|
||||
property var currentMeshType: UM.Controller.properties.getValue("MeshType")
|
||||
|
||||
// Update the view every time the currentMeshType changes
|
||||
onCurrentMeshTypeChanged:
|
||||
|
@ -56,7 +56,7 @@ Item
|
|||
|
||||
function setMeshType(type)
|
||||
{
|
||||
UM.ActiveTool.setProperty("MeshType", type)
|
||||
UM.Controller.setProperty("MeshType", type)
|
||||
updateMeshTypeCheckedState(type)
|
||||
}
|
||||
|
||||
|
@ -224,7 +224,7 @@ Item
|
|||
visibilityHandler: Cura.PerObjectSettingVisibilityHandler
|
||||
{
|
||||
id: visibility_handler
|
||||
selectedObjectId: UM.ActiveTool.properties.getValue("SelectedObjectId")
|
||||
selectedObjectId: UM.Controller.properties.getValue("SelectedObjectId")
|
||||
}
|
||||
|
||||
// For some reason the model object is updated after removing him from the memory and
|
||||
|
@ -320,7 +320,7 @@ Item
|
|||
{
|
||||
id: provider
|
||||
|
||||
containerStackId: UM.ActiveTool.properties.getValue("ContainerID")
|
||||
containerStackId: UM.Controller.properties.getValue("ContainerID")
|
||||
key: model.key
|
||||
watchedProperties: [ "value", "enabled", "validationState" ]
|
||||
storeIndex: 0
|
||||
|
@ -330,7 +330,7 @@ Item
|
|||
UM.SettingPropertyProvider
|
||||
{
|
||||
id: inheritStackProvider
|
||||
containerStackId: UM.ActiveTool.properties.getValue("ContainerID")
|
||||
containerStackId: UM.Controller.properties.getValue("ContainerID")
|
||||
key: model.key
|
||||
watchedProperties: [ "limit_to_extruder" ]
|
||||
}
|
||||
|
@ -381,22 +381,22 @@ Item
|
|||
|
||||
Connections
|
||||
{
|
||||
target: UM.ActiveTool
|
||||
target: UM.Controller
|
||||
function onPropertiesChanged()
|
||||
{
|
||||
// the values cannot be bound with UM.ActiveTool.properties.getValue() calls,
|
||||
// the values cannot be bound with UM.Controller.properties.getValue() calls,
|
||||
// so here we connect to the signal and update the those values.
|
||||
if (typeof UM.ActiveTool.properties.getValue("SelectedObjectId") !== "undefined")
|
||||
if (typeof UM.Controller.properties.getValue("SelectedObjectId") !== "undefined")
|
||||
{
|
||||
const selectedObjectId = UM.ActiveTool.properties.getValue("SelectedObjectId")
|
||||
const selectedObjectId = UM.Controller.properties.getValue("SelectedObjectId")
|
||||
if (addedSettingsModel.visibilityHandler.selectedObjectId != selectedObjectId)
|
||||
{
|
||||
addedSettingsModel.visibilityHandler.selectedObjectId = selectedObjectId
|
||||
}
|
||||
}
|
||||
if (typeof UM.ActiveTool.properties.getValue("ContainerID") !== "undefined")
|
||||
if (typeof UM.Controller.properties.getValue("ContainerID") !== "undefined")
|
||||
{
|
||||
const containerId = UM.ActiveTool.properties.getValue("ContainerID")
|
||||
const containerId = UM.Controller.properties.getValue("ContainerID")
|
||||
if (provider.containerStackId !== containerId)
|
||||
{
|
||||
provider.containerStackId = containerId
|
||||
|
|
837
plugins/PostProcessingPlugin/scripts/AddCoolingProfile.py
Normal file
837
plugins/PostProcessingPlugin/scripts/AddCoolingProfile.py
Normal file
|
@ -0,0 +1,837 @@
|
|||
# Designed in January 2023 by GregValiant (Greg Foresi)
|
||||
## My design intent was to make this as full featured and "industrial strength" as I could. People printing exotic materials on large custom printers may want to turn the fans off for certain layers, and then back on again later in the print. This script allows that.
|
||||
# Functions:
|
||||
## Remove all fan speed lines from the file (optional). This should be enabled for the first instance of the script. It is disabled by default in any following instances.
|
||||
## "By Layer" allows the user to adjust the fan speed up, or down, or off, within the print. "By Feature" allows different fan speeds for different features (;TYPE:WALL-OUTER, etc.).
|
||||
## If 'By Feature' then a Start Layer and/or an End Layer can be defined.
|
||||
## Fan speeds are scaled PWM (0 - 255) or RepRap (0.0 - 1.0) depending on {machine_scale_fan_speed_zero_to_one}.
|
||||
## A minimum fan speed of 12% is enforced. It is the slowest speed that my cooling fan will turn on so that's what I used. 'M106 S14' (as Cura might insert) was pretty useless.
|
||||
## If multiple extruders have separate fan circuits the speeds are set at tool changes and conform to the layer or feature setting. There is support for up to 4 layer cooling fan circuits.
|
||||
## My thanks to @5axes(@CUQ), @fieldOfView(@AHoeben), @Ghostkeeper, and @Torgeir. A special thanks to @RBurema for his patience in reviewing my 'non-pythonic' script.
|
||||
## 9/14/23 (Greg Foresi) Added support for One-at-a-Time print sequence.
|
||||
## 12/15/23 (Greg Foresi) Split off 'Single Fan By Layer', 'Multi-fan By Layer', 'Single Fan By Feature', and 'Multi-fan By Feature' from the main 'execute' script.
|
||||
## 1/5/24 (Greg Foresi) Revised the regex replacements.
|
||||
|
||||
from ..Script import Script
|
||||
from UM.Application import Application
|
||||
import re
|
||||
|
||||
class AddCoolingProfile(Script):
|
||||
|
||||
def getSettingDataString(self):
|
||||
return """{
|
||||
"name": "Advanced Cooling Fan Control",
|
||||
"key": "AddCoolingProfile",
|
||||
"metadata": {},
|
||||
"version": 2,
|
||||
"settings":
|
||||
{
|
||||
"fan_layer_or_feature":
|
||||
{
|
||||
"label": "Cooling Control by:",
|
||||
"description": "A fan percentage of ''0'' turns the fan off. Minimum Fan is 12% (when on). All layer entries are the Cura Preview number. ''By Layer'': Enter as ''Layer#/Fan%'' (foreslash is the delimiter). Your final layer speed will continue to the end of the Gcode. ''By Feature'': If you enable an 'End Layer' then the ''Final %'' is available and is the speed that will finish the file. 'By Feature' is better for large slow prints than it is for short fast prints.",
|
||||
"type": "enum",
|
||||
"options": {
|
||||
"by_layer": "Layer Numbers",
|
||||
"by_feature": "Feature Types"},
|
||||
"default_value": "by_layer"
|
||||
},
|
||||
"delete_existing_m106":
|
||||
{
|
||||
"label": "Remove M106 lines prior to inserting new.",
|
||||
"description": "If you have 2 or more instances of 'Advanced Cooling Fan Control' running (to cool a portion of a print differently), then you must uncheck this box or the followup instances will remove all the lines inserted by the first instance. Pay attention to the Start and Stop layers. Regardless of this setting: The script always removes M106 lines starting with the lowest layer number (when 'By Layer') or the starting layer number (when 'By Feature'). If you want to keep the M106 lines that Cura inserted up to the point where this post-processor will start making insertions, then un-check the box.",
|
||||
"type": "bool",
|
||||
"enabled": true,
|
||||
"value": true,
|
||||
"default_value": true
|
||||
},
|
||||
"feature_fan_start_layer":
|
||||
{
|
||||
"label": "Starting Layer",
|
||||
"description": "Layer to start the insertion at. Use the Cura preview numbers. Changes will begin at the start of that layer.",
|
||||
"type": "int",
|
||||
"default_value": 5,
|
||||
"minimum_value": 1,
|
||||
"unit": "Lay# ",
|
||||
"enabled": "fan_layer_or_feature == 'by_feature'"
|
||||
},
|
||||
"feature_fan_end_layer":
|
||||
{
|
||||
"label": "Ending Layer",
|
||||
"description": "Layer to complete the insertion at. Enter '-1' for the entire file or enter a layer number. Insertions will stop at the END of this layer. If you set an End Layer then you should set the Final % that will finish the file",
|
||||
"type": "int",
|
||||
"default_value": -1,
|
||||
"minimum_value": -1,
|
||||
"unit": "Lay# ",
|
||||
"enabled": "fan_layer_or_feature == 'by_feature'"
|
||||
},
|
||||
"layer_fan_1":
|
||||
{
|
||||
"label": "Layer/Percent #1",
|
||||
"description": "Enter as: 'LAYER / Percent' Ex: 55/100 with the layer first, then a '/' to delimit, and then the fan percentage. There are up to 8 changes. If you need more then add a second instance of this script and remember to turn off 'Remove M106 lines' in the second instance. The layer numbers in the second instance must start with a layer number higher than the last layer number in a previous script. You can't end the first script with a setting for layer 80 and then start the second script with a setting for layer 40 because 'Remove M106 lines' always starts with the lowest layer number when 'By Layer' is selected.",
|
||||
"type": "str",
|
||||
"default_value": "5/30",
|
||||
"unit": "L#/% ",
|
||||
"enabled": "fan_layer_or_feature == 'by_layer'"
|
||||
},
|
||||
"layer_fan_2":
|
||||
{
|
||||
"label": "Layer/Percent #2",
|
||||
"description": "Enter as: 'LAYER / Percent' Ex: 55/100 with the layer first, then a '/' to delimit, and then the fan percentage.",
|
||||
"type": "str",
|
||||
"default_value": "",
|
||||
"unit": "L#/% ",
|
||||
"enabled": "fan_layer_or_feature == 'by_layer'"
|
||||
},
|
||||
"layer_fan_3":
|
||||
{
|
||||
"label": "Layer/Percent #3",
|
||||
"description": "Enter as: 'LAYER / Percent' Ex: 55/100 with the layer first, then a '/' to delimit, and then the fan percentage.",
|
||||
"type": "str",
|
||||
"default_value": "",
|
||||
"unit": "L#/% ",
|
||||
"enabled": "fan_layer_or_feature == 'by_layer'"
|
||||
},
|
||||
"layer_fan_4":
|
||||
{
|
||||
"label": "Layer/Percent #4",
|
||||
"description": "Enter as: 'LAYER / Percent' Ex: 55/100 with the layer first, then a '/' to delimit, and then the fan percentage.",
|
||||
"type": "str",
|
||||
"default_value": "",
|
||||
"unit": "L#/% ",
|
||||
"enabled": "fan_layer_or_feature == 'by_layer'"
|
||||
},
|
||||
"layer_fan_5":
|
||||
{
|
||||
"label": "Layer/Percent #5",
|
||||
"description": "Enter as: 'LAYER / Percent' Ex: 55/100 with the layer first, then a '/' to delimit, and then the fan percentage.",
|
||||
"type": "str",
|
||||
"default_value": "",
|
||||
"unit": "L#/% ",
|
||||
"enabled": "fan_layer_or_feature == 'by_layer'"
|
||||
},
|
||||
"layer_fan_6":
|
||||
{
|
||||
"label": "Layer/Percent #6",
|
||||
"description": "Enter as: 'LAYER / Percent' Ex: 55/100 with the layer first, then a '/' to delimit, and then the fan percentage.",
|
||||
"type": "str",
|
||||
"default_value": "",
|
||||
"unit": "L#/% ",
|
||||
"enabled": "fan_layer_or_feature == 'by_layer'"
|
||||
},
|
||||
"layer_fan_7":
|
||||
{
|
||||
"label": "Layer/Percent #7",
|
||||
"description": "Enter as: 'LAYER / Percent' Ex: 55/100 with the layer first, then a '/' to delimit, and then the fan percentage.",
|
||||
"type": "str",
|
||||
"default_value": "",
|
||||
"unit": "L#/% ",
|
||||
"enabled": "fan_layer_or_feature == 'by_layer'"
|
||||
},
|
||||
"layer_fan_8":
|
||||
{
|
||||
"label": "Layer/Percent #8",
|
||||
"description": "Enter as: 'LAYER / Percent' Ex: 55/100 with the layer first, then a '/' to delimit, and then the fan percentage.",
|
||||
"type": "str",
|
||||
"default_value": "",
|
||||
"unit": "L#/% ",
|
||||
"enabled": "fan_layer_or_feature == 'by_layer'"
|
||||
},
|
||||
"feature_fan_skirt":
|
||||
{
|
||||
"label": "Skirt/Brim/Ooze Shield %",
|
||||
"description": "Enter the fan percentage for skirt/brim. If you are starting at a layer above 1 then this setting only affects Ooze Shields and from the Start Layer up.",
|
||||
"type": "int",
|
||||
"default_value": 0,
|
||||
"minimum_value": 0,
|
||||
"maximum_value": 100,
|
||||
"unit": "% ",
|
||||
"enabled": "fan_layer_or_feature == 'by_feature'"
|
||||
},
|
||||
"feature_fan_wall_inner":
|
||||
{
|
||||
"label": "Inner Walls %",
|
||||
"description": "Enter the fan percentage for the Wall-Inner.",
|
||||
"type": "int",
|
||||
"default_value": 35,
|
||||
"minimum_value": 0,
|
||||
"maximum_value": 100,
|
||||
"unit": "% ",
|
||||
"enabled": "fan_layer_or_feature == 'by_feature'"
|
||||
},
|
||||
"feature_fan_wall_outer":
|
||||
{
|
||||
"label": "Outer Walls %",
|
||||
"description": "Enter the fan percentage for the Wall-Outer.",
|
||||
"type": "int",
|
||||
"default_value": 75,
|
||||
"minimum_value": 0,
|
||||
"maximum_value": 100,
|
||||
"unit": "% ",
|
||||
"enabled": "fan_layer_or_feature == 'by_feature'"
|
||||
},
|
||||
"feature_fan_fill":
|
||||
{
|
||||
"label": "Infill %",
|
||||
"description": "Enter the fan percentage for the Infill.",
|
||||
"type": "int",
|
||||
"default_value": 35,
|
||||
"minimum_value": 0,
|
||||
"maximum_value": 100,
|
||||
"unit": "% ",
|
||||
"enabled": "fan_layer_or_feature == 'by_feature'"
|
||||
},
|
||||
"feature_fan_skin":
|
||||
{
|
||||
"label": "Top/Bottom (Skin) %",
|
||||
"description": "Enter the fan percentage for the Skins.",
|
||||
"type": "int",
|
||||
"default_value": 100,
|
||||
"minimum_value": 0,
|
||||
"maximum_value": 100,
|
||||
"unit": "% ",
|
||||
"enabled": "fan_layer_or_feature == 'by_feature'"
|
||||
},
|
||||
"feature_fan_support":
|
||||
{
|
||||
"label": "Support %",
|
||||
"description": "Enter the fan percentage for the Supports.",
|
||||
"type": "int",
|
||||
"default_value": 35,
|
||||
"minimum_value": 0,
|
||||
"maximum_value": 100,
|
||||
"unit": "% ",
|
||||
"enabled": "fan_layer_or_feature == 'by_feature'"
|
||||
},
|
||||
"feature_fan_support_interface":
|
||||
{
|
||||
"label": "Support Interface %",
|
||||
"description": "Enter the fan percentage for the Support Interface.",
|
||||
"type": "int",
|
||||
"default_value": 100,
|
||||
"minimum_value": 0,
|
||||
"maximum_value": 100,
|
||||
"unit": "% ",
|
||||
"enabled": "fan_layer_or_feature == 'by_feature'"
|
||||
},
|
||||
"feature_fan_prime_tower":
|
||||
{
|
||||
"label": "Prime Tower %",
|
||||
"description": "Enter the fan percentage for the Prime Tower (whether it's used or not).",
|
||||
"type": "int",
|
||||
"default_value": 35,
|
||||
"minimum_value": 0,
|
||||
"maximum_value": 100,
|
||||
"unit": "% ",
|
||||
"enabled": "fan_layer_or_feature == 'by_feature'"
|
||||
},
|
||||
"feature_fan_bridge":
|
||||
{
|
||||
"label": "Bridge %",
|
||||
"description": "Enter the fan percentage for any Bridging (whether it's used on not).",
|
||||
"type": "int",
|
||||
"default_value": 100,
|
||||
"minimum_value": 0,
|
||||
"maximum_value": 100,
|
||||
"unit": "% ",
|
||||
"enabled": "fan_layer_or_feature == 'by_feature'"
|
||||
},
|
||||
"feature_fan_combing":
|
||||
{
|
||||
"label": "Fan 'OFF' during Combing:",
|
||||
"description": "When checked will set the fan to 0% for combing moves over 5 lines long in the gcode. When un-checked the fan speed during combing is whatever the previous speed is set to.",
|
||||
"type": "bool",
|
||||
"enabled": "fan_layer_or_feature == 'by_feature'",
|
||||
"default_value": true
|
||||
},
|
||||
"feature_fan_feature_final":
|
||||
{
|
||||
"label": "Final %",
|
||||
"description": "If you choose an 'End Layer' then this is the fan speed that will carry through to the end of the gcode file. It will go into effect at the 'END' of your End layer.",
|
||||
"type": "int",
|
||||
"default_value": 35,
|
||||
"minimum_value": 0,
|
||||
"maximum_value": 100,
|
||||
"unit": "% ",
|
||||
"enabled": "(int(feature_fan_end_layer) != -1) and (fan_layer_or_feature == 'by_feature')"
|
||||
},
|
||||
"fan_enable_raft":
|
||||
{
|
||||
"label": "Enable Raft Cooling",
|
||||
"description": "Enable the fan for the raft layers. When enabled the Raft Fan Speed will continue until another Layer or Feature setting over-rides it.",
|
||||
"type": "bool",
|
||||
"default_value": false,
|
||||
"enabled": true
|
||||
},
|
||||
"fan_raft_percent":
|
||||
{
|
||||
"label": "Raft Fan %:",
|
||||
"description": "Enter the percentage for the Raft.",
|
||||
"type": "int",
|
||||
"default_value": 35,
|
||||
"minimum_value": 0,
|
||||
"maximum_value": 100,
|
||||
"unit": "% ",
|
||||
"enabled": "fan_enable_raft"
|
||||
}
|
||||
}
|
||||
}"""
|
||||
|
||||
def initialize(self) -> None:
|
||||
super().initialize()
|
||||
scripts = Application.getInstance().getGlobalContainerStack().getMetaDataEntry("post_processing_scripts")
|
||||
if scripts != None:
|
||||
script_count = scripts.count("AddCoolingProfile")
|
||||
if script_count > 0:
|
||||
## Set 'Remove M106 lines' to "false" if there is already an instance of this script running.
|
||||
self._instance.setProperty("delete_existing_m106", "value", False)
|
||||
|
||||
def execute(self, data):
|
||||
#Initialize variables that are buried in if statements.
|
||||
mycura = Application.getInstance().getGlobalContainerStack()
|
||||
t0_fan = " P0"; t1_fan = " P0"; t2_fan = " P0"; t3_fan = " P0"; is_multi_extr_print = True
|
||||
|
||||
#Get some information from Cura-----------------------------------
|
||||
extruder = mycura.extruderList
|
||||
|
||||
#This will be true when fan scale is 0-255pwm and false when it's RepRap 0-1 (Cura 5.x)
|
||||
fan_mode = True
|
||||
##For 4.x versions that don't have the 0-1 option
|
||||
try:
|
||||
fan_mode = not bool(extruder[0].getProperty("machine_scale_fan_speed_zero_to_one", "value"))
|
||||
except:
|
||||
pass
|
||||
bed_adhesion = (extruder[0].getProperty("adhesion_type", "value"))
|
||||
extruder_count = mycura.getProperty("machine_extruder_count", "value")
|
||||
print_sequence = str(mycura.getProperty("print_sequence", "value"))
|
||||
|
||||
#Assign the fan numbers to the tools------------------------------
|
||||
if extruder_count == 1:
|
||||
is_multi_fan = False
|
||||
is_multi_extr_print = False
|
||||
if int((extruder[0].getProperty("machine_extruder_cooling_fan_number", "value"))) > 0:
|
||||
t0_fan = " P" + str((extruder[0].getProperty("machine_extruder_cooling_fan_number", "value")))
|
||||
else:
|
||||
#No P parameter if there is a single fan circuit------------------
|
||||
t0_fan = ""
|
||||
|
||||
#Get the cooling fan numbers for each extruder if the printer has multiple extruders
|
||||
elif extruder_count > 1:
|
||||
is_multi_fan = True
|
||||
t0_fan = " P" + str((extruder[0].getProperty("machine_extruder_cooling_fan_number", "value")))
|
||||
if is_multi_fan:
|
||||
if extruder_count > 1: t1_fan = " P" + str((extruder[1].getProperty("machine_extruder_cooling_fan_number", "value")))
|
||||
if extruder_count > 2: t2_fan = " P" + str((extruder[2].getProperty("machine_extruder_cooling_fan_number", "value")))
|
||||
if extruder_count > 3: t3_fan = " P" + str((extruder[3].getProperty("machine_extruder_cooling_fan_number", "value")))
|
||||
|
||||
#Initialize the fan_list with defaults----------------------------
|
||||
fan_list = ["z"] * 16
|
||||
for num in range(0,15,2):
|
||||
fan_list[num] = len(data)
|
||||
fan_list[num + 1] = "M106 S0"
|
||||
|
||||
#Assign the variable values if "By Layer"-------------------------
|
||||
by_layer_or_feature = self.getSettingValueByKey("fan_layer_or_feature")
|
||||
if by_layer_or_feature == "by_layer":
|
||||
## By layer doesn't do any feature search so there is no need to look for combing moves
|
||||
feature_fan_combing = False
|
||||
fan_list[0] = self.getSettingValueByKey("layer_fan_1")
|
||||
fan_list[2] = self.getSettingValueByKey("layer_fan_2")
|
||||
fan_list[4] = self.getSettingValueByKey("layer_fan_3")
|
||||
fan_list[6] = self.getSettingValueByKey("layer_fan_4")
|
||||
fan_list[8] = self.getSettingValueByKey("layer_fan_5")
|
||||
fan_list[10] = self.getSettingValueByKey("layer_fan_6")
|
||||
fan_list[12] = self.getSettingValueByKey("layer_fan_7")
|
||||
fan_list[14] = self.getSettingValueByKey("layer_fan_8")
|
||||
## If there is no '/' delimiter then ignore the line else put the settings in a list
|
||||
for num in range(0,15,2):
|
||||
if "/" in fan_list[num]:
|
||||
fan_list[num + 1] = self._layer_checker(fan_list[num], "p", fan_mode)
|
||||
fan_list[num] = self._layer_checker(fan_list[num], "l", fan_mode)
|
||||
|
||||
## Assign the variable values if "By Feature"
|
||||
elif by_layer_or_feature == "by_feature":
|
||||
the_start_layer = self.getSettingValueByKey("feature_fan_start_layer") - 1
|
||||
the_end_layer = self.getSettingValueByKey("feature_fan_end_layer")
|
||||
try:
|
||||
if int(the_end_layer) != -1:
|
||||
## Catch a possible input error.
|
||||
if the_end_layer < the_start_layer:
|
||||
the_end_layer = the_start_layer
|
||||
except:
|
||||
the_end_layer = -1 ## If there is an input error default to the entire gcode file.
|
||||
|
||||
## Get the speed for each feature
|
||||
feature_name_list = []
|
||||
feature_speed_list = []
|
||||
feature_speed_list.append(self._feature_checker(self.getSettingValueByKey("feature_fan_skirt"), fan_mode)); feature_name_list.append(";TYPE:SKIRT")
|
||||
feature_speed_list.append(self._feature_checker(self.getSettingValueByKey("feature_fan_wall_inner"), fan_mode)); feature_name_list.append(";TYPE:WALL-INNER")
|
||||
feature_speed_list.append(self._feature_checker(self.getSettingValueByKey("feature_fan_wall_outer"), fan_mode)); feature_name_list.append(";TYPE:WALL-OUTER")
|
||||
feature_speed_list.append(self._feature_checker(self.getSettingValueByKey("feature_fan_fill"), fan_mode)); feature_name_list.append(";TYPE:FILL")
|
||||
feature_speed_list.append(self._feature_checker(self.getSettingValueByKey("feature_fan_skin"), fan_mode)); feature_name_list.append(";TYPE:SKIN")
|
||||
feature_speed_list.append(self._feature_checker(self.getSettingValueByKey("feature_fan_support"), fan_mode)); feature_name_list.append(";TYPE:SUPPORT")
|
||||
feature_speed_list.append(self._feature_checker(self.getSettingValueByKey("feature_fan_support_interface"), fan_mode)); feature_name_list.append(";TYPE:SUPPORT-INTERFACE")
|
||||
feature_speed_list.append(self._feature_checker(self.getSettingValueByKey("feature_fan_prime_tower"), fan_mode)); feature_name_list.append(";TYPE:PRIME-TOWER")
|
||||
feature_speed_list.append(self._feature_checker(self.getSettingValueByKey("feature_fan_bridge"), fan_mode)); feature_name_list.append(";BRIDGE")
|
||||
feature_speed_list.append(self._feature_checker(self.getSettingValueByKey("feature_fan_feature_final"), fan_mode)); feature_name_list.append("FINAL_FAN")
|
||||
feature_fan_combing = self.getSettingValueByKey("feature_fan_combing")
|
||||
if the_end_layer > -1 and by_layer_or_feature == "by_feature":
|
||||
## Required so the final speed input can be determined
|
||||
the_end_is_enabled = True
|
||||
else:
|
||||
## There is no ending layer so do the whole file
|
||||
the_end_is_enabled = False
|
||||
if the_end_layer == -1 or the_end_is_enabled == False:
|
||||
the_end_layer = len(data) + 2
|
||||
|
||||
## Find the Layer0Index and the RaftIndex
|
||||
raft_start_index = 0
|
||||
number_of_raft_layers = 0
|
||||
layer_0_index = 0
|
||||
## Catch the number of raft layers.
|
||||
for l_num in range(1,10,1):
|
||||
layer = data[l_num]
|
||||
if ";LAYER:-" in layer:
|
||||
number_of_raft_layers += 1
|
||||
if raft_start_index == 0:
|
||||
raft_start_index = l_num
|
||||
if ";LAYER:0" in layer:
|
||||
layer_0_index = l_num
|
||||
break
|
||||
|
||||
## Is this a single extruder print on a multi-extruder printer? - get the correct fan number for the extruder being used.
|
||||
if is_multi_fan:
|
||||
T0_used = False
|
||||
T1_used = False
|
||||
T2_used = False
|
||||
T3_used = False
|
||||
## Bypass the file header and ending gcode.
|
||||
for num in range(1,len(data)-1,1):
|
||||
lines = data[num]
|
||||
if "T0" in lines:
|
||||
T0_used = True
|
||||
if "T1" in lines:
|
||||
T1_used = True
|
||||
if "T2" in lines:
|
||||
T2_used = True
|
||||
if "T3" in lines:
|
||||
T3_used = True
|
||||
is_multi_extr_print = True if sum([T0_used, T1_used, T2_used, T3_used]) > 1 else False
|
||||
|
||||
## On a multi-extruder printer and single extruder print find out which extruder starts the file.
|
||||
init_fan = t0_fan
|
||||
if not is_multi_extr_print:
|
||||
startup = data[1]
|
||||
lines = startup.split("\n")
|
||||
for line in lines:
|
||||
if line == "T1":
|
||||
t0_fan = t1_fan
|
||||
elif line == "T2":
|
||||
t0_fan = t2_fan
|
||||
elif line == "T3":
|
||||
t0_fan = t3_fan
|
||||
elif is_multi_extr_print:
|
||||
## On a multi-extruder printer and multi extruder print find out which extruder starts the file.
|
||||
startup = data[1]
|
||||
lines = startup.split("\n")
|
||||
for line in lines:
|
||||
if line == "T0":
|
||||
init_fan = t0_fan
|
||||
elif line == "T1":
|
||||
init_fan = t1_fan
|
||||
elif line == "T2":
|
||||
init_fan = t2_fan
|
||||
elif line == "T3":
|
||||
init_fan = t3_fan
|
||||
else:
|
||||
init_fan = ""
|
||||
## Assign the variable values if "Raft Enabled"
|
||||
raft_enabled = self.getSettingValueByKey("fan_enable_raft")
|
||||
if raft_enabled and bed_adhesion == "raft":
|
||||
fan_sp_raft = self._feature_checker(self.getSettingValueByKey("fan_raft_percent"), fan_mode)
|
||||
else:
|
||||
fan_sp_raft = "M106 S0"
|
||||
|
||||
# Start to alter the data-----------------------------------------
|
||||
## Strip the existing M106 lines from the file up to the end of the last layer. If a user wants to use more than one instance of this plugin then they won't want to erase the M106 lines that the preceding plugins inserted so 'delete_existing_m106' is an option.
|
||||
delete_existing_m106 = self.getSettingValueByKey("delete_existing_m106")
|
||||
if delete_existing_m106:
|
||||
## Start deleting from the beginning
|
||||
start_from = int(raft_start_index)
|
||||
else:
|
||||
if by_layer_or_feature == "by_layer":
|
||||
altered_start_layer = str(len(data))
|
||||
## The fan list layers don't need to be in ascending order. Get the lowest.
|
||||
for num in range(0,15,2):
|
||||
try:
|
||||
if int(fan_list[num]) < int(altered_start_layer):
|
||||
altered_start_layer = int(fan_list[num])
|
||||
except:
|
||||
pass
|
||||
elif by_layer_or_feature == "by_feature":
|
||||
altered_start_layer = int(the_start_layer) - 1
|
||||
start_from = int(layer_0_index) + int(altered_start_layer)
|
||||
## Strip the M106 and M107 lines from the file
|
||||
for l_index in range(int(start_from), len(data) - 1, 1):
|
||||
data[l_index] = re.sub(re.compile("M106(.*)\n"), "", data[l_index])
|
||||
data[l_index] = re.sub(re.compile("M107(.*)\n"), "", data[l_index])
|
||||
|
||||
## Deal with a raft and with One-At-A-Time print sequence
|
||||
if raft_enabled and bed_adhesion == "raft":
|
||||
if print_sequence == "one_at_a_time":
|
||||
for r_index in range(2,len(data)-2,1):
|
||||
lines = data[r_index].split("\n")
|
||||
if not raft_enabled or bed_adhesion != "raft":
|
||||
if ";LAYER:0" in data[r_index] or ";LAYER:-" in data[r_index]:
|
||||
lines.insert(1, "M106 S0" + str(t0_fan))
|
||||
if raft_enabled and bed_adhesion == "raft":
|
||||
if ";LAYER:-" in data[r_index]:
|
||||
## Turn the raft fan on
|
||||
lines.insert(1, fan_sp_raft + str(t0_fan))
|
||||
## Shut the raft fan off at layer 0
|
||||
if ";LAYER:0" in data[r_index]:
|
||||
lines.insert(1,"M106 S0" + str(t0_fan))
|
||||
data[r_index] = "\n".join(lines)
|
||||
elif print_sequence == "all_at_once":
|
||||
layer = data[raft_start_index]
|
||||
lines = layer.split("\n")
|
||||
if ";LAYER:-" in layer:
|
||||
## Turn the raft fan on
|
||||
lines.insert(1, fan_sp_raft + str(init_fan))
|
||||
layer = "\n".join(lines)
|
||||
data[raft_start_index] = layer
|
||||
layer = data[layer_0_index]
|
||||
lines = layer.split("\n")
|
||||
## Shut the raft fan off
|
||||
lines.insert(1, "M106 S0" + str(init_fan))
|
||||
data[layer_0_index] = "\n".join(lines)
|
||||
else:
|
||||
for r_index in range(2,len(data)-2,1):
|
||||
lines = data[r_index].split("\n")
|
||||
if ";LAYER:0" in data[r_index] or ";LAYER:-" in data[r_index]:
|
||||
if not "0" in fan_list:
|
||||
lines.insert(1, "M106 S0" + str(t0_fan))
|
||||
data[r_index] = "\n".join(lines)
|
||||
|
||||
## Turn off all fans at the end of data[1]. If more than one instance of this script is running then this will result in multiple M106 lines.
|
||||
temp_startup = data[1].split("\n")
|
||||
temp_startup.insert(len(temp_startup)-2,"M106 S0" + str(t0_fan))
|
||||
## If there are multiple cooling fans shut them all off
|
||||
if is_multi_fan:
|
||||
if extruder_count > 1 and t1_fan != t0_fan: temp_startup.insert(len(temp_startup)-2,"M106 S0" + str(t1_fan))
|
||||
if extruder_count > 2 and t2_fan != t1_fan and t2_fan != t0_fan: temp_startup.insert(len(temp_startup)-2,"M106 S0" + str(t2_fan))
|
||||
if extruder_count > 3 and t3_fan != t2_fan and t3_fan != t1_fan and t3_fan != t0_fan: temp_startup.insert(len(temp_startup)-2,"M106 S0" + str(t3_fan))
|
||||
data[1] = "\n".join(temp_startup)
|
||||
|
||||
## If 'feature_fan_combing' is True then add additional 'MESH:NONMESH' lines for travel moves over 5 lines long
|
||||
## For compatibility with 5.3.0 change any MESH:NOMESH to MESH:NONMESH.
|
||||
if feature_fan_combing:
|
||||
for layer_num in range(2,len(data)):
|
||||
layer = data[layer_num]
|
||||
data[layer_num] = re.sub(";MESH:NOMESH", ";MESH:NONMESH", layer)
|
||||
data = self._add_travel_comment(data, layer_0_index)
|
||||
|
||||
# Single Fan "By Layer"--------------------------------------------
|
||||
if by_layer_or_feature == "by_layer" and not is_multi_fan:
|
||||
return self._single_fan_by_layer(data, layer_0_index, fan_list, t0_fan)
|
||||
|
||||
# Multi-Fan "By Layer"---------------------------------------------
|
||||
if by_layer_or_feature == "by_layer" and is_multi_fan:
|
||||
return self._multi_fan_by_layer(data, layer_0_index, fan_list, t0_fan, t1_fan, t2_fan, t3_fan)
|
||||
|
||||
#Single Fan "By Feature"------------------------------------------
|
||||
if by_layer_or_feature == "by_feature" and (not is_multi_fan or not is_multi_extr_print):
|
||||
return self._single_fan_by_feature(data, layer_0_index, the_start_layer, the_end_layer, the_end_is_enabled, fan_list, t0_fan, feature_speed_list, feature_name_list, feature_fan_combing)
|
||||
|
||||
#Multi Fan "By Feature"-------------------------------------------
|
||||
if by_layer_or_feature == "by_feature" and is_multi_fan:
|
||||
return self._multi_fan_by_feature(data, layer_0_index, the_start_layer, the_end_layer, the_end_is_enabled, fan_list, t0_fan, t1_fan, t2_fan, t3_fan, feature_speed_list, feature_name_list, feature_fan_combing)
|
||||
|
||||
# The Single Fan "By Layer"----------------------------------------
|
||||
def _single_fan_by_layer(self, data: str, layer_0_index: int, fan_list: str, t0_fan: str)->str:
|
||||
layer_number = "0"
|
||||
single_fan_data = data
|
||||
for l_index in range(layer_0_index,len(single_fan_data)-1,1):
|
||||
layer = single_fan_data[l_index]
|
||||
fan_lines = layer.split("\n")
|
||||
for fan_line in fan_lines:
|
||||
if ";LAYER:" in fan_line:
|
||||
layer_number = str(fan_line.split(":")[1])
|
||||
## If there is a match for the current layer number make the insertion
|
||||
for num in range(0,15,2):
|
||||
if layer_number == str(fan_list[num]):
|
||||
layer = layer.replace(fan_lines[0],fan_lines[0] + "\n" + fan_list[num + 1] + str(t0_fan))
|
||||
single_fan_data[l_index] = layer
|
||||
return single_fan_data
|
||||
|
||||
# Multi-Fan "By Layer"-----------------------------------------
|
||||
def _multi_fan_by_layer(self, data: str, layer_0_index: int, fan_list: str, t0_fan: str, t1_fan: str, t2_fan: str, t3_fan: str)->str:
|
||||
multi_fan_data = data
|
||||
layer_number = "0"
|
||||
current_fan_speed = "0"
|
||||
prev_fan = str(t0_fan)
|
||||
this_fan = str(t0_fan)
|
||||
start_index = str(len(multi_fan_data))
|
||||
for num in range(0,15,2):
|
||||
## The fan_list may not be in ascending order. Get the lowest layer number
|
||||
try:
|
||||
if int(fan_list[num]) < int(start_index):
|
||||
start_index = str(fan_list[num])
|
||||
except:
|
||||
pass
|
||||
## Move the start point if delete_existing_m106 is false
|
||||
start_index = int(start_index) + int(layer_0_index)
|
||||
## Track the tool number
|
||||
for num in range(1,int(start_index),1):
|
||||
layer = multi_fan_data[num]
|
||||
lines = layer.split("\n")
|
||||
for line in lines:
|
||||
if line == "T0":
|
||||
prev_fan = this_fan
|
||||
this_fan = t0_fan
|
||||
elif line == "T1":
|
||||
prev_fan = this_fan
|
||||
this_fan = t1_fan
|
||||
elif line == "T2":
|
||||
prev_fan = this_fan
|
||||
this_fan = t2_fan
|
||||
elif line == "T3":
|
||||
prev_fan = this_fan
|
||||
this_fan = t3_fan
|
||||
for l_index in range(int(start_index),len(multi_fan_data)-1,1):
|
||||
modified_data = ""
|
||||
layer = multi_fan_data[l_index]
|
||||
fan_lines = layer.split("\n")
|
||||
for fan_line in fan_lines:
|
||||
## Prepare to shut down the previous fan and start the next one.
|
||||
if fan_line.startswith("T"):
|
||||
if fan_line == "T0": this_fan = str(t0_fan)
|
||||
if fan_line == "T1": this_fan = str(t1_fan)
|
||||
if fan_line == "T2": this_fan = str(t2_fan)
|
||||
if fan_line == "T3": this_fan = str(t3_fan)
|
||||
modified_data += "M106 S0" + prev_fan + "\n"
|
||||
modified_data += fan_line + "\n"
|
||||
modified_data += "M106 S" + str(current_fan_speed) + this_fan + "\n"
|
||||
prev_fan = this_fan
|
||||
elif ";LAYER:" in fan_line:
|
||||
modified_data += fan_line + "\n"
|
||||
layer_number = str(fan_line.split(":")[1])
|
||||
for num in range(0,15,2):
|
||||
if layer_number == str(fan_list[num]):
|
||||
modified_data += fan_list[num + 1] + this_fan + "\n"
|
||||
current_fan_speed = str(fan_list[num + 1].split("S")[1])
|
||||
current_fan_speed = str(current_fan_speed.split(" ")[0]) ## Just in case
|
||||
else:
|
||||
modified_data += fan_line + "\n"
|
||||
if modified_data.endswith("\n"): modified_data = modified_data[0:-1]
|
||||
multi_fan_data[l_index] = modified_data
|
||||
return multi_fan_data
|
||||
|
||||
# Single fan by feature-----------------------------------------------
|
||||
def _single_fan_by_feature(self, data: str, layer_0_index: int, the_start_layer: str, the_end_layer: str, the_end_is_enabled: str, fan_list: str, t0_fan: str, feature_speed_list: str, feature_name_list: str, feature_fan_combing: bool)->str:
|
||||
single_fan_data = data
|
||||
layer_number = "0"
|
||||
index = 1
|
||||
## Start with layer:0
|
||||
for l_index in range(layer_0_index,len(single_fan_data)-1,1):
|
||||
modified_data = ""
|
||||
layer = single_fan_data[l_index]
|
||||
lines = layer.split("\n")
|
||||
for line in lines:
|
||||
if ";LAYER:" in line:
|
||||
layer_number = str(line.split(":")[1])
|
||||
if int(layer_number) >= int(the_start_layer) and int(layer_number) < int(the_end_layer)-1:
|
||||
temp = line.split(" ")[0]
|
||||
try:
|
||||
name_index = feature_name_list.index(temp)
|
||||
except:
|
||||
name_index = -1
|
||||
if name_index != -1:
|
||||
modified_data += feature_speed_list[name_index] + t0_fan + "\n"
|
||||
elif ";MESH:NONMESH" in line:
|
||||
if feature_fan_combing == True:
|
||||
modified_data += "M106 S0" + t0_fan + "\n"
|
||||
modified_data += line + "\n"
|
||||
## If an End Layer is defined and is less than the last layer then insert the Final Speed
|
||||
if line == ";LAYER:" + str(the_end_layer) and the_end_is_enabled == True:
|
||||
modified_data += feature_speed_list[len(feature_speed_list) - 1] + t0_fan + "\n"
|
||||
if modified_data.endswith("\n"): modified_data = modified_data[0: - 1]
|
||||
single_fan_data[l_index] = modified_data
|
||||
return single_fan_data
|
||||
|
||||
# Multi-fan by feature------------------------------------------------
|
||||
def _multi_fan_by_feature(self, data: str, layer_0_index: int, the_start_layer: str, the_end_layer: str, the_end_is_enabled: str, fan_list: str, t0_fan: str, t1_fan: str, t2_fan: str, t3_fan: str, feature_speed_list: str, feature_name_list: str, feature_fan_combing: bool)->str:
|
||||
multi_fan_data = data
|
||||
layer_number = "0"
|
||||
start_index = 1
|
||||
prev_fan = t0_fan
|
||||
this_fan = t0_fan
|
||||
modified_data = ""
|
||||
current_fan_speed = "0"
|
||||
for my_index in range(1, len(multi_fan_data) - 1, 1):
|
||||
layer = multi_fan_data[my_index]
|
||||
if ";LAYER:" + str(the_start_layer) + "\n" in layer:
|
||||
start_index = int(my_index) - 1
|
||||
break
|
||||
## Track the previous tool changes
|
||||
for num in range(1,start_index,1):
|
||||
layer = multi_fan_data[num]
|
||||
lines = layer.split("\n")
|
||||
for line in lines:
|
||||
if line == "T0":
|
||||
prev_fan = this_fan
|
||||
this_fan = t0_fan
|
||||
elif line == "T1":
|
||||
prev_fan = this_fan
|
||||
this_fan = t1_fan
|
||||
elif line == "T2":
|
||||
prev_fan = this_fan
|
||||
this_fan = t2_fan
|
||||
elif line == "T3":
|
||||
prev_fan = this_fan
|
||||
this_fan = t3_fan
|
||||
## Get the current tool.
|
||||
for l_index in range(start_index,start_index + 1,1):
|
||||
layer = multi_fan_data[l_index]
|
||||
lines = layer.split("\n")
|
||||
for line in lines:
|
||||
if line.startswith("T"):
|
||||
if line == "T0": this_fan = t0_fan
|
||||
if line == "T1": this_fan = t1_fan
|
||||
if line == "T2": this_fan = t2_fan
|
||||
if line == "T3": this_fan = t3_fan
|
||||
prev_fan = this_fan
|
||||
|
||||
## Start to make insertions-------------------------------------
|
||||
for l_index in range(start_index+1,len(multi_fan_data)-1,1):
|
||||
layer = multi_fan_data[l_index]
|
||||
lines = layer.split("\n")
|
||||
for line in lines:
|
||||
if line.startswith("T"):
|
||||
if line == "T0": this_fan = t0_fan
|
||||
if line == "T1": this_fan = t1_fan
|
||||
if line == "T2": this_fan = t2_fan
|
||||
if line == "T3": this_fan = t3_fan
|
||||
## Turn off the prev fan
|
||||
modified_data += "M106 S0" + prev_fan + "\n"
|
||||
modified_data += line + "\n"
|
||||
## Turn on the current fan
|
||||
modified_data += "M106 S" + str(current_fan_speed) + this_fan + "\n"
|
||||
prev_fan = this_fan
|
||||
if ";LAYER:" in line:
|
||||
layer_number = str(line.split(":")[1])
|
||||
modified_data += line + "\n"
|
||||
if int(layer_number) >= int(the_start_layer):
|
||||
temp = line.split(" ")[0]
|
||||
try:
|
||||
name_index = feature_name_list.index(temp)
|
||||
except:
|
||||
name_index = -1
|
||||
if name_index != -1:
|
||||
modified_data += line + "\n" + feature_speed_list[name_index] + this_fan + "\n"
|
||||
#modified_data += feature_speed_list[name_index] + this_fan + "\n"
|
||||
current_fan_speed = str(feature_speed_list[name_index].split("S")[1])
|
||||
elif ";MESH:NONMESH" in line:
|
||||
if feature_fan_combing == True:
|
||||
modified_data += line + "\n"
|
||||
modified_data += "M106 S0" + this_fan + "\n"
|
||||
current_fan_speed = "0"
|
||||
else:
|
||||
modified_data += line + "\n"
|
||||
## If an end layer is defined - Insert the final speed and set the other variables to Final Speed to finish the file
|
||||
## There cannot be a break here because if there are multiple fan numbers they still need to be shut off and turned on.
|
||||
elif line == ";LAYER:" + str(the_end_layer):
|
||||
modified_data += feature_speed_list[len(feature_speed_list) - 1] + this_fan + "\n"
|
||||
for set_speed in range(0, len(feature_speed_list) - 2):
|
||||
feature_speed_list[set_speed] = feature_speed_list[len(feature_speed_list) - 1]
|
||||
else:
|
||||
## Layer and Tool get inserted into modified_data above. All other lines go into modified_data here
|
||||
if not line.startswith("T") and not line.startswith(";LAYER:"): modified_data += line + "\n"
|
||||
if modified_data.endswith("\n"): modified_data = modified_data[0: - 1]
|
||||
multi_fan_data[l_index] = modified_data
|
||||
modified_data = ""
|
||||
return multi_fan_data
|
||||
|
||||
#Try to catch layer input errors, set the minimum speed to 12%, and put the strings together
|
||||
def _layer_checker(self, fan_string: str, ty_pe: str, fan_mode: bool) -> str:
|
||||
fan_string_l = str(fan_string.split("/")[0])
|
||||
try:
|
||||
if int(fan_string_l) <= 1: fan_string_l = "1"
|
||||
if fan_string_l == "": fan_string_l = str(len(data))
|
||||
except ValueError:
|
||||
fan_string_l = str(len(data))
|
||||
fan_string_l = str(int(fan_string_l) - 1)
|
||||
fan_string_p = str(fan_string.split("/")[1])
|
||||
if fan_string_p == "": fan_string_p = "0"
|
||||
try:
|
||||
if int(fan_string_p) < 0: fan_string_p = "0"
|
||||
if int(fan_string_p) > 100: fan_string_p = "100"
|
||||
except ValueError:
|
||||
fan_string_p = "0"
|
||||
## Set the minimum fan speed to 12%
|
||||
if int(fan_string_p) < 12 and int(fan_string_p) != 0:
|
||||
fan_string_p = "12"
|
||||
fan_layer_line = str(fan_string_l)
|
||||
if fan_mode:
|
||||
fan_percent_line = "M106 S" + str(round(int(fan_string_p) * 2.55))
|
||||
else:
|
||||
fan_percent_line = "M106 S" + str(round(int(fan_string_p) / 100, 1))
|
||||
if ty_pe == "l":
|
||||
return str(fan_layer_line)
|
||||
elif ty_pe == "p":
|
||||
return fan_percent_line
|
||||
|
||||
#Try to catch feature input errors, set the minimum speed to 12%, and put the strings together when 'By Feature'
|
||||
def _feature_checker(self, fan_feat_string: int, fan_mode: bool) -> str:
|
||||
if fan_feat_string < 0: fan_feat_string = 0
|
||||
## Set the minimum fan speed to 12%
|
||||
if fan_feat_string > 0 and fan_feat_string < 12: fan_feat_string = 12
|
||||
if fan_feat_string > 100: fan_feat_string = 100
|
||||
if fan_mode:
|
||||
fan_sp_feat = "M106 S" + str(round(fan_feat_string * 2.55))
|
||||
else:
|
||||
fan_sp_feat = "M106 S" + str(round(fan_feat_string / 100, 1))
|
||||
return fan_sp_feat
|
||||
|
||||
# Add additional travel comments to turn the fan off during combing.
|
||||
def _add_travel_comment(self, comment_data: str, lay_0_index: str) -> str:
|
||||
for lay_num in range(int(lay_0_index), len(comment_data)-1,1):
|
||||
layer = comment_data[lay_num]
|
||||
lines = layer.split("\n")
|
||||
## Copy the data to new_data and make the insertions there
|
||||
new_data = lines
|
||||
g0_count = 0
|
||||
g0_index = -1
|
||||
feature_type = ";TYPE:SUPPORT"
|
||||
is_travel = False
|
||||
for index, line in enumerate(lines):
|
||||
insert_index = 0
|
||||
if ";TYPE:" in line:
|
||||
feature_type = line
|
||||
is_travel = False
|
||||
g0_count = 0
|
||||
if ";MESH:NONMESH" in line:
|
||||
is_travel = True
|
||||
g0_count = 0
|
||||
if line.startswith("G0 ") and not is_travel:
|
||||
g0_count += 1
|
||||
if g0_index == -1:
|
||||
g0_index = lines.index(line)
|
||||
elif not line.startswith("G0 ") and not is_travel:
|
||||
## Add additional 'NONMESH' lines to shut the fan off during long combing moves--------
|
||||
if g0_count > 5:
|
||||
if not is_travel:
|
||||
new_data.insert(g0_index + insert_index, ";MESH:NONMESH")
|
||||
insert_index += 1
|
||||
## Add the feature_type at the end of the combing move to turn the fan back on
|
||||
new_data.insert(g0_index + g0_count + 1, feature_type)
|
||||
insert_index += 1
|
||||
g0_count = 0
|
||||
g0_index = -1
|
||||
is_travel = False
|
||||
elif g0_count <= 5:
|
||||
g0_count = 0
|
||||
g0_index = -1
|
||||
is_travel = False
|
||||
comment_data[lay_num] = "\n".join(new_data)
|
||||
return comment_data
|
|
@ -21,7 +21,7 @@
|
|||
# M163 - Set Mix Factor
|
||||
# M164 - Save Mix - saves to T2 as a unique mix
|
||||
|
||||
import re #To perform the search and replace.
|
||||
import re # To perform the search and replace.
|
||||
from ..Script import Script
|
||||
|
||||
class ColorMix(Script):
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
# Description: This plugin is now an option in 'Display Info on LCD'
|
||||
|
||||
from ..Script import Script
|
||||
from UM.Application import Application
|
||||
from UM.Message import Message
|
||||
|
||||
class DisplayFilenameAndLayerOnLCD(Script):
|
||||
|
|
|
@ -30,9 +30,6 @@
|
|||
from ..Script import Script
|
||||
from UM.Application import Application
|
||||
from UM.Qt.Duration import DurationFormat
|
||||
import UM.Util
|
||||
import configparser
|
||||
from UM.Preferences import Preferences
|
||||
import time
|
||||
import datetime
|
||||
import math
|
||||
|
|
|
@ -7,8 +7,6 @@
|
|||
|
||||
from ..Script import Script
|
||||
|
||||
import re
|
||||
import datetime
|
||||
from UM.Message import Message
|
||||
|
||||
class DisplayProgressOnLCD(Script):
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
from typing import List
|
||||
from ..Script import Script
|
||||
|
||||
from UM.Application import Application #To get the current printer's settings.
|
||||
from UM.Application import Application # To get the current printer's settings.
|
||||
|
||||
class FilamentChange(Script):
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
from ..Script import Script
|
||||
import re
|
||||
from UM.Application import Application #To get the current printer's settings.
|
||||
from UM.Application import Application # To get the current printer's settings.
|
||||
from UM.Logger import Logger
|
||||
|
||||
from typing import List, Tuple
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
# Copyright (c) 2017 Ghostkeeper
|
||||
# The PostProcessingPlugin is released under the terms of the LGPLv3 or higher.
|
||||
|
||||
import re #To perform the search and replace.
|
||||
import re # To perform the search and replace.
|
||||
|
||||
from ..Script import Script
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@ from UM.Application import Application
|
|||
from UM.Logger import Logger
|
||||
from UM.Message import Message
|
||||
from UM.FileHandler.WriteFileJob import WriteFileJob
|
||||
from UM.FileHandler.FileWriter import FileWriter #To check against the write modes (text vs. binary).
|
||||
from UM.FileHandler.FileWriter import FileWriter # To check against the write modes (text vs. binary).
|
||||
from UM.Scene.Iterator.BreadthFirstIterator import BreadthFirstIterator
|
||||
from UM.OutputDevice.OutputDevice import OutputDevice
|
||||
from UM.OutputDevice import OutputDeviceError
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
# Copyright (c) 2021 Ultimaker B.V.
|
||||
# Cura is released under the terms of the LGPLv3 or higher.
|
||||
import math
|
||||
|
||||
from UM.Math.Color import Color
|
||||
from UM.Math.Vector import Vector
|
||||
|
@ -35,7 +36,7 @@ class SimulationPass(RenderPass):
|
|||
self._nozzle_shader = None
|
||||
self._disabled_shader = None
|
||||
self._old_current_layer = 0
|
||||
self._old_current_path = 0
|
||||
self._old_current_path: float = 0.0
|
||||
self._switching_layers = True # Tracking whether the user is moving across layers (True) or across paths (False). If false, lower layers render as shadowy.
|
||||
self._gl = OpenGL.getInstance().getBindingsObject()
|
||||
self._scene = Application.getInstance().getController().getScene()
|
||||
|
@ -139,7 +140,7 @@ class SimulationPass(RenderPass):
|
|||
continue
|
||||
|
||||
# Render all layers below a certain number as line mesh instead of vertices.
|
||||
if self._layer_view._current_layer_num > -1 and ((not self._layer_view._only_show_top_layers) or (not self._layer_view.getCompatibilityMode())):
|
||||
if self._layer_view.getCurrentLayer() > -1 and ((not self._layer_view._only_show_top_layers) or (not self._layer_view.getCompatibilityMode())):
|
||||
start = 0
|
||||
end = 0
|
||||
element_counts = layer_data.getElementCounts()
|
||||
|
@ -147,33 +148,42 @@ class SimulationPass(RenderPass):
|
|||
# In the current layer, we show just the indicated paths
|
||||
if layer == self._layer_view._current_layer_num:
|
||||
# We look for the position of the head, searching the point of the current path
|
||||
index = self._layer_view._current_path_num
|
||||
offset = 0
|
||||
index = int(self._layer_view.getCurrentPath())
|
||||
for polygon in layer_data.getLayer(layer).polygons:
|
||||
# The size indicates all values in the two-dimension array, and the second dimension is
|
||||
# always size 3 because we have 3D points.
|
||||
if index >= polygon.data.size // 3 - offset:
|
||||
index -= polygon.data.size // 3 - offset
|
||||
offset = 1 # This is to avoid the first point when there is more than one polygon, since has the same value as the last point in the previous polygon
|
||||
if index >= polygon.data.size // 3 :
|
||||
index -= polygon.data.size // 3
|
||||
continue
|
||||
# The head position is calculated and translated
|
||||
head_position = Vector(polygon.data[index+offset][0], polygon.data[index+offset][1], polygon.data[index+offset][2]) + node.getWorldPosition()
|
||||
ratio = self._layer_view.getCurrentPath() - math.floor(self._layer_view.getCurrentPath())
|
||||
pos_a = Vector(polygon.data[index][0], polygon.data[index][1],
|
||||
polygon.data[index][2])
|
||||
if ratio <= 0.0001 or index + 1 == len(polygon.data):
|
||||
# in case there multiple polygons and polygon changes, the first point has the same value as the last point in the previous polygon
|
||||
head_position = pos_a + node.getWorldPosition()
|
||||
else:
|
||||
pos_b = Vector(polygon.data[index + 1][0],
|
||||
polygon.data[index + 1][1],
|
||||
polygon.data[index + 1][2])
|
||||
vec = pos_a * (1.0 - ratio) + pos_b * ratio
|
||||
head_position = vec + node.getWorldPosition()
|
||||
break
|
||||
break
|
||||
if self._layer_view._minimum_layer_num > layer:
|
||||
if self._layer_view.getMinimumLayer() > layer:
|
||||
start += element_counts[layer]
|
||||
end += element_counts[layer]
|
||||
|
||||
# Calculate the range of paths in the last layer
|
||||
current_layer_start = end
|
||||
current_layer_end = end + self._layer_view._current_path_num * 2 # Because each point is used twice
|
||||
current_layer_end = end + int( self._layer_view.getCurrentPath()) * 2 # Because each point is used twice
|
||||
|
||||
# This uses glDrawRangeElements internally to only draw a certain range of lines.
|
||||
# All the layers but the current selected layer are rendered first
|
||||
if self._old_current_path != self._layer_view._current_path_num:
|
||||
if self._old_current_path != self._layer_view.getCurrentPath():
|
||||
self._current_shader = self._layer_shadow_shader
|
||||
self._switching_layers = False
|
||||
if not self._layer_view.isSimulationRunning() and self._old_current_layer != self._layer_view._current_layer_num:
|
||||
if not self._layer_view.isSimulationRunning() and self._old_current_layer != self._layer_view.getCurrentLayer():
|
||||
self._current_shader = self._layer_shader
|
||||
self._switching_layers = True
|
||||
|
||||
|
@ -193,8 +203,8 @@ class SimulationPass(RenderPass):
|
|||
current_layer_batch.addItem(node.getWorldTransformation(), layer_data)
|
||||
current_layer_batch.render(self._scene.getActiveCamera())
|
||||
|
||||
self._old_current_layer = self._layer_view._current_layer_num
|
||||
self._old_current_path = self._layer_view._current_path_num
|
||||
self._old_current_layer = self._layer_view.getCurrentLayer()
|
||||
self._old_current_path = self._layer_view.getCurrentPath()
|
||||
|
||||
# Create a new batch that is not range-limited
|
||||
batch = RenderBatch(self._layer_shader, type = RenderBatch.RenderType.Solid)
|
||||
|
@ -230,4 +240,4 @@ class SimulationPass(RenderPass):
|
|||
if changed_object.callDecoration("getLayerData"): # Any layer data has changed.
|
||||
self._switching_layers = True
|
||||
self._old_current_layer = 0
|
||||
self._old_current_path = 0
|
||||
self._old_current_path = 0.0
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
# Copyright (c) 2021 Ultimaker B.V.
|
||||
# Cura is released under the terms of the LGPLv3 or higher.
|
||||
|
||||
import sys
|
||||
|
||||
from PyQt6.QtCore import Qt
|
||||
|
@ -58,6 +57,7 @@ class SimulationView(CuraView):
|
|||
LAYER_VIEW_TYPE_LINE_TYPE = 1
|
||||
LAYER_VIEW_TYPE_FEEDRATE = 2
|
||||
LAYER_VIEW_TYPE_THICKNESS = 3
|
||||
SIMULATION_FACTOR = 2
|
||||
|
||||
_no_layers_warning_preference = "view/no_layers_warning"
|
||||
|
||||
|
@ -74,19 +74,20 @@ class SimulationView(CuraView):
|
|||
self._old_max_layers = 0
|
||||
|
||||
self._max_paths = 0
|
||||
self._current_path_num = 0
|
||||
self._current_path_num: float = 0.0
|
||||
self._current_time = 0.0
|
||||
self._minimum_path_num = 0
|
||||
self.currentLayerNumChanged.connect(self._onCurrentLayerNumChanged)
|
||||
|
||||
self._busy = False
|
||||
self._simulation_running = False
|
||||
|
||||
self._ghost_shader = None # type: Optional["ShaderProgram"]
|
||||
self._layer_pass = None # type: Optional[SimulationPass]
|
||||
self._composite_pass = None # type: Optional[CompositePass]
|
||||
self._old_layer_bindings = None # type: Optional[List[str]]
|
||||
self._simulationview_composite_shader = None # type: Optional["ShaderProgram"]
|
||||
self._old_composite_shader = None # type: Optional["ShaderProgram"]
|
||||
self._ghost_shader: Optional["ShaderProgram"] = None
|
||||
self._layer_pass: Optional[SimulationPass] = None
|
||||
self._composite_pass: Optional[CompositePass] = None
|
||||
self._old_layer_bindings: Optional[List[str]] = None
|
||||
self._simulationview_composite_shader: Optional["ShaderProgram"] = None
|
||||
self._old_composite_shader: Optional["ShaderProgram"] = None
|
||||
|
||||
self._max_feedrate = sys.float_info.min
|
||||
self._min_feedrate = sys.float_info.max
|
||||
|
@ -96,14 +97,16 @@ class SimulationView(CuraView):
|
|||
self._min_line_width = sys.float_info.max
|
||||
self._min_flow_rate = sys.float_info.max
|
||||
self._max_flow_rate = sys.float_info.min
|
||||
self._cumulative_line_duration_layer: Optional[int] = None
|
||||
self._cumulative_line_duration: List[float] = []
|
||||
|
||||
self._global_container_stack = None # type: Optional[ContainerStack]
|
||||
self._global_container_stack: Optional[ContainerStack] = None
|
||||
self._proxy = None
|
||||
|
||||
self._resetSettings()
|
||||
self._legend_items = None
|
||||
self._show_travel_moves = False
|
||||
self._nozzle_node = None # type: Optional[NozzleNode]
|
||||
self._nozzle_node: Optional[NozzleNode] = None
|
||||
|
||||
Application.getInstance().getPreferences().addPreference("view/top_layer_count", 5)
|
||||
Application.getInstance().getPreferences().addPreference("view/only_show_top_layers", False)
|
||||
|
@ -125,13 +128,12 @@ class SimulationView(CuraView):
|
|||
self._only_show_top_layers = bool(Application.getInstance().getPreferences().getValue("view/only_show_top_layers"))
|
||||
self._compatibility_mode = self._evaluateCompatibilityMode()
|
||||
|
||||
self._slice_first_warning_message = Message(catalog.i18nc("@info:status",
|
||||
"Nothing is shown because you need to slice first."),
|
||||
title = catalog.i18nc("@info:title", "No layers to show"),
|
||||
option_text = catalog.i18nc("@info:option_text",
|
||||
"Do not show this message again"),
|
||||
option_state = False,
|
||||
message_type = Message.MessageType.WARNING)
|
||||
self._slice_first_warning_message = Message(catalog.i18nc("@info:status", "Nothing is shown because you need to slice first."),
|
||||
title=catalog.i18nc("@info:title", "No layers to show"),
|
||||
option_text=catalog.i18nc("@info:option_text",
|
||||
"Do not show this message again"),
|
||||
option_state=False,
|
||||
message_type=Message.MessageType.WARNING)
|
||||
self._slice_first_warning_message.optionToggled.connect(self._onDontAskMeAgain)
|
||||
CuraApplication.getInstance().getPreferences().addPreference(self._no_layers_warning_preference, True)
|
||||
|
||||
|
@ -187,9 +189,90 @@ class SimulationView(CuraView):
|
|||
def getMaxLayers(self) -> int:
|
||||
return self._max_layers
|
||||
|
||||
def getCurrentPath(self) -> int:
|
||||
def getCurrentPath(self) -> float:
|
||||
return self._current_path_num
|
||||
|
||||
def setTime(self, time: float) -> None:
|
||||
cumulative_line_duration = self.cumulativeLineDuration()
|
||||
if len(cumulative_line_duration) > 0:
|
||||
self._current_time = time
|
||||
left_i = 0
|
||||
right_i = len(cumulative_line_duration) - 1
|
||||
total_duration = cumulative_line_duration[-1]
|
||||
# make an educated guess about where to start
|
||||
i = int(right_i * max(0.0, min(1.0, self._current_time / total_duration)))
|
||||
# binary search for the correct path
|
||||
while left_i < right_i:
|
||||
if cumulative_line_duration[i] <= self._current_time:
|
||||
left_i = i + 1
|
||||
else:
|
||||
right_i = i
|
||||
i = int((left_i + right_i) / 2)
|
||||
|
||||
left_value = cumulative_line_duration[i - 1] if i > 0 else 0.0
|
||||
right_value = cumulative_line_duration[i]
|
||||
|
||||
if not (left_value <= self._current_time <= right_value):
|
||||
Logger.warn(
|
||||
f"Binary search error (out of bounds): index {i}: left value {left_value} right value {right_value} and current time is {self._current_time}")
|
||||
|
||||
fractional_value = (self._current_time - left_value) / (right_value - left_value)
|
||||
|
||||
self.setPath(i + fractional_value)
|
||||
|
||||
def advanceTime(self, time_increase: float) -> bool:
|
||||
"""
|
||||
Advance the time by the given amount.
|
||||
|
||||
:param time_increase: The amount of time to advance (in seconds).
|
||||
:return: True if the time was advanced, False if the end of the simulation was reached.
|
||||
"""
|
||||
total_duration = 0.0
|
||||
if len(self.cumulativeLineDuration()) > 0:
|
||||
total_duration = self.cumulativeLineDuration()[-1]
|
||||
|
||||
if self._current_time + time_increase > total_duration:
|
||||
# If we have reached the end of the simulation, go to the next layer.
|
||||
if self.getCurrentLayer() == self.getMaxLayers():
|
||||
# If we are already at the last layer, go to the first layer.
|
||||
self.setTime(total_duration)
|
||||
return False
|
||||
|
||||
# advance to the next layer, and reset the time
|
||||
self.setLayer(self.getCurrentLayer() + 1)
|
||||
self.setTime(0.0)
|
||||
else:
|
||||
self.setTime(self._current_time + time_increase)
|
||||
return True
|
||||
|
||||
def cumulativeLineDuration(self) -> List[float]:
|
||||
# Make sure _cumulative_line_duration is initialized properly
|
||||
if self.getCurrentLayer() != self._cumulative_line_duration_layer:
|
||||
#clear cache
|
||||
self._cumulative_line_duration = []
|
||||
total_duration = 0.0
|
||||
polylines = self.getLayerData()
|
||||
if polylines is not None:
|
||||
for polyline in polylines.polygons:
|
||||
for line_duration in list((polyline.lineLengths / polyline.lineFeedrates)[0]):
|
||||
total_duration += line_duration / SimulationView.SIMULATION_FACTOR
|
||||
self._cumulative_line_duration.append(total_duration)
|
||||
# for tool change we add an extra tool path
|
||||
self._cumulative_line_duration.append(total_duration)
|
||||
# set current cached layer
|
||||
self._cumulative_line_duration_layer = self.getCurrentLayer()
|
||||
|
||||
return self._cumulative_line_duration
|
||||
|
||||
def getLayerData(self) -> Optional["LayerData"]:
|
||||
scene = self.getController().getScene()
|
||||
for node in DepthFirstIterator(scene.getRoot()): # type: ignore
|
||||
layer_data = node.callDecoration("getLayerData")
|
||||
if not layer_data:
|
||||
continue
|
||||
return layer_data.getLayer(self.getCurrentLayer())
|
||||
return None
|
||||
|
||||
def getMinimumPath(self) -> int:
|
||||
return self._minimum_path_num
|
||||
|
||||
|
@ -277,7 +360,7 @@ class SimulationView(CuraView):
|
|||
self._startUpdateTopLayers()
|
||||
self.currentLayerNumChanged.emit()
|
||||
|
||||
def setPath(self, value: int) -> None:
|
||||
def setPath(self, value: float) -> None:
|
||||
"""
|
||||
Set the upper end of the range of visible paths on the current layer.
|
||||
|
||||
|
@ -287,6 +370,12 @@ class SimulationView(CuraView):
|
|||
if self._current_path_num != value:
|
||||
self._current_path_num = min(max(value, 0), self._max_paths)
|
||||
self._minimum_path_num = min(self._minimum_path_num, self._current_path_num)
|
||||
# update _current time when the path is changed by user
|
||||
if self._current_path_num < self._max_paths and round(self._current_path_num)== self._current_path_num:
|
||||
actual_path_num = int(self._current_path_num)
|
||||
cumulative_line_duration = self.cumulativeLineDuration()
|
||||
if actual_path_num < len(cumulative_line_duration):
|
||||
self._current_time = cumulative_line_duration[actual_path_num]
|
||||
|
||||
self._startUpdateTopLayers()
|
||||
self.currentPathNumChanged.emit()
|
||||
|
@ -492,6 +581,7 @@ class SimulationView(CuraView):
|
|||
self._max_thickness = sys.float_info.min
|
||||
self._min_flow_rate = sys.float_info.max
|
||||
self._max_flow_rate = sys.float_info.min
|
||||
self._cumulative_line_duration = {}
|
||||
|
||||
# The colour scheme is only influenced by the visible lines, so filter the lines by if they should be visible.
|
||||
visible_line_types = []
|
||||
|
|
|
@ -127,6 +127,7 @@ Item
|
|||
function resumeSimulation()
|
||||
{
|
||||
UM.SimulationView.setSimulationRunning(true)
|
||||
UM.SimulationView.setCurrentPath(UM.SimulationView.currentPath)
|
||||
simulationTimer.start()
|
||||
layerSlider.manuallyChanged = false
|
||||
pathSlider.manuallyChanged = false
|
||||
|
@ -136,54 +137,19 @@ Item
|
|||
Timer
|
||||
{
|
||||
id: simulationTimer
|
||||
interval: 100
|
||||
interval: 1000 / 15
|
||||
running: false
|
||||
repeat: true
|
||||
onTriggered:
|
||||
{
|
||||
var currentPath = UM.SimulationView.currentPath
|
||||
var numPaths = UM.SimulationView.numPaths
|
||||
var currentLayer = UM.SimulationView.currentLayer
|
||||
var numLayers = UM.SimulationView.numLayers
|
||||
|
||||
// When the user plays the simulation, if the path slider is at the end of this layer, we start
|
||||
// the simulation at the beginning of the current layer.
|
||||
if (!isSimulationPlaying)
|
||||
{
|
||||
if (currentPath >= numPaths)
|
||||
{
|
||||
UM.SimulationView.setCurrentPath(0)
|
||||
}
|
||||
else
|
||||
{
|
||||
UM.SimulationView.setCurrentPath(currentPath + 1)
|
||||
}
|
||||
}
|
||||
// If the simulation is already playing and we reach the end of a layer, then it automatically
|
||||
// starts at the beginning of the next layer.
|
||||
else
|
||||
{
|
||||
if (currentPath >= numPaths)
|
||||
{
|
||||
// At the end of the model, the simulation stops
|
||||
if (currentLayer >= numLayers)
|
||||
{
|
||||
playButton.pauseSimulation()
|
||||
}
|
||||
else
|
||||
{
|
||||
UM.SimulationView.setCurrentLayer(currentLayer + 1)
|
||||
UM.SimulationView.setCurrentPath(0)
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
UM.SimulationView.setCurrentPath(currentPath + 1)
|
||||
}
|
||||
// divide by 1000 to account for ms to s conversion
|
||||
const advance_time = simulationTimer.interval / 1000.0;
|
||||
if (!UM.SimulationView.advanceTime(advance_time)) {
|
||||
playButton.pauseSimulation();
|
||||
}
|
||||
// The status must be set here instead of in the resumeSimulation function otherwise it won't work
|
||||
// correctly, because part of the logic is in this trigger function.
|
||||
isSimulationPlaying = true
|
||||
isSimulationPlaying = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -50,10 +50,14 @@ class SimulationViewProxy(QObject):
|
|||
def numPaths(self):
|
||||
return self._simulation_view.getMaxPaths()
|
||||
|
||||
@pyqtProperty(int, notify=currentPathChanged)
|
||||
@pyqtProperty(float, notify=currentPathChanged)
|
||||
def currentPath(self):
|
||||
return self._simulation_view.getCurrentPath()
|
||||
|
||||
@pyqtSlot(float, result=bool)
|
||||
def advanceTime(self, duration: float) -> bool:
|
||||
return self._simulation_view.advanceTime(duration)
|
||||
|
||||
@pyqtProperty(int, notify=currentPathChanged)
|
||||
def minimumPath(self):
|
||||
return self._simulation_view.getMinimumPath()
|
||||
|
@ -78,8 +82,8 @@ class SimulationViewProxy(QObject):
|
|||
def setMinimumLayer(self, layer_num):
|
||||
self._simulation_view.setMinimumLayer(layer_num)
|
||||
|
||||
@pyqtSlot(int)
|
||||
def setCurrentPath(self, path_num):
|
||||
@pyqtSlot(float)
|
||||
def setCurrentPath(self, path_num: float):
|
||||
self._simulation_view.setPath(path_num)
|
||||
|
||||
@pyqtSlot(int)
|
||||
|
@ -215,4 +219,3 @@ class SimulationViewProxy(QObject):
|
|||
self._simulation_view.activityChanged.disconnect(self._onActivityChanged)
|
||||
self._simulation_view.globalStackChanged.disconnect(self._onGlobalStackChanged)
|
||||
self._simulation_view.preferencesChanged.disconnect(self._onPreferencesChanged)
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@ import json
|
|||
import os
|
||||
import platform
|
||||
import time
|
||||
from typing import cast, Optional, Set, TYPE_CHECKING
|
||||
from typing import Optional, Set, TYPE_CHECKING
|
||||
|
||||
from PyQt6.QtCore import pyqtSlot, QObject
|
||||
from PyQt6.QtNetwork import QNetworkRequest
|
||||
|
|
|
@ -16,8 +16,6 @@ from UM.Application import Application
|
|||
from UM.Logger import Logger
|
||||
from UM.Message import Message
|
||||
from UM.Math.Color import Color
|
||||
from UM.PluginRegistry import PluginRegistry
|
||||
from UM.Platform import Platform
|
||||
from UM.Event import Event
|
||||
|
||||
from UM.View.RenderBatch import RenderBatch
|
||||
|
|
|
@ -22,7 +22,6 @@ from UM.Scene.Iterator.DepthFirstIterator import DepthFirstIterator
|
|||
from UM.Scene.SceneNode import SceneNode
|
||||
from UM.Settings.InstanceContainer import InstanceContainer
|
||||
from cura.CuraApplication import CuraApplication
|
||||
from cura.Settings.CuraStackBuilder import CuraStackBuilder
|
||||
from cura.Settings.GlobalStack import GlobalStack
|
||||
from cura.Utils.Threading import call_on_qt_thread
|
||||
|
||||
|
|
|
@ -9,8 +9,8 @@ try:
|
|||
except ImportError:
|
||||
Logger.log("w", "Could not import UFPWriter; libCharon may be missing")
|
||||
|
||||
from UM.i18n import i18nCatalog #To translate the file format description.
|
||||
from UM.Mesh.MeshWriter import MeshWriter #For the binary mode flag.
|
||||
from UM.i18n import i18nCatalog # To translate the file format description.
|
||||
from UM.Mesh.MeshWriter import MeshWriter # For the binary mode flag.
|
||||
|
||||
i18n_catalog = i18nCatalog("cura")
|
||||
|
||||
|
|
|
@ -331,7 +331,7 @@ class CloudOutputDevice(UltimakerNetworkedPrinterOutputDevice):
|
|||
return False
|
||||
|
||||
[printer, *_] = self._printers
|
||||
return printer.pinterType in ("ultimaker_methodx", "ultimaker_methodxl")
|
||||
return printer.type in ("MakerBot Method X", "MakerBot Method XL")
|
||||
|
||||
@pyqtProperty(bool, notify=_cloudClusterPrintersChanged)
|
||||
def supportsPrintJobActions(self) -> bool:
|
||||
|
|
|
@ -4,9 +4,6 @@
|
|||
from UM.Job import Job
|
||||
from UM.Logger import Logger
|
||||
|
||||
from .avr_isp import ispBase
|
||||
from .avr_isp.stk500v2 import Stk500v2
|
||||
|
||||
from time import time, sleep
|
||||
from serial import Serial, SerialException
|
||||
|
||||
|
|
|
@ -5,9 +5,9 @@ import os
|
|||
|
||||
from UM.i18n import i18nCatalog
|
||||
from UM.Logger import Logger
|
||||
from UM.Mesh.MeshWriter import MeshWriter #To get the g-code output.
|
||||
from UM.Message import Message #Show an error when already printing.
|
||||
from UM.PluginRegistry import PluginRegistry #To get the g-code output.
|
||||
from UM.Mesh.MeshWriter import MeshWriter # To get the g-code output.
|
||||
from UM.Message import Message # Show an error when already printing.
|
||||
from UM.PluginRegistry import PluginRegistry # To get the g-code output.
|
||||
from UM.Qt.Duration import DurationFormat
|
||||
|
||||
from cura.CuraApplication import CuraApplication
|
||||
|
@ -19,7 +19,7 @@ from cura.PrinterOutput.GenericOutputController import GenericOutputController
|
|||
from .AutoDetectBaudJob import AutoDetectBaudJob
|
||||
from .AvrFirmwareUpdater import AvrFirmwareUpdater
|
||||
|
||||
from io import StringIO #To write the g-code output.
|
||||
from io import StringIO # To write the g-code output.
|
||||
from queue import Queue
|
||||
from serial import Serial, SerialException, SerialTimeoutException
|
||||
from threading import Thread, Event
|
||||
|
|
|
@ -1,16 +1,16 @@
|
|||
# Copyright (c) 2018 Ultimaker B.V.
|
||||
# Cura is released under the terms of the LGPLv3 or higher.
|
||||
|
||||
import configparser #To read config files.
|
||||
import io #To write config files to strings as if they were files.
|
||||
import os.path #To get the path to write new user profiles to.
|
||||
import configparser # To read config files.
|
||||
import io # To write config files to strings as if they were files.
|
||||
import os.path # To get the path to write new user profiles to.
|
||||
from typing import Dict, List, Optional, Set, Tuple
|
||||
import urllib #To serialise the user container file name properly.
|
||||
import urllib # To serialise the user container file name properly.
|
||||
import urllib.parse
|
||||
|
||||
import UM.VersionUpgrade #To indicate that a file is of incorrect format.
|
||||
import UM.VersionUpgradeManager #To schedule more files to be upgraded.
|
||||
from UM.Resources import Resources #To get the config storage path.
|
||||
import UM.VersionUpgrade # To indicate that a file is of incorrect format.
|
||||
import UM.VersionUpgradeManager # To schedule more files to be upgraded.
|
||||
from UM.Resources import Resources # To get the config storage path.
|
||||
|
||||
## Creates a new machine instance instance by parsing a serialised machine
|
||||
# instance in version 1 of the file format.
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
# Copyright (c) 2018 Ultimaker B.V.
|
||||
# Cura is released under the terms of the LGPLv3 or higher.
|
||||
|
||||
import configparser #To read config files.
|
||||
import io #To output config files to string.
|
||||
import configparser # To read config files.
|
||||
import io # To output config files to string.
|
||||
from typing import List, Optional, Tuple
|
||||
|
||||
import UM.VersionUpgrade #To indicate that a file is of the wrong format.
|
||||
import UM.VersionUpgrade # To indicate that a file is of the wrong format.
|
||||
|
||||
## Creates a new preferences instance by parsing a serialised preferences file
|
||||
# in version 1 of the file format.
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
# Copyright (c) 2018 Ultimaker B.V.
|
||||
# Cura is released under the terms of the LGPLv3 or higher.
|
||||
|
||||
import configparser #To read config files.
|
||||
import io #To write config files to strings as if they were files.
|
||||
import configparser # To read config files.
|
||||
import io # To write config files to strings as if they were files.
|
||||
from typing import Dict, List, Optional, Tuple
|
||||
|
||||
import UM.VersionUpgrade
|
||||
|
|
|
@ -0,0 +1,95 @@
|
|||
# Copyright (c) 2024 UltiMaker
|
||||
# Cura is released under the terms of the LGPLv3 or higher.
|
||||
|
||||
import configparser
|
||||
from typing import Tuple, List
|
||||
import io
|
||||
from UM.VersionUpgrade import VersionUpgrade
|
||||
|
||||
_REMOVED_SETTINGS = {
|
||||
"support_interface_skip_height",
|
||||
}
|
||||
_NEW_SETTING_VERSION = "23"
|
||||
|
||||
|
||||
class VersionUpgrade56to57(VersionUpgrade):
|
||||
def upgradePreferences(self, serialized: str, filename: str) -> Tuple[List[str], List[str]]:
|
||||
"""
|
||||
Upgrades preferences to remove from the visibility list the settings that were removed in this version.
|
||||
It also changes the preferences to have the new version number.
|
||||
|
||||
This removes any settings that were removed in the new Cura version.
|
||||
:param serialized: The original contents of the preferences file.
|
||||
:param filename: The file name of the preferences file.
|
||||
:return: A list of new file names, and a list of the new contents for
|
||||
those files.
|
||||
"""
|
||||
parser = configparser.ConfigParser(interpolation = None)
|
||||
parser.read_string(serialized)
|
||||
|
||||
# Update version number.
|
||||
parser["metadata"]["setting_version"] = _NEW_SETTING_VERSION
|
||||
|
||||
# Remove deleted settings from the visible settings list.
|
||||
if "general" in parser and "visible_settings" in parser["general"]:
|
||||
visible_settings = set(parser["general"]["visible_settings"].split(";"))
|
||||
for removed in _REMOVED_SETTINGS:
|
||||
if removed in visible_settings:
|
||||
visible_settings.remove(removed)
|
||||
|
||||
parser["general"]["visible_settings"] = ";".join(visible_settings)
|
||||
|
||||
result = io.StringIO()
|
||||
parser.write(result)
|
||||
return [filename], [result.getvalue()]
|
||||
|
||||
def upgradeInstanceContainer(self, serialized: str, filename: str) -> Tuple[List[str], List[str]]:
|
||||
"""
|
||||
Upgrades instance containers to remove the settings that were removed in this version.
|
||||
It also changes the instance containers to have the new version number.
|
||||
|
||||
This removes any settings that were removed in the new Cura version and updates settings that need to be updated
|
||||
with a new value.
|
||||
|
||||
:param serialized: The original contents of the instance container.
|
||||
:param filename: The original file name of the instance container.
|
||||
:return: A list of new file names, and a list of the new contents for
|
||||
those files.
|
||||
"""
|
||||
parser = configparser.ConfigParser(interpolation = None, comment_prefixes = ())
|
||||
parser.read_string(serialized)
|
||||
|
||||
# Update version number.
|
||||
parser["metadata"]["setting_version"] = _NEW_SETTING_VERSION
|
||||
|
||||
if "values" in parser:
|
||||
# Remove deleted settings from the instance containers.
|
||||
for removed in _REMOVED_SETTINGS:
|
||||
if removed in parser["values"]:
|
||||
del parser["values"][removed]
|
||||
|
||||
result = io.StringIO()
|
||||
parser.write(result)
|
||||
return [filename], [result.getvalue()]
|
||||
|
||||
def upgradeStack(self, serialized: str, filename: str) -> Tuple[List[str], List[str]]:
|
||||
"""
|
||||
Upgrades stacks to have the new version number.
|
||||
|
||||
:param serialized: The original contents of the stack.
|
||||
:param filename: The original file name of the stack.
|
||||
:return: A list of new file names, and a list of the new contents for
|
||||
those files.
|
||||
"""
|
||||
parser = configparser.ConfigParser(interpolation = None)
|
||||
parser.read_string(serialized)
|
||||
|
||||
# Update version number.
|
||||
if "metadata" not in parser:
|
||||
parser["metadata"] = {}
|
||||
|
||||
parser["metadata"]["setting_version"] = _NEW_SETTING_VERSION
|
||||
|
||||
result = io.StringIO()
|
||||
parser.write(result)
|
||||
return [filename], [result.getvalue()]
|
61
plugins/VersionUpgrade/VersionUpgrade56to57/__init__.py
Normal file
61
plugins/VersionUpgrade/VersionUpgrade56to57/__init__.py
Normal file
|
@ -0,0 +1,61 @@
|
|||
# Copyright (c) 2024 UltiMaker
|
||||
# Cura is released under the terms of the LGPLv3 or higher.
|
||||
|
||||
from typing import Any, Dict, TYPE_CHECKING
|
||||
|
||||
from . import VersionUpgrade56to57
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from UM.Application import Application
|
||||
|
||||
upgrade = VersionUpgrade56to57.VersionUpgrade56to57()
|
||||
|
||||
|
||||
def getMetaData() -> Dict[str, Any]:
|
||||
return {
|
||||
"version_upgrade": {
|
||||
# From To Upgrade function
|
||||
("preferences", 7000022): ("preferences", 7000023, upgrade.upgradePreferences),
|
||||
("machine_stack", 6000022): ("machine_stack", 6000023, upgrade.upgradeStack),
|
||||
("extruder_train", 6000022): ("extruder_train", 6000023, upgrade.upgradeStack),
|
||||
("definition_changes", 4000022): ("definition_changes", 4000023, upgrade.upgradeInstanceContainer),
|
||||
("quality_changes", 4000022): ("quality_changes", 4000023, upgrade.upgradeInstanceContainer),
|
||||
("quality", 4000022): ("quality", 4000023, upgrade.upgradeInstanceContainer),
|
||||
("user", 4000022): ("user", 4000023, upgrade.upgradeInstanceContainer),
|
||||
("intent", 4000022): ("intent", 4000023, upgrade.upgradeInstanceContainer),
|
||||
},
|
||||
"sources": {
|
||||
"preferences": {
|
||||
"get_version": upgrade.getCfgVersion,
|
||||
"location": {"."}
|
||||
},
|
||||
"machine_stack": {
|
||||
"get_version": upgrade.getCfgVersion,
|
||||
"location": {"./machine_instances"}
|
||||
},
|
||||
"extruder_train": {
|
||||
"get_version": upgrade.getCfgVersion,
|
||||
"location": {"./extruders"}
|
||||
},
|
||||
"definition_changes": {
|
||||
"get_version": upgrade.getCfgVersion,
|
||||
"location": {"./definition_changes"}
|
||||
},
|
||||
"quality_changes": {
|
||||
"get_version": upgrade.getCfgVersion,
|
||||
"location": {"./quality_changes"}
|
||||
},
|
||||
"quality": {
|
||||
"get_version": upgrade.getCfgVersion,
|
||||
"location": {"./quality"}
|
||||
},
|
||||
"user": {
|
||||
"get_version": upgrade.getCfgVersion,
|
||||
"location": {"./user"}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
def register(app: "Application") -> Dict[str, Any]:
|
||||
return {"version_upgrade": upgrade}
|
8
plugins/VersionUpgrade/VersionUpgrade56to57/plugin.json
Normal file
8
plugins/VersionUpgrade/VersionUpgrade56to57/plugin.json
Normal file
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"name": "Version Upgrade 5.6 to 5.7",
|
||||
"author": "UltiMaker",
|
||||
"version": "1.0.0",
|
||||
"description": "Upgrades configurations from Cura 5.6 to Cura 5.7.",
|
||||
"api": 8,
|
||||
"i18n-catalog": "cura"
|
||||
}
|
|
@ -7,7 +7,6 @@ from PyQt6.QtGui import QOpenGLContext, QImage
|
|||
from UM.Application import Application
|
||||
from UM.Logger import Logger
|
||||
from UM.Math.Color import Color
|
||||
from UM.PluginRegistry import PluginRegistry
|
||||
from UM.Resources import Resources
|
||||
from UM.Platform import Platform
|
||||
from UM.Event import Event
|
||||
|
|
|
@ -3,9 +3,9 @@
|
|||
|
||||
import copy
|
||||
import io
|
||||
import json #To parse the product-to-id mapping file.
|
||||
import os.path #To find the product-to-id mapping.
|
||||
from typing import Any, Dict, List, Optional, Tuple, cast, Set, Union
|
||||
import json # To parse the product-to-id mapping file.
|
||||
import os.path # To find the product-to-id mapping.
|
||||
from typing import Any, Dict, List, Optional, Tuple, cast, Set
|
||||
import xml.etree.ElementTree as ET
|
||||
|
||||
from UM.PluginRegistry import PluginRegistry
|
||||
|
|
|
@ -1,41 +1,47 @@
|
|||
### Direct requirements for Uranium and libCharon ###
|
||||
PyQt6-sip==13.4.1 \
|
||||
--hash=sha256:0df998f2b6ceeacfd10de773441572e215be0c9cae566cc7dd36e231bf714a12 \
|
||||
--hash=sha256:224575e84805c4317bacd5d1b8e93e0ad5c48685dadbbe1e902d4ebe16f22828 \
|
||||
--hash=sha256:36ae29cdc223cacc1257d0f5075cf81474550c6d26b728f922487a2aa935f130 \
|
||||
--hash=sha256:3a674c591d4274d4ea8127205290e927a7dab0eb87a0038d4f4ea1d430782649 \
|
||||
--hash=sha256:3ef9392e4ae29d393b79237d85840cdc6b8831f36eed5d56c7d9b329b380cc8d \
|
||||
--hash=sha256:43935873d60f57719632840d517afee04ef8f30e92cfe0dadc7e6326691920fc \
|
||||
--hash=sha256:5731f22618435654352ef07684549a17be82b75254227fc80b4b5b0b59fc6656 \
|
||||
--hash=sha256:5bc4beb6fb1de4c9ba8beee7b1a4a813fa888c3b095206dafcd25d7e6e4ed2a7 \
|
||||
--hash=sha256:5c36ab984402e96792eebf4b031abfaa589aa20af3190a79c54502c16964d97e \
|
||||
--hash=sha256:a2a0461992c6657f343308b150c4d6b57e9e7a0e5c2f79538434e7fb869ea827 \
|
||||
--hash=sha256:a81490ee84d7a41a126b116081bd97d758f41bf706aee0a8cec24d6e4c660184 \
|
||||
--hash=sha256:e00e287ea05bbc293fc6e2198301962af9b7b622bd2daf4288f925a88ae35dc9 \
|
||||
--hash=sha256:e670a7b2fb7e32204ce67d274017bfff3e21139d217d60cebbfcb75b019c91ee \
|
||||
--hash=sha256:ee06f255787a0b4957f357f93b78d2a11ca3761916833e3afa83f1381d4d1a46 \
|
||||
--hash=sha256:fbee0d554e0e98f56dbf6d94b00a28cc32425938ad7ae98fd91f8822c5b24d45 \
|
||||
--hash=sha256:fcc6d78314783f4a193f02353f431b7ea4d357f47c3c7a7d0740e723f69c64dc
|
||||
PyQt6==6.4.2 \
|
||||
--hash=sha256:18d1daf98d9236d55102cdadafd1056f5802f3c9288fcf7238569937b71a89f0 \
|
||||
--hash=sha256:25bd399b4a95dce65d5f937c1aa85d3c7e14a21745ae2a4ca14c0116cd104290 \
|
||||
--hash=sha256:740244f608fe15ee1d89695c43f31a14caeca41c4f02ac36c86dfba4a5d5813d \
|
||||
--hash=sha256:c128bc0f17833e324593e3db83e99470d451a197dd17ff0333927b946c935bd9
|
||||
PyQt6-Qt6==6.4.2 \
|
||||
--hash=sha256:9f07c3c100cb46cca4074965e7494d4df4f0fc016497d5303c1fe135822876e1 \
|
||||
--hash=sha256:a29b8c858babd523e80c8db5f8fd19792641588ec04eab49af18b7a4423eb99f \
|
||||
--hash=sha256:c0e91d0275d428496cacff717a9b719c52bfa52b21f124d638b79cc2217bc81e \
|
||||
--hash=sha256:d19c4e72615762cd6f0b043f23fa5f0b02656091427ce6de1efccd58e10e6a53
|
||||
PyQt6-NetworkAuth==6.4.0 \
|
||||
--hash=sha256:ab6178b3b2902ae9939a148555cfcee8c7803d6b0d5924cd1bd8f3407b8b9210 \
|
||||
--hash=sha256:c16ec80232d88024b60d04386a23cc93067e5644a65f47f26ffb13d84dcd4a6d \
|
||||
--hash=sha256:c302cd0d838c7229eda5e26e0b1b3d3ec4f8720f8d9379472bce5a89ff0735c2 \
|
||||
--hash=sha256:d948fc0cf43b64afbda2acb5bf2392f785a1e7a2950d79ea850c1a3f4ae12f1a
|
||||
PyQt6-NetworkAuth-Qt6==6.4.2 \
|
||||
--hash=sha256:179094bcb4d4d056316c22d3d067cd94d4591da23f804461bfb025ccfa29b2b4 \
|
||||
--hash=sha256:1de6abbb5fa6585b97ae49d3f64b0dfad40bd56b1a31744d9775ff26247241c8 \
|
||||
--hash=sha256:79ec4b0fc9450bbedbff03541b93b10d1c7e761cd2cc16ce70d2b09dcdf8c720 \
|
||||
--hash=sha256:d96d557fe61edb9b68d189f270f0393d6579c8d308e6b0d41bc0699371d7cb4e
|
||||
PyQt6-sip==13.6.0 \
|
||||
--hash=sha256:0dfd22cfedd87e96f9d51e0778ca2ba3dc0be83e424e9e0f98f6994d8d9c90f0 \
|
||||
--hash=sha256:13885361ca2cb2f5085d50359ba61b3fabd41b139fb58f37332acbe631ef2357 \
|
||||
--hash=sha256:24441032a29791e82beb7dfd76878339058def0e97fdb7c1cea517f3a0e6e96b \
|
||||
--hash=sha256:2486e1588071943d4f6657ba09096dc9fffd2322ad2c30041e78ea3f037b5778 \
|
||||
--hash=sha256:3075d8b325382750829e6cde6971c943352309d35768a4d4da0587459606d562 \
|
||||
--hash=sha256:33ea771fe777eb0d1a2c3ef35bcc3f7a286eb3ff09cd5b2fdd3d87d1f392d7e8 \
|
||||
--hash=sha256:39854dba35f8e5a4288da26ecb5f40b4c5ec1932efffb3f49d5ea435a7f37fb3 \
|
||||
--hash=sha256:3bf03e130fbfd75c9c06e687b86ba375410c7a9e835e4e03285889e61dd4b0c4 \
|
||||
--hash=sha256:43fb8551796030aae3d66d6e35e277494071ec6172cd182c9569ab7db268a2f5 \
|
||||
--hash=sha256:58f68a48400e0b3d1ccb18090090299bad26e3aed7ccb7057c65887b79b8aeea \
|
||||
--hash=sha256:5b9c6b6f9cfccb48cbb78a59603145a698fb4ffd176764d7083e5bf47631d8df \
|
||||
--hash=sha256:747f6ca44af81777a2c696bd501bc4815a53ec6fc94d4e25830e10bc1391f8ab \
|
||||
--hash=sha256:86a7b67c64436e32bffa9c28c9f21bf14a9faa54991520b12c3f6f435f24df7f \
|
||||
--hash=sha256:8c282062125eea5baf830c6998587d98c50be7c3a817a057fb95fef647184012 \
|
||||
--hash=sha256:8f9df9f7ccd8a9f0f1d36948c686f03ce1a1281543a3e636b7b7d5e086e1a436 \
|
||||
--hash=sha256:98bf954103b087162fa63b3a78f30b0b63da22fd6450b610ec1b851dbb798228 \
|
||||
--hash=sha256:9adf672f9114687533a74d5c2d4c03a9a929ad5ad9c3e88098a7da1a440ab916 \
|
||||
--hash=sha256:a6ce80bc24618d8a41be8ca51ad9f10e8bc4296dd90ab2809573df30a23ae0e5 \
|
||||
--hash=sha256:d6b5f699aaed0ac1fcd23e8fbca70d8a77965831b7c1ce474b81b1678817a49d \
|
||||
--hash=sha256:fa759b6339ff7e25f9afe2a6b651b775f0a36bcb3f5fa85e81a90d3b033c83f4 \
|
||||
--hash=sha256:fa7b10af7488efc5e53b41dd42c0f421bde6c2865a107af7ae259aff9d841da9
|
||||
PyQt6==6.6.0 \
|
||||
--hash=sha256:33655db05ac2de699320f035250c21434c77144a6a2943aca3f4c579dabc3f7b \
|
||||
--hash=sha256:3ef68830a9b32050c30f7962c56a5927802c9193b68eaf405faecb8ce9ae10a8 \
|
||||
--hash=sha256:d41512d66044c2df9c5f515a56a922170d68a37b3406ffddc8b4adc57181b576 \
|
||||
--hash=sha256:fc7185d65755f26d7a6842492ec5398c92544dc4eafbbcbef1b1922aca585c96
|
||||
PyQt6-Qt6==6.6.0 \
|
||||
--hash=sha256:1b079a33088d32ff47872cdb37fd15aa42101f0be46c3340244483849b781438 \
|
||||
--hash=sha256:8cb30d64a4d32465ea1686bc827cbe452225fb387c4873356b0fa7b9ae63534f \
|
||||
--hash=sha256:a151f34712cd645111e89cb30b02e5fb69c9dcc3603ab3c03a561e874bd7cbcf \
|
||||
--hash=sha256:e5483ae04bf107411c7469f1be9f9e2eb9840303e788b3ac524fe30af90d45f4
|
||||
PyQt6-NetworkAuth==6.6.0 \
|
||||
--hash=sha256:7b90b81792fe53105287c8cbb5e4b22bc44a482268ffb7d3e33f852807f86182 \
|
||||
--hash=sha256:c7e2335159aa795e2fe6fb069ccce6308672ab80f26c50fab57caf957371cbb5 \
|
||||
--hash=sha256:cdfc0bfaea16a9e09f075bdafefb996aa9fdec392052ba4fb3cbac233c1958fb \
|
||||
--hash=sha256:f60ff9a62f5129dc2a9d4c495fb47f9a03e4dfb666b50fb7d61f46e89bf7b6a2
|
||||
PyQt6-NetworkAuth-Qt6==6.6.0 \
|
||||
--hash=sha256:481d9093e1fb1ac6843d8beabcd359cc34b74b9a2cbb3e2b68d96bd3f178d4e0 \
|
||||
--hash=sha256:4cc48fd375730a0ba5fbed9d64abb2914f587377560a78a63aff893f9e276a45 \
|
||||
--hash=sha256:5006deabf55304d4a3e0b3c954f93e5835546b11e789d14653a2493d12d3a063 \
|
||||
--hash=sha256:bcd56bfc892fec961c51eba3c0bf32ba8317a762d9e254d3830569611ed569d6
|
||||
|
||||
certifi==2023.5.7; \
|
||||
--hash=sha256:c6c2e98f5c7869efca1f8916fed228dd91539f9f1b444c314c06eef02980c716
|
||||
cryptography==41.0.1 \
|
||||
|
|
|
@ -112,7 +112,6 @@
|
|||
"support_interface_density": { "value": 33.333 },
|
||||
"support_interface_enable": { "value": true },
|
||||
"support_interface_pattern": { "value": "'grid'" },
|
||||
"support_interface_skip_height": { "value": 0.2 },
|
||||
"support_roof_enable": { "value": true },
|
||||
"support_xy_distance": { "value": "wall_line_width_0 * 2" },
|
||||
"support_xy_distance_overhang": { "value": "wall_line_width_0" },
|
||||
|
|
|
@ -114,7 +114,6 @@
|
|||
"support_interface_enable": { "value": true },
|
||||
"support_interface_height": { "value": "layer_height * 4" },
|
||||
"support_interface_pattern": { "value": "'grid'" },
|
||||
"support_interface_skip_height": { "value": 0.2 },
|
||||
"support_xy_distance": { "value": "wall_line_width_0 * 2" },
|
||||
"support_xy_distance_overhang": { "value": "wall_line_width_0" },
|
||||
"support_xy_overrides_z": { "value": "'xy_overrides_z'" },
|
||||
|
|
|
@ -154,7 +154,6 @@
|
|||
"support_infill_rate": { "value": "20" },
|
||||
"support_interface_enable": { "value": "True" },
|
||||
"support_interface_height": { "value": "1" },
|
||||
"support_interface_skip_height": { "value": "layer_height" },
|
||||
"support_join_distance": { "value": "1" },
|
||||
"support_offset": { "value": "1.5" },
|
||||
"support_pattern": { "default_value": "zigzag" },
|
||||
|
|
|
@ -108,7 +108,6 @@
|
|||
"support_interface_enable": { "value": true },
|
||||
"support_interface_height": { "value": "layer_height * 4" },
|
||||
"support_interface_pattern": { "value": "'grid'" },
|
||||
"support_interface_skip_height": { "value": 0.2 },
|
||||
"support_pattern": { "value": "'zigzag'" },
|
||||
"support_wall_count": { "value": 1 },
|
||||
"support_xy_distance": { "value": "wall_line_width_0 * 2" },
|
||||
|
|
|
@ -97,7 +97,6 @@
|
|||
"support_interface_enable": { "value": true },
|
||||
"support_interface_height": { "value": "layer_height * 4" },
|
||||
"support_interface_pattern": { "value": "'grid'" },
|
||||
"support_interface_skip_height": { "value": 0.2 },
|
||||
"support_pattern": { "value": "'zigzag'" },
|
||||
"support_xy_distance": { "value": "wall_line_width_0 * 2" },
|
||||
"support_xy_distance_overhang": { "value": "wall_line_width_0" },
|
||||
|
|
|
@ -9,16 +9,20 @@
|
|||
},
|
||||
"overrides":
|
||||
{
|
||||
"acceleration_layer_0": { "value": 3000 },
|
||||
"acceleration_print": { "value": 3000 },
|
||||
"acceleration_travel": { "value": 5000 },
|
||||
"acceleration_print":
|
||||
{
|
||||
"maximum_value_warning": "20000",
|
||||
"value": 10000
|
||||
},
|
||||
"acceleration_wall": { "value": "acceleration_print/2" },
|
||||
"cool_fan_full_layer": { "value": 2 },
|
||||
"infill_line_width": { "value": "line_width + 0.05" },
|
||||
"infill_overlap": { "value": "0 if infill_sparse_density < 40.01 and infill_pattern != 'concentric' else -5" },
|
||||
"infill_pattern": { "value": "'lines' if infill_sparse_density > 35 else 'grid'" },
|
||||
"initial_layer_line_width_factor": { "value": "100.0 if resolveOrValue('adhesion_type') == 'raft' else 125 if line_width < 0.5 else 110" },
|
||||
"machine_acceleration": { "value": 3000 },
|
||||
"machine_acceleration": { "value": 5000 },
|
||||
"machine_depth": { "default_value": 230 },
|
||||
"machine_end_gcode": { "default_value": "G91 ;Relative positionning\nG1 E-2 F2700 ;Retract a bit\nG1 E-2 Z0.2 F2400 ;Retract and raise Z\nG1 X5 Y5 F3000 ;Wipe out\nG1 Z2 ;Raise Z more\nG90 ;Absolute positionning\nG1 X0 Y{machine_depth} ;Present print\nM106 S0 ;Turn-off fan\nM104 S0 ;Turn-off hotend\nM140 S0 ;Turn-off bed\nM84 X Y E ;Disable all steppers but Z" },
|
||||
"machine_end_gcode": { "default_value": "G91 ;Relative positionning\nG1 E-2 F2700 ;Retract a bit\nG1 E-2 Z0.2 F2400 ;Retract and raise Z\nG1 X5 Y5 F3000 ;Wipe out\nG1 Z2 ;Raise Z more\nG90 ;Absolute positionning\nG1 X0 Y{machine_depth - 5} ;Present print\nM106 S0 ;Turn-off fan\nM104 S0 ;Turn-off hotend\nM140 S0 ;Turn-off bed\nM84 X Y E ;Disable all steppers but Z" },
|
||||
"machine_gcode_flavor": { "default_value": "RepRap (Marlin/Sprinter)" },
|
||||
"machine_head_with_fans_polygon":
|
||||
{
|
||||
|
@ -32,12 +36,12 @@
|
|||
"machine_heated_bed": { "default_value": true },
|
||||
"machine_height": { "default_value": 270 },
|
||||
"machine_max_acceleration_e": { "value": 5000 },
|
||||
"machine_max_acceleration_x": { "value": 5000 },
|
||||
"machine_max_acceleration_y": { "value": 5000 },
|
||||
"machine_max_acceleration_x": { "value": 20000 },
|
||||
"machine_max_acceleration_y": { "value": 20000 },
|
||||
"machine_name": { "default_value": "ELEGOO NEPTUNE 4" },
|
||||
"machine_nozzle_cool_down_speed": { "value": 0.75 },
|
||||
"machine_nozzle_heat_up_speed": { "value": 1.6 },
|
||||
"machine_start_gcode": { "default_value": "G28 ;home\nG92 E0 ;Reset Extruder\nG1 Z4.0 F3000 ;Move Z Axis up\nG92 E0 ;Reset Extruder\nG1 X1.1 Y20 Z0.28 F5000.0 ;Move to start position\nG1 X1.1 Y80.0 Z0.28 F1500.0 E10 ;Draw the first line\nG1 X1.4 Y80.0 Z0.28 F5000.0 ;Move to side a little\nG1 X1.4 Y20 Z0.28 F1500.0 E20 ;Draw the second line\nG92 E0 ;Reset Extruder\nG1 Z2.0 F3000 ;Move Z Axis up" },
|
||||
"machine_start_gcode": { "default_value": ";ELEGOO NEPTUNE 4 / 4 PRO\nM220 S100 ;Set the feed speed to 100%\nM221 S100 ;Set the flow rate to 100%\nM104 S140 ;Start heating extruder\nM190 S{material_bed_temperature_layer_0} ;Wait for the bed to reach print temp\nG90\nG28 ;home\nG1 Z10 F300\nG1 X67.5 Y0 F6000\nG1 Z0 F300\nM109 S{material_print_temperature_layer_0} ;Wait for extruder to reach print temp\nG92 E0 ;Reset Extruder\nG1 X67.5 Y0 Z0.4 F300 ;Move to start position\nG1 X167.5 E30 F400 ;Draw the first line\nG1 Z0.6 F120.0 ;Move to side a little\nG1 X162.5 F3000\nG92 E0 ;Reset Extruder" },
|
||||
"machine_width": { "default_value": 235 },
|
||||
"retraction_amount": { "default_value": 0.5 },
|
||||
"retraction_count_max": { "value": 80 },
|
||||
|
|
62
resources/definitions/elegoo_neptune_4max.def.json
Normal file
62
resources/definitions/elegoo_neptune_4max.def.json
Normal file
|
@ -0,0 +1,62 @@
|
|||
{
|
||||
"version": 2,
|
||||
"name": "ELEGOO NEPTUNE 4 Max",
|
||||
"inherits": "elegoo_neptune_4",
|
||||
"metadata":
|
||||
{
|
||||
"visible": true,
|
||||
"author": "mastercaution",
|
||||
"platform": "elegoo_platform_max.3mf",
|
||||
"platform_offset": [
|
||||
-2.1,
|
||||
-0.2,
|
||||
0
|
||||
],
|
||||
"quality_definition": "elegoo_neptune_4"
|
||||
},
|
||||
"overrides":
|
||||
{
|
||||
"acceleration_print":
|
||||
{
|
||||
"maximum_value_warning": "15000",
|
||||
"value": 2500
|
||||
},
|
||||
"machine_depth": { "default_value": 430 },
|
||||
"machine_height": { "default_value": 482 },
|
||||
"machine_max_acceleration_e": { "value": 5000 },
|
||||
"machine_max_acceleration_x": { "value": 15000 },
|
||||
"machine_max_acceleration_y": { "value": 15000 },
|
||||
"machine_name": { "default_value": "ELEGOO NEPTUNE 4 Max" },
|
||||
"machine_start_gcode": { "default_value": ";ELEGOO NEPTUNE 4 MAX\nM220 S100 ;Set the feed speed to 100%\nM221 S100 ;Set the flow rate to 100%\nM104 S140 ;Start heating extruder\nM190 S{material_bed_temperature_layer_0} ;Wait for the bed to reach print temp\nG90\nG28 ;home\nG1 Z10 F300\nG1 X165 Y0 F6000\nG1 Z0 F300\nM109 S{material_print_temperature_layer_0} ;Wait for extruder to reach print temp\nG92 E0 ;Reset Extruder\nG1 X165 Y0 Z0.4 F300 ;Move to start position\nG1 X265 E30 F400 ;Draw the first line\nG1 Z0.6 F120.0 ;Move to side a little\nG1 X260 F3000\nG92 E0 ;Reset Extruder" },
|
||||
"machine_width": { "default_value": 430 },
|
||||
"nozzle_disallowed_areas":
|
||||
{
|
||||
"default_value": [
|
||||
[
|
||||
[-215, -215],
|
||||
[-215, 215],
|
||||
[-211, 215],
|
||||
[-211, -215]
|
||||
],
|
||||
[
|
||||
[215, 215],
|
||||
[215, -215],
|
||||
[211, -215],
|
||||
[211, 215]
|
||||
],
|
||||
[
|
||||
[-215, -215],
|
||||
[215, -215],
|
||||
[-215, -211],
|
||||
[215, -211]
|
||||
],
|
||||
[
|
||||
[-215, 215],
|
||||
[215, 215],
|
||||
[-215, 211],
|
||||
[215, 211]
|
||||
]
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
59
resources/definitions/elegoo_neptune_4plus.def.json
Normal file
59
resources/definitions/elegoo_neptune_4plus.def.json
Normal file
|
@ -0,0 +1,59 @@
|
|||
{
|
||||
"version": 2,
|
||||
"name": "ELEGOO NEPTUNE 4 Plus",
|
||||
"inherits": "elegoo_neptune_4",
|
||||
"metadata":
|
||||
{
|
||||
"visible": true,
|
||||
"author": "mastercaution",
|
||||
"platform": "elegoo_platform_max.3mf",
|
||||
"platform_offset": [
|
||||
-2.1,
|
||||
-0.2,
|
||||
0
|
||||
],
|
||||
"quality_definition": "elegoo_neptune_4"
|
||||
},
|
||||
"overrides":
|
||||
{
|
||||
"acceleration_print": { "value": 4000 },
|
||||
"machine_acceleration": { "value": 4000 },
|
||||
"machine_depth": { "default_value": 330 },
|
||||
"machine_height": { "default_value": 387 },
|
||||
"machine_max_acceleration_e": { "value": 5000 },
|
||||
"machine_max_acceleration_x": { "value": 20000 },
|
||||
"machine_max_acceleration_y": { "value": 20000 },
|
||||
"machine_name": { "default_value": "ELEGOO NEPTUNE 4 Plus" },
|
||||
"machine_start_gcode": { "default_value": ";ELEGOO NEPTUNE 4 PLUS\nM220 S100 ;Set the feed speed to 100%\nM221 S100 ;Set the flow rate to 100%\nM104 S140 ;Start heating extruder\nM190 S{material_bed_temperature_layer_0} ;Wait for the bed to reach print temp\nG90\nG28 ;home\nG1 Z10 F300\nG1 X115 Y0 F6000\nG1 Z0 F300\nM109 S{material_print_temperature_layer_0} ;Wait for extruder to reach print temp\nG92 E0 ;Reset Extruder\nG1 X115 Y0 Z0.4 F300 ;Move to start position\nG1 X215 E30 F400 ;Draw the first line\nG1 Z0.6 F120.0 ;Move to side a little\nG1 X210 F3000\nG92 E0 ;Reset Extruder" },
|
||||
"machine_width": { "default_value": 330 },
|
||||
"nozzle_disallowed_areas":
|
||||
{
|
||||
"default_value": [
|
||||
[
|
||||
[-165, -165],
|
||||
[-165, 165],
|
||||
[-161, 165],
|
||||
[-161, -165]
|
||||
],
|
||||
[
|
||||
[165, 165],
|
||||
[165, -165],
|
||||
[161, -165],
|
||||
[161, 165]
|
||||
],
|
||||
[
|
||||
[-165, -165],
|
||||
[165, -165],
|
||||
[-165, -161],
|
||||
[165, -161]
|
||||
],
|
||||
[
|
||||
[-165, 165],
|
||||
[165, 165],
|
||||
[-165, 161],
|
||||
[165, 161]
|
||||
]
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1159,7 +1159,7 @@
|
|||
"label": "Optimize Wall Printing Order",
|
||||
"description": "Optimize the order in which walls are printed so as to reduce the number of retractions and the distance travelled. Most parts will benefit from this being enabled but some may actually take longer so please compare the print time estimates with and without optimization. First layer is not optimized when choosing brim as build plate adhesion type.",
|
||||
"type": "bool",
|
||||
"default_value": false,
|
||||
"default_value": true,
|
||||
"settable_per_mesh": true
|
||||
},
|
||||
"inset_direction":
|
||||
|
@ -1478,6 +1478,7 @@
|
|||
"description": "Print top surface lines in an ordering that causes them to always overlap with adjacent lines in a single direction. This takes slightly more time to print, but makes flat surfaces look more consistent.",
|
||||
"type": "bool",
|
||||
"value": true,
|
||||
"default_value": true,
|
||||
"enabled": "roofing_layer_count > 0 and top_layers > 0 and roofing_pattern != 'concentric'",
|
||||
"limit_to_extruder": "roofing_extruder_nr",
|
||||
"settable_per_mesh": true
|
||||
|
@ -4578,6 +4579,7 @@
|
|||
"unit": "\u00b0C",
|
||||
"type": "float",
|
||||
"value": "material_print_temperature",
|
||||
"default_value": 0,
|
||||
"enabled": "cool_min_layer_time > 0",
|
||||
"minimum_value_warning": "max(material_final_print_temperature, material_initial_print_temperature)",
|
||||
"maximum_value_warning": "material_print_temperature",
|
||||
|
@ -5421,20 +5423,6 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"support_interface_skip_height":
|
||||
{
|
||||
"label": "Support Interface Resolution",
|
||||
"description": "When checking where there's model above and below the support, take steps of the given height. Lower values will slice slower, while higher values may cause normal support to be printed in some places where there should have been support interface.",
|
||||
"unit": "mm",
|
||||
"type": "float",
|
||||
"default_value": 0.2,
|
||||
"value": "layer_height",
|
||||
"minimum_value": "0",
|
||||
"maximum_value_warning": "support_interface_height",
|
||||
"limit_to_extruder": "support_interface_extruder_nr",
|
||||
"enabled": "support_interface_enable and (support_enable or support_meshes_present)",
|
||||
"settable_per_mesh": true
|
||||
},
|
||||
"support_interface_density":
|
||||
{
|
||||
"label": "Support Interface Density",
|
||||
|
@ -6112,7 +6100,101 @@
|
|||
"enabled": "resolveOrValue('adhesion_type') == 'raft'",
|
||||
"limit_to_extruder": "adhesion_extruder_nr",
|
||||
"settable_per_mesh": false,
|
||||
"settable_per_extruder": true
|
||||
"settable_per_extruder": true,
|
||||
"children":
|
||||
{
|
||||
"raft_base_margin":
|
||||
{
|
||||
"label": "Raft Base Extra Margin",
|
||||
"description": "If the raft base is enabled, this is the extra raft area around the model which is also given a raft. Increasing this margin will create a stronger raft while using more material and leaving less area for your print.",
|
||||
"unit": "mm",
|
||||
"type": "float",
|
||||
"value": "raft_margin",
|
||||
"default_value": 15,
|
||||
"minimum_value_warning": "raft_interface_line_width",
|
||||
"maximum_value_warning": "min(raft_interface_margin, 20)",
|
||||
"enabled": "resolveOrValue('adhesion_type') == 'raft'",
|
||||
"limit_to_extruder": "raft_base_extruder_nr",
|
||||
"settable_per_mesh": false,
|
||||
"settable_per_extruder": true
|
||||
},
|
||||
"raft_interface_margin":
|
||||
{
|
||||
"label": "Raft Middle Extra Margin",
|
||||
"description": "If the raft middle is enabled, this is the extra raft area around the model which is also given a raft. Increasing this margin will create a stronger raft while using more material and leaving less area for your print.",
|
||||
"unit": "mm",
|
||||
"type": "float",
|
||||
"value": "raft_margin",
|
||||
"default_value": 15,
|
||||
"minimum_value_warning": "raft_interface_line_width",
|
||||
"maximum_value_warning": "min(raft_surface_margin, 20)",
|
||||
"enabled": "resolveOrValue('adhesion_type') == 'raft'",
|
||||
"limit_to_extruder": "raft_interface_extruder_nr",
|
||||
"settable_per_mesh": false,
|
||||
"settable_per_extruder": true
|
||||
},
|
||||
"raft_surface_margin":
|
||||
{
|
||||
"label": "Raft Top Extra Margin",
|
||||
"description": "If the raft top is enabled, this is the extra raft area around the model which is also given a raft. Increasing this margin will create a stronger raft while using more material and leaving less area for your print.",
|
||||
"unit": "mm",
|
||||
"type": "float",
|
||||
"value": "raft_margin",
|
||||
"default_value": 15,
|
||||
"minimum_value_warning": "raft_interface_line_width",
|
||||
"maximum_value_warning": "20",
|
||||
"enabled": "resolveOrValue('adhesion_type') == 'raft'",
|
||||
"limit_to_extruder": "raft_surface_extruder_nr",
|
||||
"settable_per_mesh": false,
|
||||
"settable_per_extruder": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"raft_remove_inside_corners":
|
||||
{
|
||||
"label": "Remove Raft Inside Corners",
|
||||
"description": "Remove inside corners from the raft, causing the raft to become convex.",
|
||||
"type": "bool",
|
||||
"default_value": false,
|
||||
"enabled": "resolveOrValue('adhesion_type') == 'raft'",
|
||||
"settable_per_mesh": false,
|
||||
"settable_per_extruder": false,
|
||||
"children":
|
||||
{
|
||||
"raft_base_remove_inside_corners":
|
||||
{
|
||||
"label": "Remove Raft Base Inside Corners",
|
||||
"description": "Remove inside corners from the raft base, causing the raft to become convex.",
|
||||
"type": "bool",
|
||||
"value": "raft_remove_inside_corners",
|
||||
"default_value": false,
|
||||
"enabled": "resolveOrValue('adhesion_type') == 'raft'",
|
||||
"settable_per_mesh": false,
|
||||
"settable_per_extruder": false
|
||||
},
|
||||
"raft_interface_remove_inside_corners":
|
||||
{
|
||||
"label": "Remove Raft Middle Inside Corners",
|
||||
"description": "Remove inside corners from the raft middle part, causing the raft to become convex.",
|
||||
"type": "bool",
|
||||
"value": "raft_remove_inside_corners",
|
||||
"default_value": false,
|
||||
"enabled": "resolveOrValue('adhesion_type') == 'raft'",
|
||||
"settable_per_mesh": false,
|
||||
"settable_per_extruder": false
|
||||
},
|
||||
"raft_surface_remove_inside_corners":
|
||||
{
|
||||
"label": "Remove Raft Top Inside Corners",
|
||||
"description": "Remove inside corners from the raft top part, causing the raft to become convex.",
|
||||
"type": "bool",
|
||||
"value": "raft_remove_inside_corners",
|
||||
"default_value": false,
|
||||
"enabled": "resolveOrValue('adhesion_type') == 'raft'",
|
||||
"settable_per_mesh": false,
|
||||
"settable_per_extruder": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"raft_smoothing":
|
||||
{
|
||||
|
@ -6124,9 +6206,53 @@
|
|||
"minimum_value": "0",
|
||||
"minimum_value_warning": "raft_interface_line_width",
|
||||
"enabled": "resolveOrValue('adhesion_type') == 'raft' and not raft_remove_inside_corners",
|
||||
"limit_to_extruder": "adhesion_extruder_nr",
|
||||
"settable_per_mesh": false,
|
||||
"settable_per_extruder": true
|
||||
"settable_per_extruder": false,
|
||||
"children":
|
||||
{
|
||||
"raft_base_smoothing":
|
||||
{
|
||||
"label": "Raft Base Smoothing",
|
||||
"description": "This setting controls how much inner corners in the raft base outline are rounded. Inward corners are rounded to a semi circle with a radius equal to the value given here. This setting also removes holes in the raft outline which are smaller than such a circle.",
|
||||
"unit": "mm",
|
||||
"type": "float",
|
||||
"value": "raft_smoothing",
|
||||
"default_value": 5,
|
||||
"minimum_value": "0",
|
||||
"minimum_value_warning": "raft_interface_line_width",
|
||||
"enabled": "resolveOrValue('adhesion_type') == 'raft' and not raft_base_remove_inside_corners",
|
||||
"settable_per_mesh": false,
|
||||
"settable_per_extruder": false
|
||||
},
|
||||
"raft_interface_smoothing":
|
||||
{
|
||||
"label": "Raft Middle Smoothing",
|
||||
"description": "This setting controls how much inner corners in the raft middle outline are rounded. Inward corners are rounded to a semi circle with a radius equal to the value given here. This setting also removes holes in the raft outline which are smaller than such a circle.",
|
||||
"unit": "mm",
|
||||
"type": "float",
|
||||
"value": "raft_smoothing",
|
||||
"default_value": 5,
|
||||
"minimum_value": "0",
|
||||
"minimum_value_warning": "raft_interface_line_width",
|
||||
"enabled": "resolveOrValue('adhesion_type') == 'raft' and not raft_interface_remove_inside_corners",
|
||||
"settable_per_mesh": false,
|
||||
"settable_per_extruder": false
|
||||
},
|
||||
"raft_surface_smoothing":
|
||||
{
|
||||
"label": "Raft Top Smoothing",
|
||||
"description": "This setting controls how much inner corners in the raft top outline are rounded. Inward corners are rounded to a semi circle with a radius equal to the value given here. This setting also removes holes in the raft outline which are smaller than such a circle.",
|
||||
"unit": "mm",
|
||||
"type": "float",
|
||||
"value": "raft_smoothing",
|
||||
"default_value": 5,
|
||||
"minimum_value": "0",
|
||||
"minimum_value_warning": "raft_interface_line_width",
|
||||
"enabled": "resolveOrValue('adhesion_type') == 'raft' and not raft_surface_remove_inside_corners",
|
||||
"settable_per_mesh": false,
|
||||
"settable_per_extruder": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"raft_airgap":
|
||||
{
|
||||
|
@ -6157,66 +6283,53 @@
|
|||
"settable_per_extruder": true,
|
||||
"limit_to_extruder": "raft_surface_extruder_nr"
|
||||
},
|
||||
"raft_surface_layers":
|
||||
"raft_base_thickness":
|
||||
{
|
||||
"label": "Raft Top Layers",
|
||||
"description": "The number of top layers on top of the 2nd raft layer. These are fully filled layers that the model sits on. 2 layers result in a smoother top surface than 1.",
|
||||
"type": "int",
|
||||
"default_value": 2,
|
||||
"minimum_value": "0",
|
||||
"maximum_value_warning": "20",
|
||||
"label": "Raft Base Thickness",
|
||||
"description": "Layer thickness of the base raft layer. This should be a thick layer which sticks firmly to the printer build plate.",
|
||||
"unit": "mm",
|
||||
"type": "float",
|
||||
"default_value": 0.3,
|
||||
"value": "resolveOrValue('layer_height_0') * 1.2",
|
||||
"minimum_value": "0.001",
|
||||
"minimum_value_warning": "0.04",
|
||||
"maximum_value_warning": "0.75 * raft_base_line_width",
|
||||
"enabled": "resolveOrValue('adhesion_type') == 'raft'",
|
||||
"settable_per_mesh": false,
|
||||
"settable_per_extruder": true,
|
||||
"limit_to_extruder": "raft_surface_extruder_nr"
|
||||
"limit_to_extruder": "raft_base_extruder_nr"
|
||||
},
|
||||
"raft_surface_thickness":
|
||||
"raft_base_line_width":
|
||||
{
|
||||
"label": "Raft Top Layer Thickness",
|
||||
"description": "Layer thickness of the top raft layers.",
|
||||
"label": "Raft Base Line Width",
|
||||
"description": "Width of the lines in the base raft layer. These should be thick lines to assist in build plate adhesion.",
|
||||
"unit": "mm",
|
||||
"type": "float",
|
||||
"default_value": 0.1,
|
||||
"value": "resolveOrValue('layer_height')",
|
||||
"default_value": 0.8,
|
||||
"minimum_value": "0.001",
|
||||
"minimum_value_warning": "0.04",
|
||||
"maximum_value_warning": "0.75 * machine_nozzle_size",
|
||||
"enabled": "resolveOrValue('adhesion_type') == 'raft' and raft_surface_layers > 0",
|
||||
"value": "machine_nozzle_size * 2",
|
||||
"minimum_value_warning": "machine_nozzle_size * 0.5",
|
||||
"maximum_value_warning": "machine_nozzle_size * 3",
|
||||
"enabled": "resolveOrValue('adhesion_type') == 'raft'",
|
||||
"settable_per_mesh": false,
|
||||
"settable_per_extruder": true,
|
||||
"limit_to_extruder": "raft_surface_extruder_nr"
|
||||
"limit_to_extruder": "raft_base_extruder_nr"
|
||||
},
|
||||
"raft_surface_line_width":
|
||||
"raft_base_line_spacing":
|
||||
{
|
||||
"label": "Raft Top Line Width",
|
||||
"description": "Width of the lines in the top surface of the raft. These can be thin lines so that the top of the raft becomes smooth.",
|
||||
"label": "Raft Base Line Spacing",
|
||||
"description": "The distance between the raft lines for the base raft layer. Wide spacing makes for easy removal of the raft from the build plate.",
|
||||
"unit": "mm",
|
||||
"type": "float",
|
||||
"default_value": 0.4,
|
||||
"value": "line_width",
|
||||
"minimum_value": "0.001",
|
||||
"minimum_value_warning": "machine_nozzle_size * 0.1",
|
||||
"maximum_value_warning": "machine_nozzle_size * 2",
|
||||
"enabled": "resolveOrValue('adhesion_type') == 'raft' and raft_surface_layers > 0",
|
||||
"settable_per_mesh": false,
|
||||
"settable_per_extruder": true,
|
||||
"limit_to_extruder": "raft_surface_extruder_nr"
|
||||
},
|
||||
"raft_surface_line_spacing":
|
||||
{
|
||||
"label": "Raft Top Spacing",
|
||||
"description": "The distance between the raft lines for the top raft layers. The spacing should be equal to the line width, so that the surface is solid.",
|
||||
"unit": "mm",
|
||||
"type": "float",
|
||||
"default_value": 0.4,
|
||||
"default_value": 1.6,
|
||||
"value": "raft_base_line_width * 2",
|
||||
"minimum_value": "0",
|
||||
"minimum_value_warning": "raft_surface_line_width",
|
||||
"maximum_value_warning": "raft_surface_line_width * 3",
|
||||
"enabled": "resolveOrValue('adhesion_type') == 'raft' and raft_surface_layers > 0",
|
||||
"value": "raft_surface_line_width",
|
||||
"minimum_value_warning": "raft_base_line_width",
|
||||
"maximum_value_warning": "100",
|
||||
"enabled": "resolveOrValue('adhesion_type') == 'raft'",
|
||||
"settable_per_mesh": false,
|
||||
"settable_per_extruder": true,
|
||||
"limit_to_extruder": "raft_surface_extruder_nr"
|
||||
"limit_to_extruder": "raft_base_extruder_nr"
|
||||
},
|
||||
"raft_interface_layers":
|
||||
{
|
||||
|
@ -6279,53 +6392,126 @@
|
|||
"settable_per_extruder": true,
|
||||
"limit_to_extruder": "raft_interface_extruder_nr"
|
||||
},
|
||||
"raft_base_thickness":
|
||||
"raft_surface_layers":
|
||||
{
|
||||
"label": "Raft Base Thickness",
|
||||
"description": "Layer thickness of the base raft layer. This should be a thick layer which sticks firmly to the printer build plate.",
|
||||
"label": "Raft Top Layers",
|
||||
"description": "The number of top layers on top of the 2nd raft layer. These are fully filled layers that the model sits on. 2 layers result in a smoother top surface than 1.",
|
||||
"type": "int",
|
||||
"default_value": 2,
|
||||
"minimum_value": "0",
|
||||
"maximum_value_warning": "20",
|
||||
"enabled": "resolveOrValue('adhesion_type') == 'raft'",
|
||||
"settable_per_mesh": false,
|
||||
"settable_per_extruder": true,
|
||||
"limit_to_extruder": "raft_surface_extruder_nr"
|
||||
},
|
||||
"raft_surface_thickness":
|
||||
{
|
||||
"label": "Raft Top Layer Thickness",
|
||||
"description": "Layer thickness of the top raft layers.",
|
||||
"unit": "mm",
|
||||
"type": "float",
|
||||
"default_value": 0.3,
|
||||
"value": "resolveOrValue('layer_height_0') * 1.2",
|
||||
"default_value": 0.1,
|
||||
"value": "resolveOrValue('layer_height')",
|
||||
"minimum_value": "0.001",
|
||||
"minimum_value_warning": "0.04",
|
||||
"maximum_value_warning": "0.75 * raft_base_line_width",
|
||||
"enabled": "resolveOrValue('adhesion_type') == 'raft'",
|
||||
"maximum_value_warning": "0.75 * machine_nozzle_size",
|
||||
"enabled": "resolveOrValue('adhesion_type') == 'raft' and raft_surface_layers > 0",
|
||||
"settable_per_mesh": false,
|
||||
"settable_per_extruder": true,
|
||||
"limit_to_extruder": "raft_base_extruder_nr"
|
||||
"limit_to_extruder": "raft_surface_extruder_nr"
|
||||
},
|
||||
"raft_base_line_width":
|
||||
"raft_surface_line_width":
|
||||
{
|
||||
"label": "Raft Base Line Width",
|
||||
"description": "Width of the lines in the base raft layer. These should be thick lines to assist in build plate adhesion.",
|
||||
"label": "Raft Top Line Width",
|
||||
"description": "Width of the lines in the top surface of the raft. These can be thin lines so that the top of the raft becomes smooth.",
|
||||
"unit": "mm",
|
||||
"type": "float",
|
||||
"default_value": 0.8,
|
||||
"default_value": 0.4,
|
||||
"value": "line_width",
|
||||
"minimum_value": "0.001",
|
||||
"value": "machine_nozzle_size * 2",
|
||||
"minimum_value_warning": "machine_nozzle_size * 0.5",
|
||||
"maximum_value_warning": "machine_nozzle_size * 3",
|
||||
"enabled": "resolveOrValue('adhesion_type') == 'raft'",
|
||||
"minimum_value_warning": "machine_nozzle_size * 0.1",
|
||||
"maximum_value_warning": "machine_nozzle_size * 2",
|
||||
"enabled": "resolveOrValue('adhesion_type') == 'raft' and raft_surface_layers > 0",
|
||||
"settable_per_mesh": false,
|
||||
"settable_per_extruder": true,
|
||||
"limit_to_extruder": "raft_base_extruder_nr"
|
||||
"limit_to_extruder": "raft_surface_extruder_nr"
|
||||
},
|
||||
"raft_base_line_spacing":
|
||||
"raft_surface_line_spacing":
|
||||
{
|
||||
"label": "Raft Base Line Spacing",
|
||||
"description": "The distance between the raft lines for the base raft layer. Wide spacing makes for easy removal of the raft from the build plate.",
|
||||
"label": "Raft Top Spacing",
|
||||
"description": "The distance between the raft lines for the top raft layers. The spacing should be equal to the line width, so that the surface is solid.",
|
||||
"unit": "mm",
|
||||
"type": "float",
|
||||
"default_value": 1.6,
|
||||
"value": "raft_base_line_width * 2",
|
||||
"default_value": 0.4,
|
||||
"minimum_value": "0",
|
||||
"minimum_value_warning": "raft_base_line_width",
|
||||
"maximum_value_warning": "100",
|
||||
"enabled": "resolveOrValue('adhesion_type') == 'raft'",
|
||||
"minimum_value_warning": "raft_surface_line_width",
|
||||
"maximum_value_warning": "raft_surface_line_width * 3",
|
||||
"enabled": "resolveOrValue('adhesion_type') == 'raft' and raft_surface_layers > 0",
|
||||
"value": "raft_surface_line_width",
|
||||
"settable_per_mesh": false,
|
||||
"settable_per_extruder": true,
|
||||
"limit_to_extruder": "raft_base_extruder_nr"
|
||||
"limit_to_extruder": "raft_surface_extruder_nr"
|
||||
},
|
||||
"raft_surface_monotonic":
|
||||
{
|
||||
"label": "Monotonic Raft Top Surface Order",
|
||||
"description": "Print raft top surface lines in an ordering that causes them to always overlap with adjacent lines in a single direction. This takes slightly more time to print, but makes the surface look more consistent, which is also visible on the model bottom surface.",
|
||||
"type": "bool",
|
||||
"default_value": false,
|
||||
"value": "skin_monotonic",
|
||||
"enabled": "resolveOrValue('adhesion_type') == 'raft' and raft_surface_layers > 0",
|
||||
"settable_per_mesh": false,
|
||||
"settable_per_extruder": true,
|
||||
"limit_to_extruder": "raft_surface_extruder_nr"
|
||||
},
|
||||
"raft_wall_count":
|
||||
{
|
||||
"label": "Raft Wall Count",
|
||||
"description": "The number of contours to print around the linear pattern of the raft.",
|
||||
"type": "int",
|
||||
"default_value": 1,
|
||||
"minimum_value": "0",
|
||||
"enabled": "resolveOrValue('adhesion_type') == 'raft'",
|
||||
"settable_per_mesh": false,
|
||||
"settable_per_extruder": false,
|
||||
"children":
|
||||
{
|
||||
"raft_base_wall_count":
|
||||
{
|
||||
"label": "Raft Base Wall Count",
|
||||
"description": "The number of contours to print around the linear pattern in the base layer of the raft.",
|
||||
"type": "int",
|
||||
"default_value": 1,
|
||||
"value": "raft_wall_count",
|
||||
"minimum_value": "0",
|
||||
"enabled": "resolveOrValue('adhesion_type') == 'raft'",
|
||||
"settable_per_mesh": false,
|
||||
"settable_per_extruder": false
|
||||
},
|
||||
"raft_interface_wall_count":
|
||||
{
|
||||
"label": "Raft Middle Wall Count",
|
||||
"description": "The number of contours to print around the linear pattern in the middle layers of the raft.",
|
||||
"type": "int",
|
||||
"default_value": 0,
|
||||
"minimum_value": "0",
|
||||
"enabled": "resolveOrValue('adhesion_type') == 'raft'",
|
||||
"settable_per_mesh": false,
|
||||
"settable_per_extruder": false
|
||||
},
|
||||
"raft_surface_wall_count":
|
||||
{
|
||||
"label": "Raft Top Wall Count",
|
||||
"description": "The number of contours to print around the linear pattern in the top layers of the raft.",
|
||||
"type": "int",
|
||||
"default_value": 0,
|
||||
"minimum_value": "0",
|
||||
"enabled": "resolveOrValue('adhesion_type') == 'raft'",
|
||||
"settable_per_mesh": false,
|
||||
"settable_per_extruder": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"raft_speed":
|
||||
{
|
||||
|
@ -6344,21 +6530,21 @@
|
|||
"limit_to_extruder": "adhesion_extruder_nr",
|
||||
"children":
|
||||
{
|
||||
"raft_surface_speed":
|
||||
"raft_base_speed":
|
||||
{
|
||||
"label": "Raft Top Print Speed",
|
||||
"description": "The speed at which the top raft layers are printed. These should be printed a bit slower, so that the nozzle can slowly smooth out adjacent surface lines.",
|
||||
"label": "Raft Base Print Speed",
|
||||
"description": "The speed at which the base raft layer is printed. This should be printed quite slowly, as the volume of material coming out of the nozzle is quite high.",
|
||||
"unit": "mm/s",
|
||||
"type": "float",
|
||||
"default_value": 20,
|
||||
"default_value": 15,
|
||||
"minimum_value": "0.1",
|
||||
"maximum_value": "math.sqrt(machine_max_feedrate_x ** 2 + machine_max_feedrate_y ** 2)",
|
||||
"maximum_value_warning": "100",
|
||||
"enabled": "resolveOrValue('adhesion_type') == 'raft' and raft_surface_layers > 0",
|
||||
"value": "raft_speed",
|
||||
"maximum_value_warning": "200",
|
||||
"enabled": "resolveOrValue('adhesion_type') == 'raft'",
|
||||
"value": "0.75 * raft_speed",
|
||||
"settable_per_mesh": false,
|
||||
"settable_per_extruder": true,
|
||||
"limit_to_extruder": "raft_surface_extruder_nr"
|
||||
"limit_to_extruder": "raft_base_extruder_nr"
|
||||
},
|
||||
"raft_interface_speed":
|
||||
{
|
||||
|
@ -6376,21 +6562,21 @@
|
|||
"settable_per_extruder": true,
|
||||
"limit_to_extruder": "raft_interface_extruder_nr"
|
||||
},
|
||||
"raft_base_speed":
|
||||
"raft_surface_speed":
|
||||
{
|
||||
"label": "Raft Base Print Speed",
|
||||
"description": "The speed at which the base raft layer is printed. This should be printed quite slowly, as the volume of material coming out of the nozzle is quite high.",
|
||||
"label": "Raft Top Print Speed",
|
||||
"description": "The speed at which the top raft layers are printed. These should be printed a bit slower, so that the nozzle can slowly smooth out adjacent surface lines.",
|
||||
"unit": "mm/s",
|
||||
"type": "float",
|
||||
"default_value": 15,
|
||||
"default_value": 20,
|
||||
"minimum_value": "0.1",
|
||||
"maximum_value": "math.sqrt(machine_max_feedrate_x ** 2 + machine_max_feedrate_y ** 2)",
|
||||
"maximum_value_warning": "200",
|
||||
"enabled": "resolveOrValue('adhesion_type') == 'raft'",
|
||||
"value": "0.75 * raft_speed",
|
||||
"maximum_value_warning": "100",
|
||||
"enabled": "resolveOrValue('adhesion_type') == 'raft' and raft_surface_layers > 0",
|
||||
"value": "raft_speed",
|
||||
"settable_per_mesh": false,
|
||||
"settable_per_extruder": true,
|
||||
"limit_to_extruder": "raft_base_extruder_nr"
|
||||
"limit_to_extruder": "raft_surface_extruder_nr"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -6410,10 +6596,10 @@
|
|||
"limit_to_extruder": "adhesion_extruder_nr",
|
||||
"children":
|
||||
{
|
||||
"raft_surface_acceleration":
|
||||
"raft_base_acceleration":
|
||||
{
|
||||
"label": "Raft Top Print Acceleration",
|
||||
"description": "The acceleration with which the top raft layers are printed.",
|
||||
"label": "Raft Base Print Acceleration",
|
||||
"description": "The acceleration with which the base raft layer is printed.",
|
||||
"unit": "mm/s\u00b2",
|
||||
"type": "float",
|
||||
"default_value": 3000,
|
||||
|
@ -6421,9 +6607,9 @@
|
|||
"minimum_value": "0.1",
|
||||
"minimum_value_warning": "100",
|
||||
"maximum_value_warning": "10000",
|
||||
"enabled": "resolveOrValue('adhesion_type') == 'raft' and resolveOrValue('acceleration_enabled') and raft_surface_layers > 0",
|
||||
"enabled": "resolveOrValue('adhesion_type') == 'raft' and resolveOrValue('acceleration_enabled')",
|
||||
"settable_per_mesh": false,
|
||||
"limit_to_extruder": "raft_surface_extruder_nr"
|
||||
"limit_to_extruder": "raft_base_extruder_nr"
|
||||
},
|
||||
"raft_interface_acceleration":
|
||||
{
|
||||
|
@ -6440,10 +6626,10 @@
|
|||
"settable_per_mesh": false,
|
||||
"limit_to_extruder": "raft_interface_extruder_nr"
|
||||
},
|
||||
"raft_base_acceleration":
|
||||
"raft_surface_acceleration":
|
||||
{
|
||||
"label": "Raft Base Print Acceleration",
|
||||
"description": "The acceleration with which the base raft layer is printed.",
|
||||
"label": "Raft Top Print Acceleration",
|
||||
"description": "The acceleration with which the top raft layers are printed.",
|
||||
"unit": "mm/s\u00b2",
|
||||
"type": "float",
|
||||
"default_value": 3000,
|
||||
|
@ -6451,9 +6637,9 @@
|
|||
"minimum_value": "0.1",
|
||||
"minimum_value_warning": "100",
|
||||
"maximum_value_warning": "10000",
|
||||
"enabled": "resolveOrValue('adhesion_type') == 'raft' and resolveOrValue('acceleration_enabled')",
|
||||
"enabled": "resolveOrValue('adhesion_type') == 'raft' and resolveOrValue('acceleration_enabled') and raft_surface_layers > 0",
|
||||
"settable_per_mesh": false,
|
||||
"limit_to_extruder": "raft_base_extruder_nr"
|
||||
"limit_to_extruder": "raft_surface_extruder_nr"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -6473,20 +6659,20 @@
|
|||
"limit_to_extruder": "adhesion_extruder_nr",
|
||||
"children":
|
||||
{
|
||||
"raft_surface_jerk":
|
||||
"raft_base_jerk":
|
||||
{
|
||||
"label": "Raft Top Print Jerk",
|
||||
"description": "The jerk with which the top raft layers are printed.",
|
||||
"label": "Raft Base Print Jerk",
|
||||
"description": "The jerk with which the base raft layer is printed.",
|
||||
"unit": "mm/s",
|
||||
"type": "float",
|
||||
"default_value": 20,
|
||||
"value": "raft_jerk",
|
||||
"minimum_value": "0",
|
||||
"minimum_value_warning": "5",
|
||||
"maximum_value_warning": "100",
|
||||
"enabled": "resolveOrValue('adhesion_type') == 'raft' and resolveOrValue('jerk_enabled') and raft_surface_layers > 0",
|
||||
"maximum_value_warning": "50",
|
||||
"enabled": "resolveOrValue('adhesion_type') == 'raft' and resolveOrValue('jerk_enabled')",
|
||||
"settable_per_mesh": false,
|
||||
"limit_to_extruder": "raft_surface_extruder_nr"
|
||||
"limit_to_extruder": "raft_base_extruder_nr"
|
||||
},
|
||||
"raft_interface_jerk":
|
||||
{
|
||||
|
@ -6503,20 +6689,20 @@
|
|||
"settable_per_mesh": false,
|
||||
"limit_to_extruder": "raft_interface_extruder_nr"
|
||||
},
|
||||
"raft_base_jerk":
|
||||
"raft_surface_jerk":
|
||||
{
|
||||
"label": "Raft Base Print Jerk",
|
||||
"description": "The jerk with which the base raft layer is printed.",
|
||||
"label": "Raft Top Print Jerk",
|
||||
"description": "The jerk with which the top raft layers are printed.",
|
||||
"unit": "mm/s",
|
||||
"type": "float",
|
||||
"default_value": 20,
|
||||
"value": "raft_jerk",
|
||||
"minimum_value": "0",
|
||||
"minimum_value_warning": "5",
|
||||
"maximum_value_warning": "50",
|
||||
"enabled": "resolveOrValue('adhesion_type') == 'raft' and resolveOrValue('jerk_enabled')",
|
||||
"maximum_value_warning": "100",
|
||||
"enabled": "resolveOrValue('adhesion_type') == 'raft' and resolveOrValue('jerk_enabled') and raft_surface_layers > 0",
|
||||
"settable_per_mesh": false,
|
||||
"limit_to_extruder": "raft_base_extruder_nr"
|
||||
"limit_to_extruder": "raft_surface_extruder_nr"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -6535,20 +6721,20 @@
|
|||
"limit_to_extruder": "adhesion_extruder_nr",
|
||||
"children":
|
||||
{
|
||||
"raft_surface_fan_speed":
|
||||
"raft_base_fan_speed":
|
||||
{
|
||||
"label": "Raft Top Fan Speed",
|
||||
"description": "The fan speed for the top raft layers.",
|
||||
"label": "Raft Base Fan Speed",
|
||||
"description": "The fan speed for the base raft layer.",
|
||||
"unit": "%",
|
||||
"type": "float",
|
||||
"minimum_value": "0",
|
||||
"maximum_value": "100",
|
||||
"default_value": 0,
|
||||
"value": "raft_fan_speed",
|
||||
"enabled": "resolveOrValue('adhesion_type') == 'raft' and raft_surface_layers > 0",
|
||||
"enabled": "resolveOrValue('adhesion_type') == 'raft'",
|
||||
"settable_per_mesh": false,
|
||||
"settable_per_extruder": true,
|
||||
"limit_to_extruder": "raft_surface_extruder_nr"
|
||||
"limit_to_extruder": "raft_base_extruder_nr"
|
||||
},
|
||||
"raft_interface_fan_speed":
|
||||
{
|
||||
|
@ -6565,20 +6751,20 @@
|
|||
"settable_per_extruder": true,
|
||||
"limit_to_extruder": "raft_interface_extruder_nr"
|
||||
},
|
||||
"raft_base_fan_speed":
|
||||
"raft_surface_fan_speed":
|
||||
{
|
||||
"label": "Raft Base Fan Speed",
|
||||
"description": "The fan speed for the base raft layer.",
|
||||
"label": "Raft Top Fan Speed",
|
||||
"description": "The fan speed for the top raft layers.",
|
||||
"unit": "%",
|
||||
"type": "float",
|
||||
"minimum_value": "0",
|
||||
"maximum_value": "100",
|
||||
"default_value": 0,
|
||||
"value": "raft_fan_speed",
|
||||
"enabled": "resolveOrValue('adhesion_type') == 'raft'",
|
||||
"enabled": "resolveOrValue('adhesion_type') == 'raft' and raft_surface_layers > 0",
|
||||
"settable_per_mesh": false,
|
||||
"settable_per_extruder": true,
|
||||
"limit_to_extruder": "raft_base_extruder_nr"
|
||||
"limit_to_extruder": "raft_surface_extruder_nr"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -6689,7 +6875,7 @@
|
|||
"type": "float",
|
||||
"unit": "mm",
|
||||
"enabled": "resolveOrValue('prime_tower_enable') and (resolveOrValue('prime_tower_brim_enable') or resolveOrValue('adhesion_type') == 'raft')",
|
||||
"default_value": "resolveOrValue('brim_width')",
|
||||
"default_value": 1.2,
|
||||
"minimum_value": "0",
|
||||
"maximum_value": "min(0.5 * machine_width, 0.5 * machine_depth)",
|
||||
"settable_per_mesh": false,
|
||||
|
@ -8273,28 +8459,6 @@
|
|||
"settable_per_mesh": true,
|
||||
"settable_per_extruder": true
|
||||
},
|
||||
"raft_remove_inside_corners":
|
||||
{
|
||||
"label": "Remove Raft Inside Corners",
|
||||
"description": "Remove inside corners from the raft, causing the raft to become convex.",
|
||||
"type": "bool",
|
||||
"default_value": false,
|
||||
"resolve": "any(extruderValues('raft_remove_inside_corners'))",
|
||||
"enabled": "resolveOrValue('adhesion_type') == 'raft'",
|
||||
"settable_per_mesh": false,
|
||||
"settable_per_extruder": false
|
||||
},
|
||||
"raft_base_wall_count":
|
||||
{
|
||||
"label": "Raft Base Wall Count",
|
||||
"description": "The number of contours to print around the linear pattern in the base layer of the raft.",
|
||||
"type": "int",
|
||||
"default_value": 1,
|
||||
"enabled": "resolveOrValue('adhesion_type') == 'raft'",
|
||||
"resolve": "max(extruderValues('raft_base_wall_count'))",
|
||||
"settable_per_mesh": false,
|
||||
"settable_per_extruder": false
|
||||
},
|
||||
"group_outer_walls":
|
||||
{
|
||||
"label": "Group Outer Walls",
|
||||
|
@ -8305,6 +8469,88 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"ppr":
|
||||
{
|
||||
"label": "Print Process Reporting",
|
||||
"type": "category",
|
||||
"icon": "DocumentFilled",
|
||||
"description": "Reporting events that go out of set thresholds",
|
||||
"enabled": false,
|
||||
"children":
|
||||
{
|
||||
"ppr_enable":
|
||||
{
|
||||
"label": "Enable Print Process Reporting",
|
||||
"description": "Enable print process reporting for setting threshold values for possible fault detection.",
|
||||
"type": "bool",
|
||||
"enabled": false,
|
||||
"default_value": false,
|
||||
"value": false,
|
||||
"settable_per_mesh": false,
|
||||
"settable_per_extruder": false
|
||||
},
|
||||
"flow_warn_limit":
|
||||
{
|
||||
"label": "Flow Warning",
|
||||
"description": "Limit on the flow warning for detection.",
|
||||
"default_value": 15.0,
|
||||
"enabled": "ppr_enable",
|
||||
"unit": "%",
|
||||
"type": "float",
|
||||
"settable_per_extruder": true
|
||||
},
|
||||
"flow_anomaly_limit":
|
||||
{
|
||||
"label": "Flow Limit",
|
||||
"description": "Limit on flow anomaly for detection.",
|
||||
"default_value": 25.0,
|
||||
"enabled": "ppr_enable",
|
||||
"unit": "%",
|
||||
"type": "float",
|
||||
"settable_per_extruder": true
|
||||
},
|
||||
"print_temp_warn_limit":
|
||||
{
|
||||
"label": "Print temperature Warning",
|
||||
"description": "Limit on Print temperature warning for detection.",
|
||||
"unit": "\u00b0C",
|
||||
"type": "float",
|
||||
"default_value": 3.0,
|
||||
"enabled": "ppr_enable",
|
||||
"settable_per_extruder": true
|
||||
},
|
||||
"print_temp_anomaly_limit":
|
||||
{
|
||||
"label": "Print temperature Limit",
|
||||
"description": "Limit on Print Temperature anomaly for detection.",
|
||||
"unit": "\u00b0C",
|
||||
"type": "float",
|
||||
"default_value": 7.0,
|
||||
"enabled": "ppr_enable",
|
||||
"settable_per_extruder": true
|
||||
},
|
||||
"bv_temp_warn_limit":
|
||||
{
|
||||
"label": "Build Volume temperature Warning",
|
||||
"description": "Limit on Build Volume Temperature warning for detection.",
|
||||
"unit": "\u00b0C",
|
||||
"type": "float",
|
||||
"default_value": 7.5,
|
||||
"enabled": "ppr_enable",
|
||||
"settable_per_extruder": false
|
||||
},
|
||||
"bv_temp_anomaly_limit":
|
||||
{
|
||||
"label": "Build Volume temperature Limit",
|
||||
"description": "Limit on Build Volume temperature Anomaly for detection.",
|
||||
"unit": "\u00b0C",
|
||||
"type": "float",
|
||||
"default_value": 10.0,
|
||||
"enabled": "ppr_enable",
|
||||
"settable_per_extruder": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"command_line_settings":
|
||||
{
|
||||
"label": "Command Line Settings",
|
||||
|
|
15
resources/definitions/flashforge_adventurer3.def.json
Normal file
15
resources/definitions/flashforge_adventurer3.def.json
Normal file
|
@ -0,0 +1,15 @@
|
|||
{
|
||||
"version": 2,
|
||||
"name": "Adventurer 3",
|
||||
"inherits": "flashforge_adventurer3c",
|
||||
"metadata":
|
||||
{
|
||||
"visible": true,
|
||||
"author": "Jeremie-C",
|
||||
"supports_network_connection": true
|
||||
},
|
||||
"overrides":
|
||||
{
|
||||
"machine_name": { "default_value": "Adventurer 3" }
|
||||
}
|
||||
}
|
33
resources/definitions/flashforge_adventurer3c.def.json
Normal file
33
resources/definitions/flashforge_adventurer3c.def.json
Normal file
|
@ -0,0 +1,33 @@
|
|||
{
|
||||
"version": 2,
|
||||
"name": "Adventurer 3C",
|
||||
"inherits": "flashforge_adventurer_base",
|
||||
"metadata":
|
||||
{
|
||||
"visible": true,
|
||||
"author": "Jeremie-C",
|
||||
"quality_definition": "flashforge_adventurer3"
|
||||
},
|
||||
"overrides":
|
||||
{
|
||||
"default_material_bed_temperature": { "maximum_value_warning": "100" },
|
||||
"gantry_height": { "value": "150" },
|
||||
"machine_center_is_zero": { "default_value": true },
|
||||
"machine_depth": { "default_value": 150 },
|
||||
"machine_end_gcode": { "default_value": ";end gcode\nM104 S0 T0\nM140 S0 T0\nG162 Z F1800\nG28 X Y\nM132 X Y A B\nM652\nG91\nM18" },
|
||||
"machine_head_with_fans_polygon":
|
||||
{
|
||||
"default_value": [
|
||||
[-20, 10],
|
||||
[-20, -10],
|
||||
[10, 10],
|
||||
[10, -10]
|
||||
]
|
||||
},
|
||||
"machine_height": { "default_value": 150 },
|
||||
"machine_name": { "default_value": "Adventurer 3C" },
|
||||
"machine_start_gcode": { "default_value": ";Start Gcode\nG28\nM132 X Y Z A B\nG1 Z50.000 F420\nG161 X Y F3300\nM7 T0\nM6 T0\nM651 S255\n;End Start" },
|
||||
"machine_width": { "default_value": 150 },
|
||||
"speed_print": { "maximum_value_warning": 100 }
|
||||
}
|
||||
}
|
33
resources/definitions/flashforge_adventurer4.def.json
Normal file
33
resources/definitions/flashforge_adventurer4.def.json
Normal file
|
@ -0,0 +1,33 @@
|
|||
{
|
||||
"version": 2,
|
||||
"name": "Adventurer 4",
|
||||
"inherits": "flashforge_adventurer_base",
|
||||
"metadata":
|
||||
{
|
||||
"visible": true,
|
||||
"author": "Jeremie-C",
|
||||
"quality_definition": "flashforge_adventurer4",
|
||||
"supports_network_connection": true
|
||||
},
|
||||
"overrides":
|
||||
{
|
||||
"default_material_bed_temperature": { "maximum_value_warning": "110" },
|
||||
"gantry_height": { "value": "250" },
|
||||
"machine_depth": { "default_value": 200 },
|
||||
"machine_end_gcode": { "default_value": ";End Gcode\nM104 S0 T0\nM140 S0 T0\nG162 Z F1800\nG28 X Y\nM132 X Y A B\nM652\nG91\nM18" },
|
||||
"machine_head_with_fans_polygon":
|
||||
{
|
||||
"default_value": [
|
||||
[-20, 10],
|
||||
[-20, -10],
|
||||
[10, 10],
|
||||
[10, -10]
|
||||
]
|
||||
},
|
||||
"machine_height": { "default_value": 250 },
|
||||
"machine_name": { "default_value": "Adventurer 4" },
|
||||
"machine_start_gcode": { "default_value": ";Start Gcode\nG28\nM132 X Y Z A B\nG1 Z50.000 F420\nG161 X Y F3300\nM7 T0\nM6 T0\nM651 S255\n;End Start" },
|
||||
"machine_use_extruder_offset_to_offset_coords": { "default_value": false },
|
||||
"machine_width": { "default_value": 220 }
|
||||
}
|
||||
}
|
14
resources/definitions/flashforge_adventurer4lite.def.json
Normal file
14
resources/definitions/flashforge_adventurer4lite.def.json
Normal file
|
@ -0,0 +1,14 @@
|
|||
{
|
||||
"version": 2,
|
||||
"name": "Adventurer 4 Lite",
|
||||
"inherits": "flashforge_adventurer4",
|
||||
"metadata":
|
||||
{
|
||||
"visible": true,
|
||||
"author": "Jeremie-C"
|
||||
},
|
||||
"overrides":
|
||||
{
|
||||
"machine_name": { "default_value": "Adventurer 4 Lite" }
|
||||
}
|
||||
}
|
34
resources/definitions/flashforge_adventurer_base.def.json
Normal file
34
resources/definitions/flashforge_adventurer_base.def.json
Normal file
|
@ -0,0 +1,34 @@
|
|||
{
|
||||
"version": 2,
|
||||
"name": "Flashforge Adventurer Base",
|
||||
"inherits": "fdmprinter",
|
||||
"metadata":
|
||||
{
|
||||
"visible": false,
|
||||
"author": "Jeremie-C",
|
||||
"manufacturer": "Flashforge",
|
||||
"file_formats": "application/gx;text/x-gcode",
|
||||
"first_start_actions": [ "MachineSettingsAction" ],
|
||||
"has_machine_quality": true,
|
||||
"has_materials": true,
|
||||
"has_variants": true,
|
||||
"machine_extruder_trains": { "0": "flashforge_adventurer_extruder_0" },
|
||||
"preferred_material": "generic_pla",
|
||||
"preferred_quality_type": "normal",
|
||||
"preferred_variant_name": "0.4mm Nozzle",
|
||||
"variants_name": "Nozzle Size"
|
||||
},
|
||||
"overrides":
|
||||
{
|
||||
"adhesion_type": { "default_value": "skirt" },
|
||||
"default_material_print_temperature": { "maximum_value_warning": "265" },
|
||||
"layer_height":
|
||||
{
|
||||
"maximum_value_warning": "0.4",
|
||||
"minimum_value_warning": "0.1"
|
||||
},
|
||||
"machine_center_is_zero": { "default_value": true },
|
||||
"machine_gcode_flavor": { "default_value": "RepRap (Marlin/Sprinter)" },
|
||||
"machine_heated_bed": { "default_value": true }
|
||||
}
|
||||
}
|
|
@ -92,7 +92,6 @@
|
|||
"support_interface_height": { "value": "layer_height * 4" },
|
||||
"support_interface_line_width": { "value": "line_width - 0.1" },
|
||||
"support_interface_pattern": { "value": "'grid'" },
|
||||
"support_interface_skip_height": { "value": 0.2 },
|
||||
"support_pattern": { "value": "'zigzag'" },
|
||||
"support_wall_count": { "value": 1 },
|
||||
"support_xy_distance": { "value": "wall_line_width_0 * 2" },
|
||||
|
|
|
@ -112,7 +112,6 @@
|
|||
"support_interface_density": { "value": 33.333 },
|
||||
"support_interface_height": { "value": "layer_height * 4" },
|
||||
"support_interface_pattern": { "value": "'grid'" },
|
||||
"support_interface_skip_height": { "value": 0.2 },
|
||||
"support_pattern": { "value": "'zigzag'" },
|
||||
"support_wall_count": { "value": 0 },
|
||||
"support_xy_distance": { "value": "wall_line_width_0 * 3" },
|
||||
|
|
|
@ -133,7 +133,6 @@
|
|||
"support_interface_enable": { "value": true },
|
||||
"support_interface_height": { "value": "layer_height * 4" },
|
||||
"support_interface_pattern": { "value": "'grid'" },
|
||||
"support_interface_skip_height": { "value": 0.2 },
|
||||
"support_pattern": { "value": "'zigzag'" },
|
||||
"support_wall_count": { "value": 1 },
|
||||
"support_xy_distance": { "value": "wall_line_width_0 * 2" },
|
||||
|
|
|
@ -70,7 +70,6 @@
|
|||
"support_interface_enable": { "value": true },
|
||||
"support_interface_height": { "value": "layer_height * 4" },
|
||||
"support_interface_pattern": { "value": "'grid'" },
|
||||
"support_interface_skip_height": { "value": 0.2 },
|
||||
"support_pattern": { "value": "'zigzag'" },
|
||||
"support_wall_count": { "value": 1 },
|
||||
"support_xy_distance": { "value": "wall_line_width_0 * 2" },
|
||||
|
|
|
@ -88,7 +88,6 @@
|
|||
"support_interface_enable": { "value": true },
|
||||
"support_interface_height": { "value": "layer_height * 4" },
|
||||
"support_interface_pattern": { "value": "'grid'" },
|
||||
"support_interface_skip_height": { "value": 0.2 },
|
||||
"support_pattern": { "value": "'zigzag'" },
|
||||
"support_wall_count": { "value": 1 },
|
||||
"support_xy_distance": { "value": "wall_line_width_0 * 2" },
|
||||
|
|
|
@ -88,7 +88,6 @@
|
|||
"support_interface_enable": { "value": true },
|
||||
"support_interface_height": { "value": "layer_height * 4" },
|
||||
"support_interface_pattern": { "value": "'grid'" },
|
||||
"support_interface_skip_height": { "value": 0.2 },
|
||||
"support_pattern": { "value": "'zigzag'" },
|
||||
"support_wall_count": { "value": 1 },
|
||||
"support_xy_distance": { "value": "wall_line_width_0 * 2" },
|
||||
|
|
|
@ -109,7 +109,6 @@
|
|||
"support_interface_enable": { "value": true },
|
||||
"support_interface_height": { "value": "layer_height * 4" },
|
||||
"support_interface_pattern": { "value": "'grid'" },
|
||||
"support_interface_skip_height": { "value": 0.2 },
|
||||
"support_pattern": { "value": "'zigzag'" },
|
||||
"support_wall_count": { "value": 1 },
|
||||
"support_xy_distance": { "value": "wall_line_width_0 * 2" },
|
||||
|
|
|
@ -119,7 +119,6 @@
|
|||
"support_interface_enable": { "value": true },
|
||||
"support_interface_height": { "value": "layer_height * 4" },
|
||||
"support_interface_pattern": { "value": "'grid'" },
|
||||
"support_interface_skip_height": { "value": 0.2 },
|
||||
"support_pattern": { "value": "'zigzag'" },
|
||||
"support_wall_count": { "value": 1 },
|
||||
"support_xy_distance": { "value": "wall_line_width_0 * 2" },
|
||||
|
|
19
resources/definitions/ratrig_base.def.json
Normal file
19
resources/definitions/ratrig_base.def.json
Normal file
|
@ -0,0 +1,19 @@
|
|||
{
|
||||
"version": 2,
|
||||
"name": "RatRig Printer",
|
||||
"inherits": "fdmprinter",
|
||||
"metadata":
|
||||
{
|
||||
"visible": false,
|
||||
"author": "nu-hin",
|
||||
"manufacturer": "RatRig",
|
||||
"file_formats": "text/x-gcode",
|
||||
"exclude_materials": [],
|
||||
"first_start_actions": [ "MachineSettingsAction" ],
|
||||
"has_materials": true,
|
||||
"preferred_material": "generic_pla",
|
||||
"preferred_quality_type": "standard",
|
||||
"quality_definition": "ratrig_base",
|
||||
"supported_actions": [ "MachineSettingsAction" ]
|
||||
}
|
||||
}
|
23
resources/definitions/ratrig_vcore3_200.def.json
Normal file
23
resources/definitions/ratrig_vcore3_200.def.json
Normal file
|
@ -0,0 +1,23 @@
|
|||
{
|
||||
"version": 2,
|
||||
"name": "RatRig V-Core 3 200mm",
|
||||
"inherits": "ratrig_vcore3_base",
|
||||
"metadata":
|
||||
{
|
||||
"visible": true,
|
||||
"platform": "ratrig_vcore3_200.stl",
|
||||
"platform_offset": [
|
||||
0,
|
||||
5,
|
||||
0
|
||||
],
|
||||
"weight": 16
|
||||
},
|
||||
"overrides":
|
||||
{
|
||||
"machine_depth": { "default_value": 200 },
|
||||
"machine_height": { "default_value": 200 },
|
||||
"machine_name": { "default_value": "RatRig V-Core 3 200mm" },
|
||||
"machine_width": { "default_value": 200 }
|
||||
}
|
||||
}
|
23
resources/definitions/ratrig_vcore3_300.def.json
Normal file
23
resources/definitions/ratrig_vcore3_300.def.json
Normal file
|
@ -0,0 +1,23 @@
|
|||
{
|
||||
"version": 2,
|
||||
"name": "RatRig V-Core 3 300mm",
|
||||
"inherits": "ratrig_vcore3_base",
|
||||
"metadata":
|
||||
{
|
||||
"visible": true,
|
||||
"platform": "ratrig_vcore3_300.stl",
|
||||
"platform_offset": [
|
||||
0,
|
||||
5,
|
||||
0
|
||||
],
|
||||
"weight": 16
|
||||
},
|
||||
"overrides":
|
||||
{
|
||||
"machine_depth": { "default_value": 300 },
|
||||
"machine_height": { "default_value": 300 },
|
||||
"machine_name": { "default_value": "RatRig V-Core 3 300mm" },
|
||||
"machine_width": { "default_value": 300 }
|
||||
}
|
||||
}
|
23
resources/definitions/ratrig_vcore3_400.def.json
Normal file
23
resources/definitions/ratrig_vcore3_400.def.json
Normal file
|
@ -0,0 +1,23 @@
|
|||
{
|
||||
"version": 2,
|
||||
"name": "RatRig V-Core 3 400mm",
|
||||
"inherits": "ratrig_vcore3_base",
|
||||
"metadata":
|
||||
{
|
||||
"visible": true,
|
||||
"platform": "ratrig_vcore3_400.stl",
|
||||
"platform_offset": [
|
||||
0,
|
||||
3,
|
||||
0
|
||||
],
|
||||
"weight": 16
|
||||
},
|
||||
"overrides":
|
||||
{
|
||||
"machine_depth": { "default_value": 400 },
|
||||
"machine_height": { "default_value": 400 },
|
||||
"machine_name": { "default_value": "RatRig V-Core 3 400mm" },
|
||||
"machine_width": { "default_value": 400 }
|
||||
}
|
||||
}
|
23
resources/definitions/ratrig_vcore3_500.def.json
Normal file
23
resources/definitions/ratrig_vcore3_500.def.json
Normal file
|
@ -0,0 +1,23 @@
|
|||
{
|
||||
"version": 2,
|
||||
"name": "RatRig V-Core 3 500mm",
|
||||
"inherits": "ratrig_vcore3_base",
|
||||
"metadata":
|
||||
{
|
||||
"visible": true,
|
||||
"platform": "ratrig_vcore3_500.stl",
|
||||
"platform_offset": [
|
||||
0,
|
||||
0,
|
||||
0
|
||||
],
|
||||
"weight": 16
|
||||
},
|
||||
"overrides":
|
||||
{
|
||||
"machine_depth": { "default_value": 500 },
|
||||
"machine_height": { "default_value": 500 },
|
||||
"machine_name": { "default_value": "RatRig V-Core 3 500mm" },
|
||||
"machine_width": { "default_value": 500 }
|
||||
}
|
||||
}
|
117
resources/definitions/ratrig_vcore3_base.def.json
Normal file
117
resources/definitions/ratrig_vcore3_base.def.json
Normal file
|
@ -0,0 +1,117 @@
|
|||
{
|
||||
"version": 2,
|
||||
"name": "RatRig V-Core 3",
|
||||
"inherits": "ratrig_base",
|
||||
"metadata":
|
||||
{
|
||||
"visible": false,
|
||||
"has_machine_quality": true,
|
||||
"has_variants": true,
|
||||
"machine_extruder_trains": { "0": "ratrig_base_extruder_0" },
|
||||
"preferred_variant_name": "0.4mm Nozzle",
|
||||
"variants_name": "Nozzle Size"
|
||||
},
|
||||
"overrides":
|
||||
{
|
||||
"acceleration_enabled": { "value": true },
|
||||
"acceleration_layer_0": { "value": "acceleration_topbottom" },
|
||||
"acceleration_roofing": { "enabled": "acceleration_enabled and roofing_layer_count > 0 and top_layers > 0" },
|
||||
"acceleration_topbottom": { "value": "acceleration_print / 3" },
|
||||
"acceleration_travel": { "value": 3000 },
|
||||
"acceleration_travel_layer_0": { "value": "acceleration_travel / 3" },
|
||||
"adaptive_layer_height_variation": { "value": 0.04 },
|
||||
"adaptive_layer_height_variation_step": { "value": 0.04 },
|
||||
"adhesion_type": { "value": "'skirt'" },
|
||||
"brim_replaces_support": { "value": false },
|
||||
"brim_width": { "value": "3" },
|
||||
"cool_fan_full_at_height": { "value": "layer_height_0 + 2 * layer_height" },
|
||||
"cool_min_layer_time": { "value": 2 },
|
||||
"fill_outline_gaps": { "value": false },
|
||||
"filter_out_tiny_gaps": { "value": false },
|
||||
"gantry_height": { "value": 30 },
|
||||
"infill_before_walls": { "value": false },
|
||||
"infill_overlap": { "value": 30 },
|
||||
"infill_pattern": { "value": "'lines' if infill_sparse_density > 50 else 'cubic'" },
|
||||
"infill_wipe_dist": { "value": 0 },
|
||||
"layer_height": { "default_value": 0.2 },
|
||||
"layer_height_0": { "default_value": 0.2 },
|
||||
"machine_acceleration": { "value": 3000 },
|
||||
"machine_end_gcode": { "default_value": "END_PRINT" },
|
||||
"machine_extruder_count": { "default_value": 1 },
|
||||
"machine_head_with_fans_polygon":
|
||||
{
|
||||
"default_value": [
|
||||
[-40, 90],
|
||||
[-40, -30],
|
||||
[40, -30],
|
||||
[40, 90]
|
||||
]
|
||||
},
|
||||
"machine_heated_bed": { "default_value": true },
|
||||
"machine_max_acceleration_e": { "value": 5000 },
|
||||
"machine_max_acceleration_x": { "value": 9000 },
|
||||
"machine_max_acceleration_y": { "value": 9000 },
|
||||
"machine_max_acceleration_z": { "value": 100 },
|
||||
"machine_max_feedrate_e": { "value": 60 },
|
||||
"machine_max_feedrate_x": { "value": 500 },
|
||||
"machine_max_feedrate_y": { "value": 500 },
|
||||
"machine_max_feedrate_z": { "value": 10 },
|
||||
"machine_max_jerk_e": { "value": 5 },
|
||||
"machine_max_jerk_xy": { "value": 5 },
|
||||
"machine_max_jerk_z": { "value": 0.4 },
|
||||
"machine_name": { "default_value": "RatRig V-Core 3" },
|
||||
"machine_shape": { "default_value": "rectangular" },
|
||||
"machine_show_variants": { "default_value": true },
|
||||
"machine_start_gcode": { "default_value": "START_PRINT EXTRUDER_TEMP={material_print_temperature_layer_0} BED_TEMP={material_bed_temperature_layer_0}" },
|
||||
"material_diameter": { "default_value": 1.75 },
|
||||
"material_final_print_temperature": { "value": "material_print_temperature" },
|
||||
"material_initial_print_temperature": { "value": "material_print_temperature" },
|
||||
"meshfix_maximum_resolution": { "value": "0.25" },
|
||||
"meshfix_maximum_travel_resolution": { "value": "meshfix_maximum_resolution" },
|
||||
"minimum_interface_area": { "value": 10 },
|
||||
"minimum_support_area": { "value": 2 },
|
||||
"optimize_wall_printing_order": { "value": true },
|
||||
"retraction_amount": { "value": "machine_nozzle_size * 2" },
|
||||
"retraction_combing": { "value": "'off' if retraction_hop_enabled else 'noskin'" },
|
||||
"retraction_combing_max_distance": { "value": 30 },
|
||||
"retraction_count_max": { "value": 100 },
|
||||
"retraction_extrusion_window": { "value": 10 },
|
||||
"retraction_speed": { "value": 40 },
|
||||
"roofing_layer_count": { "value": 1 },
|
||||
"skin_overlap": { "value": 18 },
|
||||
"skirt_brim_minimal_length": { "default_value": 30 },
|
||||
"skirt_gap": { "value": 10 },
|
||||
"skirt_line_count": { "value": 3 },
|
||||
"speed_layer_0": { "value": "math.floor(speed_print * 3 / 10)" },
|
||||
"speed_print": { "value": 100 },
|
||||
"speed_roofing": { "value": "math.floor(speed_print * 3 / 10)" },
|
||||
"speed_support": { "value": "math.floor(speed_print * 3 / 10)" },
|
||||
"speed_support_interface": { "value": "speed_topbottom" },
|
||||
"speed_topbottom": { "value": "math.floor(speed_print / 2)" },
|
||||
"speed_travel": { "value": 250 },
|
||||
"speed_travel_layer_0": { "value": "100 if speed_layer_0 < 20 else 150 if speed_layer_0 > 30 else speed_layer_0 * 5" },
|
||||
"speed_wall_x": { "value": "speed_wall" },
|
||||
"speed_z_hop": { "value": 5 },
|
||||
"support_angle": { "value": "math.floor(math.degrees(math.atan(line_width/2.0/layer_height)))" },
|
||||
"support_brim_width": { "value": 4 },
|
||||
"support_infill_rate": { "value": "0 if support_enable and support_structure == 'tree' else 20" },
|
||||
"support_interface_density": { "value": 33.333 },
|
||||
"support_interface_enable": { "value": true },
|
||||
"support_interface_height": { "value": "layer_height * 4" },
|
||||
"support_interface_pattern": { "value": "'grid'" },
|
||||
"support_pattern": { "value": "'zigzag'" },
|
||||
"support_use_towers": { "value": false },
|
||||
"support_xy_distance": { "value": "wall_line_width_0 * 2" },
|
||||
"support_xy_distance_overhang": { "value": "wall_line_width_0" },
|
||||
"support_xy_overrides_z": { "value": "'xy_overrides_z'" },
|
||||
"support_z_distance": { "value": "layer_height if layer_height >= 0.16 else layer_height * 2" },
|
||||
"top_bottom_pattern": { "value": "'lines'" },
|
||||
"top_bottom_thickness": { "value": "layer_height_0 + layer_height * 3" },
|
||||
"travel_avoid_supports": { "value": true },
|
||||
"travel_retract_before_outer_wall": { "value": true },
|
||||
"wall_0_wipe_dist": { "value": 0 },
|
||||
"wall_thickness": { "value": "line_width * 2" },
|
||||
"z_seam_corner": { "value": "'z_seam_corner_weighted'" },
|
||||
"z_seam_type": { "value": "'back'" }
|
||||
}
|
||||
}
|
128
resources/definitions/ratrig_vminion.def.json
Normal file
128
resources/definitions/ratrig_vminion.def.json
Normal file
|
@ -0,0 +1,128 @@
|
|||
{
|
||||
"version": 2,
|
||||
"name": "RatRig V-Minion",
|
||||
"inherits": "ratrig_base",
|
||||
"metadata":
|
||||
{
|
||||
"visible": true,
|
||||
"platform": "ratrig_vminion.stl",
|
||||
"has_machine_quality": true,
|
||||
"has_variants": true,
|
||||
"machine_extruder_trains": { "0": "ratrig_base_extruder_0" },
|
||||
"platform_offset": [
|
||||
0,
|
||||
5,
|
||||
0
|
||||
],
|
||||
"preferred_variant_name": "0.4mm Nozzle",
|
||||
"variants_name": "Nozzle Size",
|
||||
"weight": 8
|
||||
},
|
||||
"overrides":
|
||||
{
|
||||
"acceleration_enabled": { "value": true },
|
||||
"acceleration_layer_0": { "value": "acceleration_topbottom" },
|
||||
"acceleration_roofing": { "enabled": "acceleration_enabled and roofing_layer_count > 0 and top_layers > 0" },
|
||||
"acceleration_topbottom": { "value": "acceleration_print / 3" },
|
||||
"acceleration_travel": { "value": 3000 },
|
||||
"acceleration_travel_layer_0": { "value": "acceleration_travel / 3" },
|
||||
"adaptive_layer_height_variation": { "value": 0.04 },
|
||||
"adaptive_layer_height_variation_step": { "value": 0.04 },
|
||||
"adhesion_type": { "value": "'skirt'" },
|
||||
"brim_replaces_support": { "value": false },
|
||||
"brim_width": { "value": "3" },
|
||||
"cool_fan_full_at_height": { "value": "layer_height_0 + 2 * layer_height" },
|
||||
"cool_min_layer_time": { "value": 2 },
|
||||
"fill_outline_gaps": { "value": false },
|
||||
"filter_out_tiny_gaps": { "value": false },
|
||||
"gantry_height": { "value": 30 },
|
||||
"infill_before_walls": { "value": false },
|
||||
"infill_overlap": { "value": 30 },
|
||||
"infill_pattern": { "value": "'lines' if infill_sparse_density > 50 else 'cubic'" },
|
||||
"infill_wipe_dist": { "value": 0 },
|
||||
"layer_height": { "default_value": 0.2 },
|
||||
"layer_height_0": { "default_value": 0.2 },
|
||||
"machine_acceleration": { "value": 3000 },
|
||||
"machine_depth": { "default_value": 180 },
|
||||
"machine_end_gcode": { "default_value": "END_PRINT" },
|
||||
"machine_extruder_count": { "default_value": 1 },
|
||||
"machine_head_with_fans_polygon":
|
||||
{
|
||||
"default_value": [
|
||||
[-40, 90],
|
||||
[-40, -30],
|
||||
[40, -30],
|
||||
[40, 90]
|
||||
]
|
||||
},
|
||||
"machine_heated_bed": { "default_value": true },
|
||||
"machine_height": { "default_value": 180 },
|
||||
"machine_max_acceleration_e": { "value": 5000 },
|
||||
"machine_max_acceleration_x": { "value": 9000 },
|
||||
"machine_max_acceleration_y": { "value": 9000 },
|
||||
"machine_max_acceleration_z": { "value": 100 },
|
||||
"machine_max_feedrate_e": { "value": 60 },
|
||||
"machine_max_feedrate_x": { "value": 500 },
|
||||
"machine_max_feedrate_y": { "value": 500 },
|
||||
"machine_max_feedrate_z": { "value": 10 },
|
||||
"machine_max_jerk_e": { "value": 5 },
|
||||
"machine_max_jerk_xy": { "value": 5 },
|
||||
"machine_max_jerk_z": { "value": 0.4 },
|
||||
"machine_name": { "default_value": "RatRig V-Minion" },
|
||||
"machine_shape": { "default_value": "rectangular" },
|
||||
"machine_show_variants": { "default_value": true },
|
||||
"machine_start_gcode": { "default_value": "START_PRINT EXTRUDER_TEMP={material_print_temperature_layer_0} BED_TEMP={material_bed_temperature_layer_0}" },
|
||||
"machine_width": { "default_value": 180 },
|
||||
"material_diameter": { "default_value": 1.75 },
|
||||
"material_final_print_temperature": { "value": "material_print_temperature" },
|
||||
"material_initial_print_temperature": { "value": "material_print_temperature" },
|
||||
"meshfix_maximum_resolution": { "value": "0.25" },
|
||||
"meshfix_maximum_travel_resolution": { "value": "meshfix_maximum_resolution" },
|
||||
"minimum_interface_area": { "value": 10 },
|
||||
"minimum_support_area": { "value": 2 },
|
||||
"optimize_wall_printing_order": { "value": true },
|
||||
"retraction_amount": { "value": "machine_nozzle_size * 2" },
|
||||
"retraction_combing": { "value": "'off' if retraction_hop_enabled else 'noskin'" },
|
||||
"retraction_combing_max_distance": { "value": 30 },
|
||||
"retraction_count_max": { "value": 100 },
|
||||
"retraction_extrusion_window": { "value": 10 },
|
||||
"retraction_speed": { "value": 40 },
|
||||
"roofing_layer_count": { "value": 1 },
|
||||
"skin_overlap": { "value": 18 },
|
||||
"skirt_brim_minimal_length": { "default_value": 30 },
|
||||
"skirt_gap": { "value": 10 },
|
||||
"skirt_line_count": { "value": 3 },
|
||||
"speed_layer_0": { "value": "math.floor(speed_print * 3 / 10)" },
|
||||
"speed_print": { "value": 100 },
|
||||
"speed_roofing": { "value": "math.floor(speed_print * 3 / 10)" },
|
||||
"speed_support": { "value": "math.floor(speed_print * 3 / 10)" },
|
||||
"speed_support_interface": { "value": "speed_topbottom" },
|
||||
"speed_topbottom": { "value": "math.floor(speed_print / 2)" },
|
||||
"speed_travel": { "value": 250 },
|
||||
"speed_travel_layer_0": { "value": "100 if speed_layer_0 < 20 else 150 if speed_layer_0 > 30 else speed_layer_0 * 5" },
|
||||
"speed_wall": { "value": "math.floor(speed_print / 2)" },
|
||||
"speed_wall_x": { "value": "speed_wall" },
|
||||
"speed_z_hop": { "value": 5 },
|
||||
"support_angle": { "value": "math.floor(math.degrees(math.atan(line_width/2.0/layer_height)))" },
|
||||
"support_brim_width": { "value": 4 },
|
||||
"support_infill_rate": { "value": "0 if support_enable and support_structure == 'tree' else 20" },
|
||||
"support_interface_density": { "value": 33.333 },
|
||||
"support_interface_enable": { "value": true },
|
||||
"support_interface_height": { "value": "layer_height * 4" },
|
||||
"support_interface_pattern": { "value": "'grid'" },
|
||||
"support_pattern": { "value": "'zigzag'" },
|
||||
"support_use_towers": { "value": false },
|
||||
"support_xy_distance": { "value": "wall_line_width_0 * 2" },
|
||||
"support_xy_distance_overhang": { "value": "wall_line_width_0" },
|
||||
"support_xy_overrides_z": { "value": "'xy_overrides_z'" },
|
||||
"support_z_distance": { "value": "layer_height if layer_height >= 0.16 else layer_height * 2" },
|
||||
"top_bottom_pattern": { "value": "'lines'" },
|
||||
"top_bottom_thickness": { "value": "layer_height_0 + layer_height * 3" },
|
||||
"travel_avoid_supports": { "value": true },
|
||||
"travel_retract_before_outer_wall": { "value": true },
|
||||
"wall_0_wipe_dist": { "value": 0 },
|
||||
"wall_thickness": { "value": "line_width * 2" },
|
||||
"z_seam_corner": { "value": "'z_seam_corner_weighted'" },
|
||||
"z_seam_type": { "value": "'back'" }
|
||||
}
|
||||
}
|
|
@ -70,7 +70,6 @@
|
|||
"support_interface_enable": { "value": true },
|
||||
"support_interface_height": { "value": "layer_height * 4" },
|
||||
"support_interface_pattern": { "value": "'grid'" },
|
||||
"support_interface_skip_height": { "value": 0.2 },
|
||||
"support_pattern": { "value": "'zigzag'" },
|
||||
"support_wall_count": { "value": 1 },
|
||||
"support_xy_distance": { "value": "wall_line_width_0 * 2" },
|
||||
|
|
|
@ -111,7 +111,6 @@
|
|||
"support_interface_density": { "value": 33.333 },
|
||||
"support_interface_height": { "value": "layer_height * 4" },
|
||||
"support_interface_pattern": { "value": "'grid'" },
|
||||
"support_interface_skip_height": { "value": 0.2 },
|
||||
"support_pattern": { "value": "'zigzag'" },
|
||||
"support_wall_count": { "value": "1 if (support_structure == 'tree') else 0" },
|
||||
"support_xy_distance": { "value": "wall_line_width_0 * 3" },
|
||||
|
|
|
@ -68,7 +68,6 @@
|
|||
"support_interface_density": { "value": 33.333 },
|
||||
"support_interface_height": { "value": "layer_height * 4" },
|
||||
"support_interface_pattern": { "value": "'grid'" },
|
||||
"support_interface_skip_height": { "value": 0.2 },
|
||||
"support_pattern": { "value": "'zigzag'" },
|
||||
"support_wall_count": { "value": "1 if (support_structure == 'tree') else 0" },
|
||||
"support_xy_distance": { "value": "wall_line_width_0 * 2" },
|
||||
|
|
|
@ -99,7 +99,7 @@
|
|||
"acceleration_print":
|
||||
{
|
||||
"enabled": false,
|
||||
"value": 300
|
||||
"value": 800
|
||||
},
|
||||
"acceleration_print_layer_0":
|
||||
{
|
||||
|
@ -234,7 +234,7 @@
|
|||
"jerk_print":
|
||||
{
|
||||
"enabled": false,
|
||||
"value": 12.5
|
||||
"value": 6.25
|
||||
},
|
||||
"jerk_print_layer_0":
|
||||
{
|
||||
|
@ -279,7 +279,7 @@
|
|||
"jerk_travel":
|
||||
{
|
||||
"enabled": false,
|
||||
"value": 12.5
|
||||
"value": "jerk_print"
|
||||
},
|
||||
"jerk_travel_enabled":
|
||||
{
|
||||
|
@ -354,14 +354,17 @@
|
|||
"print_sequence": { "enabled": false },
|
||||
"raft_base_line_spacing": { "value": "2*raft_base_line_width" },
|
||||
"raft_base_line_width": { "value": 1.4 },
|
||||
"raft_base_speed": { "value": 5 },
|
||||
"raft_base_speed": { "value": 10 },
|
||||
"raft_base_thickness": { "value": 0.8 },
|
||||
"raft_interface_extruder_nr": { "value": "raft_surface_extruder_nr" },
|
||||
"raft_interface_layers": { "value": 2 },
|
||||
"raft_interface_line_width": { "value": 1.2 },
|
||||
"raft_interface_line_width": { "value": 0.7 },
|
||||
"raft_interface_speed": { "value": 90 },
|
||||
"raft_interface_thickness": { "value": 0.3 },
|
||||
"raft_margin": { "value": 3 },
|
||||
"raft_interface_wall_count": { "value": "raft_wall_count" },
|
||||
"raft_margin": { "value": 1.2 },
|
||||
"raft_surface_extruder_nr": { "value": "int(anyExtruderWithMaterial('material_is_support_material')) if support_enable and extruderValue(support_extruder_nr,'material_is_support_material') else raft_base_extruder_nr" },
|
||||
"raft_surface_wall_count": { "value": "raft_wall_count" },
|
||||
"retraction_amount": { "value": 0.75 },
|
||||
"retraction_combing": { "value": "'off'" },
|
||||
"retraction_combing_max_distance": { "value": "speed_travel / 10" },
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue