From e01b1406e31c87b580f0f9640d0cabe440473dc7 Mon Sep 17 00:00:00 2001 From: GregValiant <64202104+GregValiant@users.noreply.github.com> Date: Thu, 29 Jun 2023 17:08:41 -0400 Subject: [PATCH 01/54] Update LimitXYAccelJerk.py Added Gradual Accel Change. Update LimitXYAccelJerk.py Round the Accel numbers to nearest "50". Create LimitXYAccelJerk.py New post processor to limit the X and or Y accel and jerk for bed-slinger printers. Update LimitXYAccelJerk.py Removed debug code. Update LimitXYAccelJerk.py Remove debug code Update LimitXYAccelJerk.py Bug Fix --- .../scripts/LimitXYAccelJerk.py | 273 ++++++++++++++++++ 1 file changed, 273 insertions(+) create mode 100644 plugins/PostProcessingPlugin/scripts/LimitXYAccelJerk.py diff --git a/plugins/PostProcessingPlugin/scripts/LimitXYAccelJerk.py b/plugins/PostProcessingPlugin/scripts/LimitXYAccelJerk.py new file mode 100644 index 00000000000..8932d8e4ea4 --- /dev/null +++ b/plugins/PostProcessingPlugin/scripts/LimitXYAccelJerk.py @@ -0,0 +1,273 @@ +# Limit XY Accel: Authored by: Greg Foresi (GregValiant) +# July 2023 +# Sometimes bed-slinger printers need different Accel and Jerk values for the Y but Cura always makes them the same. +# This script changes the Accel and/or Jerk from the beginning of the 'Start Layer' to the end of the 'End Layer'. +# The existing M201 Max Accel will be changed to limit the Y (and/or X) accel at the printer. If you have Accel enabled in Cura and the XY Accel is set to 3000 then setting the Y limit to 1000 will result in the printer limiting the Y to 1000. This can keep tall skinny prints from breaking loose of the bed and failing. The script was not tested with Junction Deviation. +# If enabled - the Jerk setting is changed line-by-line within the gcode as there is no "limit" on Jerk. +# if 'Gradual ACCEL change' is enabled then the Accel is changed gradually from the Start to the End layer and that will be the final Accel setting in the file. If 'Gradual' is enabled then the Jerk settings will continue to be changed to the end of the file (rather than ending at the End layer). + +from ..Script import Script +from cura.CuraApplication import CuraApplication +import re + +class LimitXYAccelJerk(Script): + def __init__(self): + super().__init__() + + def initialize(self) -> None: + super().initialize() + # Get the Accel and Jerk and set the values in the setting boxes--------------------------------------------- + mycura = CuraApplication.getInstance().getGlobalContainerStack() + extruder = mycura.extruderList + accel_print = extruder[0].getProperty("acceleration_print", "value") + accel_travel = extruder[0].getProperty("acceleration_travel", "value") + jerk_print_old = extruder[0].getProperty("jerk_print", "value") + jerk_travel_old = extruder[0].getProperty("jerk_travel", "value") + self._instance.setProperty("X_accel_limit", "value", round(accel_print)) + self._instance.setProperty("Y_accel_limit", "value", round(accel_print)) + self._instance.setProperty("X_jerk", "value", jerk_print_old) + self._instance.setProperty("Y_jerk", "value", jerk_print_old) + + def getSettingDataString(self): + return """{ + "name": "Limit the X-Y Accel/Jerk", + "key": "LimitXYAccelJerk", + "metadata": {}, + "version": 2, + "settings": + { + "X_accel_limit": + { + "label": "X MAX Acceleration", + "description": "If this number is lower than the 'X Print Accel' in Cura then this will limit the Accel on the X axis. Enter the Maximum Acceleration value for the X axis. This will affect both Print and Travel Accel. If you enable an End Layer then at the end of that layer the Accel Limit will be reset (unless you choose 'Gradual' in which case the new limit goes to the top layer).", + "type": "int", + "enabled": true, + "minimum_value": 50, + "unit": "mm/sec² ", + "default_value": 500 + }, + "Y_accel_limit": + { + "label": "Y MAX Acceleration", + "description": "If this number is lower than the Y accel in Cura then this will limit the Accel on the Y axis. Enter the Maximum Acceleration value for the Y axis. This will affect both Print and Travel Accel. If you enable an End Layer then at the end of that layer the Accel Limit will be reset (unless you choose 'Gradual' in which case the new limit goes to the top layer).", + "type": "int", + "enabled": true, + "minimum_value": 50, + "unit": "mm/sec² ", + "default_value": 500 + }, + "jerk_enable": + { + "label": "Change the Jerk", + "description": "Whether to change the Jerk values.", + "type": "bool", + "enabled": true, + "default_value": false + }, + "X_jerk": + { + "label": " X jerk", + "description": "Enter the Jerk value for the X axis. Enter '0' to use the existing X Jerk. This setting will affect both the Print and Travel jerk.", + "type": "int", + "enabled": "jerk_enable", + "unit": "mm/sec ", + "default_value": 8 + }, + "Y_jerk": + { + "label": " Y jerk", + "description": "Enter the Jerk value for the Y axis. Enter '0' to use the existing Y Jerk. This setting will affect both the Print and Travel jerk.", + "type": "int", + "enabled": "jerk_enable", + "unit": "mm/sec ", + "default_value": 8 + }, + "start_layer": + { + "label": "From Start of Layer:", + "description": "Use the Cura Preview numbers. Enter the Layer to start the changes at. The minimum is Layer 1.", + "type": "int", + "default_value": 1, + "minimum_value": 1, + "unit": "Lay# ", + "enabled": "not gradient_change" + }, + "end_layer": + { + "label": "To End of Layer", + "description": "Use the Cura Preview numbers. Enter '-1' for the entire file or enter a layer number. The changes will end at your 'End Layer' and revert back to the original numbers.", + "type": "int", + "default_value": -1, + "minimum_value": -1, + "unit": "Lay# ", + "enabled": "not gradient_change" + }, + "gradient_change": + { + "label": "Gradual ACCEL Change", + "description": "Gradually change the Accel numbers 'From layer' - 'To Layer'. If Jerk is enabled the Jerk changes are not 'Gradual' because there is no Max Jerk setting. Unlike Constant change - using 'Gradual' the Accel and Jerk change continues from the End Layer to the end of the file.", + "type": "bool", + "default_value": false, + "enabled": true + }, + "gradient_start_layer": + { + "label": " Gradual From Layer:", + "description": "Use the Cura Preview numbers. Enter the Layer to start the changes at. The minimum is Layer 1.", + "type": "int", + "default_value": 1, + "minimum_value": 1, + "unit": "Lay# ", + "enabled": "gradient_change" + }, + "gradient_end_layer": + { + "label": " Gradual To Layer", + "description": "Use the Cura Preview numbers. Enter '-1' for the top layer or enter a layer number. The last 'Gradual' change will continue to the end of the file.", + "type": "int", + "default_value": -1, + "minimum_value": -1, + "unit": "Lay# ", + "enabled": "gradient_change" + } + } + }""" + + def execute(self, data): + mycura = CuraApplication.getInstance().getGlobalContainerStack() + extruder = mycura.extruderList + constant_change = not bool(self.getSettingValueByKey("gradient_change")) + accel_print_enabled = bool(extruder[0].getProperty("acceleration_enabled", "value")) + accel_travel_enabled = bool(extruder[0].getProperty("acceleration_travel_enabled", "value")) + accel_print = extruder[0].getProperty("acceleration_print", "value") + accel_travel = extruder[0].getProperty("acceleration_travel", "value") + jerk_print_enabled = str(extruder[0].getProperty("jerk_enabled", "value")) + jerk_travel_enabled = str(extruder[0].getProperty("jerk_travel_enabled", "value")) + jerk_print_old = extruder[0].getProperty("jerk_print", "value") + jerk_travel_old = extruder[0].getProperty("jerk_travel", "value") + if int(accel_print) >= int(accel_travel): + accel_old = accel_print + else: + accel_old = accel_travel + jerk_travel = str(extruder[0].getProperty("jerk_travel", "value")) + if int(jerk_print_old) >= int(jerk_travel_old): + jerk_old = jerk_print_old + else: + jerk_old = jerk_travel_old + + #Set the new Accel values--------------------------------------------------------------------------------- + x_accel = str(self.getSettingValueByKey("X_accel_limit")) + y_accel = str(self.getSettingValueByKey("Y_accel_limit")) + x_jerk = int(self.getSettingValueByKey("X_jerk")) + y_jerk = int(self.getSettingValueByKey("Y_jerk")) + # Put the strings together + M201_limit_new = "M201 X" + x_accel + " Y" + y_accel + M201_limit_old = "M201 X" + str(round(accel_old)) + " Y" + str(round(accel_old)) + if x_jerk == 0: + M205_jerk_pattern = "Y(\d*)" + M205_jerk_new = "Y" + str(y_jerk) + if y_jerk == 0: + M205_jerk_pattern = "X(\d*)" + M205_jerk_new = "X" + str(x_jerk) + if x_jerk != 0 and y_jerk != 0: + M205_jerk_pattern = "M205 X(\d*) Y(\d*)" + M205_jerk_new = "M205 X" + str(x_jerk) + " Y" + str(y_jerk) + M205_jerk_old = "M205 X" + str(jerk_old) + " Y" + str(jerk_old) + + #Get the indexes of the start and end layers---------------------------------------- + if constant_change: + start_layer = int(self.getSettingValueByKey("start_layer"))-1 + end_layer = int(self.getSettingValueByKey("end_layer")) + else: + start_layer = int(self.getSettingValueByKey("gradient_start_layer"))-1 + end_layer = int(self.getSettingValueByKey("gradient_end_layer")) + start_index = 2 + end_index = len(data)-2 + for num in range(2,len(data)-1): + if ";LAYER:" + str(start_layer) + "\n" in data[num]: + start_index = num + break + if int(end_layer) > 0: + for num in range(3,len(data)-1): + try: + if ";LAYER:" + str(end_layer) + "\n" in data[num]: + end_index = num + break + except: + end_index = len(data)-2 + + #Add Accel limit and new Jerk at start layer----------------------------------------------------- + if constant_change: + layer = data[start_index] + lines = layer.split("\n") + for index, line in enumerate(lines): + if lines[index].startswith(";LAYER:"): + lines.insert(index+1,M201_limit_new) + if self.getSettingValueByKey("jerk_enable"): + lines.insert(index+2,M205_jerk_new) + data[start_index] = "\n".join(lines) + break + + #Alter any existing jerk lines. Accel lines can be ignored----------------------------------- + for num in range(start_index,end_index,1): + layer = data[num] + lines = layer.split("\n") + for index, line in enumerate(lines): + if line.startswith("M205"): + lines[index] = re.sub(M205_jerk_pattern, M205_jerk_new, line) + data[num] = "\n".join(lines) + if end_layer != -1: + try: + layer = data[end_index-1] + lines = layer.split("\n") + lines.insert(len(lines)-2,M201_limit_old) + lines.insert(len(lines)-2,M205_jerk_old) + data[end_index-1] = "\n".join(lines) + except: + all + else: + data[len(data)-1] = M201_limit_old + "\n" + M205_jerk_old + "\n" + data[len(data)-1] + return data + + + elif not constant_change: + layer_spread = end_index - start_index + x_accel_hyst = round((accel_old - int(x_accel)) / layer_spread) + y_accel_hyst = round((accel_old - int(y_accel)) / layer_spread) + x_accel_start = round(round((accel_old - x_accel_hyst)/50)*50) + y_accel_start = round(round((accel_old - y_accel_hyst)/50)*50) + M201_limit_new = "M201 X" + str(x_accel_start) + " Y" + str(y_accel_start) + #Add Accel limit and new Jerk at start layer------------------------------------------------------------- + layer = data[start_index] + lines = layer.split("\n") + for index, line in enumerate(lines): + if lines[index].startswith(";LAYER:"): + lines.insert(index+1,M201_limit_new) + if self.getSettingValueByKey("jerk_enable"): + lines.insert(index+2,M205_jerk_new) + data[start_index] = "\n".join(lines) + break + for num in range(start_index + 1, end_index,1): + layer = data[num] + lines = layer.split("\n") + x_accel_start -= x_accel_hyst + if x_accel_start < int(x_accel): x_accel_start = int(x_accel) + y_accel_start -= y_accel_hyst + if y_accel_start < int(y_accel): y_accel_start = int(y_accel) + M201_limit_new = "M201 X" + str(round(round(x_accel_start/50)*50)) + " Y" + str(round(round(y_accel_start/50)*50)) + for index, line in enumerate(lines): + if line.startswith(";LAYER:"): + lines.insert(index+1, M201_limit_new) + continue + data[num] = "\n".join(lines) + #Alter any existing jerk lines. Accel lines can be ignored----------------------------------- + if self.getSettingValueByKey("jerk_enable"): + for num in range(start_index,len(data)-1,1): + layer = data[num] + lines = layer.split("\n") + for index, line in enumerate(lines): + if line.startswith("M205"): + lines[index] = re.sub(M205_jerk_pattern, M205_jerk_new, line) + data[num] = "\n".join(lines) + data[len(data)-1] = M201_limit_old + "\n" + M205_jerk_old + "\n" + data[len(data)-1] + return data \ No newline at end of file From fc159a2f5d56cb7ef01fa488802bffc4371cf63d Mon Sep 17 00:00:00 2001 From: Jelle Spijker Date: Sat, 19 Aug 2023 01:56:23 +0200 Subject: [PATCH 02/54] Also make sure that the packaging tools can be run Contributes to CURA-8415 --- .github/workflows/macos.yml | 22 ++++++++++++++++++---- .github/workflows/windows.yml | 30 +++++++++++++++++++++++++----- 2 files changed, 43 insertions(+), 9 deletions(-) diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml index 4c77692cff1..1b8eab877f3 100644 --- a/.github/workflows/macos.yml +++ b/.github/workflows/macos.yml @@ -242,27 +242,39 @@ jobs: f.writelines(f"`{package.key}/{package.version}`\n") - name: Archive the artifacts (bash) - run: tar -zcf "./${{ steps.filename.outputs.INSTALLER_FILENAME }}.tar.gz" "./dist/" + run: | + tar -zcf "./${{ steps.filename.outputs.INSTALLER_FILENAME }}.tar.gz" "./dist/" + tar -zcf "./${{ steps.filename.outputs.INSTALLER_FILENAME }}-package.tar.gz" "./cura_inst/packaging/" - - name: upload the tarred dist folder + - name: upload the tarred dist and packaging folder uses: actions/upload-artifact@v3 with: name: dist path: | ${{ steps.filename.outputs.INSTALLER_FILENAME }}.tar.gz + ${{ steps.filename.outputs.INSTALLER_FILENAME }}-package.tar.gz retention-days: 5 cura-installer-create-dmg: needs: [ cura-installer-create ] runs-on: macos-11 steps: + - name: Setup Python and pip + uses: actions/setup-python@v4 + with: + python-version: '3.10.x' + cache: 'pip' + cache-dependency-path: .github/workflows/requirements-conan-package.txt + - name: Download the dist uses: actions/download-artifact@v3 with: name: dist - name: untar the dist folder - run: tar -zxf "./${{ needs.cura-installer-create.outputs.INSTALLER_FILENAME }}.tar.gz" + run: | + tar -zxf "./${{ needs.cura-installer-create.outputs.INSTALLER_FILENAME }}.tar.gz" + tar -zxf "./${{ needs.cura-installer-create.outputs.INSTALLER_FILENAME }}-package.tar.gz" - name: Remove Macos keychain (Bash) run: security delete-keychain signing_temp.keychain || true @@ -309,7 +321,9 @@ jobs: name: dist - name: untar the dist folder - run: tar -zxf "./${{ needs.cura-installer-create.outputs.INSTALLER_FILENAME }}.tar.gz" + run: | + tar -zxf "./${{ needs.cura-installer-create.outputs.INSTALLER_FILENAME }}.tar.gz" + tar -zxf "./${{ needs.cura-installer-create.outputs.INSTALLER_FILENAME }}-package.tar.gz" - name: Remove Macos keychain (Bash) run: security delete-keychain signing_temp.keychain || true diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml index f335605b910..37f79751297 100644 --- a/.github/workflows/windows.yml +++ b/.github/workflows/windows.yml @@ -199,29 +199,40 @@ jobs: for package in pkg_resources.working_set: f.writelines(f"`{package.key}/{package.version}`\n") - - name: Archive the artifacts (Powershell) - run: Compress-Archive -Path ".\dist" -DestinationPath ".\${{ steps.filename.outputs.INSTALLER_FILENAME }}.zip" + run: | + Compress-Archive -Path ".\dist" -DestinationPath ".\${{ steps.filename.outputs.INSTALLER_FILENAME }}.zip" + Compress-Archive -Path ".\cura_inst\packaging\" -DestinationPath ".\${{ steps.filename.outputs.INSTALLER_FILENAME }}-packaging.zip" - - name: upload the zipped dist folder + - name: upload the zipped dist and packaging folder uses: actions/upload-artifact@v3 with: name: dist path: | ${{ steps.filename.outputs.INSTALLER_FILENAME }}.zip + ${{ steps.filename.outputs.INSTALLER_FILENAME }}-packaging.zip retention-days: 5 cura-installer-create-exe: needs: [ cura-installer-create ] runs-on: ${{ inputs.operating_system }} steps: + - name: Setup Python and pip + uses: actions/setup-python@v4 + with: + python-version: '3.10.x' + cache: 'pip' + cache-dependency-path: .github/workflows/requirements-conan-package.txt + - name: Download the zipped dist uses: actions/download-artifact@v3 with: name: dist - name: Extract the zipped dist - run: Expand-Archive -Path ".\${{ needs.cura-installer-create.outputs.INSTALLER_FILENAME }}.zip" -DestinationPath "." + run: | + Expand-Archive -Path ".\${{ needs.cura-installer-create.outputs.INSTALLER_FILENAME }}.zip" -DestinationPath "." + Expand-Archive -Path ".\${{ needs.cura-installer-create.outputs.INSTALLER_FILENAME }}-packaging.zip" -DestinationPath "." shell: powershell - name: Create PFX certificate from BASE64_PFX_CONTENT secret @@ -258,13 +269,22 @@ jobs: needs: [ cura-installer-create ] runs-on: ${{ inputs.operating_system }} steps: + - name: Setup Python and pip + uses: actions/setup-python@v4 + with: + python-version: '3.10.x' + cache: 'pip' + cache-dependency-path: .github/workflows/requirements-conan-package.txt + - name: Download the dist uses: actions/download-artifact@v3 with: name: dist - name: Extract the zipped dist - run: Expand-Archive -Path ".\${{ needs.cura-installer-create.outputs.INSTALLER_FILENAME }}.zip" -DestinationPath "." + run: | + Expand-Archive -Path ".\${{ needs.cura-installer-create.outputs.INSTALLER_FILENAME }}.zip" -DestinationPath "." + Expand-Archive -Path ".\${{ needs.cura-installer-create.outputs.INSTALLER_FILENAME }}-packaging.zip" -DestinationPath "." shell: powershell - name: Create PFX certificate from BASE64_PFX_CONTENT secret From 05ded4885e8dcbe26635d747b1861919273dbcea Mon Sep 17 00:00:00 2001 From: Jelle Spijker Date: Sat, 19 Aug 2023 02:00:53 +0200 Subject: [PATCH 03/54] inherit secrets Contributes to CURA-8415 --- .github/workflows/installers.yml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/.github/workflows/installers.yml b/.github/workflows/installers.yml index 283fc76ee58..ead3b7a87a4 100644 --- a/.github/workflows/installers.yml +++ b/.github/workflows/installers.yml @@ -35,6 +35,7 @@ jobs: staging: ${{ inputs.staging }} architecture: X64 operating_system: windows-2022 + secrets: inherit linux-modern-installer: uses: ./.github/workflows/linux.yml @@ -45,6 +46,7 @@ jobs: staging: ${{ inputs.staging }} architecture: X64 operating_system: ubuntu-22.04 + secrets: inherit linux-legacy-installer: uses: ./.github/workflows/linux.yml @@ -55,6 +57,7 @@ jobs: staging: ${{ inputs.staging }} architecture: X64 operating_system: ubuntu-20.04 + secrets: inherit macos-installer: uses: ./.github/workflows/macos.yml @@ -65,6 +68,7 @@ jobs: staging: ${{ inputs.staging }} architecture: X64 operating_system: macos-11.0 + secrets: inherit macos-arm-installer: uses: ./.github/workflows/macos.yml @@ -74,4 +78,5 @@ jobs: enterprise: ${{ inputs.enterprise }} staging: ${{ inputs.staging }} architecture: ARM64 - operating_system: self-hosted \ No newline at end of file + operating_system: self-hosted + secrets: inherit \ No newline at end of file From cf97b97d9e6bdbd62f64f312b3383957f6f4cd29 Mon Sep 17 00:00:00 2001 From: Jelle Spijker Date: Sat, 19 Aug 2023 02:13:25 +0200 Subject: [PATCH 04/54] don't cache pip Contributes to CURA-8415 --- .github/workflows/macos.yml | 9 ++++++--- .github/workflows/windows.yml | 8 ++------ 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml index 1b8eab877f3..418e99c4702 100644 --- a/.github/workflows/macos.yml +++ b/.github/workflows/macos.yml @@ -259,12 +259,10 @@ jobs: needs: [ cura-installer-create ] runs-on: macos-11 steps: - - name: Setup Python and pip + - name: Setup Python uses: actions/setup-python@v4 with: python-version: '3.10.x' - cache: 'pip' - cache-dependency-path: .github/workflows/requirements-conan-package.txt - name: Download the dist uses: actions/download-artifact@v3 @@ -315,6 +313,11 @@ jobs: needs: [ cura-installer-create ] runs-on: macos-11 steps: + - name: Setup Python + uses: actions/setup-python@v4 + with: + python-version: '3.10.x' + - name: Download the dist uses: actions/download-artifact@v3 with: diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml index 37f79751297..8c5cad9d68b 100644 --- a/.github/workflows/windows.yml +++ b/.github/workflows/windows.yml @@ -217,12 +217,10 @@ jobs: needs: [ cura-installer-create ] runs-on: ${{ inputs.operating_system }} steps: - - name: Setup Python and pip + - name: Setup Python uses: actions/setup-python@v4 with: python-version: '3.10.x' - cache: 'pip' - cache-dependency-path: .github/workflows/requirements-conan-package.txt - name: Download the zipped dist uses: actions/download-artifact@v3 @@ -269,12 +267,10 @@ jobs: needs: [ cura-installer-create ] runs-on: ${{ inputs.operating_system }} steps: - - name: Setup Python and pip + - name: Setup Python uses: actions/setup-python@v4 with: python-version: '3.10.x' - cache: 'pip' - cache-dependency-path: .github/workflows/requirements-conan-package.txt - name: Download the dist uses: actions/download-artifact@v3 From deffdeb6427c1d4153851286ffe1f690554af6b0 Mon Sep 17 00:00:00 2001 From: Jelle Spijker Date: Sat, 19 Aug 2023 02:42:17 +0200 Subject: [PATCH 05/54] checkout repo Contributes to CURA-8415 --- .github/workflows/macos.yml | 9 ++++++--- .github/workflows/windows.yml | 6 ++++++ 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml index 418e99c4702..024c64ad757 100644 --- a/.github/workflows/macos.yml +++ b/.github/workflows/macos.yml @@ -259,6 +259,9 @@ jobs: needs: [ cura-installer-create ] runs-on: macos-11 steps: + - name: Checkout + uses: actions/checkout@v3 + - name: Setup Python uses: actions/setup-python@v4 with: @@ -313,6 +316,9 @@ jobs: needs: [ cura-installer-create ] runs-on: macos-11 steps: + - name: Checkout + uses: actions/checkout@v3 + - name: Setup Python uses: actions/setup-python@v4 with: @@ -348,9 +354,6 @@ jobs: p12-file-base64: ${{ secrets.MACOS_CERT_INSTALLER_P12 }} p12-password: ${{ secrets.MACOS_CERT_PASSPHRASE }} - - name: Install MacOS system requirements - run: brew install create-dmg - - name: Create the Macos dmg and pkg (Bash) run: python ../cura_inst/packaging/MacOS/build_macos.py --source_path ../cura_inst --dist_path . --cura_conan_version $CURA_CONAN_VERSION --filename "${{ needs.cura-installer-create.outputs.INSTALLER_FILENAME }}" --build_pkg --app_name "$CURA_APP_NAME" working-directory: dist diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml index 8c5cad9d68b..ef26baa8ad6 100644 --- a/.github/workflows/windows.yml +++ b/.github/workflows/windows.yml @@ -217,6 +217,9 @@ jobs: needs: [ cura-installer-create ] runs-on: ${{ inputs.operating_system }} steps: + - name: Checkout + uses: actions/checkout@v3 + - name: Setup Python uses: actions/setup-python@v4 with: @@ -267,6 +270,9 @@ jobs: needs: [ cura-installer-create ] runs-on: ${{ inputs.operating_system }} steps: + - name: Checkout + uses: actions/checkout@v3 + - name: Setup Python uses: actions/setup-python@v4 with: From 365166e493c785949849628db9d19513631cfb5d Mon Sep 17 00:00:00 2001 From: Jelle Spijker Date: Sat, 19 Aug 2023 03:01:53 +0200 Subject: [PATCH 06/54] few minor fixes Contributes to CURA-8415 --- .github/workflows/linux.yml | 1 - .github/workflows/macos.yml | 7 +++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml index 42312219d65..70a15bcbb5f 100644 --- a/.github/workflows/linux.yml +++ b/.github/workflows/linux.yml @@ -179,7 +179,6 @@ jobs: run: | import os enterprise = "-Enterprise" if "${{ inputs.enterprise }}" == "true" else "" - installer_filename = f"UltiMaker-Cura-{os.getenv('CURA_VERSION_FULL')}{enterprise}-linux-${{ inputs.architecture }}" if "${{ inputs.operating_system }}" == "ubuntu-22.04": installer_filename = f"UltiMaker-Cura-{os.getenv('CURA_VERSION_FULL')}{enterprise}-linux-modern-${{ inputs.architecture }}" else: diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml index 024c64ad757..e5e8ead2cdc 100644 --- a/.github/workflows/macos.yml +++ b/.github/workflows/macos.yml @@ -300,7 +300,7 @@ jobs: - name: Install MacOS system requirements run: brew install create-dmg - - name: Create the Macos dmg and pkg (Bash) + - name: Create the Macos dmg (Bash) run: python ../cura_inst/packaging/MacOS/build_macos.py --source_path ../cura_inst --dist_path . --cura_conan_version $CURA_CONAN_VERSION --filename "${{ needs.cura-installer-create.outputs.INSTALLER_FILENAME }}" --build_dmg --app_name "$CURA_APP_NAME" working-directory: dist @@ -354,7 +354,10 @@ jobs: p12-file-base64: ${{ secrets.MACOS_CERT_INSTALLER_P12 }} p12-password: ${{ secrets.MACOS_CERT_PASSPHRASE }} - - name: Create the Macos dmg and pkg (Bash) + - name: Install MacOS system requirements + run: brew install create-dmg + + - name: Create the Macos pkg (Bash) run: python ../cura_inst/packaging/MacOS/build_macos.py --source_path ../cura_inst --dist_path . --cura_conan_version $CURA_CONAN_VERSION --filename "${{ needs.cura-installer-create.outputs.INSTALLER_FILENAME }}" --build_pkg --app_name "$CURA_APP_NAME" working-directory: dist From ddc4ec473e7604a155789c5fbb83203fe2f0d81f Mon Sep 17 00:00:00 2001 From: Jelle Spijker Date: Sat, 19 Aug 2023 03:05:54 +0200 Subject: [PATCH 07/54] no trailing / Contributes to CURA-8415 --- .github/workflows/windows.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml index ef26baa8ad6..568a3c30ded 100644 --- a/.github/workflows/windows.yml +++ b/.github/workflows/windows.yml @@ -202,7 +202,7 @@ jobs: - name: Archive the artifacts (Powershell) run: | Compress-Archive -Path ".\dist" -DestinationPath ".\${{ steps.filename.outputs.INSTALLER_FILENAME }}.zip" - Compress-Archive -Path ".\cura_inst\packaging\" -DestinationPath ".\${{ steps.filename.outputs.INSTALLER_FILENAME }}-packaging.zip" + Compress-Archive -Path ".\cura_inst\packaging" -DestinationPath ".\${{ steps.filename.outputs.INSTALLER_FILENAME }}-packaging.zip" - name: upload the zipped dist and packaging folder uses: actions/upload-artifact@v3 From 28afca187c1feec77f3a8bb555b9039725435ae0 Mon Sep 17 00:00:00 2001 From: Jelle Spijker Date: Sat, 19 Aug 2023 03:22:19 +0200 Subject: [PATCH 08/54] Nightlies Contributes to CURA-9494 --- .github/workflows/installers.yml | 103 ++++++++++++++++++++++++++++++- 1 file changed, 102 insertions(+), 1 deletion(-) diff --git a/.github/workflows/installers.yml b/.github/workflows/installers.yml index ead3b7a87a4..a0e11f63eb6 100644 --- a/.github/workflows/installers.yml +++ b/.github/workflows/installers.yml @@ -24,6 +24,16 @@ on: default: false required: true type: boolean + nightly: + description: 'Upload to nightly release' + default: false + required: true + type: boolean + +env: + CURA_CONAN_VERSION: ${{ inputs.cura_conan_version }} + ENTERPRISE: ${{ inputs.enterprise }} + STAGING: ${{ inputs.staging }} jobs: windows-installer: @@ -79,4 +89,95 @@ jobs: staging: ${{ inputs.staging }} architecture: ARM64 operating_system: self-hosted - secrets: inherit \ No newline at end of file + secrets: inherit + + update-nightly-release: + runs-on: ubuntu-latest + needs: [ windows-installer, linux-modern-installer, linux-legacy-installer, macos-installer, macos-arm-installer ] + steps: + + - name: Output the name file name and extension + id: filename + shell: python + run: | + import os + enterprise = "-Enterprise" if "${{ inputs.enterprise }}" == "true" else "" + linux_modern = f"UltiMaker-Cura-{os.getenv('CURA_VERSION_FULL')}{enterprise}-linux-modern-X64-AppImage" + linux_legacy = f"UltiMaker-Cura-{os.getenv('CURA_VERSION_FULL')}{enterprise}-linux-X64-AppImage" + mac_x64_dmg = f"UltiMaker-Cura-{os.getenv('CURA_VERSION_FULL')}{enterprise}-macos-X64-dmg" + mac_x64_pkg = f"UltiMaker-Cura-{os.getenv('CURA_VERSION_FULL')}{enterprise}-macos-X64-pkg" + mac_arm_dmg = f"UltiMaker-Cura-{os.getenv('CURA_VERSION_FULL')}{enterprise}-macos-ARM64-dmg" + mac_arm_pkg = f"UltiMaker-Cura-{os.getenv('CURA_VERSION_FULL')}{enterprise}-macos-ARM64-pkg" + win_msi = installer_filename = f"UltiMaker-Cura-{os.getenv('CURA_VERSION_FULL')}{enterprise}-win64-X64-msi + win_exe = installer_filename = f"UltiMaker-Cura-{os.getenv('CURA_VERSION_FULL')}{enterprise}-win64-X64-exe" + output_env = os.environ["GITHUB_OUTPUT"] + content = "" + if os.path.exists(output_env): + with open(output_env, "r") as f: + content = f.read() + with open(output_env, "w") as f: + f.write(content) + f.writelines(f"LINUX_MODERN={linux_modern}\n") + f.writelines(f"LINUX_LEGACY={linux_legacy}\n") + f.writelines(f"MAC_X64_DMG={mac_x64_dmg}\n") + f.writelines(f"MAC_X64_PKG={mac_x64_pkg}\n") + f.writelines(f"MAC_ARM_DMG={mac_arm_dmg}\n") + f.writelines(f"MAC_ARM_PKG={mac_arm_pkg}\n") + f.writelines(f"WIN_MSI={win_msi}\n") + f.writelines(f"WIN_EXE={win_exe}\n") + + - name: Download linux modern installer jobs artifacts + uses: actions/download-artifact@v2 + with: + name: ${{ steps.filename.outputs.LINUX_MODERN }} + path: installers + + - name: Download linux legacy installer jobs artifacts + uses: actions/download-artifact@v2 + with: + name: ${{ steps.filename.outputs.LINUX_LEGACY }} + path: installers + + - name: Download mac x64 dmg installer jobs artifacts + uses: actions/download-artifact@v2 + with: + name: ${{ steps.filename.outputs.MAC_X64_DMG }} + path: installers + + - name: Download mac x64 pkg installer jobs artifacts + uses: actions/download-artifact@v2 + with: + name: ${{ steps.filename.outputs.MAC_X64_PKG }} + path: installers + + - name: Download mac arm dmg installer jobs artifacts + uses: actions/download-artifact@v2 + with: + name: ${{ steps.filename.outputs.MAC_ARM_DMG }} + path: installers + + - name: Download mac arm pkg installer jobs artifacts + uses: actions/download-artifact@v2 + with: + name: ${{ steps.filename.outputs.MAC_ARM_PKG }} + path: installers + + - name: Download win msi installer jobs artifacts + uses: actions/download-artifact@v2 + with: + name: ${{ steps.filename.outputs.WIN_MSI }} + path: installers + + - name: Download win exe installer jobs artifacts + uses: actions/download-artifact@v2 + with: + name: ${{ steps.filename.outputs.WIN_EXE }} + path: installers + + - name: Update nightly release + uses: pyTooling/Actions/releaser@main + with: + tag: nightly + rm: true + token: ${{ secrets.GITHUB_TOKEN }} + files: installers/*.* \ No newline at end of file From 76787b9898936cb7617bd34887263f0afe66c63b Mon Sep 17 00:00:00 2001 From: Jelle Spijker Date: Sat, 19 Aug 2023 03:31:48 +0200 Subject: [PATCH 09/54] Update installers.yml for nightly release option Added a conditional statement for optionally triggering nightly releases in the installer workflow. This change allows us to initiate automatic nightly builds only when required, contributing to efficiency and resource utilization optimization. This is linked to Jira task CURA-9494. --- .github/workflows/installers.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/installers.yml b/.github/workflows/installers.yml index a0e11f63eb6..1a3a96bae0e 100644 --- a/.github/workflows/installers.yml +++ b/.github/workflows/installers.yml @@ -92,6 +92,7 @@ jobs: secrets: inherit update-nightly-release: + if: ${{ inputs.nightly }} runs-on: ubuntu-latest needs: [ windows-installer, linux-modern-installer, linux-legacy-installer, macos-installer, macos-arm-installer ] steps: From ae33d03eb25faa3d7fc7ed5a4e83e60a021ffa2a Mon Sep 17 00:00:00 2001 From: GregValiant <64202104+GregValiant@users.noreply.github.com> Date: Sat, 19 Aug 2023 08:42:27 -0400 Subject: [PATCH 10/54] Update LimitXYAccelJerk.py Add Exit for Ultimaker printers. Add notice that Accel is not-extruder specific. Changed variable names to lower case. --- .../scripts/LimitXYAccelJerk.py | 107 ++++++++++++++++++ 1 file changed, 107 insertions(+) diff --git a/plugins/PostProcessingPlugin/scripts/LimitXYAccelJerk.py b/plugins/PostProcessingPlugin/scripts/LimitXYAccelJerk.py index 8932d8e4ea4..d50726fc762 100644 --- a/plugins/PostProcessingPlugin/scripts/LimitXYAccelJerk.py +++ b/plugins/PostProcessingPlugin/scripts/LimitXYAccelJerk.py @@ -9,6 +9,10 @@ from ..Script import Script from cura.CuraApplication import CuraApplication import re +<<<<<<< Updated upstream +======= +from UM.Message import Message +>>>>>>> Stashed changes class LimitXYAccelJerk(Script): def __init__(self): @@ -16,13 +20,18 @@ def __init__(self): def initialize(self) -> None: super().initialize() +<<<<<<< Updated upstream # Get the Accel and Jerk and set the values in the setting boxes--------------------------------------------- +======= + # Get the Accel and Jerk and set the values in the setting boxes-- +>>>>>>> Stashed changes mycura = CuraApplication.getInstance().getGlobalContainerStack() extruder = mycura.extruderList accel_print = extruder[0].getProperty("acceleration_print", "value") accel_travel = extruder[0].getProperty("acceleration_travel", "value") jerk_print_old = extruder[0].getProperty("jerk_print", "value") jerk_travel_old = extruder[0].getProperty("jerk_travel", "value") +<<<<<<< Updated upstream self._instance.setProperty("X_accel_limit", "value", round(accel_print)) self._instance.setProperty("Y_accel_limit", "value", round(accel_print)) self._instance.setProperty("X_jerk", "value", jerk_print_old) @@ -31,12 +40,36 @@ def initialize(self) -> None: def getSettingDataString(self): return """{ "name": "Limit the X-Y Accel/Jerk", +======= + self._instance.setProperty("x_accel_limit", "value", round(accel_print)) + self._instance.setProperty("y_accel_limit", "value", round(accel_print)) + self._instance.setProperty("x_jerk", "value", jerk_print_old) + self._instance.setProperty("y_jerk", "value", jerk_print_old) + ext_count = int(mycura.getProperty("machine_extruder_count", "value")) + machine_name = str(mycura.getProperty("machine_name", "value")) + + # Warn the user if the printer is an Ultimaker------------------------- + if "Ultimaker" in machine_name: + Message(text = " [Limit the X-Y Accel/Jerk] WILL NOT RUN because Ultimaker printers have fixed beds (it is intended for 'bed slinger' printers only.").show() + + # Warn the user if the printer is multi-extruder------------------ + if ext_count > 1: + Message(text = " 'Limit the X-Y Accel/Jerk': The post processor treats all extruders the same. If you have multiple extruders they will all be subject to the same Accel and Jerk limits imposed. If you have different Travel and Print Accel they will be subject to the same limit. If that is not acceptable then you should not use this Post Processor.").show() + + def getSettingDataString(self): + return """{ + "name": "Limit the X-Y Accel/Jerk (all extruders equal)", +>>>>>>> Stashed changes "key": "LimitXYAccelJerk", "metadata": {}, "version": 2, "settings": { +<<<<<<< Updated upstream "X_accel_limit": +======= + "x_accel_limit": +>>>>>>> Stashed changes { "label": "X MAX Acceleration", "description": "If this number is lower than the 'X Print Accel' in Cura then this will limit the Accel on the X axis. Enter the Maximum Acceleration value for the X axis. This will affect both Print and Travel Accel. If you enable an End Layer then at the end of that layer the Accel Limit will be reset (unless you choose 'Gradual' in which case the new limit goes to the top layer).", @@ -46,7 +79,11 @@ def getSettingDataString(self): "unit": "mm/sec² ", "default_value": 500 }, +<<<<<<< Updated upstream "Y_accel_limit": +======= + "y_accel_limit": +>>>>>>> Stashed changes { "label": "Y MAX Acceleration", "description": "If this number is lower than the Y accel in Cura then this will limit the Accel on the Y axis. Enter the Maximum Acceleration value for the Y axis. This will affect both Print and Travel Accel. If you enable an End Layer then at the end of that layer the Accel Limit will be reset (unless you choose 'Gradual' in which case the new limit goes to the top layer).", @@ -64,7 +101,11 @@ def getSettingDataString(self): "enabled": true, "default_value": false }, +<<<<<<< Updated upstream "X_jerk": +======= + "x_jerk": +>>>>>>> Stashed changes { "label": " X jerk", "description": "Enter the Jerk value for the X axis. Enter '0' to use the existing X Jerk. This setting will affect both the Print and Travel jerk.", @@ -73,7 +114,11 @@ def getSettingDataString(self): "unit": "mm/sec ", "default_value": 8 }, +<<<<<<< Updated upstream "Y_jerk": +======= + "y_jerk": +>>>>>>> Stashed changes { "label": " Y jerk", "description": "Enter the Jerk value for the Y axis. Enter '0' to use the existing Y Jerk. This setting will affect both the Print and Travel jerk.", @@ -136,6 +181,17 @@ def getSettingDataString(self): def execute(self, data): mycura = CuraApplication.getInstance().getGlobalContainerStack() extruder = mycura.extruderList +<<<<<<< Updated upstream +======= + machine_name = str(mycura.getProperty("machine_name", "value")) + + # Exit if the printer is an Ultimaker------------------------- + if "Ultimaker" in machine_name: + Message(text = " [Limit the X-Y Accel/Jerk] DID NOT RUN. This post processor is not intended for fixed printers (for 'bed slinger' printers only.").show() + data[0] += "; [LimitXYAccelJerk] DID NOT RUN because the printer doesn't have a sliding bed.\n" + return data + +>>>>>>> Stashed changes constant_change = not bool(self.getSettingValueByKey("gradient_change")) accel_print_enabled = bool(extruder[0].getProperty("acceleration_enabled", "value")) accel_travel_enabled = bool(extruder[0].getProperty("acceleration_travel_enabled", "value")) @@ -145,6 +201,10 @@ def execute(self, data): jerk_travel_enabled = str(extruder[0].getProperty("jerk_travel_enabled", "value")) jerk_print_old = extruder[0].getProperty("jerk_print", "value") jerk_travel_old = extruder[0].getProperty("jerk_travel", "value") +<<<<<<< Updated upstream +======= + +>>>>>>> Stashed changes if int(accel_print) >= int(accel_travel): accel_old = accel_print else: @@ -156,10 +216,17 @@ def execute(self, data): jerk_old = jerk_travel_old #Set the new Accel values--------------------------------------------------------------------------------- +<<<<<<< Updated upstream x_accel = str(self.getSettingValueByKey("X_accel_limit")) y_accel = str(self.getSettingValueByKey("Y_accel_limit")) x_jerk = int(self.getSettingValueByKey("X_jerk")) y_jerk = int(self.getSettingValueByKey("Y_jerk")) +======= + x_accel = str(self.getSettingValueByKey("x_accel_limit")) + y_accel = str(self.getSettingValueByKey("y_accel_limit")) + x_jerk = int(self.getSettingValueByKey("x_jerk")) + y_jerk = int(self.getSettingValueByKey("y_jerk")) +>>>>>>> Stashed changes # Put the strings together M201_limit_new = "M201 X" + x_accel + " Y" + y_accel M201_limit_old = "M201 X" + str(round(accel_old)) + " Y" + str(round(accel_old)) @@ -227,6 +294,7 @@ def execute(self, data): all else: data[len(data)-1] = M201_limit_old + "\n" + M205_jerk_old + "\n" + data[len(data)-1] +<<<<<<< Updated upstream return data @@ -236,6 +304,29 @@ def execute(self, data): y_accel_hyst = round((accel_old - int(y_accel)) / layer_spread) x_accel_start = round(round((accel_old - x_accel_hyst)/50)*50) y_accel_start = round(round((accel_old - y_accel_hyst)/50)*50) +======= + return data + + elif not constant_change: + layer_spread = end_index - start_index + if accel_old >= int(x_accel): + x_accel_hyst = round((accel_old - int(x_accel)) / layer_spread) + else: + x_accel_hyst = round((int(x_accel) - accel_old) / layer_spread) + if accel_old >= int(y_accel): + y_accel_hyst = round((accel_old - int(y_accel)) / layer_spread) + else: + y_accel_hyst = round((int(y_accel) - accel_old) / layer_spread) + + if accel_old >= int(x_accel): + x_accel_start = round(round((accel_old - x_accel_hyst)/25)*25) + else: + x_accel_start = round(round((x_accel_hyst + accel_old)/25)*25) + if accel_old >= int(y_accel): + y_accel_start = round(round((accel_old - y_accel_hyst)/25)*25) + else: + y_accel_start = round(round((y_accel_hyst + accel_old)/25)*25) +>>>>>>> Stashed changes M201_limit_new = "M201 X" + str(x_accel_start) + " Y" + str(y_accel_start) #Add Accel limit and new Jerk at start layer------------------------------------------------------------- layer = data[start_index] @@ -250,11 +341,27 @@ def execute(self, data): for num in range(start_index + 1, end_index,1): layer = data[num] lines = layer.split("\n") +<<<<<<< Updated upstream x_accel_start -= x_accel_hyst if x_accel_start < int(x_accel): x_accel_start = int(x_accel) y_accel_start -= y_accel_hyst if y_accel_start < int(y_accel): y_accel_start = int(y_accel) M201_limit_new = "M201 X" + str(round(round(x_accel_start/50)*50)) + " Y" + str(round(round(y_accel_start/50)*50)) +======= + if accel_old >= int(x_accel): + x_accel_start -= x_accel_hyst + if x_accel_start < int(x_accel): x_accel_start = int(x_accel) + else: + x_accel_start += x_accel_hyst + if x_accel_start > int(x_accel): x_accel_start = int(x_accel) + if accel_old >= int(y_accel): + y_accel_start -= y_accel_hyst + if y_accel_start < int(y_accel): y_accel_start = int(y_accel) + else: + y_accel_start += y_accel_hyst + if y_accel_start > int(y_accel): y_accel_start = int(y_accel) + M201_limit_new = "M201 X" + str(round(round(x_accel_start/25)*25)) + " Y" + str(round(round(y_accel_start/25)*25)) +>>>>>>> Stashed changes for index, line in enumerate(lines): if line.startswith(";LAYER:"): lines.insert(index+1, M201_limit_new) From 43036953162739d77ec4a274cd45b59b16cffcec Mon Sep 17 00:00:00 2001 From: Jelle Spijker Date: Sun, 20 Aug 2023 14:08:00 +0200 Subject: [PATCH 11/54] Add automatic scheduled updates for nightly release A daily schedule for the update-nightly-release workflow was added. Now, apart from when the 'nightly' input is set to true, the release update will be triggered everyday at 5:20 CET. This functionality allows more up to date releases without manual input. Also, installer file names were updated and it now includes the daily creation timestamp which provides visibility on when the nightly build was generated. Contributes to CURA-9494 --- .github/workflows/installers.yml | 89 +++++++++++++++++++++++--------- .github/workflows/linux.yml | 15 ++++++ .github/workflows/macos.yml | 15 ++++++ .github/workflows/windows.yml | 15 ++++++ 4 files changed, 111 insertions(+), 23 deletions(-) diff --git a/.github/workflows/installers.yml b/.github/workflows/installers.yml index 1a3a96bae0e..451387eddd6 100644 --- a/.github/workflows/installers.yml +++ b/.github/workflows/installers.yml @@ -29,6 +29,9 @@ on: default: false required: true type: boolean + schedule: + # Daily at 5:20 CET + - cron: '20 4 * * *' env: CURA_CONAN_VERSION: ${{ inputs.cura_conan_version }} @@ -91,26 +94,41 @@ jobs: operating_system: self-hosted secrets: inherit + # Run and update nightly release when the nightly input is set to true or if the schedule is triggered update-nightly-release: - if: ${{ inputs.nightly }} + if: ${{ inputs.nightly == 'true' || github.event_name == 'schedule' }} runs-on: ubuntu-latest needs: [ windows-installer, linux-modern-installer, linux-legacy-installer, macos-installer, macos-arm-installer ] steps: + - name: Checkout + uses: actions/checkout@v3 + + - name: Download the run info + uses: actions/download-artifact@v2 + with: + name: macos-run-info + + - name: Set the run info as environment variables + run: | + . run_info.sh - name: Output the name file name and extension id: filename shell: python run: | import os + import datetime enterprise = "-Enterprise" if "${{ inputs.enterprise }}" == "true" else "" - linux_modern = f"UltiMaker-Cura-{os.getenv('CURA_VERSION_FULL')}{enterprise}-linux-modern-X64-AppImage" - linux_legacy = f"UltiMaker-Cura-{os.getenv('CURA_VERSION_FULL')}{enterprise}-linux-X64-AppImage" - mac_x64_dmg = f"UltiMaker-Cura-{os.getenv('CURA_VERSION_FULL')}{enterprise}-macos-X64-dmg" - mac_x64_pkg = f"UltiMaker-Cura-{os.getenv('CURA_VERSION_FULL')}{enterprise}-macos-X64-pkg" - mac_arm_dmg = f"UltiMaker-Cura-{os.getenv('CURA_VERSION_FULL')}{enterprise}-macos-ARM64-dmg" - mac_arm_pkg = f"UltiMaker-Cura-{os.getenv('CURA_VERSION_FULL')}{enterprise}-macos-ARM64-pkg" - win_msi = installer_filename = f"UltiMaker-Cura-{os.getenv('CURA_VERSION_FULL')}{enterprise}-win64-X64-msi - win_exe = installer_filename = f"UltiMaker-Cura-{os.getenv('CURA_VERSION_FULL')}{enterprise}-win64-X64-exe" + linux_modern = f"UltiMaker-Cura-{os.getenv('CURA_VERSION_FULL')}{enterprise}-linux-modern-X64" + linux_legacy = f"UltiMaker-Cura-{os.getenv('CURA_VERSION_FULL')}{enterprise}-linux-X64" + mac_x64_dmg = f"UltiMaker-Cura-{os.getenv('CURA_VERSION_FULL')}{enterprise}-macos-X64" + mac_x64_pkg = f"UltiMaker-Cura-{os.getenv('CURA_VERSION_FULL')}{enterprise}-macos-X64" + mac_arm_dmg = f"UltiMaker-Cura-{os.getenv('CURA_VERSION_FULL')}{enterprise}-macos-ARM64" + mac_arm_pkg = f"UltiMaker-Cura-{os.getenv('CURA_VERSION_FULL')}{enterprise}-macos-ARM64" + win_msi = installer_filename = f"UltiMaker-Cura-{os.getenv('CURA_VERSION_FULL')}{enterprise}-win64-X64" + win_exe = installer_filename = f"UltiMaker-Cura-{os.getenv('CURA_VERSION_FULL')}{enterprise}-win64-X64" + nightly_name = "UltiMaker-Cura-" + os.getenv('CURA_VERSION_FULL').split("+")[0] + nightly_creation_time = str(datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")) output_env = os.environ["GITHUB_OUTPUT"] content = "" if os.path.exists(output_env): @@ -126,59 +144,84 @@ jobs: f.writelines(f"MAC_ARM_PKG={mac_arm_pkg}\n") f.writelines(f"WIN_MSI={win_msi}\n") f.writelines(f"WIN_EXE={win_exe}\n") + f.writelines(f"NIGHTLY_NAME={nightly_name}\n") + f.writelines(f"NIGHTLY_TIME={nightly_creation_time}\n") - name: Download linux modern installer jobs artifacts uses: actions/download-artifact@v2 with: - name: ${{ steps.filename.outputs.LINUX_MODERN }} + name: ${{ steps.filename.outputs.LINUX_MODERN }}-AppImage path: installers - name: Download linux legacy installer jobs artifacts uses: actions/download-artifact@v2 with: - name: ${{ steps.filename.outputs.LINUX_LEGACY }} + name: ${{ steps.filename.outputs.LINUX_LEGACY }}-AppImage path: installers - name: Download mac x64 dmg installer jobs artifacts uses: actions/download-artifact@v2 with: - name: ${{ steps.filename.outputs.MAC_X64_DMG }} + name: ${{ steps.filename.outputs.MAC_X64_DMG }}-dmg path: installers - name: Download mac x64 pkg installer jobs artifacts uses: actions/download-artifact@v2 with: - name: ${{ steps.filename.outputs.MAC_X64_PKG }} + name: ${{ steps.filename.outputs.MAC_X64_PKG }}-pkg path: installers - name: Download mac arm dmg installer jobs artifacts uses: actions/download-artifact@v2 with: - name: ${{ steps.filename.outputs.MAC_ARM_DMG }} + name: ${{ steps.filename.outputs.MAC_ARM_DMG }}-dmg path: installers - name: Download mac arm pkg installer jobs artifacts uses: actions/download-artifact@v2 with: - name: ${{ steps.filename.outputs.MAC_ARM_PKG }} + name: ${{ steps.filename.outputs.MAC_ARM_PKG }}-pkg path: installers - name: Download win msi installer jobs artifacts uses: actions/download-artifact@v2 with: - name: ${{ steps.filename.outputs.WIN_MSI }} + name: ${{ steps.filename.outputs.WIN_MSI }}-msi path: installers - name: Download win exe installer jobs artifacts uses: actions/download-artifact@v2 with: - name: ${{ steps.filename.outputs.WIN_EXE }} + name: ${{ steps.filename.outputs.WIN_EXE }}-exe path: installers + - name: Rename installers to nightlies + run: | + mv installers/${{ steps.filename.outputs.LINUX_MODERN }}.AppImage installers/${{ steps.filename.outputs.NIGHTLY_NAME }}-linux-modern-X64.AppImage + mv installers/${{ steps.filename.outputs.LINUX_LEGACY }}.AppImage installers/${{ steps.filename.outputs.NIGHTLY_NAME }}-linux-X64.AppImage + mv installers/${{ steps.filename.outputs.MAC_X64_DMG }}.dmg installers/${{ steps.filename.outputs.NIGHTLY_NAME }}-macos-X64.dmg + mv installers/${{ steps.filename.outputs.MAC_X64_PKG }}.pkg installers/${{ steps.filename.outputs.NIGHTLY_NAME }}-macos-X64.pkg + mv installers/${{ steps.filename.outputs.MAC_ARM_DMG }}.dmg installers/${{ steps.filename.outputs.NIGHTLY_NAME }}-macos-ARM64.dmg + mv installers/${{ steps.filename.outputs.MAC_ARM_PKG }}.pkg installers/${{ steps.filename.outputs.NIGHTLY_NAME }}-macos-ARM64.pkg + mv installers/${{ steps.filename.outputs.WIN_MSI }}.msi installers/${{ steps.filename.outputs.NIGHTLY_NAME }}-win64-X64.msi + mv installers/${{ steps.filename.outputs.WIN_EXE }}.exe installers/${{ steps.filename.outputs.NIGHTLY_NAME }}-win64-X64.exe + - name: Update nightly release - uses: pyTooling/Actions/releaser@main - with: - tag: nightly - rm: true - token: ${{ secrets.GITHUB_TOKEN }} - files: installers/*.* \ No newline at end of file + run: | + gh release upload nightly installers/${{ steps.filename.outputs.NIGHTLY_NAME }}-linux-modern-X64.AppImage --clobber + gh release upload nightly installers/${{ steps.filename.outputs.NIGHTLY_NAME }}-linux-X64.AppImage --clobber + gh release upload nightly installers/${{ steps.filename.outputs.NIGHTLY_NAME }}-macos-X64.dmg --clobber + gh release upload nightly installers/${{ steps.filename.outputs.NIGHTLY_NAME }}-macos-X64.pkg --clobber + gh release upload nightly installers/${{ steps.filename.outputs.NIGHTLY_NAME }}-macos-ARM64.dmg --clobber + gh release upload nightly installers/${{ steps.filename.outputs.NIGHTLY_NAME }}-macos-ARM64.pkg --clobber + gh release upload nightly installers/${{ steps.filename.outputs.NIGHTLY_NAME }}-win64-X64.msi --clobber + gh release upload nightly installers/${{ steps.filename.outputs.NIGHTLY_NAME }}-win64-X64.exe --clobber + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Update nightly release description (with date) + run: | + gh release edit nightly --title "${{ steps.filename.outputs.NIGHTLY_NAME }}-alpha" --notes "Nightly release created on: ${{ steps.filename.outputs.NIGHTLY_TIME }}" + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml index 4d58dcee34f..7f68aed0b43 100644 --- a/.github/workflows/linux.yml +++ b/.github/workflows/linux.yml @@ -252,6 +252,21 @@ jobs: dist/${{ steps.filename.outputs.INSTALLER_FILENAME }}.AppImage retention-days: 5 + - name: Write the run info + shell: python + run: | + import os + with open("run_info.sh", "w") as f: + f.writelines(f'echo "CURA_VERSION_FULL={os.environ["CURA_VERSION_FULL"]}" >> $GITHUB_ENV\n') + + - name: Upload the run info + uses: actions/upload-artifact@v3 + with: + name: linux-run-info + path: | + run_info.sh + retention-days: 5 + notify-export: if: ${{ always() }} needs: [ cura-installer-create ] diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml index 4690d278784..6ba952d6bdd 100644 --- a/.github/workflows/macos.yml +++ b/.github/workflows/macos.yml @@ -259,6 +259,21 @@ jobs: dist/${{ steps.filename.outputs.INSTALLER_FILENAME }}.pkg retention-days: 5 + - name: Write the run info + shell: python + run: | + import os + with open("run_info.sh", "w") as f: + f.writelines(f'echo "CURA_VERSION_FULL={os.environ["CURA_VERSION_FULL"]}" >> $GITHUB_ENV\n') + + - name: Upload the run info + uses: actions/upload-artifact@v3 + with: + name: macos-run-info + path: | + run_info.sh + retention-days: 5 + notify-export: if: ${{ always() }} diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml index 88d9d84e949..9844d7724cb 100644 --- a/.github/workflows/windows.yml +++ b/.github/workflows/windows.yml @@ -251,6 +251,21 @@ jobs: dist/${{steps.filename.outputs.INSTALLER_FILENAME }}.exe retention-days: 5 + - name: Write the run info + shell: python + run: | + import os + with open("run_info.sh", "w") as f: + f.writelines(f'echo "CURA_VERSION_FULL={os.environ["CURA_VERSION_FULL"]}" >> $GITHUB_ENV\n') + + - name: Upload the run info + uses: actions/upload-artifact@v3 + with: + name: windows-run-info + path: | + run_info.sh + retention-days: 5 + notify-export: if: ${{ always() }} needs: [ cura-installer-create ] From d90da61f44199fe688dbc30bd5f216182d5f2dc3 Mon Sep 17 00:00:00 2001 From: Jelle Spijker Date: Sun, 20 Aug 2023 18:20:25 +0200 Subject: [PATCH 12/54] Fixed nighlty title alpha Contributes to CURA-9494 --- .github/workflows/installers.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/installers.yml b/.github/workflows/installers.yml index 451387eddd6..169d6af22a7 100644 --- a/.github/workflows/installers.yml +++ b/.github/workflows/installers.yml @@ -221,7 +221,7 @@ jobs: - name: Update nightly release description (with date) run: | - gh release edit nightly --title "${{ steps.filename.outputs.NIGHTLY_NAME }}-alpha" --notes "Nightly release created on: ${{ steps.filename.outputs.NIGHTLY_TIME }}" + gh release edit nightly --title "${{ steps.filename.outputs.NIGHTLY_NAME }}" --notes "Nightly release created on: ${{ steps.filename.outputs.NIGHTLY_TIME }}" env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} From ac60b59da592eaea08af8d969a06f59c80002ca1 Mon Sep 17 00:00:00 2001 From: Jelle Spijker Date: Sun, 20 Aug 2023 18:53:25 +0200 Subject: [PATCH 13/54] Fixed nightlies run check Contributes to CURA-9494 --- .github/workflows/installers.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/installers.yml b/.github/workflows/installers.yml index 169d6af22a7..96b67a05412 100644 --- a/.github/workflows/installers.yml +++ b/.github/workflows/installers.yml @@ -96,7 +96,7 @@ jobs: # Run and update nightly release when the nightly input is set to true or if the schedule is triggered update-nightly-release: - if: ${{ inputs.nightly == 'true' || github.event_name == 'schedule' }} + if: ${{ inputs.nightly || github.event_name == 'schedule' }} runs-on: ubuntu-latest needs: [ windows-installer, linux-modern-installer, linux-legacy-installer, macos-installer, macos-arm-installer ] steps: From 7efe485f65f31dc5e58a2c10cd298a7f4d9b0dc2 Mon Sep 17 00:00:00 2001 From: Jelle Spijker Date: Sun, 20 Aug 2023 19:24:38 +0200 Subject: [PATCH 14/54] Show version in Title bar except for actual releases Contributes to CURA-9494 --- cura/CuraApplication.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index 64d88d13dc1..e81584660ac 100755 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -50,6 +50,7 @@ from UM.View.SelectionPass import SelectionPass # For typing. from UM.Workspace.WorkspaceReader import WorkspaceReader from UM.i18n import i18nCatalog +from UM.Version import Version from cura import ApplicationMetadata from cura.API import CuraAPI from cura.API.Account import Account @@ -614,6 +615,9 @@ def startSplashWindowPhase(self) -> None: def _onEngineCreated(self): self._qml_engine.addImageProvider("print_job_preview", PrintJobPreviewImageProvider.PrintJobPreviewImageProvider()) + version = Version(self.getVersion()) + if version.hasPostFix(): + self._qml_engine.rootObjects()[0].setTitle(f"{ApplicationMetadata.CuraAppDisplayName} {ApplicationMetadata.CuraVersion}") @pyqtProperty(bool) def needToShowUserAgreement(self) -> bool: From 6424c26f782a9ec3dcccfd24dc8b81e543c28aed Mon Sep 17 00:00:00 2001 From: Jelle Spijker Date: Sun, 20 Aug 2023 19:41:58 +0200 Subject: [PATCH 15/54] Show warning message when using nightly build Only shown in builds, for alpha versions Contributes to CURA-9494 --- cura/CuraApplication.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index e81584660ac..44ea69bd74a 100755 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -616,8 +616,15 @@ def startSplashWindowPhase(self) -> None: def _onEngineCreated(self): self._qml_engine.addImageProvider("print_job_preview", PrintJobPreviewImageProvider.PrintJobPreviewImageProvider()) version = Version(self.getVersion()) - if version.hasPostFix(): + if hasattr(sys, "frozen") and version.hasPostFix() and "beta" not in version.getPostfixType(): self._qml_engine.rootObjects()[0].setTitle(f"{ApplicationMetadata.CuraAppDisplayName} {ApplicationMetadata.CuraVersion}") + message = Message( + self._i18n_catalog.i18nc("@info:warning", + f"This version is not intended for production use. If you encounter any issues, please report them on our GitHub page, mentioning the full version {self.getVersion()}"), + lifetime = 0, + title = self._i18n_catalog.i18nc("@info:title", "Nightly build"), + message_type = Message.MessageType.WARNING) + message.show() @pyqtProperty(bool) def needToShowUserAgreement(self) -> bool: From d7a218b30246e158d4b618fd3f9051980ced2627 Mon Sep 17 00:00:00 2001 From: Jelle Spijker Date: Mon, 28 Aug 2023 15:36:46 +0200 Subject: [PATCH 16/54] Bundle the gradualflow plugin Contributes CURA-10466 --- .gitignore | 1 + conanfile.py | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+) diff --git a/.gitignore b/.gitignore index 048bb915c74..90171b3561c 100644 --- a/.gitignore +++ b/.gitignore @@ -102,3 +102,4 @@ Ultimaker-Cura.spec .run/ /printer-linter/src/printerlinter.egg-info/ /resources/qml/Dialogs/AboutDialogVersionsList.qml +/plugins/CuraEngineGradualFlow diff --git a/conanfile.py b/conanfile.py index 608a450c39c..3a6dbdf1a57 100644 --- a/conanfile.py +++ b/conanfile.py @@ -304,6 +304,7 @@ def requirements(self): self.requires("boost/1.81.0") self.requires("pyarcus/(latest)@ultimaker/cura_10475") self.requires("curaengine/(latest)@ultimaker/cura_10446") + self.requires("curaengine_plugin_gradual_flow/(latest)@ultimaker/cura_10951") self.requires("pysavitar/5.2.2") self.requires("pynest2d/5.2.2") self.requires("uranium/(latest)@ultimaker/cura_10475") @@ -395,6 +396,16 @@ def imports(self): self.copy("*.pyi", src = "@libdirs", dst = self._site_packages) self.copy("*.dylib", src = "@libdirs", dst = self._script_dir) + if self.settings.arch == "x86_64" or self.settings.arch == "armv8": + # Copy the external plugins that we want to bundle with Cura + curaengine_plugin_gradual_flow = self.dependencies["curaengine_plugin_gradual_flow"].cpp_info + print(curaengine_plugin_gradual_flow.resdirs) + copy(self, "*.py", curaengine_plugin_gradual_flow.resdirs[0], str(self.source_path.joinpath("plugins", "CuraEngineGradualFlow")), keep_path = True) + copy(self, "*.json", curaengine_plugin_gradual_flow.resdirs[0], str(self.source_path.joinpath("plugins", "CuraEngineGradualFlow")), keep_path = True) + curaengine_plugin_gradual_flow_binary_path = self.source_path.joinpath("plugins", "CuraEngineGradualFlow", {"armv8": "arm64"}.get(str(self.settings.arch), str(self.settings.arch)), {"Macos": "Darwin"}.get(str(self.settings.os), str(self.settings.os))) + copy(self, "curaengine_plugin_gradual_flow.exe", curaengine_plugin_gradual_flow.bindirs[0], curaengine_plugin_gradual_flow_binary_path, keep_path = False) + copy(self, "curaengine_plugin_gradual_flow", curaengine_plugin_gradual_flow.bindirs[0], curaengine_plugin_gradual_flow_binary_path, keep_path = False) + def deploy(self): # Copy CuraEngine.exe to bindirs of Virtual Python Environment curaengine = self.dependencies["curaengine"].cpp_info @@ -476,6 +487,14 @@ def deploy(self): icon_path = "'{}'".format(os.path.join(self.package_folder, self.cpp_info.resdirs[2], self.conan_data["pyinstaller"]["icon"][str(self.settings.os)])).replace("\\", "\\\\"), entitlements_file = entitlements_file if self.settings.os == "Macos" else "None") + if self.settings.arch == "x86_64" or self.settings.arch == "armv8": + # Copy the external plugins that we want to bundle with Cura + curaengine_plugin_gradual_flow = self.dependencies["curaengine_plugin_gradual_flow"].cpp_info + copy(self, "*.py", curaengine_plugin_gradual_flow.resdirs[0], str(self._share_dir.joinpath("cura", "plugins")), keep_path = True) + copy(self, "*.json", curaengine_plugin_gradual_flow.resdirs[0], str(self._share_dir.joinpath("cura", "plugins")), keep_path = True) + curaengine_plugin_gradual_flow_binary_path = self._share_dir.joinpath("cura", "plugins", "CuraEngineGradualFlow", {"armv8": "arm64"}.get(str(self.settings.arch), str(self.settings.arch)), {"Macos": "Darwin"}.get(str(self.settings.os), str(self.settings.os))) + copy(self, "curaengine_plugin_gradual_flow.exe", curaengine_plugin_gradual_flow.bindirs[0], curaengine_plugin_gradual_flow_binary_path, keep_path = False) + copy(self, "curaengine_plugin_gradual_flow", curaengine_plugin_gradual_flow.bindirs[0], curaengine_plugin_gradual_flow_binary_path, keep_path = False) def package(self): copy(self, "cura_app.py", src = self.source_folder, dst = os.path.join(self.package_folder, self.cpp.package.bindirs[0])) From b648eddfd795d8a1301e1b654058acbad133dd01 Mon Sep 17 00:00:00 2001 From: Jelle Spijker Date: Mon, 28 Aug 2023 17:33:15 +0200 Subject: [PATCH 17/54] Update requirements-conan-package.txt --- .github/workflows/requirements-conan-package.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/requirements-conan-package.txt b/.github/workflows/requirements-conan-package.txt index 6b4d4cffc88..fd101a0b3ab 100644 --- a/.github/workflows/requirements-conan-package.txt +++ b/.github/workflows/requirements-conan-package.txt @@ -1,2 +1,2 @@ conan==1.60.2 -sip +sip==6.7.1 From 7cb2e96b63598f3ac7d436bc7782982118ba3d5c Mon Sep 17 00:00:00 2001 From: Jelle Spijker Date: Tue, 29 Aug 2023 08:24:01 +0200 Subject: [PATCH 18/54] Use pyarcus 10951 Contributes to CURA-10951 and CURA-10446 --- conanfile.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/conanfile.py b/conanfile.py index 3a6dbdf1a57..e9de2419475 100644 --- a/conanfile.py +++ b/conanfile.py @@ -302,7 +302,7 @@ def validate(self): def requirements(self): self.requires("boost/1.81.0") - self.requires("pyarcus/(latest)@ultimaker/cura_10475") + self.requires("pyarcus/(latest)@ultimaker/cura_10951") self.requires("curaengine/(latest)@ultimaker/cura_10446") self.requires("curaengine_plugin_gradual_flow/(latest)@ultimaker/cura_10951") self.requires("pysavitar/5.2.2") From 89fe3d2777c51b40403870acd51c6e783d8cb730 Mon Sep 17 00:00:00 2001 From: Jelle Spijker Date: Tue, 29 Aug 2023 13:07:23 +0200 Subject: [PATCH 19/54] Don't use the import method This will be deprecated, since we are also using self.dependencies we should do this in the generate. Contributes to CURA-10951 --- conanfile.py | 93 +++++++++++++++++++++++++++------------------------- 1 file changed, 48 insertions(+), 45 deletions(-) diff --git a/conanfile.py b/conanfile.py index d7eed0799cf..35c683f5dc1 100644 --- a/conanfile.py +++ b/conanfile.py @@ -341,7 +341,47 @@ def generate(self): vr.generate() self._generate_cura_version(os.path.join(self.source_folder, "cura")) + self._generate_about_versions(os.path.join(self.source_folder, "resources","qml", "Dialogs")) + + if not self.in_local_cache: + # Copy CuraEngine.exe to bindirs of Virtual Python Environment + curaengine = self.dependencies["curaengine"].cpp_info + copy(self, "CuraEngine.exe", curaengine.bindirs[0], self.source_folder, keep_path = False) + copy(self, "CuraEngine", curaengine.bindirs[0], self.source_folder, keep_path = False) + # Copy the external plugins that we want to bundle with Cura + rmdir(self,str(self.source_path.joinpath("plugins", "CuraEngineGradualFlow"))) + curaengine_plugin_gradual_flow = self.dependencies["curaengine_plugin_gradual_flow"].cpp_info + copy(self, "*.py", curaengine_plugin_gradual_flow.resdirs[0], str(self.source_path.joinpath("plugins", "CuraEngineGradualFlow")), keep_path = True) + copy(self, "*.json", curaengine_plugin_gradual_flow.resdirs[0], str(self.source_path.joinpath("plugins", "CuraEngineGradualFlow")), keep_path = True) + curaengine_plugin_gradual_flow_binary_path = self.source_path.joinpath("plugins", "CuraEngineGradualFlow", {"armv8": "arm64"}.get(str(self.settings.arch), str(self.settings.arch)), {"Macos": "Darwin"}.get(str(self.settings.os), str(self.settings.os))) + copy(self, "curaengine_plugin_gradual_flow.exe", curaengine_plugin_gradual_flow.bindirs[0], curaengine_plugin_gradual_flow_binary_path, keep_path = False) + copy(self, "curaengine_plugin_gradual_flow", curaengine_plugin_gradual_flow.bindirs[0], curaengine_plugin_gradual_flow_binary_path, keep_path = False) + + # Copy resources of cura_binary_data + cura_binary_data = self.dependencies["cura_binary_data"].cpp_info + copy(self, "*", cura_binary_data.resdirs[0], str(self._share_dir.joinpath("cura")), keep_path = True) + copy(self, "*", cura_binary_data.resdirs[1], str(self._share_dir.joinpath("uranium")), keep_path = True) + if self.settings.os == "Windows": + copy(self, "*", cura_binary_data.resdirs[2], str(self._share_dir.joinpath("windows")), keep_path = True) + + for dependency in self.dependencies.host.values(): + for bindir in dependency.cpp_info.bindirs: + copy(self, "*.dll", bindir, str(self._site_packages), keep_path = False) + for libdir in dependency.cpp_info.libdirs: + copy(self, "*.pyd", libdir, str(self._site_packages), keep_path = False) + copy(self, "*.pyi", libdir, str(self._site_packages), keep_path = False) + copy(self, "*.dylib", libdir, str(self._base_dir.joinpath("lib")), keep_path = False) + + # Copy materials (flat) + rmdir(self, os.path.join(self.source_folder, "resources", "materials")) + fdm_materials = self.dependencies["fdm_materials"].cpp_info + copy(self, "*", fdm_materials.resdirs[0], str(self._share_dir.joinpath("cura"))) + + # Copy internal resources + if self.options.internal: + cura_private_data = self.dependencies["cura_private_data"].cpp_info + copy(self, "*", cura_private_data.resdirs[0], str(self._share_dir.joinpath("cura"))) if self.options.devtools: entitlements_file = "'{}'".format(os.path.join(self.source_folder, "packaging", "MacOS", "cura.entitlements")) @@ -360,8 +400,6 @@ def generate(self): pot = self.python_requires["translationextractor"].module.ExtractTranslations(self, cpp_info.bindirs[0]) pot.generate() - self._generate_about_versions(os.path.join(self.source_folder, "resources","qml", "Dialogs")) - def build(self): if self.options.devtools: if self.settings.os != "Windows" or self.conf.get("tools.microsoft.bash:path", check_type = str): @@ -373,44 +411,20 @@ def build(self): cpp_info = self.dependencies["gettext"].cpp_info self.run(f"{cpp_info.bindirs[0]}/msgfmt {po_file} -o {mo_file} -f", env="conanbuild", ignore_errors=True) - def imports(self): - self.copy("CuraEngine.exe", root_package = "curaengine", src = "@bindirs", dst = "", keep_path = False) - self.copy("CuraEngine", root_package = "curaengine", src = "@bindirs", dst = "", keep_path = False) - - rmdir(self, os.path.join(self.source_folder, "resources", "materials")) - self.copy("*.fdm_material", root_package = "fdm_materials", src = "@resdirs", dst = "resources/materials", keep_path = False) - self.copy("*.sig", root_package = "fdm_materials", src = "@resdirs", dst = "resources/materials", keep_path = False) - - if self.options.internal: - self.copy("*", root_package = "cura_private_data", src = self.deps_cpp_info["cura_private_data"].resdirs[0], - dst = self._share_dir.joinpath("cura", "resources"), keep_path = True) - - # Copy resources of cura_binary_data - self.copy("*", root_package = "cura_binary_data", src = self.deps_cpp_info["cura_binary_data"].resdirs[0], - dst = self._share_dir.joinpath("cura", "resources"), keep_path = True) - self.copy("*", root_package = "cura_binary_data", src = self.deps_cpp_info["cura_binary_data"].resdirs[1], - dst =self._share_dir.joinpath("uranium", "resources"), keep_path = True) - - self.copy("*.dll", src = "@bindirs", dst = self._site_packages) - self.copy("*.pyd", src = "@libdirs", dst = self._site_packages) - self.copy("*.pyi", src = "@libdirs", dst = self._site_packages) - self.copy("*.dylib", src = "@libdirs", dst = self._script_dir) - - if self.settings.arch == "x86_64" or self.settings.arch == "armv8": - # Copy the external plugins that we want to bundle with Cura - curaengine_plugin_gradual_flow = self.dependencies["curaengine_plugin_gradual_flow"].cpp_info - copy(self, "*.py", curaengine_plugin_gradual_flow.resdirs[0], str(self.source_path.joinpath("plugins", "CuraEngineGradualFlow")), keep_path = True) - copy(self, "*.json", curaengine_plugin_gradual_flow.resdirs[0], str(self.source_path.joinpath("plugins", "CuraEngineGradualFlow")), keep_path = True) - curaengine_plugin_gradual_flow_binary_path = self.source_path.joinpath("plugins", "CuraEngineGradualFlow", {"armv8": "arm64"}.get(str(self.settings.arch), str(self.settings.arch)), {"Macos": "Darwin"}.get(str(self.settings.os), str(self.settings.os))) - copy(self, "curaengine_plugin_gradual_flow.exe", curaengine_plugin_gradual_flow.bindirs[0], curaengine_plugin_gradual_flow_binary_path, keep_path = False) - copy(self, "curaengine_plugin_gradual_flow", curaengine_plugin_gradual_flow.bindirs[0], curaengine_plugin_gradual_flow_binary_path, keep_path = False) - def deploy(self): # Copy CuraEngine.exe to bindirs of Virtual Python Environment curaengine = self.dependencies["curaengine"].cpp_info copy(self, "CuraEngine.exe", curaengine.bindirs[0], str(self._base_dir), keep_path = False) copy(self, "CuraEngine", curaengine.bindirs[0], str(self._base_dir), keep_path = False) + # Copy the external plugins that we want to bundle with Cura + curaengine_plugin_gradual_flow = self.dependencies["curaengine_plugin_gradual_flow"].cpp_info + copy(self, "*.py", curaengine_plugin_gradual_flow.resdirs[0], str(self._share_dir.joinpath("cura", "plugins")), keep_path = True) + copy(self, "*.json", curaengine_plugin_gradual_flow.resdirs[0], str(self._share_dir.joinpath("cura", "plugins")), keep_path = True) + curaengine_plugin_gradual_flow_binary_path = self._share_dir.joinpath("cura", "plugins", "CuraEngineGradualFlow", {"armv8": "arm64"}.get(str(self.settings.arch), str(self.settings.arch)), {"Macos": "Darwin"}.get(str(self.settings.os), str(self.settings.os))) + copy(self, "curaengine_plugin_gradual_flow.exe", curaengine_plugin_gradual_flow.bindirs[0], curaengine_plugin_gradual_flow_binary_path, keep_path = False) + copy(self, "curaengine_plugin_gradual_flow", curaengine_plugin_gradual_flow.bindirs[0], curaengine_plugin_gradual_flow_binary_path, keep_path = False) + # Copy resources of Cura (keep folder structure) copy(self, "*", os.path.join(self.package_folder, self.cpp_info.bindirs[0]), str(self._base_dir), keep_path = False) copy(self, "*", os.path.join(self.package_folder, self.cpp_info.libdirs[0]), str(self._site_packages.joinpath("cura")), keep_path = True) @@ -486,15 +500,6 @@ def deploy(self): icon_path = "'{}'".format(os.path.join(self.package_folder, self.cpp_info.resdirs[2], self.conan_data["pyinstaller"]["icon"][str(self.settings.os)])).replace("\\", "\\\\"), entitlements_file = entitlements_file if self.settings.os == "Macos" else "None") - if self.settings.arch == "x86_64" or self.settings.arch == "armv8": - # Copy the external plugins that we want to bundle with Cura - curaengine_plugin_gradual_flow = self.dependencies["curaengine_plugin_gradual_flow"].cpp_info - copy(self, "*.py", curaengine_plugin_gradual_flow.resdirs[0], str(self._share_dir.joinpath("cura", "plugins")), keep_path = True) - copy(self, "*.json", curaengine_plugin_gradual_flow.resdirs[0], str(self._share_dir.joinpath("cura", "plugins")), keep_path = True) - curaengine_plugin_gradual_flow_binary_path = self._share_dir.joinpath("cura", "plugins", "CuraEngineGradualFlow", {"armv8": "arm64"}.get(str(self.settings.arch), str(self.settings.arch)), {"Macos": "Darwin"}.get(str(self.settings.os), str(self.settings.os))) - copy(self, "curaengine_plugin_gradual_flow.exe", curaengine_plugin_gradual_flow.bindirs[0], curaengine_plugin_gradual_flow_binary_path, keep_path = False) - copy(self, "curaengine_plugin_gradual_flow", curaengine_plugin_gradual_flow.bindirs[0], curaengine_plugin_gradual_flow_binary_path, keep_path = False) - def package(self): copy(self, "cura_app.py", src = self.source_folder, dst = os.path.join(self.package_folder, self.cpp.package.bindirs[0])) copy(self, "*", src = os.path.join(self.source_folder, "cura"), dst = os.path.join(self.package_folder, self.cpp.package.libdirs[0])) @@ -517,8 +522,6 @@ def package_info(self): self.runenv_info.append_path("PYTHONPATH", os.path.join(self.source_folder, "plugins")) def package_id(self): - self.info.clear() - # The following options shouldn't be used to determine the hash, since these are only used to set the CuraVersion.py # which will als be generated by the deploy method during the `conan install cura/5.1.0@_/_` del self.info.options.enterprise From 8f0fb5ef12f72b63223b28cd8fc3f358f36a29bc Mon Sep 17 00:00:00 2001 From: GregValiant <64202104+GregValiant@users.noreply.github.com> Date: Tue, 29 Aug 2023 07:51:58 -0400 Subject: [PATCH 20/54] Update LimitXYAccelJerk.py Changes made per Rburema requests. --- .../scripts/LimitXYAccelJerk.py | 174 ++++++------------ 1 file changed, 60 insertions(+), 114 deletions(-) diff --git a/plugins/PostProcessingPlugin/scripts/LimitXYAccelJerk.py b/plugins/PostProcessingPlugin/scripts/LimitXYAccelJerk.py index d50726fc762..b47a5876d80 100644 --- a/plugins/PostProcessingPlugin/scripts/LimitXYAccelJerk.py +++ b/plugins/PostProcessingPlugin/scripts/LimitXYAccelJerk.py @@ -5,42 +5,26 @@ # The existing M201 Max Accel will be changed to limit the Y (and/or X) accel at the printer. If you have Accel enabled in Cura and the XY Accel is set to 3000 then setting the Y limit to 1000 will result in the printer limiting the Y to 1000. This can keep tall skinny prints from breaking loose of the bed and failing. The script was not tested with Junction Deviation. # If enabled - the Jerk setting is changed line-by-line within the gcode as there is no "limit" on Jerk. # if 'Gradual ACCEL change' is enabled then the Accel is changed gradually from the Start to the End layer and that will be the final Accel setting in the file. If 'Gradual' is enabled then the Jerk settings will continue to be changed to the end of the file (rather than ending at the End layer). +# This post is intended for printers with moving beds (bed slingers) so UltiMaker printers are excluded. +# When setting an accel limit on multi-extruder printers ALL extruders are effected. +# This post does not distinguish between Print Accel and Travel Accel. The limit is the limit for all regardless. Example: Skin Accel = 1000 and Outer Wall accel = 500. If the limit is set to 300 then both Skin and Outer Wall will be Accel = 300. from ..Script import Script from cura.CuraApplication import CuraApplication import re -<<<<<<< Updated upstream -======= from UM.Message import Message ->>>>>>> Stashed changes class LimitXYAccelJerk(Script): - def __init__(self): - super().__init__() def initialize(self) -> None: super().initialize() -<<<<<<< Updated upstream - # Get the Accel and Jerk and set the values in the setting boxes--------------------------------------------- -======= # Get the Accel and Jerk and set the values in the setting boxes-- ->>>>>>> Stashed changes mycura = CuraApplication.getInstance().getGlobalContainerStack() extruder = mycura.extruderList accel_print = extruder[0].getProperty("acceleration_print", "value") accel_travel = extruder[0].getProperty("acceleration_travel", "value") jerk_print_old = extruder[0].getProperty("jerk_print", "value") jerk_travel_old = extruder[0].getProperty("jerk_travel", "value") -<<<<<<< Updated upstream - self._instance.setProperty("X_accel_limit", "value", round(accel_print)) - self._instance.setProperty("Y_accel_limit", "value", round(accel_print)) - self._instance.setProperty("X_jerk", "value", jerk_print_old) - self._instance.setProperty("Y_jerk", "value", jerk_print_old) - - def getSettingDataString(self): - return """{ - "name": "Limit the X-Y Accel/Jerk", -======= self._instance.setProperty("x_accel_limit", "value", round(accel_print)) self._instance.setProperty("y_accel_limit", "value", round(accel_print)) self._instance.setProperty("x_jerk", "value", jerk_print_old) @@ -50,26 +34,31 @@ def getSettingDataString(self): # Warn the user if the printer is an Ultimaker------------------------- if "Ultimaker" in machine_name: - Message(text = " [Limit the X-Y Accel/Jerk] WILL NOT RUN because Ultimaker printers have fixed beds (it is intended for 'bed slinger' printers only.").show() + Message(text = " [Limit the X-Y Accel/Jerk] DID NOT RUN because Ultimaker printers don't have sliding beds.").show() # Warn the user if the printer is multi-extruder------------------ if ext_count > 1: - Message(text = " 'Limit the X-Y Accel/Jerk': The post processor treats all extruders the same. If you have multiple extruders they will all be subject to the same Accel and Jerk limits imposed. If you have different Travel and Print Accel they will be subject to the same limit. If that is not acceptable then you should not use this Post Processor.").show() + Message(text = " 'Limit the X-Y Accel/Jerk': The post processor treats all extruders the same. If you have multiple extruders they will all be subject to the same Accel and Jerk limits imposed. If you have different Travel and Print Accel they will also be subject to the same limits. If that is not acceptable then you should not use this Post Processor.").show() def getSettingDataString(self): return """{ "name": "Limit the X-Y Accel/Jerk (all extruders equal)", ->>>>>>> Stashed changes "key": "LimitXYAccelJerk", "metadata": {}, "version": 2, "settings": { -<<<<<<< Updated upstream - "X_accel_limit": -======= + "type_of_change": + { + "label": "Immediate or Gradual change", + "description": "An 'Immediate' change will insert the new numbers immediately at the Start Layer. A 'Gradual' change will transition from the starting Accel to the new Accel limit across a range of layers.", + "type": "enum", + "options": { + "immediate_change": "Immediate", + "gradual_change": "Gradual"}, + "default_value": "immediate_change" + }, "x_accel_limit": ->>>>>>> Stashed changes { "label": "X MAX Acceleration", "description": "If this number is lower than the 'X Print Accel' in Cura then this will limit the Accel on the X axis. Enter the Maximum Acceleration value for the X axis. This will affect both Print and Travel Accel. If you enable an End Layer then at the end of that layer the Accel Limit will be reset (unless you choose 'Gradual' in which case the new limit goes to the top layer).", @@ -79,11 +68,7 @@ def getSettingDataString(self): "unit": "mm/sec² ", "default_value": 500 }, -<<<<<<< Updated upstream - "Y_accel_limit": -======= "y_accel_limit": ->>>>>>> Stashed changes { "label": "Y MAX Acceleration", "description": "If this number is lower than the Y accel in Cura then this will limit the Accel on the Y axis. Enter the Maximum Acceleration value for the Y axis. This will affect both Print and Travel Accel. If you enable an End Layer then at the end of that layer the Accel Limit will be reset (unless you choose 'Gradual' in which case the new limit goes to the top layer).", @@ -101,11 +86,7 @@ def getSettingDataString(self): "enabled": true, "default_value": false }, -<<<<<<< Updated upstream - "X_jerk": -======= "x_jerk": ->>>>>>> Stashed changes { "label": " X jerk", "description": "Enter the Jerk value for the X axis. Enter '0' to use the existing X Jerk. This setting will affect both the Print and Travel jerk.", @@ -114,11 +95,7 @@ def getSettingDataString(self): "unit": "mm/sec ", "default_value": 8 }, -<<<<<<< Updated upstream - "Y_jerk": -======= "y_jerk": ->>>>>>> Stashed changes { "label": " Y jerk", "description": "Enter the Jerk value for the Y axis. Enter '0' to use the existing Y Jerk. This setting will affect both the Print and Travel jerk.", @@ -135,7 +112,7 @@ def getSettingDataString(self): "default_value": 1, "minimum_value": 1, "unit": "Lay# ", - "enabled": "not gradient_change" + "enabled": "type_of_change == 'immediate_change'" }, "end_layer": { @@ -145,15 +122,7 @@ def getSettingDataString(self): "default_value": -1, "minimum_value": -1, "unit": "Lay# ", - "enabled": "not gradient_change" - }, - "gradient_change": - { - "label": "Gradual ACCEL Change", - "description": "Gradually change the Accel numbers 'From layer' - 'To Layer'. If Jerk is enabled the Jerk changes are not 'Gradual' because there is no Max Jerk setting. Unlike Constant change - using 'Gradual' the Accel and Jerk change continues from the End Layer to the end of the file.", - "type": "bool", - "default_value": false, - "enabled": true + "enabled": "type_of_change == 'immediate_change'" }, "gradient_start_layer": { @@ -163,7 +132,7 @@ def getSettingDataString(self): "default_value": 1, "minimum_value": 1, "unit": "Lay# ", - "enabled": "gradient_change" + "enabled": "type_of_change == 'gradual_change'" }, "gradient_end_layer": { @@ -173,7 +142,7 @@ def getSettingDataString(self): "default_value": -1, "minimum_value": -1, "unit": "Lay# ", - "enabled": "gradient_change" + "enabled": "type_of_change == 'gradual_change'" } } }""" @@ -181,18 +150,22 @@ def getSettingDataString(self): def execute(self, data): mycura = CuraApplication.getInstance().getGlobalContainerStack() extruder = mycura.extruderList -<<<<<<< Updated upstream -======= machine_name = str(mycura.getProperty("machine_name", "value")) + print_sequence = str(mycura.getProperty("print_sequence", "value")) + + # Exit if 'one_at_a_time' is enabled------------------------- + if print_sequence == "one_at_a_time": + Message(text = " [Limit the X-Y Accel/Jerk] DID NOT RUN. This post processor is not compatible with 'One-at-a-Time' mode.").show() + data[0] += "; [LimitXYAccelJerk] DID NOT RUN because Cura is set to 'One-at-a-Time' mode.\n" + return data # Exit if the printer is an Ultimaker------------------------- if "Ultimaker" in machine_name: - Message(text = " [Limit the X-Y Accel/Jerk] DID NOT RUN. This post processor is not intended for fixed printers (for 'bed slinger' printers only.").show() + Message(text = " [Limit the X-Y Accel/Jerk] DID NOT RUN. This post processor is for bed slinger printers only.").show() data[0] += "; [LimitXYAccelJerk] DID NOT RUN because the printer doesn't have a sliding bed.\n" return data ->>>>>>> Stashed changes - constant_change = not bool(self.getSettingValueByKey("gradient_change")) + type_of_change = str(self.getSettingValueByKey("type_of_change")) accel_print_enabled = bool(extruder[0].getProperty("acceleration_enabled", "value")) accel_travel_enabled = bool(extruder[0].getProperty("acceleration_travel_enabled", "value")) accel_print = extruder[0].getProperty("acceleration_print", "value") @@ -201,10 +174,7 @@ def execute(self, data): jerk_travel_enabled = str(extruder[0].getProperty("jerk_travel_enabled", "value")) jerk_print_old = extruder[0].getProperty("jerk_print", "value") jerk_travel_old = extruder[0].getProperty("jerk_travel", "value") -<<<<<<< Updated upstream -======= ->>>>>>> Stashed changes if int(accel_print) >= int(accel_travel): accel_old = accel_print else: @@ -215,34 +185,29 @@ def execute(self, data): else: jerk_old = jerk_travel_old - #Set the new Accel values--------------------------------------------------------------------------------- -<<<<<<< Updated upstream - x_accel = str(self.getSettingValueByKey("X_accel_limit")) - y_accel = str(self.getSettingValueByKey("Y_accel_limit")) - x_jerk = int(self.getSettingValueByKey("X_jerk")) - y_jerk = int(self.getSettingValueByKey("Y_jerk")) -======= + #Set the new Accel values---------------------------------------------------------- x_accel = str(self.getSettingValueByKey("x_accel_limit")) y_accel = str(self.getSettingValueByKey("y_accel_limit")) x_jerk = int(self.getSettingValueByKey("x_jerk")) y_jerk = int(self.getSettingValueByKey("y_jerk")) ->>>>>>> Stashed changes - # Put the strings together - M201_limit_new = "M201 X" + x_accel + " Y" + y_accel - M201_limit_old = "M201 X" + str(round(accel_old)) + " Y" + str(round(accel_old)) + + # Put the strings together------------------------------------------- + m201_limit_new = "M201 X" + x_accel + " Y" + y_accel + m201_limit_old = "M201 X" + str(round(accel_old)) + " Y" + str(round(accel_old)) if x_jerk == 0: - M205_jerk_pattern = "Y(\d*)" - M205_jerk_new = "Y" + str(y_jerk) + m205_jerk_pattern = "Y(\d*)" + m205_jerk_new = "Y" + str(y_jerk) if y_jerk == 0: - M205_jerk_pattern = "X(\d*)" - M205_jerk_new = "X" + str(x_jerk) + m205_jerk_pattern = "X(\d*)" + m205_jerk_new = "X" + str(x_jerk) if x_jerk != 0 and y_jerk != 0: - M205_jerk_pattern = "M205 X(\d*) Y(\d*)" - M205_jerk_new = "M205 X" + str(x_jerk) + " Y" + str(y_jerk) - M205_jerk_old = "M205 X" + str(jerk_old) + " Y" + str(jerk_old) - + m205_jerk_pattern = "M205 X(\d*) Y(\d*)" + m205_jerk_new = "M205 X" + str(x_jerk) + " Y" + str(y_jerk) + m205_jerk_old = "M205 X" + str(jerk_old) + " Y" + str(jerk_old) + type_of_change = self.getSettingValueByKey("type_of_change") + #Get the indexes of the start and end layers---------------------------------------- - if constant_change: + if type_of_change == 'immediate_change': start_layer = int(self.getSettingValueByKey("start_layer"))-1 end_layer = int(self.getSettingValueByKey("end_layer")) else: @@ -264,14 +229,14 @@ def execute(self, data): end_index = len(data)-2 #Add Accel limit and new Jerk at start layer----------------------------------------------------- - if constant_change: + if type_of_change == "immediate_change": layer = data[start_index] lines = layer.split("\n") for index, line in enumerate(lines): if lines[index].startswith(";LAYER:"): - lines.insert(index+1,M201_limit_new) + lines.insert(index+1,m201_limit_new) if self.getSettingValueByKey("jerk_enable"): - lines.insert(index+2,M205_jerk_new) + lines.insert(index+2,m205_jerk_new) data[start_index] = "\n".join(lines) break @@ -281,33 +246,22 @@ def execute(self, data): lines = layer.split("\n") for index, line in enumerate(lines): if line.startswith("M205"): - lines[index] = re.sub(M205_jerk_pattern, M205_jerk_new, line) + lines[index] = re.sub(m205_jerk_pattern, m205_jerk_new, line) data[num] = "\n".join(lines) if end_layer != -1: try: layer = data[end_index-1] lines = layer.split("\n") - lines.insert(len(lines)-2,M201_limit_old) - lines.insert(len(lines)-2,M205_jerk_old) + lines.insert(len(lines)-2,m201_limit_old) + lines.insert(len(lines)-2,m205_jerk_old) data[end_index-1] = "\n".join(lines) except: all else: - data[len(data)-1] = M201_limit_old + "\n" + M205_jerk_old + "\n" + data[len(data)-1] -<<<<<<< Updated upstream - return data - - - elif not constant_change: - layer_spread = end_index - start_index - x_accel_hyst = round((accel_old - int(x_accel)) / layer_spread) - y_accel_hyst = round((accel_old - int(y_accel)) / layer_spread) - x_accel_start = round(round((accel_old - x_accel_hyst)/50)*50) - y_accel_start = round(round((accel_old - y_accel_hyst)/50)*50) -======= + data[len(data)-1] = m201_limit_old + "\n" + m205_jerk_old + "\n" + data[len(data)-1] return data - elif not constant_change: + elif type_of_change == "gradual_change": layer_spread = end_index - start_index if accel_old >= int(x_accel): x_accel_hyst = round((accel_old - int(x_accel)) / layer_spread) @@ -326,28 +280,20 @@ def execute(self, data): y_accel_start = round(round((accel_old - y_accel_hyst)/25)*25) else: y_accel_start = round(round((y_accel_hyst + accel_old)/25)*25) ->>>>>>> Stashed changes - M201_limit_new = "M201 X" + str(x_accel_start) + " Y" + str(y_accel_start) + m201_limit_new = "M201 X" + str(x_accel_start) + " Y" + str(y_accel_start) #Add Accel limit and new Jerk at start layer------------------------------------------------------------- layer = data[start_index] lines = layer.split("\n") for index, line in enumerate(lines): if lines[index].startswith(";LAYER:"): - lines.insert(index+1,M201_limit_new) + lines.insert(index+1,m201_limit_new) if self.getSettingValueByKey("jerk_enable"): - lines.insert(index+2,M205_jerk_new) + lines.insert(index+2,m205_jerk_new) data[start_index] = "\n".join(lines) break for num in range(start_index + 1, end_index,1): layer = data[num] lines = layer.split("\n") -<<<<<<< Updated upstream - x_accel_start -= x_accel_hyst - if x_accel_start < int(x_accel): x_accel_start = int(x_accel) - y_accel_start -= y_accel_hyst - if y_accel_start < int(y_accel): y_accel_start = int(y_accel) - M201_limit_new = "M201 X" + str(round(round(x_accel_start/50)*50)) + " Y" + str(round(round(y_accel_start/50)*50)) -======= if accel_old >= int(x_accel): x_accel_start -= x_accel_hyst if x_accel_start < int(x_accel): x_accel_start = int(x_accel) @@ -360,21 +306,21 @@ def execute(self, data): else: y_accel_start += y_accel_hyst if y_accel_start > int(y_accel): y_accel_start = int(y_accel) - M201_limit_new = "M201 X" + str(round(round(x_accel_start/25)*25)) + " Y" + str(round(round(y_accel_start/25)*25)) ->>>>>>> Stashed changes + m201_limit_new = "M201 X" + str(round(round(x_accel_start/25)*25)) + " Y" + str(round(round(y_accel_start/25)*25)) for index, line in enumerate(lines): if line.startswith(";LAYER:"): - lines.insert(index+1, M201_limit_new) + lines.insert(index+1, m201_limit_new) continue data[num] = "\n".join(lines) - #Alter any existing jerk lines. Accel lines can be ignored----------------------------------- + + #Alter any existing jerk lines. Accel lines can be ignored--------------- if self.getSettingValueByKey("jerk_enable"): for num in range(start_index,len(data)-1,1): layer = data[num] lines = layer.split("\n") for index, line in enumerate(lines): if line.startswith("M205"): - lines[index] = re.sub(M205_jerk_pattern, M205_jerk_new, line) + lines[index] = re.sub(m205_jerk_pattern, m205_jerk_new, line) data[num] = "\n".join(lines) - data[len(data)-1] = M201_limit_old + "\n" + M205_jerk_old + "\n" + data[len(data)-1] + data[len(data)-1] = m201_limit_old + "\n" + m205_jerk_old + "\n" + data[len(data)-1] return data \ No newline at end of file From 2f2b88fd24355c2c8c8b5ab84d718ef4f8945401 Mon Sep 17 00:00:00 2001 From: Jelle Spijker Date: Tue, 29 Aug 2023 15:25:32 +0200 Subject: [PATCH 21/54] Use the source_folder as a rootfor materials Contributes to CURA-10951 --- conanfile.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/conanfile.py b/conanfile.py index 35c683f5dc1..25209af26c4 100644 --- a/conanfile.py +++ b/conanfile.py @@ -376,7 +376,7 @@ def generate(self): # Copy materials (flat) rmdir(self, os.path.join(self.source_folder, "resources", "materials")) fdm_materials = self.dependencies["fdm_materials"].cpp_info - copy(self, "*", fdm_materials.resdirs[0], str(self._share_dir.joinpath("cura"))) + copy(self, "*", fdm_materials.resdirs[0], self.source_folder) # Copy internal resources if self.options.internal: From d3809f8bd7def1cfdcc0f7b5163df109c755cbdf Mon Sep 17 00:00:00 2001 From: Jelle Spijker Date: Tue, 29 Aug 2023 16:18:47 +0200 Subject: [PATCH 22/54] Still a header only Contributes to CURA-10951 --- conanfile.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/conanfile.py b/conanfile.py index c1646fb5586..ac1aebde3b0 100644 --- a/conanfile.py +++ b/conanfile.py @@ -522,6 +522,8 @@ def package_info(self): self.runenv_info.append_path("PYTHONPATH", os.path.join(self.source_folder, "plugins")) def package_id(self): + self.info.clear() + # The following options shouldn't be used to determine the hash, since these are only used to set the CuraVersion.py # which will als be generated by the deploy method during the `conan install cura/5.1.0@_/_` del self.info.options.enterprise From eeb3050e08f2bbd606e4d7cd71d9e1d381a85f1b Mon Sep 17 00:00:00 2001 From: jellespijker Date: Wed, 30 Aug 2023 10:44:28 +0200 Subject: [PATCH 23/54] Change the order of plugin deploy Contributes to CURA-10951 --- conanfile.py | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/conanfile.py b/conanfile.py index ac1aebde3b0..b61a8e0251f 100644 --- a/conanfile.py +++ b/conanfile.py @@ -352,8 +352,7 @@ def generate(self): # Copy the external plugins that we want to bundle with Cura rmdir(self,str(self.source_path.joinpath("plugins", "CuraEngineGradualFlow"))) curaengine_plugin_gradual_flow = self.dependencies["curaengine_plugin_gradual_flow"].cpp_info - copy(self, "*.py", curaengine_plugin_gradual_flow.resdirs[0], str(self.source_path.joinpath("plugins", "CuraEngineGradualFlow")), keep_path = True) - copy(self, "*.json", curaengine_plugin_gradual_flow.resdirs[0], str(self.source_path.joinpath("plugins", "CuraEngineGradualFlow")), keep_path = True) + copy(self, "*", curaengine_plugin_gradual_flow.resdirs[0], str(self.source_path.joinpath("plugins", "CuraEngineGradualFlow")), keep_path = True, excludes = ".gitignore") curaengine_plugin_gradual_flow_binary_path = self.source_path.joinpath("plugins", "CuraEngineGradualFlow", {"armv8": "arm64"}.get(str(self.settings.arch), str(self.settings.arch)), {"Macos": "Darwin"}.get(str(self.settings.os), str(self.settings.os))) copy(self, "curaengine_plugin_gradual_flow.exe", curaengine_plugin_gradual_flow.bindirs[0], curaengine_plugin_gradual_flow_binary_path, keep_path = False) copy(self, "curaengine_plugin_gradual_flow", curaengine_plugin_gradual_flow.bindirs[0], curaengine_plugin_gradual_flow_binary_path, keep_path = False) @@ -417,20 +416,19 @@ def deploy(self): copy(self, "CuraEngine.exe", curaengine.bindirs[0], str(self._base_dir), keep_path = False) copy(self, "CuraEngine", curaengine.bindirs[0], str(self._base_dir), keep_path = False) - # Copy the external plugins that we want to bundle with Cura - curaengine_plugin_gradual_flow = self.dependencies["curaengine_plugin_gradual_flow"].cpp_info - copy(self, "*.py", curaengine_plugin_gradual_flow.resdirs[0], str(self._share_dir.joinpath("cura", "plugins")), keep_path = True) - copy(self, "*.json", curaengine_plugin_gradual_flow.resdirs[0], str(self._share_dir.joinpath("cura", "plugins")), keep_path = True) - curaengine_plugin_gradual_flow_binary_path = self._share_dir.joinpath("cura", "plugins", "CuraEngineGradualFlow", {"armv8": "arm64"}.get(str(self.settings.arch), str(self.settings.arch)), {"Macos": "Darwin"}.get(str(self.settings.os), str(self.settings.os))) - copy(self, "curaengine_plugin_gradual_flow.exe", curaengine_plugin_gradual_flow.bindirs[0], curaengine_plugin_gradual_flow_binary_path, keep_path = False) - copy(self, "curaengine_plugin_gradual_flow", curaengine_plugin_gradual_flow.bindirs[0], curaengine_plugin_gradual_flow_binary_path, keep_path = False) - # Copy resources of Cura (keep folder structure) copy(self, "*", os.path.join(self.package_folder, self.cpp_info.bindirs[0]), str(self._base_dir), keep_path = False) copy(self, "*", os.path.join(self.package_folder, self.cpp_info.libdirs[0]), str(self._site_packages.joinpath("cura")), keep_path = True) copy(self, "*", os.path.join(self.package_folder, self.cpp_info.resdirs[0]), str(self._share_dir.joinpath("cura", "resources")), keep_path = True) copy(self, "*", os.path.join(self.package_folder, self.cpp_info.resdirs[1]), str(self._share_dir.joinpath("cura", "plugins")), keep_path = True) + # Copy the external plugins that we want to bundle with Cura + curaengine_plugin_gradual_flow = self.dependencies["curaengine_plugin_gradual_flow"].cpp_info + copy(self, "*", curaengine_plugin_gradual_flow.resdirs[0], str(self._share_dir.joinpath("cura", "plugins")), keep_path = True, excludes = ".gitignore") + curaengine_plugin_gradual_flow_binary_path = self._share_dir.joinpath("cura", "plugins", "CuraEngineGradualFlow", {"armv8": "arm64"}.get(str(self.settings.arch), str(self.settings.arch)), {"Macos": "Darwin"}.get(str(self.settings.os), str(self.settings.os))) + copy(self, "curaengine_plugin_gradual_flow.exe", curaengine_plugin_gradual_flow.bindirs[0], curaengine_plugin_gradual_flow_binary_path, keep_path = False) + copy(self, "curaengine_plugin_gradual_flow", curaengine_plugin_gradual_flow.bindirs[0], curaengine_plugin_gradual_flow_binary_path, keep_path = False) + # Copy materials (flat) fdm_materials = self.dependencies["fdm_materials"].cpp_info copy(self, "*", fdm_materials.resdirs[0], str(self._share_dir.joinpath("cura"))) From 0210b06fbb8179c38cd597e54566b72ad9dcafde Mon Sep 17 00:00:00 2001 From: jellespijker Date: Wed, 30 Aug 2023 10:51:53 +0200 Subject: [PATCH 24/54] Pyinstaller package directories from the instal directory Contributes to CURA-10951 --- conandata.yml | 4 ++++ conanfile.py | 4 ++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/conandata.yml b/conandata.yml index efbb7f83496..28179cecd96 100644 --- a/conandata.yml +++ b/conandata.yml @@ -19,6 +19,10 @@ pyinstaller: package: "cura" src: "plugins" dst: "share/cura/plugins" + curaengine_gradual_flow_plugin: + root: "." + src: "share/cura/plugins/CuraEngineGradualFlow" + dst: "share/cura/plugins/CuraEngineGradualFlow" cura_resources: package: "cura" src: "resources" diff --git a/conanfile.py b/conanfile.py index b61a8e0251f..d459cdabb6f 100644 --- a/conanfile.py +++ b/conanfile.py @@ -210,8 +210,8 @@ def _generate_pyinstaller_spec(self, location, entrypoint_location, icon_path, e src_path = os.path.join(self.source_folder, data["src"]) else: src_path = os.path.join(self.deps_cpp_info[data["package"]].rootpath, data["src"]) - elif "root" in data: # get the paths relative from the sourcefolder - src_path = os.path.join(self.source_folder, data["root"], data["src"]) + elif "root" in data: # get the paths relative from the install folder + src_path = os.path.join(self.install_folder, data["root"], data["src"]) else: continue if Path(src_path).exists(): From 4517364eb3a3d258e9b572da92aaf2137c5173cf Mon Sep 17 00:00:00 2001 From: Jelle Spijker Date: Wed, 30 Aug 2023 11:31:14 +0200 Subject: [PATCH 25/54] Copy the bundled external package info Contributes to CURA-10951 --- .gitignore | 1 + conanfile.py | 2 ++ 2 files changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index 90171b3561c..8fe6978fe8f 100644 --- a/.gitignore +++ b/.gitignore @@ -103,3 +103,4 @@ Ultimaker-Cura.spec /printer-linter/src/printerlinter.egg-info/ /resources/qml/Dialogs/AboutDialogVersionsList.qml /plugins/CuraEngineGradualFlow +/resources/bundled_packages/bundled_*.json diff --git a/conanfile.py b/conanfile.py index d459cdabb6f..a68a649228d 100644 --- a/conanfile.py +++ b/conanfile.py @@ -353,6 +353,7 @@ def generate(self): rmdir(self,str(self.source_path.joinpath("plugins", "CuraEngineGradualFlow"))) curaengine_plugin_gradual_flow = self.dependencies["curaengine_plugin_gradual_flow"].cpp_info copy(self, "*", curaengine_plugin_gradual_flow.resdirs[0], str(self.source_path.joinpath("plugins", "CuraEngineGradualFlow")), keep_path = True, excludes = ".gitignore") + copy(self, "bundled_*.json", curaengine_plugin_gradual_flow.resdirs[0], str(self.source_path.joinpath("resources", "bundled_packages")), keep_path = False) curaengine_plugin_gradual_flow_binary_path = self.source_path.joinpath("plugins", "CuraEngineGradualFlow", {"armv8": "arm64"}.get(str(self.settings.arch), str(self.settings.arch)), {"Macos": "Darwin"}.get(str(self.settings.os), str(self.settings.os))) copy(self, "curaengine_plugin_gradual_flow.exe", curaengine_plugin_gradual_flow.bindirs[0], curaengine_plugin_gradual_flow_binary_path, keep_path = False) copy(self, "curaengine_plugin_gradual_flow", curaengine_plugin_gradual_flow.bindirs[0], curaengine_plugin_gradual_flow_binary_path, keep_path = False) @@ -425,6 +426,7 @@ def deploy(self): # Copy the external plugins that we want to bundle with Cura curaengine_plugin_gradual_flow = self.dependencies["curaengine_plugin_gradual_flow"].cpp_info copy(self, "*", curaengine_plugin_gradual_flow.resdirs[0], str(self._share_dir.joinpath("cura", "plugins")), keep_path = True, excludes = ".gitignore") + copy(self, "bundled_*.json", curaengine_plugin_gradual_flow.resdirs[0], str(self._share_dir.joinpath("resources", "bundled_packages")), keep_path = False) curaengine_plugin_gradual_flow_binary_path = self._share_dir.joinpath("cura", "plugins", "CuraEngineGradualFlow", {"armv8": "arm64"}.get(str(self.settings.arch), str(self.settings.arch)), {"Macos": "Darwin"}.get(str(self.settings.os), str(self.settings.os))) copy(self, "curaengine_plugin_gradual_flow.exe", curaengine_plugin_gradual_flow.bindirs[0], curaengine_plugin_gradual_flow_binary_path, keep_path = False) copy(self, "curaengine_plugin_gradual_flow", curaengine_plugin_gradual_flow.bindirs[0], curaengine_plugin_gradual_flow_binary_path, keep_path = False) From c30c403a651e0009958683ea2e123d8eddd56d69 Mon Sep 17 00:00:00 2001 From: Jelle Spijker Date: Wed, 30 Aug 2023 13:04:01 +0200 Subject: [PATCH 26/54] Don't exclude Contributes to CURA-10951 --- conanfile.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/conanfile.py b/conanfile.py index a68a649228d..d1d3399ed17 100644 --- a/conanfile.py +++ b/conanfile.py @@ -352,7 +352,7 @@ def generate(self): # Copy the external plugins that we want to bundle with Cura rmdir(self,str(self.source_path.joinpath("plugins", "CuraEngineGradualFlow"))) curaengine_plugin_gradual_flow = self.dependencies["curaengine_plugin_gradual_flow"].cpp_info - copy(self, "*", curaengine_plugin_gradual_flow.resdirs[0], str(self.source_path.joinpath("plugins", "CuraEngineGradualFlow")), keep_path = True, excludes = ".gitignore") + copy(self, "*", curaengine_plugin_gradual_flow.resdirs[0], str(self.source_path.joinpath("plugins", "CuraEngineGradualFlow")), keep_path = True) copy(self, "bundled_*.json", curaengine_plugin_gradual_flow.resdirs[0], str(self.source_path.joinpath("resources", "bundled_packages")), keep_path = False) curaengine_plugin_gradual_flow_binary_path = self.source_path.joinpath("plugins", "CuraEngineGradualFlow", {"armv8": "arm64"}.get(str(self.settings.arch), str(self.settings.arch)), {"Macos": "Darwin"}.get(str(self.settings.os), str(self.settings.os))) copy(self, "curaengine_plugin_gradual_flow.exe", curaengine_plugin_gradual_flow.bindirs[0], curaengine_plugin_gradual_flow_binary_path, keep_path = False) @@ -425,7 +425,7 @@ def deploy(self): # Copy the external plugins that we want to bundle with Cura curaengine_plugin_gradual_flow = self.dependencies["curaengine_plugin_gradual_flow"].cpp_info - copy(self, "*", curaengine_plugin_gradual_flow.resdirs[0], str(self._share_dir.joinpath("cura", "plugins")), keep_path = True, excludes = ".gitignore") + copy(self, "*", curaengine_plugin_gradual_flow.resdirs[0], str(self._share_dir.joinpath("cura", "plugins")), keep_path = True) copy(self, "bundled_*.json", curaengine_plugin_gradual_flow.resdirs[0], str(self._share_dir.joinpath("resources", "bundled_packages")), keep_path = False) curaengine_plugin_gradual_flow_binary_path = self._share_dir.joinpath("cura", "plugins", "CuraEngineGradualFlow", {"armv8": "arm64"}.get(str(self.settings.arch), str(self.settings.arch)), {"Macos": "Darwin"}.get(str(self.settings.os), str(self.settings.os))) copy(self, "curaengine_plugin_gradual_flow.exe", curaengine_plugin_gradual_flow.bindirs[0], curaengine_plugin_gradual_flow_binary_path, keep_path = False) From c62e392c81274b4609791ee20f3296eab742b15d Mon Sep 17 00:00:00 2001 From: Jelle Spijker Date: Wed, 30 Aug 2023 13:09:22 +0200 Subject: [PATCH 27/54] use Windows slashes on Windows Contributes to CURA-10951 --- conanfile.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/conanfile.py b/conanfile.py index d1d3399ed17..0728a1c3374 100644 --- a/conanfile.py +++ b/conanfile.py @@ -222,7 +222,9 @@ def _generate_pyinstaller_spec(self, location, entrypoint_location, icon_path, e if "package" in binary: # get the paths from conan package src_path = os.path.join(self.deps_cpp_info[binary["package"]].rootpath, binary["src"]) elif "root" in binary: # get the paths relative from the sourcefolder - src_path = os.path.join(self.source_folder, binary["root"], binary["src"]) + src_path = str(self.source_path.joinpath(binary["root"], binary["src"]).as_posix()) + if self.settings.os == "Windows": + src_path = src_path.replace("\\", "\\\\") else: continue if not Path(src_path).exists(): From 2d389a6819700f8bd9c7025d1dfd2ccbd286e46a Mon Sep 17 00:00:00 2001 From: Jelle Spijker Date: Wed, 30 Aug 2023 16:51:56 +0200 Subject: [PATCH 28/54] Windows packaging Contributes to CURA-10951 --- conandata.yml | 4 ++++ conanfile.py | 10 ++++++---- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/conandata.yml b/conandata.yml index 28179cecd96..df87ba2113e 100644 --- a/conandata.yml +++ b/conandata.yml @@ -23,6 +23,10 @@ pyinstaller: root: "." src: "share/cura/plugins/CuraEngineGradualFlow" dst: "share/cura/plugins/CuraEngineGradualFlow" + curaengine_gradual_flow_plugin_resources: + root: "." + src: "share/cura/resources/bundled_packages" + dst: "share/cura/resources/bundled_packages" cura_resources: package: "cura" src: "resources" diff --git a/conanfile.py b/conanfile.py index 0728a1c3374..40d8aabe544 100644 --- a/conanfile.py +++ b/conanfile.py @@ -222,7 +222,7 @@ def _generate_pyinstaller_spec(self, location, entrypoint_location, icon_path, e if "package" in binary: # get the paths from conan package src_path = os.path.join(self.deps_cpp_info[binary["package"]].rootpath, binary["src"]) elif "root" in binary: # get the paths relative from the sourcefolder - src_path = str(self.source_path.joinpath(binary["root"], binary["src"]).as_posix()) + src_path = str(self.source_path.joinpath(binary["root"], binary["src"])) if self.settings.os == "Windows": src_path = src_path.replace("\\", "\\\\") else: @@ -354,7 +354,8 @@ def generate(self): # Copy the external plugins that we want to bundle with Cura rmdir(self,str(self.source_path.joinpath("plugins", "CuraEngineGradualFlow"))) curaengine_plugin_gradual_flow = self.dependencies["curaengine_plugin_gradual_flow"].cpp_info - copy(self, "*", curaengine_plugin_gradual_flow.resdirs[0], str(self.source_path.joinpath("plugins", "CuraEngineGradualFlow")), keep_path = True) + copy(self, "*.py", curaengine_plugin_gradual_flow.resdirs[0], str(self.source_path.joinpath("plugins", "CuraEngineGradualFlow")), keep_path = True) + copy(self, "*.json", curaengine_plugin_gradual_flow.resdirs[0], str(self.source_path.joinpath("plugins", "CuraEngineGradualFlow")), keep_path = True) copy(self, "bundled_*.json", curaengine_plugin_gradual_flow.resdirs[0], str(self.source_path.joinpath("resources", "bundled_packages")), keep_path = False) curaengine_plugin_gradual_flow_binary_path = self.source_path.joinpath("plugins", "CuraEngineGradualFlow", {"armv8": "arm64"}.get(str(self.settings.arch), str(self.settings.arch)), {"Macos": "Darwin"}.get(str(self.settings.os), str(self.settings.os))) copy(self, "curaengine_plugin_gradual_flow.exe", curaengine_plugin_gradual_flow.bindirs[0], curaengine_plugin_gradual_flow_binary_path, keep_path = False) @@ -427,8 +428,9 @@ def deploy(self): # Copy the external plugins that we want to bundle with Cura curaengine_plugin_gradual_flow = self.dependencies["curaengine_plugin_gradual_flow"].cpp_info - copy(self, "*", curaengine_plugin_gradual_flow.resdirs[0], str(self._share_dir.joinpath("cura", "plugins")), keep_path = True) - copy(self, "bundled_*.json", curaengine_plugin_gradual_flow.resdirs[0], str(self._share_dir.joinpath("resources", "bundled_packages")), keep_path = False) + copy(self, "*.py", curaengine_plugin_gradual_flow.resdirs[0], str(self._share_dir.joinpath("cura", "plugins")), keep_path = True) + copy(self, "*.json", curaengine_plugin_gradual_flow.resdirs[0], str(self._share_dir.joinpath("cura", "plugins")), keep_path = True) + copy(self, "bundled_*.json", curaengine_plugin_gradual_flow.resdirs[0], str(self._share_dir.joinpath("cura", "resources", "bundled_packages")), keep_path = False) curaengine_plugin_gradual_flow_binary_path = self._share_dir.joinpath("cura", "plugins", "CuraEngineGradualFlow", {"armv8": "arm64"}.get(str(self.settings.arch), str(self.settings.arch)), {"Macos": "Darwin"}.get(str(self.settings.os), str(self.settings.os))) copy(self, "curaengine_plugin_gradual_flow.exe", curaengine_plugin_gradual_flow.bindirs[0], curaengine_plugin_gradual_flow_binary_path, keep_path = False) copy(self, "curaengine_plugin_gradual_flow", curaengine_plugin_gradual_flow.bindirs[0], curaengine_plugin_gradual_flow_binary_path, keep_path = False) From f2948338aee1926000dabf69c003f3ea3028a45d Mon Sep 17 00:00:00 2001 From: jellespijker Date: Thu, 31 Aug 2023 06:01:16 +0200 Subject: [PATCH 29/54] Use shared curaengine_grpc_definitions Although not a direct dependency of Cura, still need to define it here, such that we can set it as shared for all dependencies. Needed to overcome the issues with glibc and static compiling of the gradual flow plugin on ubuntu 20.04 with gcc-13 Contributes to CURA-10951 --- conanfile.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/conanfile.py b/conanfile.py index 041fd2b9b13..a401c8fe2f0 100644 --- a/conanfile.py +++ b/conanfile.py @@ -296,6 +296,7 @@ def configure(self): self.options["pynest2d"].shared = True self.options["cpython"].shared = True self.options["boost"].header_only = True + self.options["curaengine_grpc_definitions"].shared = True def validate(self): version = self.conf_info.get("user.cura:version", default = self.version, check_type = str) @@ -304,6 +305,7 @@ def validate(self): def requirements(self): self.requires("boost/1.82.0") + self.requires("curaengine_grpc_definitions/latest@ultimaker/testing") self.requires("pyarcus/(latest)@ultimaker/cura_10951") self.requires("curaengine/(latest)@ultimaker/cura_10475") self.requires("pysavitar/(latest)@ultimaker/cura_10951") From f958d69f1cb4206c40bc4b2e3f8d71462b9a5ef3 Mon Sep 17 00:00:00 2001 From: jellespijker Date: Thu, 31 Aug 2023 06:17:15 +0200 Subject: [PATCH 30/54] Override zlib version to 1.2.13 fixes incompatible mismatch in versions between pyarcus and protobuf Contributes to CURA-10951 --- conanfile.py | 1 + 1 file changed, 1 insertion(+) diff --git a/conanfile.py b/conanfile.py index a401c8fe2f0..ca84990cf58 100644 --- a/conanfile.py +++ b/conanfile.py @@ -306,6 +306,7 @@ def validate(self): def requirements(self): self.requires("boost/1.82.0") self.requires("curaengine_grpc_definitions/latest@ultimaker/testing") + self.requires("zlib/1.2.13") self.requires("pyarcus/(latest)@ultimaker/cura_10951") self.requires("curaengine/(latest)@ultimaker/cura_10475") self.requires("pysavitar/(latest)@ultimaker/cura_10951") From 5cf2ecc66606684dc7f88205e3b21847536fce5f Mon Sep 17 00:00:00 2001 From: jellespijker Date: Thu, 31 Aug 2023 08:40:11 +0200 Subject: [PATCH 31/54] Only use shared grpc defs on Linux Contributes to CURA-10951 --- conanfile.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/conanfile.py b/conanfile.py index ca84990cf58..902e5b28375 100644 --- a/conanfile.py +++ b/conanfile.py @@ -296,7 +296,8 @@ def configure(self): self.options["pynest2d"].shared = True self.options["cpython"].shared = True self.options["boost"].header_only = True - self.options["curaengine_grpc_definitions"].shared = True + if self.settings.os == "Linux": + self.options["curaengine_grpc_definitions"].shared = True def validate(self): version = self.conf_info.get("user.cura:version", default = self.version, check_type = str) From 59ce5a6c496bc61557418fc00a989c478f5a62ee Mon Sep 17 00:00:00 2001 From: Jelle Spijker Date: Fri, 1 Sep 2023 07:37:34 +0200 Subject: [PATCH 32/54] Don't build on linux-legacy Contributes CURA-10951 --- .github/workflows/conan-package-create.yml | 2 +- .github/workflows/installers.yml | 11 ----------- .github/workflows/linux.yml | 5 +---- 3 files changed, 2 insertions(+), 16 deletions(-) diff --git a/.github/workflows/conan-package-create.yml b/.github/workflows/conan-package-create.yml index e8329fa7b15..18e2600e1d7 100644 --- a/.github/workflows/conan-package-create.yml +++ b/.github/workflows/conan-package-create.yml @@ -119,7 +119,7 @@ jobs: sudo apt upgrade sudo apt install build-essential checkinstall libegl-dev zlib1g-dev libssl-dev ninja-build autoconf libx11-dev libx11-xcb-dev libfontenc-dev libice-dev libsm-dev libxau-dev libxaw7-dev libxcomposite-dev libxcursor-dev libxdamage-dev libxdmcp-dev libxext-dev libxfixes-dev libxi-dev libxinerama-dev libxkbfile-dev libxmu-dev libxmuu-dev libxpm-dev libxrandr-dev libxrender-dev libxres-dev libxss-dev libxt-dev libxtst-dev libxv-dev libxvmc-dev libxxf86vm-dev xtrans-dev libxcb-render0-dev libxcb-render-util0-dev libxcb-xkb-dev libxcb-icccm4-dev libxcb-image0-dev libxcb-keysyms1-dev libxcb-randr0-dev libxcb-shape0-dev libxcb-sync-dev libxcb-xfixes0-dev libxcb-xinerama0-dev xkb-data libxcb-dri3-dev uuid-dev libxcb-util-dev libxkbcommon-x11-dev pkg-config flex bison -y - - name: Install GCC-132 on ubuntu + - name: Install GCC-13 on ubuntu if: ${{ startsWith(inputs.runs_on, 'ubuntu') }} run: | sudo apt install g++-13 gcc-13 -y diff --git a/.github/workflows/installers.yml b/.github/workflows/installers.yml index ead3b7a87a4..ed7c1cd0697 100644 --- a/.github/workflows/installers.yml +++ b/.github/workflows/installers.yml @@ -48,17 +48,6 @@ jobs: operating_system: ubuntu-22.04 secrets: inherit - linux-legacy-installer: - uses: ./.github/workflows/linux.yml - with: - cura_conan_version: ${{ inputs.cura_conan_version }} - conan_args: ${{ inputs.conan_args }} - enterprise: ${{ inputs.enterprise }} - staging: ${{ inputs.staging }} - architecture: X64 - operating_system: ubuntu-20.04 - secrets: inherit - macos-installer: uses: ./.github/workflows/macos.yml with: diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml index 2e15584299c..833d52c06eb 100644 --- a/.github/workflows/linux.yml +++ b/.github/workflows/linux.yml @@ -179,10 +179,7 @@ jobs: run: | import os enterprise = "-Enterprise" if "${{ inputs.enterprise }}" == "true" else "" - if "${{ inputs.operating_system }}" == "ubuntu-22.04": - installer_filename = f"UltiMaker-Cura-{os.getenv('CURA_VERSION_FULL')}{enterprise}-linux-modern-${{ inputs.architecture }}" - else: - installer_filename = f"UltiMaker-Cura-{os.getenv('CURA_VERSION_FULL')}{enterprise}-linux-${{ inputs.architecture }}" + installer_filename = f"UltiMaker-Cura-{os.getenv('CURA_VERSION_FULL')}{enterprise}-linux-${{ inputs.architecture }}" output_env = os.environ["GITHUB_OUTPUT"] content = "" if os.path.exists(output_env): From e5aab096e939ac1744d8384661e1b2a5d2002978 Mon Sep 17 00:00:00 2001 From: Jelle Spijker Date: Fri, 1 Sep 2023 07:51:52 +0200 Subject: [PATCH 33/54] Add AppImage-builder and dependencies Contributes CURA-10951 --- .github/workflows/linux.yml | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml index 833d52c06eb..f1b627cb759 100644 --- a/.github/workflows/linux.yml +++ b/.github/workflows/linux.yml @@ -119,10 +119,20 @@ jobs: sudo add-apt-repository ppa:ubuntu-toolchain-r/test -y sudo apt update sudo apt upgrade - sudo apt install build-essential checkinstall libegl-dev zlib1g-dev libssl-dev ninja-build autoconf libx11-dev libx11-xcb-dev libfontenc-dev libice-dev libsm-dev libxau-dev libxaw7-dev libxcomposite-dev libxcursor-dev libxdamage-dev libxdmcp-dev libxext-dev libxfixes-dev libxi-dev libxinerama-dev libxkbfile-dev libxmu-dev libxmuu-dev libxpm-dev libxrandr-dev libxrender-dev libxres-dev libxss-dev libxt-dev libxtst-dev libxv-dev libxvmc-dev libxxf86vm-dev xtrans-dev libxcb-render0-dev libxcb-render-util0-dev libxcb-xkb-dev libxcb-icccm4-dev libxcb-image0-dev libxcb-keysyms1-dev libxcb-randr0-dev libxcb-shape0-dev libxcb-sync-dev libxcb-xfixes0-dev libxcb-xinerama0-dev xkb-data libxcb-dri3-dev uuid-dev libxcb-util-dev libxkbcommon-x11-dev pkg-config -y + sudo apt install build-essential checkinstall libegl-dev zlib1g-dev libssl-dev ninja-build autoconf libx11-dev libx11-xcb-dev libfontenc-dev libice-dev libsm-dev libxau-dev libxaw7-dev libxcomposite-dev libxcursor-dev libxdamage-dev libxdmcp-dev libxext-dev libxfixes-dev libxi-dev libxinerama-dev libxkbfile-dev libxmu-dev libxmuu-dev libxpm-dev libxrandr-dev libxrender-dev libxres-dev libxss-dev libxt-dev libxtst-dev libxv-dev libxvmc-dev libxxf86vm-dev xtrans-dev libxcb-render0-dev libxcb-render-util0-dev libxcb-xkb-dev libxcb-icccm4-dev libxcb-image0-dev libxcb-keysyms1-dev libxcb-randr0-dev libxcb-shape0-dev libxcb-sync-dev libxcb-xfixes0-dev libxcb-xinerama0-dev xkb-data libxcb-dri3-dev uuid-dev libxcb-util-dev libxkbcommon-x11-dev pkg-config binutils coreutils desktop-file-utils fakeroot fuse libgdk-pixbuf2.0-dev patchelf squashfs-tools strace util-linux zsync -y + + # Get the AppImage tool wget --no-check-certificate --quiet https://github.com/AppImage/AppImageKit/releases/download/continuous/appimagetool-x86_64.AppImage -O $GITHUB_WORKSPACE/appimagetool chmod +x $GITHUB_WORKSPACE/appimagetool echo "APPIMAGETOOL_LOCATION=$GITHUB_WORKSPACE/appimagetool" >> $GITHUB_ENV + + # Get the AppImage builder + wget --no-check-certificate --quiet -O $GITHUB_WORKSPACE/appimage-builder-x86_64.AppImage https://github.com/AppImageCrafters/appimage-builder/releases/download/v1.1.0/appimage-builder-1.1.0-x86_64.AppImage + chmod +x appimage-builder-x86_64.AppImage + echo "APPIMAGEBUILDER_LOCATION=$GITHUB_WORKSPACE/appimage-builder-x86_64.AppImage" >> $GITHUB_ENV + + # Make sure these tools can be found on the path + echo "$GITHUB_WORKSPACE" >> $GITHUB_PATH - name: Install GCC-13 run: | From 68806f42267ee52a489e4712f68d1858b0de9f09 Mon Sep 17 00:00:00 2001 From: "c.lamboo" Date: Fri, 1 Sep 2023 11:11:09 +0200 Subject: [PATCH 34/54] Allow objects to be placed near border Issue before was the following: when placing objects within a grid cell there is a margin around the object. This margin comes from both the integer rounding of the cell and the defined min distance between objects. When trying to place object near the buildplate border we marked any cell that is not fully within the buildplate area as an invalid cell to place objects in. This was however too strict; there is the aforementioned margin around the object, and if only this margin would be outside the buildplate it is perfectly fine to place object in that cell. CURA-7951 --- cura/Arranging/GridArrange.py | 100 ++++++++++++++++++++-------------- 1 file changed, 58 insertions(+), 42 deletions(-) diff --git a/cura/Arranging/GridArrange.py b/cura/Arranging/GridArrange.py index 493c81b27cb..4caf472b5d3 100644 --- a/cura/Arranging/GridArrange.py +++ b/cura/Arranging/GridArrange.py @@ -1,11 +1,13 @@ import math -from typing import List, TYPE_CHECKING, Tuple, Set +from typing import List, TYPE_CHECKING, Tuple, Set, Union if TYPE_CHECKING: from UM.Scene.SceneNode import SceneNode from cura.BuildVolume import BuildVolume from UM.Application import Application +from UM.Math.AxisAlignedBox import AxisAlignedBox +from UM.Math.Polygon import Polygon from UM.Math.Vector import Vector from UM.Operations.AddSceneNodeOperation import AddSceneNodeOperation from UM.Operations.GroupedOperation import GroupedOperation @@ -34,10 +36,18 @@ def __init__(self, nodes_to_arrange: List["SceneNode"], build_volume: "BuildVolu self._grid_width += self._margin_x self._grid_height += self._margin_y - # Round up the grid size to the nearest cm + # Round up the grid size to the nearest cm, this assures that new objects will + # be placed on integer offsets from each other grid_precision = 10 # 1cm - self._grid_width = math.ceil(self._grid_width / grid_precision) * grid_precision - self._grid_height = math.ceil(self._grid_height / grid_precision) * grid_precision + rounded_grid_width = math.ceil(self._grid_width / grid_precision) * grid_precision + rounded_grid_height = math.ceil(self._grid_height / grid_precision) * grid_precision + + # The space added by the "grid precision rounding up" of the grid size + self._grid_round_margin_x = rounded_grid_width - self._grid_width + self._grid_round_margin_y = rounded_grid_height - self._grid_height + + self._grid_width = rounded_grid_width + self._grid_height = rounded_grid_height self._offset_x = 0 self._offset_y = 0 @@ -56,10 +66,9 @@ def __init__(self, nodes_to_arrange: List["SceneNode"], build_volume: "BuildVolu self._fixed_nodes_grid_ids = self._fixed_nodes_grid_ids.union( self._intersectingGridIdxInclusive(node.getBoundingBox())) - #grid indexes that are in disallowed area + # grid indexes that are in disallowed area for polygon in self._build_volume.getDisallowedAreas(): - self._fixed_nodes_grid_ids = self._fixed_nodes_grid_ids.union( - self._getIntersectingGridIdForPolygon(polygon)) + self._fixed_nodes_grid_ids = self._fixed_nodes_grid_ids.union(self._intersectingGridIdxInclusive(polygon)) self._build_plate_grid_ids = self._intersectingGridIdxExclusive(self._build_volume_bounding_box) @@ -240,51 +249,58 @@ def _moveNodeOnGrid(self, node: "SceneNode", grid_x: int, grid_y: int) -> "Opera return TranslateOperation(node, Vector(delta_x, 0, delta_y)) - def _getGridCornerPoints(self, bounding_box: "BoundingVolume") -> Tuple[float, float, float, float]: - coord_x1 = bounding_box.left - coord_x2 = bounding_box.right - coord_y1 = bounding_box.back - coord_y2 = bounding_box.front + def _getGridCornerPoints( + self, + bounds: Union[AxisAlignedBox, Polygon], + *, + margin_x: float = 0.0, + margin_y: float = 0.0 + ) -> Tuple[float, float, float, float]: + if isinstance(bounds, AxisAlignedBox): + coord_x1 = bounds.left - margin_x + coord_x2 = bounds.right + margin_x + coord_y1 = bounds.back - margin_y + coord_y2 = bounds.front + margin_y + elif isinstance(bounds, Polygon): + coord_x1 = float('inf') + coord_y1 = float('inf') + coord_x2 = float('-inf') + coord_y2 = float('-inf') + for x, y in bounds.getPoints(): + coord_x1 = min(coord_x1, x) + coord_y1 = min(coord_y1, y) + coord_x2 = max(coord_x2, x) + coord_y2 = max(coord_y2, y) + else: + raise TypeError("bounds must be either an AxisAlignedBox or a Polygon") + + coord_x1 -= margin_x + coord_x2 += margin_x + coord_y1 -= margin_y + coord_y2 += margin_y + grid_x1, grid_y1 = self._coordSpaceToGridSpace(coord_x1, coord_y1) grid_x2, grid_y2 = self._coordSpaceToGridSpace(coord_x2, coord_y2) return grid_x1, grid_y1, grid_x2, grid_y2 - def _getIntersectingGridIdForPolygon(self, polygon)-> Set[Tuple[int, int]]: - # (x0, y0) - # | - # v - # ┌─────────────┐ - # │ │ - # │ │ - # └─────────────┘ < (x1, y1) - x0 = float('inf') - y0 = float('inf') - x1 = float('-inf') - y1 = float('-inf') - grid_idx = set() - for [x, y] in polygon.getPoints(): - x0 = min(x0, x) - y0 = min(y0, y) - x1 = max(x1, x) - y1 = max(y1, y) - grid_x1, grid_y1 = self._coordSpaceToGridSpace(x0, y0) - grid_x2, grid_y2 = self._coordSpaceToGridSpace(x1, y1) - - for grid_x in range(math.floor(grid_x1), math.ceil(grid_x2)): - for grid_y in range(math.floor(grid_y1), math.ceil(grid_y2)): - grid_idx.add((grid_x, grid_y)) - return grid_idx - - def _intersectingGridIdxInclusive(self, bounding_box: "BoundingVolume") -> Set[Tuple[int, int]]: - grid_x1, grid_y1, grid_x2, grid_y2 = self._getGridCornerPoints(bounding_box) + def _intersectingGridIdxInclusive(self, bounds: Union[AxisAlignedBox, Polygon]) -> Set[Tuple[int, int]]: + grid_x1, grid_y1, grid_x2, grid_y2 = self._getGridCornerPoints( + bounds, + margin_x=-(self._margin_x + self._grid_round_margin_x) * 0.5, + margin_y=-(self._margin_y + self._grid_round_margin_y) * 0.5, + ) grid_idx = set() for grid_x in range(math.floor(grid_x1), math.ceil(grid_x2)): for grid_y in range(math.floor(grid_y1), math.ceil(grid_y2)): grid_idx.add((grid_x, grid_y)) return grid_idx - def _intersectingGridIdxExclusive(self, bounding_box: "BoundingVolume") -> Set[Tuple[int, int]]: - grid_x1, grid_y1, grid_x2, grid_y2 = self._getGridCornerPoints(bounding_box) + def _intersectingGridIdxExclusive(self, bounds: Union[AxisAlignedBox, Polygon]) -> Set[Tuple[int, int]]: + grid_x1, grid_y1, grid_x2, grid_y2 = self._getGridCornerPoints( + bounds, + margin_x=(self._margin_x + self._grid_round_margin_x) * 0.5, + margin_y=(self._margin_y + self._grid_round_margin_y) * 0.5, + ) grid_idx = set() for grid_x in range(math.ceil(grid_x1), math.floor(grid_x2)): for grid_y in range(math.ceil(grid_y1), math.floor(grid_y2)): From 7fbd716bb47260cac534f53daea1215f01d5cc60 Mon Sep 17 00:00:00 2001 From: Jelle Spijker Date: Tue, 5 Sep 2023 05:11:51 +0200 Subject: [PATCH 35/54] Bundling the Gradualflow plugin This commit simplifies the deploy method in conanfile.py by reducing the number of lines of code and refactor the handling of the Gradualflow plugin in the deploy method. In conandata.yml, the paths for the Gradualflow plugin resources have been adjusted for correct deployment. This update aims to fix the pyinstaller deployment failures associated with the Gradualflow plugin. It resolves the CURA-10951 tracking issue. Contributes CURA-10951 --- conandata.yml | 14 +++--- conanfile.py | 120 ++++++++++++++++---------------------------------- 2 files changed, 46 insertions(+), 88 deletions(-) diff --git a/conandata.yml b/conandata.yml index df87ba2113e..1bdd4f824a3 100644 --- a/conandata.yml +++ b/conandata.yml @@ -20,13 +20,13 @@ pyinstaller: src: "plugins" dst: "share/cura/plugins" curaengine_gradual_flow_plugin: - root: "." - src: "share/cura/plugins/CuraEngineGradualFlow" - dst: "share/cura/plugins/CuraEngineGradualFlow" - curaengine_gradual_flow_plugin_resources: - root: "." - src: "share/cura/resources/bundled_packages" - dst: "share/cura/resources/bundled_packages" + package: "curaengine_plugin_gradual_flow" + src: "res/plugins/CuraEngineGradualFlow" + dst: "share/cura/plugins/CuraEngineGradualFlow" + curaengine_gradual_flow_plugin_bundled: + package: "curaengine_plugin_gradual_flow" + src: "res/bundled_packages" + dst: "share/cura/resources/bundled_packages" cura_resources: package: "cura" src: "resources" diff --git a/conanfile.py b/conanfile.py index 902e5b28375..16dff0b93cd 100644 --- a/conanfile.py +++ b/conanfile.py @@ -4,7 +4,7 @@ from jinja2 import Template from conan import ConanFile -from conan.tools.files import copy, rmdir, save, mkdir +from conan.tools.files import copy, rmdir, save, mkdir, rm from conan.tools.microsoft import unix_path from conan.tools.env import VirtualRunEnv, Environment, VirtualBuildEnv from conan.tools.scm import Version @@ -21,12 +21,11 @@ class CuraConan(ConanFile): description = "3D printer / slicing GUI built on top of the Uranium framework" topics = ("conan", "python", "pyqt6", "qt", "qml", "3d-printing", "slicer") build_policy = "missing" - exports = "LICENSE*", "UltiMaker-Cura.spec.jinja", "CuraVersion.py.jinja", "AboutDialogVersionsList.qml.jinja" + exports = "LICENSE*", "*.jinja" settings = "os", "compiler", "build_type", "arch" # FIXME: Remove specific branch once merged to main - python_requires = "umbase/[>=0.1.7]@ultimaker/stable", "translationextractor/[>=2.1.1]@ultimaker/stable" - python_requires_extend = "umbase.UMBaseConanfile" + python_requires = "translationextractor/[>=2.1.1]@ultimaker/stable" options = { "enterprise": ["True", "False", "true", "false"], # Workaround for GH Action passing boolean as lowercase string @@ -359,36 +358,35 @@ def generate(self): rmdir(self,str(self.source_path.joinpath("plugins", "CuraEngineGradualFlow"))) curaengine_plugin_gradual_flow = self.dependencies["curaengine_plugin_gradual_flow"].cpp_info copy(self, "*.py", curaengine_plugin_gradual_flow.resdirs[0], str(self.source_path.joinpath("plugins", "CuraEngineGradualFlow")), keep_path = True) + ext = ".exe" if self.settings.os == "Windows" else "" + copy(self, f"curaengine_plugin_gradual_flow{ext}", curaengine_plugin_gradual_flow.resdirs[0], str(self.source_path.joinpath("plugins", "CuraEngineGradualFlow")), keep_path = True) copy(self, "*.json", curaengine_plugin_gradual_flow.resdirs[0], str(self.source_path.joinpath("plugins", "CuraEngineGradualFlow")), keep_path = True) - copy(self, "bundled_*.json", curaengine_plugin_gradual_flow.resdirs[0], str(self.source_path.joinpath("resources", "bundled_packages")), keep_path = False) - curaengine_plugin_gradual_flow_binary_path = self.source_path.joinpath("plugins", "CuraEngineGradualFlow", {"armv8": "arm64"}.get(str(self.settings.arch), str(self.settings.arch)), {"Macos": "Darwin"}.get(str(self.settings.os), str(self.settings.os))) - copy(self, "curaengine_plugin_gradual_flow.exe", curaengine_plugin_gradual_flow.bindirs[0], curaengine_plugin_gradual_flow_binary_path, keep_path = False) - copy(self, "curaengine_plugin_gradual_flow", curaengine_plugin_gradual_flow.bindirs[0], curaengine_plugin_gradual_flow_binary_path, keep_path = False) - - # Copy resources of cura_binary_data - cura_binary_data = self.dependencies["cura_binary_data"].cpp_info - copy(self, "*", cura_binary_data.resdirs[0], str(self._share_dir.joinpath("cura")), keep_path = True) - copy(self, "*", cura_binary_data.resdirs[1], str(self._share_dir.joinpath("uranium")), keep_path = True) - if self.settings.os == "Windows": - copy(self, "*", cura_binary_data.resdirs[2], str(self._share_dir.joinpath("windows")), keep_path = True) - - for dependency in self.dependencies.host.values(): - for bindir in dependency.cpp_info.bindirs: - copy(self, "*.dll", bindir, str(self._site_packages), keep_path = False) - for libdir in dependency.cpp_info.libdirs: - copy(self, "*.pyd", libdir, str(self._site_packages), keep_path = False) - copy(self, "*.pyi", libdir, str(self._site_packages), keep_path = False) - copy(self, "*.dylib", libdir, str(self._base_dir.joinpath("lib")), keep_path = False) - - # Copy materials (flat) - rmdir(self, os.path.join(self.source_folder, "resources", "materials")) - fdm_materials = self.dependencies["fdm_materials"].cpp_info - copy(self, "*", fdm_materials.resdirs[0], self.source_folder) - - # Copy internal resources - if self.options.internal: - cura_private_data = self.dependencies["cura_private_data"].cpp_info - copy(self, "*", cura_private_data.resdirs[0], str(self._share_dir.joinpath("cura"))) + copy(self, "bundled_*.json", curaengine_plugin_gradual_flow.resdirs[1], str(self.source_path.joinpath("resources", "bundled_packages")), keep_path = False) + + # Copy resources of cura_binary_data + cura_binary_data = self.dependencies["cura_binary_data"].cpp_info + copy(self, "*", cura_binary_data.resdirs[0], str(self._share_dir.joinpath("cura")), keep_path = True) + copy(self, "*", cura_binary_data.resdirs[1], str(self._share_dir.joinpath("uranium")), keep_path = True) + if self.settings.os == "Windows": + copy(self, "*", cura_binary_data.resdirs[2], str(self._share_dir.joinpath("windows")), keep_path = True) + + for dependency in self.dependencies.host.values(): + for bindir in dependency.cpp_info.bindirs: + copy(self, "*.dll", bindir, str(self._site_packages), keep_path = False) + for libdir in dependency.cpp_info.libdirs: + copy(self, "*.pyd", libdir, str(self._site_packages), keep_path = False) + copy(self, "*.pyi", libdir, str(self._site_packages), keep_path = False) + copy(self, "*.dylib", libdir, str(self._base_dir.joinpath("lib")), keep_path = False) + + # Copy materials (flat) + rmdir(self, os.path.join(self.source_folder, "resources", "materials")) + fdm_materials = self.dependencies["fdm_materials"].cpp_info + copy(self, "*", fdm_materials.resdirs[0], self.source_folder) + + # Copy internal resources + if self.options.internal: + cura_private_data = self.dependencies["cura_private_data"].cpp_info + copy(self, "*", cura_private_data.resdirs[0], str(self._share_dir.joinpath("cura"))) if self.options.devtools: entitlements_file = "'{}'".format(os.path.join(self.source_folder, "packaging", "MacOS", "cura.entitlements")) @@ -419,65 +417,18 @@ def build(self): self.run(f"{cpp_info.bindirs[0]}/msgfmt {po_file} -o {mo_file} -f", env="conanbuild", ignore_errors=True) def deploy(self): - # Copy CuraEngine.exe to bindirs of Virtual Python Environment - curaengine = self.dependencies["curaengine"].cpp_info - copy(self, "CuraEngine.exe", curaengine.bindirs[0], str(self._base_dir), keep_path = False) - copy(self, "CuraEngine", curaengine.bindirs[0], str(self._base_dir), keep_path = False) - - # Copy resources of Cura (keep folder structure) + # Copy resources of Cura (keep folder structure) needed by pyinstaller to determine the module structure copy(self, "*", os.path.join(self.package_folder, self.cpp_info.bindirs[0]), str(self._base_dir), keep_path = False) copy(self, "*", os.path.join(self.package_folder, self.cpp_info.libdirs[0]), str(self._site_packages.joinpath("cura")), keep_path = True) copy(self, "*", os.path.join(self.package_folder, self.cpp_info.resdirs[0]), str(self._share_dir.joinpath("cura", "resources")), keep_path = True) copy(self, "*", os.path.join(self.package_folder, self.cpp_info.resdirs[1]), str(self._share_dir.joinpath("cura", "plugins")), keep_path = True) - # Copy the external plugins that we want to bundle with Cura - curaengine_plugin_gradual_flow = self.dependencies["curaengine_plugin_gradual_flow"].cpp_info - copy(self, "*.py", curaengine_plugin_gradual_flow.resdirs[0], str(self._share_dir.joinpath("cura", "plugins")), keep_path = True) - copy(self, "*.json", curaengine_plugin_gradual_flow.resdirs[0], str(self._share_dir.joinpath("cura", "plugins")), keep_path = True) - copy(self, "bundled_*.json", curaengine_plugin_gradual_flow.resdirs[0], str(self._share_dir.joinpath("cura", "resources", "bundled_packages")), keep_path = False) - curaengine_plugin_gradual_flow_binary_path = self._share_dir.joinpath("cura", "plugins", "CuraEngineGradualFlow", {"armv8": "arm64"}.get(str(self.settings.arch), str(self.settings.arch)), {"Macos": "Darwin"}.get(str(self.settings.os), str(self.settings.os))) - copy(self, "curaengine_plugin_gradual_flow.exe", curaengine_plugin_gradual_flow.bindirs[0], curaengine_plugin_gradual_flow_binary_path, keep_path = False) - copy(self, "curaengine_plugin_gradual_flow", curaengine_plugin_gradual_flow.bindirs[0], curaengine_plugin_gradual_flow_binary_path, keep_path = False) - - # Copy materials (flat) - fdm_materials = self.dependencies["fdm_materials"].cpp_info - copy(self, "*", fdm_materials.resdirs[0], str(self._share_dir.joinpath("cura"))) - - # Copy internal resources - if self.options.internal: - cura_private_data = self.dependencies["cura_private_data"].cpp_info - copy(self, "*", cura_private_data.resdirs[0], str(self._share_dir.joinpath("cura"))) - # Copy resources of Uranium (keep folder structure) uranium = self.dependencies["uranium"].cpp_info copy(self, "*", uranium.resdirs[0], str(self._share_dir.joinpath("uranium", "resources")), keep_path = True) copy(self, "*", uranium.resdirs[1], str(self._share_dir.joinpath("uranium", "plugins")), keep_path = True) copy(self, "*", uranium.libdirs[0], str(self._site_packages.joinpath("UM")), keep_path = True) - # TODO: figure out if this is still needed - copy(self, "*", os.path.join(uranium.libdirs[0], "Qt", "qml", "UM"), str(self._site_packages.joinpath("PyQt6", "Qt6", "qml", "UM")), keep_path = True) - - # Copy resources of cura_binary_data - cura_binary_data = self.dependencies["cura_binary_data"].cpp_info - copy(self, "*", cura_binary_data.resdirs[0], str(self._share_dir.joinpath("cura")), keep_path = True) - copy(self, "*", cura_binary_data.resdirs[1], str(self._share_dir.joinpath("uranium")), keep_path = True) - if self.settings.os == "Windows": - copy(self, "*", cura_binary_data.resdirs[2], str(self._share_dir.joinpath("windows")), keep_path = True) - - for dependency in self.dependencies.host.values(): - for bindir in dependency.cpp_info.bindirs: - copy(self, "*.dll", bindir, str(self._site_packages), keep_path = False) - for libdir in dependency.cpp_info.libdirs: - copy(self, "*.pyd", libdir, str(self._site_packages), keep_path = False) - copy(self, "*.pyi", libdir, str(self._site_packages), keep_path = False) - copy(self, "*.dylib", libdir, str(self._base_dir.joinpath("lib")), keep_path = False) - - # Copy packaging scripts - copy(self, "*", os.path.join(self.package_folder, self.cpp_info.resdirs[2]), str(self._base_dir.joinpath("packaging")), keep_path = True) - - # Copy requirements.txt's - copy(self, "*.txt", os.path.join(self.package_folder, self.cpp_info.resdirs[-1]), str(self._base_dir.joinpath("pip_requirements")), keep_path = False) - # Generate the GitHub Action version info Environment version = self.conf_info.get("user.cura:version", default = self.version, check_type = str) cura_version = Version(version) @@ -517,6 +468,13 @@ def package(self): copy(self, "requirement*.txt", src = self.source_folder, dst = os.path.join(self.package_folder, self.cpp.package.resdirs[-1])) copy(self, "*", src = os.path.join(self.source_folder, "packaging"), dst = os.path.join(self.package_folder, self.cpp.package.resdirs[2])) + # Remove the CuraEngineGradualFlow plugin from the package + rmdir(self, os.path.join(self.package_folder, self.cpp.package.resdirs[1], "CuraEngineGradualFlow")) + rm(self, "bundled_*.json", os.path.join(self.package_folder, self.cpp.package.resdirs[0], "bundled_packages"), recursive = False) + + # Remove the fdm_materials from the package + rmdir(self, os.path.join(self.package_folder, self.cpp.package.resdirs[0], "materials")) + def package_info(self): self.user_info.pip_requirements = "requirements.txt" self.user_info.pip_requirements_git = "requirements-ultimaker.txt" From b5fbcce33fba131c9cb57eaafb5f2eac0433946e Mon Sep 17 00:00:00 2001 From: Jelle Spijker Date: Tue, 5 Sep 2023 05:13:21 +0200 Subject: [PATCH 36/54] Add AppImage builder configs and scripts Added the configuration file `AppImageBuilder.yml.jinja`, the Python script `create_appimage.py`, and the shell script `entrypoint.sh.jinja` for AppImage building and packaging. These additions would enable the Cura application to be built into a single, standalone, executables file for Linux users, improving software deployment and distribution. Contributes CURA-10951 --- .../AppImageBuilder.yml.jinja | 90 +++++++++++++++++ packaging/AppImage-builder/create_appimage.py | 99 +++++++++++++++++++ .../AppImage-builder/entrypoint.sh.jinja | 8 ++ 3 files changed, 197 insertions(+) create mode 100644 packaging/AppImage-builder/AppImageBuilder.yml.jinja create mode 100644 packaging/AppImage-builder/create_appimage.py create mode 100644 packaging/AppImage-builder/entrypoint.sh.jinja diff --git a/packaging/AppImage-builder/AppImageBuilder.yml.jinja b/packaging/AppImage-builder/AppImageBuilder.yml.jinja new file mode 100644 index 00000000000..cb446af5207 --- /dev/null +++ b/packaging/AppImage-builder/AppImageBuilder.yml.jinja @@ -0,0 +1,90 @@ +version: 1 + +AppDir: + path: {{ app_dir }} + app_info: + id: com.ultimaker.cura + name: UltiMaker-Cura + icon: {{ icon }} + version: {{ version }} + exec: entrypoint.sh + exec_args: $@ + apt: + arch: + - amd64 + allow_unauthenticated: true + sources: + - sourceline: deb http://nl.archive.ubuntu.com/ubuntu/ jammy main restricted + - sourceline: deb http://nl.archive.ubuntu.com/ubuntu/ jammy-updates main restricted + - sourceline: deb http://nl.archive.ubuntu.com/ubuntu/ jammy universe + - sourceline: deb http://nl.archive.ubuntu.com/ubuntu/ jammy-updates universe + - sourceline: deb http://nl.archive.ubuntu.com/ubuntu/ jammy multiverse + - sourceline: deb http://nl.archive.ubuntu.com/ubuntu/ jammy-updates multiverse + - sourceline: deb http://nl.archive.ubuntu.com/ubuntu/ jammy-backports main restricted + universe multiverse + - sourceline: deb http://security.ubuntu.com/ubuntu jammy-security main restricted + - sourceline: deb http://security.ubuntu.com/ubuntu jammy-security universe + - sourceline: deb http://security.ubuntu.com/ubuntu jammy-security multiverse + - sourceline: deb https://releases.jfrog.io/artifactory/jfrog-debs xenial contrib + - sourceline: deb http://apt.llvm.org/jammy/ llvm-toolchain-jammy-14 main + - sourceline: deb https://ppa.launchpadcontent.net/ubuntu-toolchain-r/test/ubuntu/ + jammy main + - sourceline: deb https://ppa.launchpadcontent.net/deadsnakes/ppa/ubuntu/ jammy + main + - sourceline: deb [arch=amd64] https://packages.microsoft.com/repos/ms-teams stable + main + - sourceline: deb https://ppa.launchpadcontent.net/ppa-verse/cling/ubuntu/ jammy + main + - sourceline: deb [arch=amd64] https://dl.google.com/linux/chrome/deb/ stable + main + - sourceline: deb [signed-by=/usr/share/keyrings/nodesource.gpg] https://deb.nodesource.com/node_14.x + jammy main + - sourceline: deb [arch=amd64 signed-by=/usr/share/keyrings/transip-stack.gpg] + https://mirror.transip.net/stack/software/deb/Ubuntu_22.04/ ./ + - sourceline: deb http://repository.spotify.com stable non-free + - sourceline: deb [arch=amd64,arm64,armhf] http://packages.microsoft.com/repos/code + stable main + - sourceline: deb https://packagecloud.io/slacktechnologies/slack/debian/ jessie + main + include: + - libc6:amd64 + - xdg-desktop-portal-kde:amd64 + files: + include: [] + exclude: + - usr/share/man + - usr/share/doc/*/README.* + - usr/share/doc/*/changelog.* + - usr/share/doc/*/NEWS.* + - usr/share/doc/*/TODO.* + runtime: + env: + PYTHONPATH: "$APPDIR" + QT_PLUGIN_PATH: "$APPDIR/qt/plugins" + QML2_IMPORT_PATH: "$APPDIR/qt/qml" + QT_QPA_PLATFORMTHEME: xdgdesktopportal + test: + fedora-30: + image: appimagecrafters/tests-env:fedora-30 + command: ./AppRun + use_host_x: True + debian-stable: + image: appimagecrafters/tests-env:debian-stable + command: ./AppRun + use_host_x: True + archlinux-latest: + image: appimagecrafters/tests-env:archlinux-latest + command: ./AppRun + use_host_x: True + centos-7: + image: appimagecrafters/tests-env:centos-7 + command: ./AppRun + use_host_x: True + ubuntu-xenial: + image: appimagecrafters/tests-env:ubuntu-xenial + command: ./AppRun + use_host_x: True +AppImage: + arch: {{ arch }} + file_name: {{ file_name }} + update-information: guess diff --git a/packaging/AppImage-builder/create_appimage.py b/packaging/AppImage-builder/create_appimage.py new file mode 100644 index 00000000000..33d13ee5ada --- /dev/null +++ b/packaging/AppImage-builder/create_appimage.py @@ -0,0 +1,99 @@ +# Copyright (c) 2023 UltiMaker +# Cura is released under the terms of the LGPLv3 or higher. + + +import argparse # Command line arguments parsing and help. +from jinja2 import Template +import os # Finding installation directory. +import os.path # Finding files. +import shutil # Copying files. +import stat # For setting file permissions. +import subprocess # For calling system commands. + +def build_appimage(dist_path, version, appimage_filename): + """ + Creates an AppImage file from the build artefacts created so far. + """ + generate_appimage_builder_config(dist_path, version, appimage_filename) + generate_appimage_entrypoint(dist_path) + copy_files(dist_path) + + try: + os.remove(os.path.join(dist_path, appimage_filename)) # Ensure any old file is removed, if it exists. + except FileNotFoundError: + pass # If it didn't exist, that's even better. + create_appimage(dist_path, appimage_filename) + sign_appimage(dist_path, appimage_filename) + + +def generate_appimage_builder_config(dist_path, version, appimage_filename): + with open(os.path.join(dist_path, "AppImageBuilder.yml.jinja"), "r") as appimage_builder_file: + appimage_builder = appimage_builder_file.read() + + template = Template(appimage_builder) + appimage_builder = template.render(app_dir = dist_path, + icon = os.path.join("..", "icons", "cura-icon_256x256.png"), + version = version, + arch = "x86_64", + file_name = appimage_filename) + + with open(os.path.join(dist_path, "AppImageBuilder.yml"), "w") as appimage_builder_file: + appimage_builder_file.write(appimage_builder) + + +def generate_appimage_entrypoint(dist_path): + with open(os.path.join(dist_path, "entrypoint.sh.jinja"), "r") as entrypoint_file: + entrypoint = entrypoint_file.read() + + template = Template(entrypoint) + entrypoint = template.render(executable = "UltiMaker-Cura") + + with open(os.path.join(dist_path, "entrypoint.sh"), "w") as entrypoint_file: + entrypoint_file.write(entrypoint) + +def copy_files(dist_path): + """ + Copy metadata files for the metadata of the AppImage. + """ + copied_files = { + os.path.join("..", "icons", "cura-icon.svg"): os.path.join("usr", "share", "icons", "hicolor", "scalable", "apps", "cura-icon.svg"), + os.path.join("..", "icons", "cura-icon_64x64.png"): os.path.join("usr", "share", "icons", "hicolor", "64x64", "apps", "cura-icon.png"), + os.path.join("..", "icons", "cura-icon_128x128.png"): os.path.join("usr", "share", "icons", "hicolor", "128x128", "apps", "cura-icon.png"), + os.path.join("..", "icons", "cura-icon_256x256.png"): os.path.join("usr", "share", "icons", "hicolor", "256x256", "apps", "cura-icon.png"), + os.path.join("..", "icons", "cura-icon_256x256.png"): "cura-icon.png", + "entrypoint.sh": "entrypoint.sh" + } + + # TODO: openssl.cnf ??? + + packaging_dir = os.path.dirname(__file__) + for source, dest in copied_files.items(): + dest_file_path = os.path.join(dist_path, dest) + os.makedirs(os.path.dirname(dest_file_path), exist_ok=True) + shutil.copyfile(os.path.join(packaging_dir, source), dest_file_path) + + # Ensure that entrypoint.sh has the proper permissions: 755 (user reads, writes and executes, group reads and executes, world reads and executes). + os.chmod(os.path.join(dist_path, "entrypoint.sh"), stat.S_IRUSR | stat.S_IWUSR | stat.S_IXUSR | stat.S_IRGRP | stat.S_IXGRP | stat.S_IROTH | stat.S_IXOTH) + +def create_appimage(dist_path, appimage_filename): + appimage_path = os.path.join(dist_path, "..", appimage_filename) + appimagetool = os.getenv("APPIMAGETOOL_LOCATION", "appimagetool") + command = [appimagetool, "--appimage-extract-and-run", f"{dist_path}/", appimage_path] + result = subprocess.call(command) + if result != 0: + raise RuntimeError(f"The AppImageTool command returned non-zero: {result}") + +def sign_appimage(dist_path, appimage_filename): + appimage_path = os.path.join(dist_path, "..", appimage_filename) + command = ["gpg", "--yes", "--armor", "--detach-sig", appimage_path] + result = subprocess.call(command) + if result != 0: + raise RuntimeError(f"The GPG command returned non-zero: {result}") + +if __name__ == "__main__": + parser = argparse.ArgumentParser(description = "Create AppImages of Cura.") + parser.add_argument("dist_path", type=str, help="Path to where PyInstaller installed the distribution of Cura.") + parser.add_argument("version", type=str, help="Full version number of Cura (e.g. '5.1.0-beta')") + parser.add_argument("filename", type = str, help = "Filename of the AppImage (e.g. 'UltiMaker-Cura-5.1.0-beta-Linux-X64.AppImage')") + args = parser.parse_args() + build_appimage(args.dist_path, args.version, args.filename) diff --git a/packaging/AppImage-builder/entrypoint.sh.jinja b/packaging/AppImage-builder/entrypoint.sh.jinja new file mode 100644 index 00000000000..6ff63e6c633 --- /dev/null +++ b/packaging/AppImage-builder/entrypoint.sh.jinja @@ -0,0 +1,8 @@ +#!/bin/bash + +BIN=`basename "$ARGV0" .AppImage` +if [ -f ${APPDIR}/$BIN ]; then + ${APPDIR}/$BIN "$@" +else + ${APPDIR}/{{ executable }} "$@" +fi; \ No newline at end of file From f1df7f67d5326ce5f0d09ad5f0a254df970d61e9 Mon Sep 17 00:00:00 2001 From: Jelle Spijker Date: Tue, 5 Sep 2023 05:20:34 +0200 Subject: [PATCH 37/54] deploy packaging scripts Contributes CURA-10951 --- conanfile.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/conanfile.py b/conanfile.py index 16dff0b93cd..083f2b43f60 100644 --- a/conanfile.py +++ b/conanfile.py @@ -417,6 +417,8 @@ def build(self): self.run(f"{cpp_info.bindirs[0]}/msgfmt {po_file} -o {mo_file} -f", env="conanbuild", ignore_errors=True) def deploy(self): + copy(self, "*", os.path.join(self.package_folder, self.cpp.package.resdirs[2]), os.path.join(self.install_folder, "packaging"), keep_path = True) + # Copy resources of Cura (keep folder structure) needed by pyinstaller to determine the module structure copy(self, "*", os.path.join(self.package_folder, self.cpp_info.bindirs[0]), str(self._base_dir), keep_path = False) copy(self, "*", os.path.join(self.package_folder, self.cpp_info.libdirs[0]), str(self._site_packages.joinpath("cura")), keep_path = True) From c5e38211165390692f93cba70b832b182ed2e766 Mon Sep 17 00:00:00 2001 From: Jelle Spijker Date: Tue, 5 Sep 2023 06:12:47 +0200 Subject: [PATCH 38/54] Fix the AppImage-builder scripts Contributes CURA-10951 --- .github/workflows/linux.yml | 2 +- .../AppImageBuilder.yml.jinja | 2 +- packaging/AppImage-builder/create_appimage.py | 37 ++++++++++++------- 3 files changed, 25 insertions(+), 16 deletions(-) diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml index f1b627cb759..520687d7485 100644 --- a/.github/workflows/linux.yml +++ b/.github/workflows/linux.yml @@ -245,7 +245,7 @@ jobs: - name: Create the Linux AppImage (Bash) run: | - python ../cura_inst/packaging/AppImage/create_appimage.py ./UltiMaker-Cura $CURA_VERSION_FULL "${{ steps.filename.outputs.INSTALLER_FILENAME }}.AppImage" + python ../cura_inst/packaging/AppImage-builder/create_appimage.py ./UltiMaker-Cura $CURA_VERSION_FULL "${{ steps.filename.outputs.INSTALLER_FILENAME }}.AppImage" chmod +x "${{ steps.filename.outputs.INSTALLER_FILENAME }}.AppImage" working-directory: dist diff --git a/packaging/AppImage-builder/AppImageBuilder.yml.jinja b/packaging/AppImage-builder/AppImageBuilder.yml.jinja index cb446af5207..270279af3b3 100644 --- a/packaging/AppImage-builder/AppImageBuilder.yml.jinja +++ b/packaging/AppImage-builder/AppImageBuilder.yml.jinja @@ -7,7 +7,7 @@ AppDir: name: UltiMaker-Cura icon: {{ icon }} version: {{ version }} - exec: entrypoint.sh + exec: UltiMaker-Cura exec_args: $@ apt: arch: diff --git a/packaging/AppImage-builder/create_appimage.py b/packaging/AppImage-builder/create_appimage.py index 33d13ee5ada..03f13279e2c 100644 --- a/packaging/AppImage-builder/create_appimage.py +++ b/packaging/AppImage-builder/create_appimage.py @@ -2,6 +2,7 @@ # Cura is released under the terms of the LGPLv3 or higher. +from pathlib import Path import argparse # Command line arguments parsing and help. from jinja2 import Template import os # Finding installation directory. @@ -10,6 +11,7 @@ import stat # For setting file permissions. import subprocess # For calling system commands. + def build_appimage(dist_path, version, appimage_filename): """ Creates an AppImage file from the build artefacts created so far. @@ -27,37 +29,38 @@ def build_appimage(dist_path, version, appimage_filename): def generate_appimage_builder_config(dist_path, version, appimage_filename): - with open(os.path.join(dist_path, "AppImageBuilder.yml.jinja"), "r") as appimage_builder_file: + with open(os.path.join(Path(__file__).parent, "AppImageBuilder.yml.jinja"), "r") as appimage_builder_file: appimage_builder = appimage_builder_file.read() template = Template(appimage_builder) - appimage_builder = template.render(app_dir = dist_path, - icon = os.path.join("..", "icons", "cura-icon_256x256.png"), + appimage_builder = template.render(app_dir = "./AppDir", + icon = "cura-icon.png", version = version, arch = "x86_64", file_name = appimage_filename) - with open(os.path.join(dist_path, "AppImageBuilder.yml"), "w") as appimage_builder_file: + with open(os.path.join(Path(__file__).parent, "AppImageBuilder.yml"), "w") as appimage_builder_file: appimage_builder_file.write(appimage_builder) def generate_appimage_entrypoint(dist_path): - with open(os.path.join(dist_path, "entrypoint.sh.jinja"), "r") as entrypoint_file: + with open(os.path.join(Path(__file__).parent, "entrypoint.sh.jinja"), "r") as entrypoint_file: entrypoint = entrypoint_file.read() template = Template(entrypoint) entrypoint = template.render(executable = "UltiMaker-Cura") - with open(os.path.join(dist_path, "entrypoint.sh"), "w") as entrypoint_file: + with open(os.path.join(Path(__file__).parent, "entrypoint.sh"), "w") as entrypoint_file: entrypoint_file.write(entrypoint) + def copy_files(dist_path): """ Copy metadata files for the metadata of the AppImage. """ copied_files = { - os.path.join("..", "icons", "cura-icon.svg"): os.path.join("usr", "share", "icons", "hicolor", "scalable", "apps", "cura-icon.svg"), - os.path.join("..", "icons", "cura-icon_64x64.png"): os.path.join("usr", "share", "icons", "hicolor", "64x64", "apps", "cura-icon.png"), + os.path.join("..", "icons", "cura-icon.svg"): os.path.join("usr", "share", "icons", "hicolor", "scalable", "apps", "cura-icon.svg"), + os.path.join("..", "icons", "cura-icon_64x64.png"): os.path.join("usr", "share", "icons", "hicolor", "64x64", "apps", "cura-icon.png"), os.path.join("..", "icons", "cura-icon_128x128.png"): os.path.join("usr", "share", "icons", "hicolor", "128x128", "apps", "cura-icon.png"), os.path.join("..", "icons", "cura-icon_256x256.png"): os.path.join("usr", "share", "icons", "hicolor", "256x256", "apps", "cura-icon.png"), os.path.join("..", "icons", "cura-icon_256x256.png"): "cura-icon.png", @@ -69,20 +72,25 @@ def copy_files(dist_path): packaging_dir = os.path.dirname(__file__) for source, dest in copied_files.items(): dest_file_path = os.path.join(dist_path, dest) - os.makedirs(os.path.dirname(dest_file_path), exist_ok=True) + os.makedirs(os.path.dirname(dest_file_path), exist_ok = True) shutil.copyfile(os.path.join(packaging_dir, source), dest_file_path) # Ensure that entrypoint.sh has the proper permissions: 755 (user reads, writes and executes, group reads and executes, world reads and executes). os.chmod(os.path.join(dist_path, "entrypoint.sh"), stat.S_IRUSR | stat.S_IWUSR | stat.S_IXUSR | stat.S_IRGRP | stat.S_IXGRP | stat.S_IROTH | stat.S_IXOTH) + def create_appimage(dist_path, appimage_filename): - appimage_path = os.path.join(dist_path, "..", appimage_filename) - appimagetool = os.getenv("APPIMAGETOOL_LOCATION", "appimagetool") - command = [appimagetool, "--appimage-extract-and-run", f"{dist_path}/", appimage_path] + try: + os.rename(dist_path, "AppDir") + except OSError: + pass + appimagetool = os.getenv("APPIMAGEBUILDER_LOCATION", "appimage-builder-x86_64.AppImage") + command = [appimagetool, "--recipe", os.path.join(Path(__file__).parent, "AppImageBuilder.yml")] result = subprocess.call(command) if result != 0: raise RuntimeError(f"The AppImageTool command returned non-zero: {result}") + def sign_appimage(dist_path, appimage_filename): appimage_path = os.path.join(dist_path, "..", appimage_filename) command = ["gpg", "--yes", "--armor", "--detach-sig", appimage_path] @@ -90,10 +98,11 @@ def sign_appimage(dist_path, appimage_filename): if result != 0: raise RuntimeError(f"The GPG command returned non-zero: {result}") + if __name__ == "__main__": parser = argparse.ArgumentParser(description = "Create AppImages of Cura.") - parser.add_argument("dist_path", type=str, help="Path to where PyInstaller installed the distribution of Cura.") - parser.add_argument("version", type=str, help="Full version number of Cura (e.g. '5.1.0-beta')") + parser.add_argument("dist_path", type = str, help = "Path to where PyInstaller installed the distribution of Cura.") + parser.add_argument("version", type = str, help = "Full version number of Cura (e.g. '5.1.0-beta')") parser.add_argument("filename", type = str, help = "Filename of the AppImage (e.g. 'UltiMaker-Cura-5.1.0-beta-Linux-X64.AppImage')") args = parser.parse_args() build_appimage(args.dist_path, args.version, args.filename) From e558b11ebdab3b9db70e6c133c3b0637612c5eb4 Mon Sep 17 00:00:00 2001 From: Jelle Spijker Date: Tue, 5 Sep 2023 06:32:06 +0200 Subject: [PATCH 39/54] Minor fixes Contributes CURA-10951 --- packaging/AppImage-builder/create_appimage.py | 63 +++++++++---------- .../AppImage-builder/entrypoint.sh.jinja | 8 --- 2 files changed, 29 insertions(+), 42 deletions(-) delete mode 100644 packaging/AppImage-builder/entrypoint.sh.jinja diff --git a/packaging/AppImage-builder/create_appimage.py b/packaging/AppImage-builder/create_appimage.py index 03f13279e2c..a91ac04139a 100644 --- a/packaging/AppImage-builder/create_appimage.py +++ b/packaging/AppImage-builder/create_appimage.py @@ -1,15 +1,35 @@ # Copyright (c) 2023 UltiMaker # Cura is released under the terms of the LGPLv3 or higher. +import argparse +import os +import shutil +import subprocess from pathlib import Path -import argparse # Command line arguments parsing and help. + from jinja2 import Template -import os # Finding installation directory. -import os.path # Finding files. -import shutil # Copying files. -import stat # For setting file permissions. -import subprocess # For calling system commands. + + +def prepare_workspace(dist_path, appimage_filename): + """ + Prepare the workspace for building the AppImage. + :param dist_path: Path to the distribution of Cura created with pyinstaller. + :param appimage_filename: name of the AppImage file. + :return: + """ + if not os.path.exists(dist_path): + raise RuntimeError(f"The dist_path {dist_path} does not exist.") + + if os.path.exists(os.path.join(dist_path, appimage_filename)): + os.remove(os.path.join(dist_path, appimage_filename)) + + if not os.path.exists("AppDir"): + shutil.move(dist_path, "AppDir") + else: + print(f"AppDir already exists, assuming it is already prepared.") + + copy_files("AppDir") def build_appimage(dist_path, version, appimage_filename): @@ -17,14 +37,7 @@ def build_appimage(dist_path, version, appimage_filename): Creates an AppImage file from the build artefacts created so far. """ generate_appimage_builder_config(dist_path, version, appimage_filename) - generate_appimage_entrypoint(dist_path) - copy_files(dist_path) - - try: - os.remove(os.path.join(dist_path, appimage_filename)) # Ensure any old file is removed, if it exists. - except FileNotFoundError: - pass # If it didn't exist, that's even better. - create_appimage(dist_path, appimage_filename) + create_appimage() sign_appimage(dist_path, appimage_filename) @@ -43,17 +56,6 @@ def generate_appimage_builder_config(dist_path, version, appimage_filename): appimage_builder_file.write(appimage_builder) -def generate_appimage_entrypoint(dist_path): - with open(os.path.join(Path(__file__).parent, "entrypoint.sh.jinja"), "r") as entrypoint_file: - entrypoint = entrypoint_file.read() - - template = Template(entrypoint) - entrypoint = template.render(executable = "UltiMaker-Cura") - - with open(os.path.join(Path(__file__).parent, "entrypoint.sh"), "w") as entrypoint_file: - entrypoint_file.write(entrypoint) - - def copy_files(dist_path): """ Copy metadata files for the metadata of the AppImage. @@ -64,7 +66,6 @@ def copy_files(dist_path): os.path.join("..", "icons", "cura-icon_128x128.png"): os.path.join("usr", "share", "icons", "hicolor", "128x128", "apps", "cura-icon.png"), os.path.join("..", "icons", "cura-icon_256x256.png"): os.path.join("usr", "share", "icons", "hicolor", "256x256", "apps", "cura-icon.png"), os.path.join("..", "icons", "cura-icon_256x256.png"): "cura-icon.png", - "entrypoint.sh": "entrypoint.sh" } # TODO: openssl.cnf ??? @@ -75,15 +76,8 @@ def copy_files(dist_path): os.makedirs(os.path.dirname(dest_file_path), exist_ok = True) shutil.copyfile(os.path.join(packaging_dir, source), dest_file_path) - # Ensure that entrypoint.sh has the proper permissions: 755 (user reads, writes and executes, group reads and executes, world reads and executes). - os.chmod(os.path.join(dist_path, "entrypoint.sh"), stat.S_IRUSR | stat.S_IWUSR | stat.S_IXUSR | stat.S_IRGRP | stat.S_IXGRP | stat.S_IROTH | stat.S_IXOTH) - -def create_appimage(dist_path, appimage_filename): - try: - os.rename(dist_path, "AppDir") - except OSError: - pass +def create_appimage(): appimagetool = os.getenv("APPIMAGEBUILDER_LOCATION", "appimage-builder-x86_64.AppImage") command = [appimagetool, "--recipe", os.path.join(Path(__file__).parent, "AppImageBuilder.yml")] result = subprocess.call(command) @@ -105,4 +99,5 @@ def sign_appimage(dist_path, appimage_filename): parser.add_argument("version", type = str, help = "Full version number of Cura (e.g. '5.1.0-beta')") parser.add_argument("filename", type = str, help = "Filename of the AppImage (e.g. 'UltiMaker-Cura-5.1.0-beta-Linux-X64.AppImage')") args = parser.parse_args() + prepare_workspace(args.dist_path, args.filename) build_appimage(args.dist_path, args.version, args.filename) diff --git a/packaging/AppImage-builder/entrypoint.sh.jinja b/packaging/AppImage-builder/entrypoint.sh.jinja deleted file mode 100644 index 6ff63e6c633..00000000000 --- a/packaging/AppImage-builder/entrypoint.sh.jinja +++ /dev/null @@ -1,8 +0,0 @@ -#!/bin/bash - -BIN=`basename "$ARGV0" .AppImage` -if [ -f ${APPDIR}/$BIN ]; then - ${APPDIR}/$BIN "$@" -else - ${APPDIR}/{{ executable }} "$@" -fi; \ No newline at end of file From c29fcd7dcea9af355e1340d45f16e96667684590 Mon Sep 17 00:00:00 2001 From: Jelle Spijker Date: Tue, 5 Sep 2023 07:24:14 +0200 Subject: [PATCH 40/54] Skip the AppImage test Contributes CURA-10951 --- packaging/AppImage-builder/create_appimage.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packaging/AppImage-builder/create_appimage.py b/packaging/AppImage-builder/create_appimage.py index a91ac04139a..2e5284eaad0 100644 --- a/packaging/AppImage-builder/create_appimage.py +++ b/packaging/AppImage-builder/create_appimage.py @@ -79,7 +79,7 @@ def copy_files(dist_path): def create_appimage(): appimagetool = os.getenv("APPIMAGEBUILDER_LOCATION", "appimage-builder-x86_64.AppImage") - command = [appimagetool, "--recipe", os.path.join(Path(__file__).parent, "AppImageBuilder.yml")] + command = [appimagetool, "--recipe", os.path.join(Path(__file__).parent, "AppImageBuilder.yml"), "--skip-test"] result = subprocess.call(command) if result != 0: raise RuntimeError(f"The AppImageTool command returned non-zero: {result}") From 7eedcac62fb6d5b5dd6101be3a495698c173e948 Mon Sep 17 00:00:00 2001 From: Jelle Spijker Date: Tue, 5 Sep 2023 08:37:24 +0200 Subject: [PATCH 41/54] Add includes for apt packages Based on: https://github.com/AppImageCrafters/appimage-builder/blob/main/recipes/hello-world-qt6/AppImageBuilder.yml Contributes CURA-10951 --- .../AppImageBuilder.yml.jinja | 57 ++++++++++++++++++- packaging/AppImage-builder/create_appimage.py | 3 +- 2 files changed, 55 insertions(+), 5 deletions(-) diff --git a/packaging/AppImage-builder/AppImageBuilder.yml.jinja b/packaging/AppImage-builder/AppImageBuilder.yml.jinja index 270279af3b3..fd8b4e6485a 100644 --- a/packaging/AppImage-builder/AppImageBuilder.yml.jinja +++ b/packaging/AppImage-builder/AppImageBuilder.yml.jinja @@ -4,7 +4,7 @@ AppDir: path: {{ app_dir }} app_info: id: com.ultimaker.cura - name: UltiMaker-Cura + name: UltiMaker Cura icon: {{ icon }} version: {{ version }} exec: UltiMaker-Cura @@ -47,8 +47,58 @@ AppDir: - sourceline: deb https://packagecloud.io/slacktechnologies/slack/debian/ jessie main include: - - libc6:amd64 - - xdg-desktop-portal-kde:amd64 + - libc6:amd64 + - xdg-desktop-portal-kde:amd64 + - libcap2:amd64 + - libcom-err2:amd64 + - libdbus-1-3:amd64 + - libgpg-error0:amd64 + - libgtk-3-common + - libkeyutils1:amd64 + - libllvm13 + - liblzma5:amd64 + - libpcre3:amd64 + - libqt6gui6 + - libqt6qml6 + - libqt6qmlworkerscript6 + - libqt6quick6 + - libselinux1:amd64 + - libtinfo6:amd64 + - qml6-module-qtqml-workerscript:amd64 + - qml6-module-qtquick:amd64 + - qt6-gtk-platformtheme:amd64 + - qt6-qpa-plugins:amd64 + # x11 + - libx11-6 + - libx11-xcb1 + - libxcb1 + - libxcb-render0 + - libxcb-xfixes0 + - libxcb-shape0 + - libxcb-dri2-0 + - libxcb-shm0 + - libxcb-glx0 + - libxcb-present0 + - libxcb-dri3-0 + # graphic libraries interface (safe graphics bundle including drivers, acceleration may not work in some systems) + - libglvnd0 + - libglx0 + - libglapi-mesa + - libgl1 + - libegl1 + - libgbm1 + - libdrm2 + - libglx-mesa0 + - libgl1-amber-dri + - libgl1-mesa-dri + - mesa-utils + - libgl1-mesa-glx + - libdrm-amdgpu1 + - libdrm-nouveau2 + exclude: + - hicolor-icon-theme + - adwaita-icon-theme + - humanity-icon-theme files: include: [] exclude: @@ -59,6 +109,7 @@ AppDir: - usr/share/doc/*/TODO.* runtime: env: + APPDIR_LIBRARY_PATH: "$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" PYTHONPATH: "$APPDIR" QT_PLUGIN_PATH: "$APPDIR/qt/plugins" QML2_IMPORT_PATH: "$APPDIR/qt/qml" diff --git a/packaging/AppImage-builder/create_appimage.py b/packaging/AppImage-builder/create_appimage.py index 2e5284eaad0..819ec0b7660 100644 --- a/packaging/AppImage-builder/create_appimage.py +++ b/packaging/AppImage-builder/create_appimage.py @@ -86,8 +86,7 @@ def create_appimage(): def sign_appimage(dist_path, appimage_filename): - appimage_path = os.path.join(dist_path, "..", appimage_filename) - command = ["gpg", "--yes", "--armor", "--detach-sig", appimage_path] + command = ["gpg", "--yes", "--armor", "--detach-sig", appimage_filename] result = subprocess.call(command) if result != 0: raise RuntimeError(f"The GPG command returned non-zero: {result}") From 2bc3079af594e6334887a08ab78d093c99fc93cc Mon Sep 17 00:00:00 2001 From: Jelle Spijker Date: Wed, 6 Sep 2023 11:38:54 +0200 Subject: [PATCH 42/54] Only exclude Cura and CuraEngine still ship other executables Contributes to CURA-10951 --- packaging/msi/ExcludeComponents.xslt | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/packaging/msi/ExcludeComponents.xslt b/packaging/msi/ExcludeComponents.xslt index b964484922a..dc782e20354 100644 --- a/packaging/msi/ExcludeComponents.xslt +++ b/packaging/msi/ExcludeComponents.xslt @@ -20,10 +20,15 @@ ...but we can use this longer `substring` expression instead (see https://github.com/wixtoolset/issues/issues/5609 ) --> + /> + @@ -32,6 +37,7 @@ - - + + + \ No newline at end of file From 71dc8e22a6ed7bb0d9b740711b46915d1ea761af Mon Sep 17 00:00:00 2001 From: "c.lamboo" Date: Fri, 1 Sep 2023 11:11:09 +0200 Subject: [PATCH 43/54] Allow objects to be placed near border Issue before was the following: when placing objects within a grid cell there is a margin around the object. This margin comes from both the integer rounding of the cell and the defined min distance between objects. When trying to place object near the buildplate border we marked any cell that is not fully within the buildplate area as an invalid cell to place objects in. This was however too strict; there is the aforementioned margin around the object, and if only this margin would be outside the buildplate it is perfectly fine to place object in that cell. CURA-7951 --- cura/Arranging/GridArrange.py | 100 ++++++++++++++++++++-------------- 1 file changed, 58 insertions(+), 42 deletions(-) diff --git a/cura/Arranging/GridArrange.py b/cura/Arranging/GridArrange.py index 493c81b27cb..4caf472b5d3 100644 --- a/cura/Arranging/GridArrange.py +++ b/cura/Arranging/GridArrange.py @@ -1,11 +1,13 @@ import math -from typing import List, TYPE_CHECKING, Tuple, Set +from typing import List, TYPE_CHECKING, Tuple, Set, Union if TYPE_CHECKING: from UM.Scene.SceneNode import SceneNode from cura.BuildVolume import BuildVolume from UM.Application import Application +from UM.Math.AxisAlignedBox import AxisAlignedBox +from UM.Math.Polygon import Polygon from UM.Math.Vector import Vector from UM.Operations.AddSceneNodeOperation import AddSceneNodeOperation from UM.Operations.GroupedOperation import GroupedOperation @@ -34,10 +36,18 @@ def __init__(self, nodes_to_arrange: List["SceneNode"], build_volume: "BuildVolu self._grid_width += self._margin_x self._grid_height += self._margin_y - # Round up the grid size to the nearest cm + # Round up the grid size to the nearest cm, this assures that new objects will + # be placed on integer offsets from each other grid_precision = 10 # 1cm - self._grid_width = math.ceil(self._grid_width / grid_precision) * grid_precision - self._grid_height = math.ceil(self._grid_height / grid_precision) * grid_precision + rounded_grid_width = math.ceil(self._grid_width / grid_precision) * grid_precision + rounded_grid_height = math.ceil(self._grid_height / grid_precision) * grid_precision + + # The space added by the "grid precision rounding up" of the grid size + self._grid_round_margin_x = rounded_grid_width - self._grid_width + self._grid_round_margin_y = rounded_grid_height - self._grid_height + + self._grid_width = rounded_grid_width + self._grid_height = rounded_grid_height self._offset_x = 0 self._offset_y = 0 @@ -56,10 +66,9 @@ def __init__(self, nodes_to_arrange: List["SceneNode"], build_volume: "BuildVolu self._fixed_nodes_grid_ids = self._fixed_nodes_grid_ids.union( self._intersectingGridIdxInclusive(node.getBoundingBox())) - #grid indexes that are in disallowed area + # grid indexes that are in disallowed area for polygon in self._build_volume.getDisallowedAreas(): - self._fixed_nodes_grid_ids = self._fixed_nodes_grid_ids.union( - self._getIntersectingGridIdForPolygon(polygon)) + self._fixed_nodes_grid_ids = self._fixed_nodes_grid_ids.union(self._intersectingGridIdxInclusive(polygon)) self._build_plate_grid_ids = self._intersectingGridIdxExclusive(self._build_volume_bounding_box) @@ -240,51 +249,58 @@ def _moveNodeOnGrid(self, node: "SceneNode", grid_x: int, grid_y: int) -> "Opera return TranslateOperation(node, Vector(delta_x, 0, delta_y)) - def _getGridCornerPoints(self, bounding_box: "BoundingVolume") -> Tuple[float, float, float, float]: - coord_x1 = bounding_box.left - coord_x2 = bounding_box.right - coord_y1 = bounding_box.back - coord_y2 = bounding_box.front + def _getGridCornerPoints( + self, + bounds: Union[AxisAlignedBox, Polygon], + *, + margin_x: float = 0.0, + margin_y: float = 0.0 + ) -> Tuple[float, float, float, float]: + if isinstance(bounds, AxisAlignedBox): + coord_x1 = bounds.left - margin_x + coord_x2 = bounds.right + margin_x + coord_y1 = bounds.back - margin_y + coord_y2 = bounds.front + margin_y + elif isinstance(bounds, Polygon): + coord_x1 = float('inf') + coord_y1 = float('inf') + coord_x2 = float('-inf') + coord_y2 = float('-inf') + for x, y in bounds.getPoints(): + coord_x1 = min(coord_x1, x) + coord_y1 = min(coord_y1, y) + coord_x2 = max(coord_x2, x) + coord_y2 = max(coord_y2, y) + else: + raise TypeError("bounds must be either an AxisAlignedBox or a Polygon") + + coord_x1 -= margin_x + coord_x2 += margin_x + coord_y1 -= margin_y + coord_y2 += margin_y + grid_x1, grid_y1 = self._coordSpaceToGridSpace(coord_x1, coord_y1) grid_x2, grid_y2 = self._coordSpaceToGridSpace(coord_x2, coord_y2) return grid_x1, grid_y1, grid_x2, grid_y2 - def _getIntersectingGridIdForPolygon(self, polygon)-> Set[Tuple[int, int]]: - # (x0, y0) - # | - # v - # ┌─────────────┐ - # │ │ - # │ │ - # └─────────────┘ < (x1, y1) - x0 = float('inf') - y0 = float('inf') - x1 = float('-inf') - y1 = float('-inf') - grid_idx = set() - for [x, y] in polygon.getPoints(): - x0 = min(x0, x) - y0 = min(y0, y) - x1 = max(x1, x) - y1 = max(y1, y) - grid_x1, grid_y1 = self._coordSpaceToGridSpace(x0, y0) - grid_x2, grid_y2 = self._coordSpaceToGridSpace(x1, y1) - - for grid_x in range(math.floor(grid_x1), math.ceil(grid_x2)): - for grid_y in range(math.floor(grid_y1), math.ceil(grid_y2)): - grid_idx.add((grid_x, grid_y)) - return grid_idx - - def _intersectingGridIdxInclusive(self, bounding_box: "BoundingVolume") -> Set[Tuple[int, int]]: - grid_x1, grid_y1, grid_x2, grid_y2 = self._getGridCornerPoints(bounding_box) + def _intersectingGridIdxInclusive(self, bounds: Union[AxisAlignedBox, Polygon]) -> Set[Tuple[int, int]]: + grid_x1, grid_y1, grid_x2, grid_y2 = self._getGridCornerPoints( + bounds, + margin_x=-(self._margin_x + self._grid_round_margin_x) * 0.5, + margin_y=-(self._margin_y + self._grid_round_margin_y) * 0.5, + ) grid_idx = set() for grid_x in range(math.floor(grid_x1), math.ceil(grid_x2)): for grid_y in range(math.floor(grid_y1), math.ceil(grid_y2)): grid_idx.add((grid_x, grid_y)) return grid_idx - def _intersectingGridIdxExclusive(self, bounding_box: "BoundingVolume") -> Set[Tuple[int, int]]: - grid_x1, grid_y1, grid_x2, grid_y2 = self._getGridCornerPoints(bounding_box) + def _intersectingGridIdxExclusive(self, bounds: Union[AxisAlignedBox, Polygon]) -> Set[Tuple[int, int]]: + grid_x1, grid_y1, grid_x2, grid_y2 = self._getGridCornerPoints( + bounds, + margin_x=(self._margin_x + self._grid_round_margin_x) * 0.5, + margin_y=(self._margin_y + self._grid_round_margin_y) * 0.5, + ) grid_idx = set() for grid_x in range(math.ceil(grid_x1), math.floor(grid_x2)): for grid_y in range(math.ceil(grid_y1), math.floor(grid_y2)): From c7356ccb4ae30ff21685ccdf2b77a6bc72f2af0c Mon Sep 17 00:00:00 2001 From: Remco Burema Date: Wed, 6 Sep 2023 21:17:15 +0200 Subject: [PATCH 44/54] Pass 'all' exceptions. part of CURA-10942 --- plugins/PostProcessingPlugin/scripts/LimitXYAccelJerk.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/PostProcessingPlugin/scripts/LimitXYAccelJerk.py b/plugins/PostProcessingPlugin/scripts/LimitXYAccelJerk.py index b47a5876d80..43aceb77936 100644 --- a/plugins/PostProcessingPlugin/scripts/LimitXYAccelJerk.py +++ b/plugins/PostProcessingPlugin/scripts/LimitXYAccelJerk.py @@ -256,7 +256,7 @@ def execute(self, data): lines.insert(len(lines)-2,m205_jerk_old) data[end_index-1] = "\n".join(lines) except: - all + pass else: data[len(data)-1] = m201_limit_old + "\n" + m205_jerk_old + "\n" + data[len(data)-1] return data From 5765f398a3b9f7ad652f865b10065ca72f237bf7 Mon Sep 17 00:00:00 2001 From: Remco Burema Date: Thu, 7 Sep 2023 13:03:56 +0200 Subject: [PATCH 45/54] Add clarifying comments: Why .sh 'on' Windows? part of CURA-9494 --- .github/workflows/windows.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml index 5535f5f44f2..f6de818eb4d 100644 --- a/.github/workflows/windows.yml +++ b/.github/workflows/windows.yml @@ -256,6 +256,7 @@ jobs: dist/${{steps.filename.outputs.INSTALLER_FILENAME }}.exe retention-days: 5 + # NOTE: The extension is .sh, since this isn't going to build-environment, so not on the Win build image. - name: Write the run info shell: python run: | @@ -263,6 +264,7 @@ jobs: with open("run_info.sh", "w") as f: f.writelines(f'echo "CURA_VERSION_FULL={os.environ["CURA_VERSION_FULL"]}" >> $GITHUB_ENV\n') + # NOTE: The extension is .sh, since this isn't going to build-environment, so not on the Win build image. - name: Upload the run info uses: actions/upload-artifact@v3 with: From 13af77b4f6a97862fc528c2c04ccae7d9ce67f9c Mon Sep 17 00:00:00 2001 From: Remco Burema Date: Thu, 7 Sep 2023 20:34:54 +0200 Subject: [PATCH 46/54] Nightlies workflow: Enable skipping OS's part of CURA-9494 --- .github/workflows/installers.yml | 208 +++++++++++++++++++++---------- 1 file changed, 144 insertions(+), 64 deletions(-) diff --git a/.github/workflows/installers.yml b/.github/workflows/installers.yml index 96b67a05412..6a139b0b456 100644 --- a/.github/workflows/installers.yml +++ b/.github/workflows/installers.yml @@ -29,6 +29,11 @@ on: default: false required: true type: boolean + os_list: + description: 'List of OS(-variant)s to build for' + default: "windows, linux-modern, linux-legacy, macos-x64, macos-arm64" + required: true + type: string schedule: # Daily at 5:20 CET - cron: '20 4 * * *' @@ -40,59 +45,74 @@ env: jobs: windows-installer: - uses: ./.github/workflows/windows.yml - with: - cura_conan_version: ${{ inputs.cura_conan_version }} - conan_args: ${{ inputs.conan_args }} - enterprise: ${{ inputs.enterprise }} - staging: ${{ inputs.staging }} - architecture: X64 - operating_system: windows-2022 - secrets: inherit + steps: + - name: Build Windows installer + if: ${{ contains(inputs.os_list, "windows") }} + uses: ./.github/workflows/windows.yml + with: + cura_conan_version: ${{ inputs.cura_conan_version }} + conan_args: ${{ inputs.conan_args }} + enterprise: ${{ inputs.enterprise }} + staging: ${{ inputs.staging }} + architecture: X64 + operating_system: windows-2022 + secrets: inherit linux-modern-installer: - uses: ./.github/workflows/linux.yml - with: - cura_conan_version: ${{ inputs.cura_conan_version }} - conan_args: ${{ inputs.conan_args }} - enterprise: ${{ inputs.enterprise }} - staging: ${{ inputs.staging }} - architecture: X64 - operating_system: ubuntu-22.04 - secrets: inherit + steps: + - name: Build (modern) Linux installer + if: ${{ contains(inputs.os_list, "linux-modern") }} + uses: ./.github/workflows/linux.yml + with: + cura_conan_version: ${{ inputs.cura_conan_version }} + conan_args: ${{ inputs.conan_args }} + enterprise: ${{ inputs.enterprise }} + staging: ${{ inputs.staging }} + architecture: X64 + operating_system: ubuntu-22.04 + secrets: inherit linux-legacy-installer: - uses: ./.github/workflows/linux.yml - with: - cura_conan_version: ${{ inputs.cura_conan_version }} - conan_args: ${{ inputs.conan_args }} - enterprise: ${{ inputs.enterprise }} - staging: ${{ inputs.staging }} - architecture: X64 - operating_system: ubuntu-20.04 - secrets: inherit + steps: + - name: Build (legacy) Linux installer + if: ${{ contains(inputs.os_list, "linux-legacy") }} + uses: ./.github/workflows/linux.yml + with: + cura_conan_version: ${{ inputs.cura_conan_version }} + conan_args: ${{ inputs.conan_args }} + enterprise: ${{ inputs.enterprise }} + staging: ${{ inputs.staging }} + architecture: X64 + operating_system: ubuntu-20.04 + secrets: inherit macos-installer: - uses: ./.github/workflows/macos.yml - with: - cura_conan_version: ${{ inputs.cura_conan_version }} - conan_args: ${{ inputs.conan_args }} - enterprise: ${{ inputs.enterprise }} - staging: ${{ inputs.staging }} - architecture: X64 - operating_system: macos-11.0 - secrets: inherit + steps: + - name: Build MacOS installer for Intel chips + if: ${{ contains(inputs.os_list, "macos-x64") }} + uses: ./.github/workflows/macos.yml + with: + cura_conan_version: ${{ inputs.cura_conan_version }} + conan_args: ${{ inputs.conan_args }} + enterprise: ${{ inputs.enterprise }} + staging: ${{ inputs.staging }} + architecture: X64 + operating_system: macos-11.0 + secrets: inherit macos-arm-installer: - uses: ./.github/workflows/macos.yml - with: - cura_conan_version: ${{ inputs.cura_conan_version }} - conan_args: ${{ inputs.conan_args }} - enterprise: ${{ inputs.enterprise }} - staging: ${{ inputs.staging }} - architecture: ARM64 - operating_system: self-hosted - secrets: inherit + steps: + - name: Build MacOS installer for ARM chips + if: ${{ contains(inputs.os_list, "macos-arm64") }} + uses: ./.github/workflows/macos.yml + with: + cura_conan_version: ${{ inputs.cura_conan_version }} + conan_args: ${{ inputs.conan_args }} + enterprise: ${{ inputs.enterprise }} + staging: ${{ inputs.staging }} + architecture: ARM64 + operating_system: self-hosted + secrets: inherit # Run and update nightly release when the nightly input is set to true or if the schedule is triggered update-nightly-release: @@ -119,14 +139,20 @@ jobs: import os import datetime enterprise = "-Enterprise" if "${{ inputs.enterprise }}" == "true" else "" - linux_modern = f"UltiMaker-Cura-{os.getenv('CURA_VERSION_FULL')}{enterprise}-linux-modern-X64" - linux_legacy = f"UltiMaker-Cura-{os.getenv('CURA_VERSION_FULL')}{enterprise}-linux-X64" - mac_x64_dmg = f"UltiMaker-Cura-{os.getenv('CURA_VERSION_FULL')}{enterprise}-macos-X64" - mac_x64_pkg = f"UltiMaker-Cura-{os.getenv('CURA_VERSION_FULL')}{enterprise}-macos-X64" - mac_arm_dmg = f"UltiMaker-Cura-{os.getenv('CURA_VERSION_FULL')}{enterprise}-macos-ARM64" - mac_arm_pkg = f"UltiMaker-Cura-{os.getenv('CURA_VERSION_FULL')}{enterprise}-macos-ARM64" - win_msi = installer_filename = f"UltiMaker-Cura-{os.getenv('CURA_VERSION_FULL')}{enterprise}-win64-X64" - win_exe = installer_filename = f"UltiMaker-Cura-{os.getenv('CURA_VERSION_FULL')}{enterprise}-win64-X64" + os_list = [x.strip() for x in "${{ inputs.os_list }}".split(",")] + if "linux-modern" in os_list: + linux_modern = f"UltiMaker-Cura-{os.getenv('CURA_VERSION_FULL')}{enterprise}-linux-modern-X64" + if "linux-legacy" in os_list: + linux_legacy = f"UltiMaker-Cura-{os.getenv('CURA_VERSION_FULL')}{enterprise}-linux-X64" + if "macos-x64" in os_list: + mac_x64_dmg = f"UltiMaker-Cura-{os.getenv('CURA_VERSION_FULL')}{enterprise}-macos-X64" + mac_x64_pkg = f"UltiMaker-Cura-{os.getenv('CURA_VERSION_FULL')}{enterprise}-macos-X64" + if "macos-arm64" in os_list: + mac_arm_dmg = f"UltiMaker-Cura-{os.getenv('CURA_VERSION_FULL')}{enterprise}-macos-ARM64" + mac_arm_pkg = f"UltiMaker-Cura-{os.getenv('CURA_VERSION_FULL')}{enterprise}-macos-ARM64" + if "windows" in os_list: + win_msi = installer_filename = f"UltiMaker-Cura-{os.getenv('CURA_VERSION_FULL')}{enterprise}-win64-X64" + win_exe = installer_filename = f"UltiMaker-Cura-{os.getenv('CURA_VERSION_FULL')}{enterprise}-win64-X64" nightly_name = "UltiMaker-Cura-" + os.getenv('CURA_VERSION_FULL').split("+")[0] nightly_creation_time = str(datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")) output_env = os.environ["GITHUB_OUTPUT"] @@ -136,84 +162,139 @@ jobs: content = f.read() with open(output_env, "w") as f: f.write(content) - f.writelines(f"LINUX_MODERN={linux_modern}\n") - f.writelines(f"LINUX_LEGACY={linux_legacy}\n") - f.writelines(f"MAC_X64_DMG={mac_x64_dmg}\n") - f.writelines(f"MAC_X64_PKG={mac_x64_pkg}\n") - f.writelines(f"MAC_ARM_DMG={mac_arm_dmg}\n") - f.writelines(f"MAC_ARM_PKG={mac_arm_pkg}\n") - f.writelines(f"WIN_MSI={win_msi}\n") - f.writelines(f"WIN_EXE={win_exe}\n") + if "linux-modern" in os_list: + f.writelines(f"LINUX_MODERN={linux_modern}\n") + if "linux-legacy" in os_list: + f.writelines(f"LINUX_LEGACY={linux_legacy}\n") + if "macos-x64" in os_list: + f.writelines(f"MAC_X64_DMG={mac_x64_dmg}\n") + f.writelines(f"MAC_X64_PKG={mac_x64_pkg}\n") + if "macos-arm64" in os_list: + f.writelines(f"MAC_ARM_DMG={mac_arm_dmg}\n") + f.writelines(f"MAC_ARM_PKG={mac_arm_pkg}\n") + if "windows" in os_list: + f.writelines(f"WIN_MSI={win_msi}\n") + f.writelines(f"WIN_EXE={win_exe}\n") f.writelines(f"NIGHTLY_NAME={nightly_name}\n") f.writelines(f"NIGHTLY_TIME={nightly_creation_time}\n") - name: Download linux modern installer jobs artifacts + if: ${{ contains(inputs.os_list, "linux-modern") }} uses: actions/download-artifact@v2 with: name: ${{ steps.filename.outputs.LINUX_MODERN }}-AppImage path: installers - name: Download linux legacy installer jobs artifacts + if: ${{ contains(inputs.os_list, "linux-legacy") }} uses: actions/download-artifact@v2 with: name: ${{ steps.filename.outputs.LINUX_LEGACY }}-AppImage path: installers - name: Download mac x64 dmg installer jobs artifacts + if: ${{ contains(inputs.os_list, "macos-x64") }} uses: actions/download-artifact@v2 with: name: ${{ steps.filename.outputs.MAC_X64_DMG }}-dmg path: installers - name: Download mac x64 pkg installer jobs artifacts + if: ${{ contains(inputs.os_list, "macos-x64") }} uses: actions/download-artifact@v2 with: name: ${{ steps.filename.outputs.MAC_X64_PKG }}-pkg path: installers - name: Download mac arm dmg installer jobs artifacts + if: ${{ contains(inputs.os_list, "macos-arm64") }} uses: actions/download-artifact@v2 with: name: ${{ steps.filename.outputs.MAC_ARM_DMG }}-dmg path: installers - name: Download mac arm pkg installer jobs artifacts + if: ${{ contains(inputs.os_list, "macos-arm64") }} uses: actions/download-artifact@v2 with: name: ${{ steps.filename.outputs.MAC_ARM_PKG }}-pkg path: installers - name: Download win msi installer jobs artifacts + if: ${{ contains(inputs.os_list, "windows") }} uses: actions/download-artifact@v2 with: name: ${{ steps.filename.outputs.WIN_MSI }}-msi path: installers - name: Download win exe installer jobs artifacts + if: ${{ contains(inputs.os_list, "windows") }} uses: actions/download-artifact@v2 with: name: ${{ steps.filename.outputs.WIN_EXE }}-exe path: installers - - name: Rename installers to nightlies + - name: Rename Linux (modern) installer to nightlies + if: ${{ contains(inputs.os_list, "linux-modern") }} run: | mv installers/${{ steps.filename.outputs.LINUX_MODERN }}.AppImage installers/${{ steps.filename.outputs.NIGHTLY_NAME }}-linux-modern-X64.AppImage + + - name: Rename Linux (legacy) installer to nightlies + if: ${{ contains(inputs.os_list, "linux-legacy") }} + run: | mv installers/${{ steps.filename.outputs.LINUX_LEGACY }}.AppImage installers/${{ steps.filename.outputs.NIGHTLY_NAME }}-linux-X64.AppImage + + - name: Rename MacOS (X64) installers to nightlies + if: ${{ contains(inputs.os_list, "macos-x64") }} + run: | mv installers/${{ steps.filename.outputs.MAC_X64_DMG }}.dmg installers/${{ steps.filename.outputs.NIGHTLY_NAME }}-macos-X64.dmg mv installers/${{ steps.filename.outputs.MAC_X64_PKG }}.pkg installers/${{ steps.filename.outputs.NIGHTLY_NAME }}-macos-X64.pkg + + - name: Rename MacOS (ARM-64) installers to nightlies + if: ${{ contains(inputs.os_list, "macos-arm64") }} + run: | mv installers/${{ steps.filename.outputs.MAC_ARM_DMG }}.dmg installers/${{ steps.filename.outputs.NIGHTLY_NAME }}-macos-ARM64.dmg mv installers/${{ steps.filename.outputs.MAC_ARM_PKG }}.pkg installers/${{ steps.filename.outputs.NIGHTLY_NAME }}-macos-ARM64.pkg + + - name: Rename Windows installers to nightlies + if: ${{ contains(inputs.os_list, "windows") }} + run: | mv installers/${{ steps.filename.outputs.WIN_MSI }}.msi installers/${{ steps.filename.outputs.NIGHTLY_NAME }}-win64-X64.msi mv installers/${{ steps.filename.outputs.WIN_EXE }}.exe installers/${{ steps.filename.outputs.NIGHTLY_NAME }}-win64-X64.exe - - name: Update nightly release + - name: Update nightly release for Linux (modern) + if: ${{ contains(inputs.os_list, "linux-modern") }} run: | gh release upload nightly installers/${{ steps.filename.outputs.NIGHTLY_NAME }}-linux-modern-X64.AppImage --clobber + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Update nightly release for Linux (legacy) + if: ${{ contains(inputs.os_list, "linux-legacy") }} + run: | gh release upload nightly installers/${{ steps.filename.outputs.NIGHTLY_NAME }}-linux-X64.AppImage --clobber + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Update nightly release for MacOS (X64) + if: ${{ contains(inputs.os_list, "macos-x64") }} + run: | gh release upload nightly installers/${{ steps.filename.outputs.NIGHTLY_NAME }}-macos-X64.dmg --clobber gh release upload nightly installers/${{ steps.filename.outputs.NIGHTLY_NAME }}-macos-X64.pkg --clobber + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Update nightly release for MacOS (ARM-64) + if: ${{ contains(inputs.os_list, "macos-arm64") }} + run: | gh release upload nightly installers/${{ steps.filename.outputs.NIGHTLY_NAME }}-macos-ARM64.dmg --clobber gh release upload nightly installers/${{ steps.filename.outputs.NIGHTLY_NAME }}-macos-ARM64.pkg --clobber + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Update nightly release for Windows + if: ${{ contains(inputs.os_list, "windows") }} + run: | gh release upload nightly installers/${{ steps.filename.outputs.NIGHTLY_NAME }}-win64-X64.msi --clobber gh release upload nightly installers/${{ steps.filename.outputs.NIGHTLY_NAME }}-win64-X64.exe --clobber env: @@ -224,4 +305,3 @@ jobs: gh release edit nightly --title "${{ steps.filename.outputs.NIGHTLY_NAME }}" --notes "Nightly release created on: ${{ steps.filename.outputs.NIGHTLY_TIME }}" env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - From a35ce3d65221ef0788c8e6af8c7bae67e855ec0f Mon Sep 17 00:00:00 2001 From: Remco Burema Date: Thu, 7 Sep 2023 20:48:33 +0200 Subject: [PATCH 47/54] Use single quotes or 'if' doesn't work. part of CURA-9494 --- .github/workflows/installers.yml | 66 ++++++++++++++++---------------- 1 file changed, 33 insertions(+), 33 deletions(-) diff --git a/.github/workflows/installers.yml b/.github/workflows/installers.yml index 6a139b0b456..02b10e496b3 100644 --- a/.github/workflows/installers.yml +++ b/.github/workflows/installers.yml @@ -47,7 +47,7 @@ jobs: windows-installer: steps: - name: Build Windows installer - if: ${{ contains(inputs.os_list, "windows") }} + if: ${{ contains(inputs.os_list, 'windows') }} uses: ./.github/workflows/windows.yml with: cura_conan_version: ${{ inputs.cura_conan_version }} @@ -61,7 +61,7 @@ jobs: linux-modern-installer: steps: - name: Build (modern) Linux installer - if: ${{ contains(inputs.os_list, "linux-modern") }} + if: ${{ contains(inputs.os_list, 'linux-modern') }} uses: ./.github/workflows/linux.yml with: cura_conan_version: ${{ inputs.cura_conan_version }} @@ -75,7 +75,7 @@ jobs: linux-legacy-installer: steps: - name: Build (legacy) Linux installer - if: ${{ contains(inputs.os_list, "linux-legacy") }} + if: ${{ contains(inputs.os_list, 'linux-legacy') }} uses: ./.github/workflows/linux.yml with: cura_conan_version: ${{ inputs.cura_conan_version }} @@ -89,7 +89,7 @@ jobs: macos-installer: steps: - name: Build MacOS installer for Intel chips - if: ${{ contains(inputs.os_list, "macos-x64") }} + if: ${{ contains(inputs.os_list, 'macos-x64') }} uses: ./.github/workflows/macos.yml with: cura_conan_version: ${{ inputs.cura_conan_version }} @@ -103,7 +103,7 @@ jobs: macos-arm-installer: steps: - name: Build MacOS installer for ARM chips - if: ${{ contains(inputs.os_list, "macos-arm64") }} + if: ${{ contains(inputs.os_list, 'macos-arm64') }} uses: ./.github/workflows/macos.yml with: cura_conan_version: ${{ inputs.cura_conan_version }} @@ -140,17 +140,17 @@ jobs: import datetime enterprise = "-Enterprise" if "${{ inputs.enterprise }}" == "true" else "" os_list = [x.strip() for x in "${{ inputs.os_list }}".split(",")] - if "linux-modern" in os_list: + if 'linux-modern' in os_list: linux_modern = f"UltiMaker-Cura-{os.getenv('CURA_VERSION_FULL')}{enterprise}-linux-modern-X64" - if "linux-legacy" in os_list: + if 'linux-legacy' in os_list: linux_legacy = f"UltiMaker-Cura-{os.getenv('CURA_VERSION_FULL')}{enterprise}-linux-X64" - if "macos-x64" in os_list: + if 'macos-x64' in os_list: mac_x64_dmg = f"UltiMaker-Cura-{os.getenv('CURA_VERSION_FULL')}{enterprise}-macos-X64" mac_x64_pkg = f"UltiMaker-Cura-{os.getenv('CURA_VERSION_FULL')}{enterprise}-macos-X64" - if "macos-arm64" in os_list: + if 'macos-arm64' in os_list: mac_arm_dmg = f"UltiMaker-Cura-{os.getenv('CURA_VERSION_FULL')}{enterprise}-macos-ARM64" mac_arm_pkg = f"UltiMaker-Cura-{os.getenv('CURA_VERSION_FULL')}{enterprise}-macos-ARM64" - if "windows" in os_list: + if 'windows' in os_list: win_msi = installer_filename = f"UltiMaker-Cura-{os.getenv('CURA_VERSION_FULL')}{enterprise}-win64-X64" win_exe = installer_filename = f"UltiMaker-Cura-{os.getenv('CURA_VERSION_FULL')}{enterprise}-win64-X64" nightly_name = "UltiMaker-Cura-" + os.getenv('CURA_VERSION_FULL').split("+")[0] @@ -162,122 +162,122 @@ jobs: content = f.read() with open(output_env, "w") as f: f.write(content) - if "linux-modern" in os_list: + if 'linux-modern' in os_list: f.writelines(f"LINUX_MODERN={linux_modern}\n") - if "linux-legacy" in os_list: + if 'linux-legacy' in os_list: f.writelines(f"LINUX_LEGACY={linux_legacy}\n") - if "macos-x64" in os_list: + if 'macos-x64' in os_list: f.writelines(f"MAC_X64_DMG={mac_x64_dmg}\n") f.writelines(f"MAC_X64_PKG={mac_x64_pkg}\n") - if "macos-arm64" in os_list: + if 'macos-arm64' in os_list: f.writelines(f"MAC_ARM_DMG={mac_arm_dmg}\n") f.writelines(f"MAC_ARM_PKG={mac_arm_pkg}\n") - if "windows" in os_list: + if 'windows' in os_list: f.writelines(f"WIN_MSI={win_msi}\n") f.writelines(f"WIN_EXE={win_exe}\n") f.writelines(f"NIGHTLY_NAME={nightly_name}\n") f.writelines(f"NIGHTLY_TIME={nightly_creation_time}\n") - name: Download linux modern installer jobs artifacts - if: ${{ contains(inputs.os_list, "linux-modern") }} + if: ${{ contains(inputs.os_list, 'linux-modern') }} uses: actions/download-artifact@v2 with: name: ${{ steps.filename.outputs.LINUX_MODERN }}-AppImage path: installers - name: Download linux legacy installer jobs artifacts - if: ${{ contains(inputs.os_list, "linux-legacy") }} + if: ${{ contains(inputs.os_list, 'linux-legacy') }} uses: actions/download-artifact@v2 with: name: ${{ steps.filename.outputs.LINUX_LEGACY }}-AppImage path: installers - name: Download mac x64 dmg installer jobs artifacts - if: ${{ contains(inputs.os_list, "macos-x64") }} + if: ${{ contains(inputs.os_list, 'macos-x64') }} uses: actions/download-artifact@v2 with: name: ${{ steps.filename.outputs.MAC_X64_DMG }}-dmg path: installers - name: Download mac x64 pkg installer jobs artifacts - if: ${{ contains(inputs.os_list, "macos-x64") }} + if: ${{ contains(inputs.os_list, 'macos-x64') }} uses: actions/download-artifact@v2 with: name: ${{ steps.filename.outputs.MAC_X64_PKG }}-pkg path: installers - name: Download mac arm dmg installer jobs artifacts - if: ${{ contains(inputs.os_list, "macos-arm64") }} + if: ${{ contains(inputs.os_list, 'macos-arm64') }} uses: actions/download-artifact@v2 with: name: ${{ steps.filename.outputs.MAC_ARM_DMG }}-dmg path: installers - name: Download mac arm pkg installer jobs artifacts - if: ${{ contains(inputs.os_list, "macos-arm64") }} + if: ${{ contains(inputs.os_list, 'macos-arm64') }} uses: actions/download-artifact@v2 with: name: ${{ steps.filename.outputs.MAC_ARM_PKG }}-pkg path: installers - name: Download win msi installer jobs artifacts - if: ${{ contains(inputs.os_list, "windows") }} + if: ${{ contains(inputs.os_list, 'windows') }} uses: actions/download-artifact@v2 with: name: ${{ steps.filename.outputs.WIN_MSI }}-msi path: installers - name: Download win exe installer jobs artifacts - if: ${{ contains(inputs.os_list, "windows") }} + if: ${{ contains(inputs.os_list, 'windows') }} uses: actions/download-artifact@v2 with: name: ${{ steps.filename.outputs.WIN_EXE }}-exe path: installers - name: Rename Linux (modern) installer to nightlies - if: ${{ contains(inputs.os_list, "linux-modern") }} + if: ${{ contains(inputs.os_list, 'linux-modern') }} run: | mv installers/${{ steps.filename.outputs.LINUX_MODERN }}.AppImage installers/${{ steps.filename.outputs.NIGHTLY_NAME }}-linux-modern-X64.AppImage - name: Rename Linux (legacy) installer to nightlies - if: ${{ contains(inputs.os_list, "linux-legacy") }} + if: ${{ contains(inputs.os_list, 'linux-legacy') }} run: | mv installers/${{ steps.filename.outputs.LINUX_LEGACY }}.AppImage installers/${{ steps.filename.outputs.NIGHTLY_NAME }}-linux-X64.AppImage - name: Rename MacOS (X64) installers to nightlies - if: ${{ contains(inputs.os_list, "macos-x64") }} + if: ${{ contains(inputs.os_list, 'macos-x64') }} run: | mv installers/${{ steps.filename.outputs.MAC_X64_DMG }}.dmg installers/${{ steps.filename.outputs.NIGHTLY_NAME }}-macos-X64.dmg mv installers/${{ steps.filename.outputs.MAC_X64_PKG }}.pkg installers/${{ steps.filename.outputs.NIGHTLY_NAME }}-macos-X64.pkg - name: Rename MacOS (ARM-64) installers to nightlies - if: ${{ contains(inputs.os_list, "macos-arm64") }} + if: ${{ contains(inputs.os_list, 'macos-arm64') }} run: | mv installers/${{ steps.filename.outputs.MAC_ARM_DMG }}.dmg installers/${{ steps.filename.outputs.NIGHTLY_NAME }}-macos-ARM64.dmg mv installers/${{ steps.filename.outputs.MAC_ARM_PKG }}.pkg installers/${{ steps.filename.outputs.NIGHTLY_NAME }}-macos-ARM64.pkg - name: Rename Windows installers to nightlies - if: ${{ contains(inputs.os_list, "windows") }} + if: ${{ contains(inputs.os_list, 'windows') }} run: | mv installers/${{ steps.filename.outputs.WIN_MSI }}.msi installers/${{ steps.filename.outputs.NIGHTLY_NAME }}-win64-X64.msi mv installers/${{ steps.filename.outputs.WIN_EXE }}.exe installers/${{ steps.filename.outputs.NIGHTLY_NAME }}-win64-X64.exe - name: Update nightly release for Linux (modern) - if: ${{ contains(inputs.os_list, "linux-modern") }} + if: ${{ contains(inputs.os_list, 'linux-modern') }} run: | gh release upload nightly installers/${{ steps.filename.outputs.NIGHTLY_NAME }}-linux-modern-X64.AppImage --clobber env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - name: Update nightly release for Linux (legacy) - if: ${{ contains(inputs.os_list, "linux-legacy") }} + if: ${{ contains(inputs.os_list, 'linux-legacy') }} run: | gh release upload nightly installers/${{ steps.filename.outputs.NIGHTLY_NAME }}-linux-X64.AppImage --clobber env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - name: Update nightly release for MacOS (X64) - if: ${{ contains(inputs.os_list, "macos-x64") }} + if: ${{ contains(inputs.os_list, 'macos-x64') }} run: | gh release upload nightly installers/${{ steps.filename.outputs.NIGHTLY_NAME }}-macos-X64.dmg --clobber gh release upload nightly installers/${{ steps.filename.outputs.NIGHTLY_NAME }}-macos-X64.pkg --clobber @@ -285,7 +285,7 @@ jobs: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - name: Update nightly release for MacOS (ARM-64) - if: ${{ contains(inputs.os_list, "macos-arm64") }} + if: ${{ contains(inputs.os_list, 'macos-arm64') }} run: | gh release upload nightly installers/${{ steps.filename.outputs.NIGHTLY_NAME }}-macos-ARM64.dmg --clobber gh release upload nightly installers/${{ steps.filename.outputs.NIGHTLY_NAME }}-macos-ARM64.pkg --clobber @@ -293,7 +293,7 @@ jobs: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - name: Update nightly release for Windows - if: ${{ contains(inputs.os_list, "windows") }} + if: ${{ contains(inputs.os_list, 'windows') }} run: | gh release upload nightly installers/${{ steps.filename.outputs.NIGHTLY_NAME }}-win64-X64.msi --clobber gh release upload nightly installers/${{ steps.filename.outputs.NIGHTLY_NAME }}-win64-X64.exe --clobber From 566fdfce1c75a75b360c92414ffe2d22468299f9 Mon Sep 17 00:00:00 2001 From: Remco Burema Date: Thu, 7 Sep 2023 20:51:56 +0200 Subject: [PATCH 48/54] Whitespace can be important. part of CURA-9494 --- .github/workflows/installers.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/installers.yml b/.github/workflows/installers.yml index 02b10e496b3..766c174ed16 100644 --- a/.github/workflows/installers.yml +++ b/.github/workflows/installers.yml @@ -56,7 +56,7 @@ jobs: staging: ${{ inputs.staging }} architecture: X64 operating_system: windows-2022 - secrets: inherit + secrets: inherit linux-modern-installer: steps: @@ -70,7 +70,7 @@ jobs: staging: ${{ inputs.staging }} architecture: X64 operating_system: ubuntu-22.04 - secrets: inherit + secrets: inherit linux-legacy-installer: steps: @@ -84,7 +84,7 @@ jobs: staging: ${{ inputs.staging }} architecture: X64 operating_system: ubuntu-20.04 - secrets: inherit + secrets: inherit macos-installer: steps: @@ -98,7 +98,7 @@ jobs: staging: ${{ inputs.staging }} architecture: X64 operating_system: macos-11.0 - secrets: inherit + secrets: inherit macos-arm-installer: steps: @@ -112,7 +112,7 @@ jobs: staging: ${{ inputs.staging }} architecture: ARM64 operating_system: self-hosted - secrets: inherit + secrets: inherit # Run and update nightly release when the nightly input is set to true or if the schedule is triggered update-nightly-release: From e9fe6b9831324b65815817fa548772260398843e Mon Sep 17 00:00:00 2001 From: Remco Burema Date: Thu, 7 Sep 2023 21:10:46 +0200 Subject: [PATCH 49/54] Partial revert of unneeded code. It doesn't work out this way, and, due to the if-clause further on, it should work even if the 'need's aren't all met. part of CURA-9494 --- .github/workflows/installers.yml | 100 ++++++++++++++----------------- 1 file changed, 45 insertions(+), 55 deletions(-) diff --git a/.github/workflows/installers.yml b/.github/workflows/installers.yml index 766c174ed16..2fc4b76d417 100644 --- a/.github/workflows/installers.yml +++ b/.github/workflows/installers.yml @@ -45,73 +45,63 @@ env: jobs: windows-installer: - steps: - - name: Build Windows installer - if: ${{ contains(inputs.os_list, 'windows') }} - uses: ./.github/workflows/windows.yml - with: - cura_conan_version: ${{ inputs.cura_conan_version }} - conan_args: ${{ inputs.conan_args }} - enterprise: ${{ inputs.enterprise }} - staging: ${{ inputs.staging }} - architecture: X64 - operating_system: windows-2022 + if: ${{ contains(inputs.os_list, 'windows') }} + uses: ./.github/workflows/windows.yml + with: + cura_conan_version: ${{ inputs.cura_conan_version }} + conan_args: ${{ inputs.conan_args }} + enterprise: ${{ inputs.enterprise }} + staging: ${{ inputs.staging }} + architecture: X64 + operating_system: windows-2022 secrets: inherit linux-modern-installer: - steps: - - name: Build (modern) Linux installer - if: ${{ contains(inputs.os_list, 'linux-modern') }} - uses: ./.github/workflows/linux.yml - with: - cura_conan_version: ${{ inputs.cura_conan_version }} - conan_args: ${{ inputs.conan_args }} - enterprise: ${{ inputs.enterprise }} - staging: ${{ inputs.staging }} - architecture: X64 - operating_system: ubuntu-22.04 + if: ${{ contains(inputs.os_list, 'linux-modern') }} + uses: ./.github/workflows/linux.yml + with: + cura_conan_version: ${{ inputs.cura_conan_version }} + conan_args: ${{ inputs.conan_args }} + enterprise: ${{ inputs.enterprise }} + staging: ${{ inputs.staging }} + architecture: X64 + operating_system: ubuntu-22.04 secrets: inherit linux-legacy-installer: - steps: - - name: Build (legacy) Linux installer - if: ${{ contains(inputs.os_list, 'linux-legacy') }} - uses: ./.github/workflows/linux.yml - with: - cura_conan_version: ${{ inputs.cura_conan_version }} - conan_args: ${{ inputs.conan_args }} - enterprise: ${{ inputs.enterprise }} - staging: ${{ inputs.staging }} - architecture: X64 - operating_system: ubuntu-20.04 + if: ${{ contains(inputs.os_list, 'linux-legacy') }} + uses: ./.github/workflows/linux.yml + with: + cura_conan_version: ${{ inputs.cura_conan_version }} + conan_args: ${{ inputs.conan_args }} + enterprise: ${{ inputs.enterprise }} + staging: ${{ inputs.staging }} + architecture: X64 + operating_system: ubuntu-20.04 secrets: inherit macos-installer: - steps: - - name: Build MacOS installer for Intel chips - if: ${{ contains(inputs.os_list, 'macos-x64') }} - uses: ./.github/workflows/macos.yml - with: - cura_conan_version: ${{ inputs.cura_conan_version }} - conan_args: ${{ inputs.conan_args }} - enterprise: ${{ inputs.enterprise }} - staging: ${{ inputs.staging }} - architecture: X64 - operating_system: macos-11.0 + if: ${{ contains(inputs.os_list, 'macos-x64') }} + uses: ./.github/workflows/macos.yml + with: + cura_conan_version: ${{ inputs.cura_conan_version }} + conan_args: ${{ inputs.conan_args }} + enterprise: ${{ inputs.enterprise }} + staging: ${{ inputs.staging }} + architecture: X64 + operating_system: macos-11.0 secrets: inherit macos-arm-installer: - steps: - - name: Build MacOS installer for ARM chips - if: ${{ contains(inputs.os_list, 'macos-arm64') }} - uses: ./.github/workflows/macos.yml - with: - cura_conan_version: ${{ inputs.cura_conan_version }} - conan_args: ${{ inputs.conan_args }} - enterprise: ${{ inputs.enterprise }} - staging: ${{ inputs.staging }} - architecture: ARM64 - operating_system: self-hosted + if: ${{ contains(inputs.os_list, 'macos-arm64') }} + uses: ./.github/workflows/macos.yml + with: + cura_conan_version: ${{ inputs.cura_conan_version }} + conan_args: ${{ inputs.conan_args }} + enterprise: ${{ inputs.enterprise }} + staging: ${{ inputs.staging }} + architecture: ARM64 + operating_system: self-hosted secrets: inherit # Run and update nightly release when the nightly input is set to true or if the schedule is triggered From e1f2424f0ecc69c443d7ddebcc8f45f40dadcdaf Mon Sep 17 00:00:00 2001 From: Remco Burema Date: Thu, 7 Sep 2023 22:15:30 +0200 Subject: [PATCH 50/54] Should run nightly part even if some OS is skipped. part of CURA-9494 --- .github/workflows/installers.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/installers.yml b/.github/workflows/installers.yml index 2fc4b76d417..3b77fa76974 100644 --- a/.github/workflows/installers.yml +++ b/.github/workflows/installers.yml @@ -106,7 +106,7 @@ jobs: # Run and update nightly release when the nightly input is set to true or if the schedule is triggered update-nightly-release: - if: ${{ inputs.nightly || github.event_name == 'schedule' }} + if: ${{ always() && (! cancelled()) && contains(needs.*.result, 'success') && (! contains(needs.*.result, 'failure')) && (inputs.nightly || github.event_name == 'schedule') }} runs-on: ubuntu-latest needs: [ windows-installer, linux-modern-installer, linux-legacy-installer, macos-installer, macos-arm-installer ] steps: From 13962a563e514d26975fa6c4765a864b7ec82bca Mon Sep 17 00:00:00 2001 From: Remco Burema Date: Thu, 7 Sep 2023 22:38:11 +0200 Subject: [PATCH 51/54] Make sure there is at least one run-info. part of CURA-9494 --- .github/workflows/installers.yml | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/.github/workflows/installers.yml b/.github/workflows/installers.yml index 3b77fa76974..4ebea0660b2 100644 --- a/.github/workflows/installers.yml +++ b/.github/workflows/installers.yml @@ -113,11 +113,26 @@ jobs: - name: Checkout uses: actions/checkout@v3 + # It's not necessary to download all three, but it does make sure we have at least one if an OS is skipped. + - name: Download the run info + if: ${{ contains(inputs.os_list, 'macos-x64') || contains(inputs.os_list, 'macos-arm64') }} uses: actions/download-artifact@v2 with: name: macos-run-info + - name: Download the run info II + if: ${{ contains(inputs.os_list, 'linux-modern') || contains(inputs.os_list, 'linux-legacy') }} + uses: actions/download-artifact@v2 + with: + name: linux-run-info + + - name: Download the run info III + if: ${{ contains(inputs.os_list, 'windows') }} + uses: actions/download-artifact@v2 + with: + name: windows-run-info + - name: Set the run info as environment variables run: | . run_info.sh From bb57220756b56b2c2820765eb5b0898440d819a5 Mon Sep 17 00:00:00 2001 From: Remco Burema Date: Fri, 8 Sep 2023 08:07:34 +0200 Subject: [PATCH 52/54] Fix scheduled build. ... but skip mac for now. Try out in about 15 minutes, after that I'll put it back to 5 o'clock. related to CURA-9494 --- .github/workflows/installers.yml | 45 ++++++++++++++++---------------- 1 file changed, 23 insertions(+), 22 deletions(-) diff --git a/.github/workflows/installers.yml b/.github/workflows/installers.yml index 4ebea0660b2..2ec2f3ed131 100644 --- a/.github/workflows/installers.yml +++ b/.github/workflows/installers.yml @@ -36,7 +36,7 @@ on: type: string schedule: # Daily at 5:20 CET - - cron: '20 4 * * *' + - cron: '23 4 * * *' env: CURA_CONAN_VERSION: ${{ inputs.cura_conan_version }} @@ -45,7 +45,7 @@ env: jobs: windows-installer: - if: ${{ contains(inputs.os_list, 'windows') }} + if: ${{ contains(inputs.os_list, 'windows') || github.event_name == 'schedule' }} uses: ./.github/workflows/windows.yml with: cura_conan_version: ${{ inputs.cura_conan_version }} @@ -57,7 +57,7 @@ jobs: secrets: inherit linux-modern-installer: - if: ${{ contains(inputs.os_list, 'linux-modern') }} + if: ${{ contains(inputs.os_list, 'linux-modern') || github.event_name == 'schedule' }} uses: ./.github/workflows/linux.yml with: cura_conan_version: ${{ inputs.cura_conan_version }} @@ -69,7 +69,7 @@ jobs: secrets: inherit linux-legacy-installer: - if: ${{ contains(inputs.os_list, 'linux-legacy') }} + if: ${{ contains(inputs.os_list, 'linux-legacy') || github.event_name == 'schedule' }} uses: ./.github/workflows/linux.yml with: cura_conan_version: ${{ inputs.cura_conan_version }} @@ -122,13 +122,13 @@ jobs: name: macos-run-info - name: Download the run info II - if: ${{ contains(inputs.os_list, 'linux-modern') || contains(inputs.os_list, 'linux-legacy') }} + if: ${{ contains(inputs.os_list, 'linux-modern') || contains(inputs.os_list, 'linux-legacy') || github.event_name == 'schedule' }} uses: actions/download-artifact@v2 with: name: linux-run-info - name: Download the run info III - if: ${{ contains(inputs.os_list, 'windows') }} + if: ${{ contains(inputs.os_list, 'windows') || github.event_name == 'schedule' }} uses: actions/download-artifact@v2 with: name: windows-run-info @@ -145,9 +145,10 @@ jobs: import datetime enterprise = "-Enterprise" if "${{ inputs.enterprise }}" == "true" else "" os_list = [x.strip() for x in "${{ inputs.os_list }}".split(",")] - if 'linux-modern' in os_list: + scheduled = "${{ github.event_name == 'schedule' }}" == "true" + if 'linux-modern' in os_list or scheduled: linux_modern = f"UltiMaker-Cura-{os.getenv('CURA_VERSION_FULL')}{enterprise}-linux-modern-X64" - if 'linux-legacy' in os_list: + if 'linux-legacy' in os_list or scheduled: linux_legacy = f"UltiMaker-Cura-{os.getenv('CURA_VERSION_FULL')}{enterprise}-linux-X64" if 'macos-x64' in os_list: mac_x64_dmg = f"UltiMaker-Cura-{os.getenv('CURA_VERSION_FULL')}{enterprise}-macos-X64" @@ -155,7 +156,7 @@ jobs: if 'macos-arm64' in os_list: mac_arm_dmg = f"UltiMaker-Cura-{os.getenv('CURA_VERSION_FULL')}{enterprise}-macos-ARM64" mac_arm_pkg = f"UltiMaker-Cura-{os.getenv('CURA_VERSION_FULL')}{enterprise}-macos-ARM64" - if 'windows' in os_list: + if 'windows' in os_list or scheduled: win_msi = installer_filename = f"UltiMaker-Cura-{os.getenv('CURA_VERSION_FULL')}{enterprise}-win64-X64" win_exe = installer_filename = f"UltiMaker-Cura-{os.getenv('CURA_VERSION_FULL')}{enterprise}-win64-X64" nightly_name = "UltiMaker-Cura-" + os.getenv('CURA_VERSION_FULL').split("+")[0] @@ -167,9 +168,9 @@ jobs: content = f.read() with open(output_env, "w") as f: f.write(content) - if 'linux-modern' in os_list: + if 'linux-modern' in os_list or scheduled: f.writelines(f"LINUX_MODERN={linux_modern}\n") - if 'linux-legacy' in os_list: + if 'linux-legacy' in os_list or scheduled: f.writelines(f"LINUX_LEGACY={linux_legacy}\n") if 'macos-x64' in os_list: f.writelines(f"MAC_X64_DMG={mac_x64_dmg}\n") @@ -177,21 +178,21 @@ jobs: if 'macos-arm64' in os_list: f.writelines(f"MAC_ARM_DMG={mac_arm_dmg}\n") f.writelines(f"MAC_ARM_PKG={mac_arm_pkg}\n") - if 'windows' in os_list: + if 'windows' in os_list or scheduled: f.writelines(f"WIN_MSI={win_msi}\n") f.writelines(f"WIN_EXE={win_exe}\n") f.writelines(f"NIGHTLY_NAME={nightly_name}\n") f.writelines(f"NIGHTLY_TIME={nightly_creation_time}\n") - name: Download linux modern installer jobs artifacts - if: ${{ contains(inputs.os_list, 'linux-modern') }} + if: ${{ contains(inputs.os_list, 'linux-modern') || github.event_name == 'schedule' }} uses: actions/download-artifact@v2 with: name: ${{ steps.filename.outputs.LINUX_MODERN }}-AppImage path: installers - name: Download linux legacy installer jobs artifacts - if: ${{ contains(inputs.os_list, 'linux-legacy') }} + if: ${{ contains(inputs.os_list, 'linux-legacy') || github.event_name == 'schedule'}} uses: actions/download-artifact@v2 with: name: ${{ steps.filename.outputs.LINUX_LEGACY }}-AppImage @@ -226,26 +227,26 @@ jobs: path: installers - name: Download win msi installer jobs artifacts - if: ${{ contains(inputs.os_list, 'windows') }} + if: ${{ contains(inputs.os_list, 'windows') || github.event_name == 'schedule' }} uses: actions/download-artifact@v2 with: name: ${{ steps.filename.outputs.WIN_MSI }}-msi path: installers - name: Download win exe installer jobs artifacts - if: ${{ contains(inputs.os_list, 'windows') }} + if: ${{ contains(inputs.os_list, 'windows') || github.event_name == 'schedule' }} uses: actions/download-artifact@v2 with: name: ${{ steps.filename.outputs.WIN_EXE }}-exe path: installers - name: Rename Linux (modern) installer to nightlies - if: ${{ contains(inputs.os_list, 'linux-modern') }} + if: ${{ contains(inputs.os_list, 'linux-modern') || github.event_name == 'schedule' }} run: | mv installers/${{ steps.filename.outputs.LINUX_MODERN }}.AppImage installers/${{ steps.filename.outputs.NIGHTLY_NAME }}-linux-modern-X64.AppImage - name: Rename Linux (legacy) installer to nightlies - if: ${{ contains(inputs.os_list, 'linux-legacy') }} + if: ${{ contains(inputs.os_list, 'linux-legacy') || github.event_name == 'schedule' }} run: | mv installers/${{ steps.filename.outputs.LINUX_LEGACY }}.AppImage installers/${{ steps.filename.outputs.NIGHTLY_NAME }}-linux-X64.AppImage @@ -262,20 +263,20 @@ jobs: mv installers/${{ steps.filename.outputs.MAC_ARM_PKG }}.pkg installers/${{ steps.filename.outputs.NIGHTLY_NAME }}-macos-ARM64.pkg - name: Rename Windows installers to nightlies - if: ${{ contains(inputs.os_list, 'windows') }} + if: ${{ contains(inputs.os_list, 'windows') || github.event_name == 'schedule' }} run: | mv installers/${{ steps.filename.outputs.WIN_MSI }}.msi installers/${{ steps.filename.outputs.NIGHTLY_NAME }}-win64-X64.msi mv installers/${{ steps.filename.outputs.WIN_EXE }}.exe installers/${{ steps.filename.outputs.NIGHTLY_NAME }}-win64-X64.exe - name: Update nightly release for Linux (modern) - if: ${{ contains(inputs.os_list, 'linux-modern') }} + if: ${{ contains(inputs.os_list, 'linux-modern') || github.event_name == 'schedule' }} run: | gh release upload nightly installers/${{ steps.filename.outputs.NIGHTLY_NAME }}-linux-modern-X64.AppImage --clobber env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - name: Update nightly release for Linux (legacy) - if: ${{ contains(inputs.os_list, 'linux-legacy') }} + if: ${{ contains(inputs.os_list, 'linux-legacy') || github.event_name == 'schedule' }} run: | gh release upload nightly installers/${{ steps.filename.outputs.NIGHTLY_NAME }}-linux-X64.AppImage --clobber env: @@ -298,7 +299,7 @@ jobs: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - name: Update nightly release for Windows - if: ${{ contains(inputs.os_list, 'windows') }} + if: ${{ contains(inputs.os_list, 'windows') || github.event_name == 'schedule' }} run: | gh release upload nightly installers/${{ steps.filename.outputs.NIGHTLY_NAME }}-win64-X64.msi --clobber gh release upload nightly installers/${{ steps.filename.outputs.NIGHTLY_NAME }}-win64-X64.exe --clobber From e3f8c8d2ae3eedee81ce3ca0fd521a206a30fb4c Mon Sep 17 00:00:00 2001 From: Remco Burema Date: Fri, 8 Sep 2023 08:54:33 +0200 Subject: [PATCH 53/54] Put scheduled build back to early morning. --- .github/workflows/installers.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/installers.yml b/.github/workflows/installers.yml index 2ec2f3ed131..8f9f5690aae 100644 --- a/.github/workflows/installers.yml +++ b/.github/workflows/installers.yml @@ -36,7 +36,7 @@ on: type: string schedule: # Daily at 5:20 CET - - cron: '23 4 * * *' + - cron: '20 4 * * *' env: CURA_CONAN_VERSION: ${{ inputs.cura_conan_version }} From 2de0a9711ae82f942967a2c335c6a99715740832 Mon Sep 17 00:00:00 2001 From: Remco Burema Date: Fri, 8 Sep 2023 22:52:41 +0200 Subject: [PATCH 54/54] Require packages from main branches instead of from CURA-10915. --- conanfile.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/conanfile.py b/conanfile.py index 083f2b43f60..aff8805b62c 100644 --- a/conanfile.py +++ b/conanfile.py @@ -307,11 +307,11 @@ def requirements(self): self.requires("boost/1.82.0") self.requires("curaengine_grpc_definitions/latest@ultimaker/testing") self.requires("zlib/1.2.13") - self.requires("pyarcus/(latest)@ultimaker/cura_10951") + self.requires("pyarcus/(latest)@ultimaker/testing") self.requires("curaengine/(latest)@ultimaker/cura_10475") - self.requires("pysavitar/(latest)@ultimaker/cura_10951") - self.requires("pynest2d/(latest)@ultimaker/cura_10951") - self.requires("curaengine_plugin_gradual_flow/(latest)@ultimaker/cura_10951") + self.requires("pysavitar/(latest)@ultimaker/testing") + self.requires("pynest2d/(latest)@ultimaker/testing") + self.requires("curaengine_plugin_gradual_flow/(latest)@ultimaker/testing") self.requires("uranium/(latest)@ultimaker/cura_10475") self.requires("cura_binary_data/(latest)@ultimaker/testing") self.requires("cpython/3.10.4")