diff --git a/.github/workflows/cura-installer.yml b/.github/workflows/cura-installer.yml index 704669d642..3c3334010d 100644 --- a/.github/workflows/cura-installer.yml +++ b/.github/workflows/cura-installer.yml @@ -203,8 +203,7 @@ jobs: - name: Create the Windows exe installer (Powershell) if: ${{ github.event.inputs.installer == 'true' && runner.os == 'Windows' }} run: | - python ..\cura_inst\packaging\NSIS\nsis-configurator.py ".\Ultimaker-Cura" "..\cura_inst\packaging\NSIS\Ultimaker-Cura.nsi.jinja" "Ultimaker Cura" "Ultimaker-Cura.exe" "$Env:CURA_VERSION_MAJOR" "$Env:CURA_VERSION_MINOR" "$Env:CURA_VERSION_PATCH" "$Env:CURA_VERSION_BUILD" "Ultimaker B.V." "https://ultimaker.com" "..\cura_inst\packaging\cura_license.txt" "LZMA" "..\cura_inst\packaging\NSIS\cura_banner_nsis.bmp" "..\cura_inst\packaging\icons\Cura.ico" "Ultimaker-Cura-$Env:CURA_VERSION_FULL-${{ matrix.os_id }}-${{ runner.arch }}.exe" - makensis /V2 /P4 Ultimaker-Cura.nsi + python ..\cura_inst\packaging\NSIS\create_windows_installer.py ../cura_inst . "Ultimaker-Cura-$Env:CURA_VERSION_FULL-${{ matrix.os_id }}-${{ runner.arch }}.exe" working-directory: dist - name: Create the Linux AppImage (Bash) diff --git a/conandata.yml b/conandata.yml index e2ae2756b5..b9e9acce7d 100644 --- a/conandata.yml +++ b/conandata.yml @@ -194,3 +194,187 @@ Windows: "./icons/Cura.ico" Macos: "./icons/cura.icns" Linux: "./icons/cura-128.png" +"5.1.0-beta": + requirements: + - "arcus/5.1.0@ultimaker/stable" + - "curaengine/5.1.0@ultimaker/stable" + - "savitar/5.1.0@ultimaker/stable" + - "pynest2d/5.1.0@ultimaker/stable" + - "uranium/5.1.0@ultimaker/stable" + - "fdm_materials/5.1.0@ultimaker/stable" + - "cura_binary_data/5.1.0@ultimaker/stable" + - "cpython/3.10.4" + runinfo: + entrypoint: "cura_app.py" + pyinstaller: + datas: + cura_plugins: + package: "cura" + src: "plugins" + dst: "share/cura/plugins" + cura_resources: + package: "cura" + src: "resources" + dst: "share/cura/resources" + uranium_plugins: + package: "uranium" + src: "plugins" + dst: "share/uranium/plugins" + uranium_resources: + package: "uranium" + src: "resources" + dst: "share/uranium/resources" + uranium_um_qt_qml_um: + package: "uranium" + src: "site-packages/UM/Qt/qml/UM" + dst: "PyQt6/Qt6/qml/UM" + cura_binary_data: + package: "cura_binary_data" + src: "resources/cura/resources" + dst: "share/cura/resources" + uranium_binary_data: + package: "cura_binary_data" + src: "resources/uranium/resources" + dst: "share/uranium/resources" + windows_binary_data: + package: "cura_binary_data" + src: "windows" + dst: "share/windows" + fdm_materials: + package: "fdm_materials" + src: "materials" + dst: "share/cura/resources/materials" + tcl: + package: "tcl" + src: "lib/tcl8.6" + dst: "tcl" + tk: + package: "tk" + src: "lib/tk8.6" + dst: "tk" + binaries: + curaengine: + package: "curaengine" + src: "bin" + dst: "." + binary: "CuraEngine" + hiddenimports: + - "pySavitar" + - "pyArcus" + - "pynest2d" + - "PyQt6" + - "PyQt6.QtNetwork" + - "PyQt6.sip" + - "logging.handlers" + - "zeroconf" + - "fcntl" + - "stl" + - "serial" + collect_all: + - "cura" + - "UM" + - "serial" + - "Charon" + - "sqlite3" + - "trimesh" + - "win32ctypes" + - "PyQt6" + - "PyQt6.QtNetwork" + - "PyQt6.sip" + - "stl" + icon: + Windows: "./icons/Cura.ico" + Macos: "./icons/cura.icns" + Linux: "./icons/cura-128.png" +"cura_8665": + requirements: + - "arcus/(latest)@ultimaker/stable" + - "curaengine/(latest)@ultimaker/stable" + - "savitar/(latest)@ultimaker/stable" + - "pynest2d/(latest)@ultimaker/stable" + - "uranium/(latest)@ultimaker/stable" + - "fdm_materials/(latest)@ultimaker/stable" + - "cura_binary_data/(latest)@ultimaker/stable" + - "cpython/3.10.4" + runinfo: + entrypoint: "cura_app.py" + pyinstaller: + datas: + cura_plugins: + package: "cura" + src: "plugins" + dst: "share/cura/plugins" + cura_resources: + package: "cura" + src: "resources" + dst: "share/cura/resources" + uranium_plugins: + package: "uranium" + src: "plugins" + dst: "share/uranium/plugins" + uranium_resources: + package: "uranium" + src: "resources" + dst: "share/uranium/resources" + uranium_um_qt_qml_um: + package: "uranium" + src: "site-packages/UM/Qt/qml/UM" + dst: "PyQt6/Qt6/qml/UM" + cura_binary_data: + package: "cura_binary_data" + src: "resources/cura/resources" + dst: "share/cura/resources" + uranium_binary_data: + package: "cura_binary_data" + src: "resources/uranium/resources" + dst: "share/uranium/resources" + windows_binary_data: + package: "cura_binary_data" + src: "windows" + dst: "share/windows" + fdm_materials: + package: "fdm_materials" + src: "materials" + dst: "share/cura/resources/materials" + tcl: + package: "tcl" + src: "lib/tcl8.6" + dst: "tcl" + tk: + package: "tk" + src: "lib/tk8.6" + dst: "tk" + binaries: + curaengine: + package: "curaengine" + src: "bin" + dst: "." + binary: "CuraEngine" + hiddenimports: + - "pySavitar" + - "pyArcus" + - "pynest2d" + - "PyQt6" + - "PyQt6.QtNetwork" + - "PyQt6.sip" + - "logging.handlers" + - "zeroconf" + - "fcntl" + - "stl" + - "serial" + collect_all: + - "cura" + - "UM" + - "serial" + - "Charon" + - "sqlite3" + - "trimesh" + - "win32ctypes" + - "PyQt6" + - "PyQt6.QtNetwork" + - "PyQt6.sip" + - "stl" + icon: + Windows: "./icons/Cura.ico" + Macos: "./icons/cura.icns" + Linux: "./icons/cura-128.png" diff --git a/packaging/NSIS/Ultimaker-Cura.nsi.jinja b/packaging/NSIS/Ultimaker-Cura.nsi.jinja index fc7db794d9..70fa93e608 100644 --- a/packaging/NSIS/Ultimaker-Cura.nsi.jinja +++ b/packaging/NSIS/Ultimaker-Cura.nsi.jinja @@ -1,10 +1,11 @@ # Copyright (c) 2022 Ultimaker B.V. # Cura's build system is released under the terms of the AGPLv3 or higher. -!define APP_NAME "{{ app_name }} {{ version_major }}.{{ version_minor }}.{{ version_patch }}" +!define APP_NAME "{{ app_name }}" !define COMP_NAME "{{ company }}" !define WEB_SITE "{{ web_site }}" -!define VERSION "{{ version_major }}.{{ version_minor }}.{{ version_patch }}.{{ version_build }}" +!define VERSION "{{ version }}" +!define VIVERSION "{{ version_major }}.{{ version_minor }}.{{ version_patch }}.0" !define COPYRIGHT "Copyright (c) {{ year }} {{ company }}" !define DESCRIPTION "Application" !define LICENSE_TXT "{{ cura_license_file }}" @@ -12,7 +13,7 @@ !define MAIN_APP_EXE "{{ main_app }}" !define INSTALL_TYPE "SetShellVarContext all" !define REG_ROOT "HKCU" -!define REG_APP_PATH "Software\Microsoft\Windows\CurrentVersion\App Paths\${MAIN_APP_EXE}" +!define REG_APP_PATH "Software\Microsoft\Windows\CurrentVersion\App Paths\${APP_NAME}" !define UNINSTALL_PATH "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APP_NAME}" !define REG_START_MENU "Start Menu Folder" @@ -24,12 +25,12 @@ var SM_Folder ###################################################################### -VIProductVersion "${VERSION}" -VIAddVersionKey "ProductName" "${APP_NAME}" +VIProductVersion "${VIVERSION}" +VIAddVersionKey "ProductName" "{{ app_name }}" VIAddVersionKey "CompanyName" "${COMP_NAME}" VIAddVersionKey "LegalCopyright" "${COPYRIGHT}" VIAddVersionKey "FileDescription" "${DESCRIPTION}" -VIAddVersionKey "FileVersion" "${VERSION}" +VIAddVersionKey "FileVersion" "${VIVERSION}" ###################################################################### @@ -38,7 +39,6 @@ Name "${APP_NAME}" Caption "${APP_NAME}" OutFile "${INSTALLER_NAME}" BrandingText "${APP_NAME}" -InstallDirRegKey "${REG_ROOT}" "${REG_APP_PATH}" "" InstallDir "$PROGRAMFILES64\${APP_NAME}" ###################################################################### @@ -64,7 +64,7 @@ InstallDir "$PROGRAMFILES64\${APP_NAME}" !ifdef REG_START_MENU !define MUI_STARTMENUPAGE_NODISABLE -!define MUI_STARTMENUPAGE_DEFAULTFOLDER "{{ app_name }}" +!define MUI_STARTMENUPAGE_DEFAULTFOLDER "Ultimaker Cura" !define MUI_STARTMENUPAGE_REGISTRY_ROOT "${REG_ROOT}" !define MUI_STARTMENUPAGE_REGISTRY_KEY "${UNINSTALL_PATH}" !define MUI_STARTMENUPAGE_REGISTRY_VALUENAME "${REG_START_MENU}" @@ -113,8 +113,8 @@ CreateShortCut "$SMPROGRAMS\$SM_Folder\${APP_NAME}.lnk" "$INSTDIR\${MAIN_APP_EXE CreateShortCut "$SMPROGRAMS\$SM_Folder\Uninstall ${APP_NAME}.lnk" "$INSTDIR\uninstall.exe" !ifdef WEB_SITE -WriteIniStr "$INSTDIR\${APP_NAME} website.url" "InternetShortcut" "URL" "${WEB_SITE}" -CreateShortCut "$SMPROGRAMS\$SM_Folder\${APP_NAME} Website.lnk" "$INSTDIR\${APP_NAME} website.url" +WriteIniStr "$INSTDIR\Ultimaker Cura website.url" "InternetShortcut" "URL" "${WEB_SITE}" +CreateShortCut "$SMPROGRAMS\$SM_Folder\Ultimaker Cura website.lnk" "$INSTDIR\Ultimaker Cura website.url" !endif !insertmacro MUI_STARTMENU_WRITE_END !endif @@ -125,8 +125,8 @@ CreateShortCut "$SMPROGRAMS\{{ app_name }}\${APP_NAME}.lnk" "$INSTDIR\${MAIN_APP CreateShortCut "$SMPROGRAMS\{{ app_name }}\Uninstall ${APP_NAME}.lnk" "$INSTDIR\uninstall.exe" !ifdef WEB_SITE -WriteIniStr "$INSTDIR\${APP_NAME} website.url" "InternetShortcut" "URL" "${WEB_SITE}" -CreateShortCut "$SMPROGRAMS\{{ app_name }}\${APP_NAME} Website.lnk" "$INSTDIR\${APP_NAME} website.url" +WriteIniStr "$INSTDIR\Ultimaker Cura website.url" "InternetShortcut" "URL" "${WEB_SITE}" +CreateShortCut "$SMPROGRAMS\{{ app_name }}\Ultimaker Cura website.lnk" "$INSTDIR\Ultimaker Cura website.url" !endif !endif @@ -170,7 +170,7 @@ RmDir "$INSTDIR" Delete "$SMPROGRAMS\$SM_Folder\${APP_NAME}.lnk" Delete "$SMPROGRAMS\$SM_Folder\Uninstall ${APP_NAME}.lnk" !ifdef WEB_SITE -Delete "$SMPROGRAMS\$SM_Folder\${APP_NAME} Website.lnk" +Delete "$SMPROGRAMS\$SM_Folder\Ultimaker Cura website.lnk" !endif RmDir "$SMPROGRAMS\$SM_Folder" !endif @@ -179,7 +179,7 @@ RmDir "$SMPROGRAMS\$SM_Folder" Delete "$SMPROGRAMS\{{ app_name }}\${APP_NAME}.lnk" Delete "$SMPROGRAMS\{{ app_name }}\Uninstall ${APP_NAME}.lnk" !ifdef WEB_SITE -Delete "$SMPROGRAMS\{{ app_name }}\${APP_NAME} Website.lnk" +Delete "$SMPROGRAMS\{{ app_name }}\Ultimaker Cura website.lnk" !endif RmDir "$SMPROGRAMS\{{ app_name }}" !endif diff --git a/packaging/NSIS/create_windows_installer.py b/packaging/NSIS/create_windows_installer.py new file mode 100644 index 0000000000..c8d28c82a4 --- /dev/null +++ b/packaging/NSIS/create_windows_installer.py @@ -0,0 +1,80 @@ +# Copyright (c) 2022 Ultimaker B.V. +# Cura is released under the terms of the LGPLv3 or higher. +import os +import argparse # Command line arguments parsing and help. +import subprocess + +import shutil +from datetime import datetime + +from pathlib import Path + +from jinja2 import Template + + +def generate_nsi(source_path: str, dist_path: str, filename: str): + dist_loc = Path(os.getcwd(), dist_path) + source_loc = Path(os.getcwd(), source_path) + instdir = Path("$INSTDIR") + dist_paths = [p.relative_to(dist_loc.joinpath("Ultimaker-Cura")) for p in sorted(dist_loc.joinpath("Ultimaker-Cura").rglob("*")) if p.is_file()] + mapped_out_paths = {} + for dist_path in dist_paths: + if "__pycache__" not in dist_path.parts: + out_path = instdir.joinpath(dist_path).parent + if out_path not in mapped_out_paths: + mapped_out_paths[out_path] = [(dist_loc.joinpath("Ultimaker-Cura", dist_path), instdir.joinpath(dist_path))] + else: + mapped_out_paths[out_path].append((dist_loc.joinpath("Ultimaker-Cura", dist_path), instdir.joinpath(dist_path))) + + rmdir_paths = set() + for rmdir_f in mapped_out_paths.values(): + for _, rmdir_p in rmdir_f: + for rmdir in rmdir_p.parents: + rmdir_paths.add(rmdir) + + rmdir_paths = sorted(list(rmdir_paths), reverse = True)[:-2] # Removes the `.` and `..` from the list + + jinja_template_path = Path(source_loc.joinpath("packaging", "NSIS", "Ultimaker-Cura.nsi.jinja")) + with open(jinja_template_path, "r") as f: + template = Template(f.read()) + + + nsis_content = template.render( + app_name = f"Ultimaker Cura {os.getenv('CURA_VERSION_FULL')}", + main_app = "Ultimaker-Cura.exe", + version = os.getenv('CURA_VERSION_FULL'), + version_major = os.environ.get("CURA_VERSION_MAJOR"), + version_minor = os.environ.get("CURA_VERSION_MINOR"), + version_patch = os.environ.get("CURA_VERSION_PATCH"), + company = "Ultimaker B.V.", + web_site = "https://ultimaker.com", + year = datetime.now().year, + cura_license_file = str(source_loc.joinpath("packaging", "cura_license.txt")), + compression_method = "LZMA", # ZLIB, BZIP2 or LZMA + cura_banner_img = str(source_loc.joinpath("packaging", "NSIS", "cura_banner_nsis.bmp")), + cura_icon = str(source_loc.joinpath("packaging", "icons", "Cura.ico")), + mapped_out_paths = mapped_out_paths, + rmdir_paths = rmdir_paths, + destination = filename + ) + + with open(dist_loc.joinpath("Ultimaker-Cura.nsi"), "w") as f: + f.write(nsis_content) + + shutil.copy(source_loc.joinpath("packaging", "NSIS", "fileassoc.nsh"), dist_loc.joinpath("fileassoc.nsh")) + + +def build(dist_path: str): + dist_loc = Path(os.getcwd(), dist_path) + command = ["makensis", "/V2", "/P4", str(dist_loc.joinpath("Ultimaker-Cura.nsi"))] + subprocess.run(command) + + +if __name__ == "__main__": + parser = argparse.ArgumentParser(description = "Create Windows exe installer of Cura.") + parser.add_argument("source_path", type=str, help="Path to Conan install Cura folder.") + parser.add_argument("dist_path", type=str, help="Path to Pyinstaller dist folder") + parser.add_argument("filename", type = str, help = "Filename of the exe (e.g. 'Ultimaker-Cura-5.1.0-beta-Windows-X64.exe')") + args = parser.parse_args() + generate_nsi(args.source_path, args.dist_path, args.filename) + build(args.dist_path) diff --git a/packaging/NSIS/nsis-configurator.py b/packaging/NSIS/nsis-configurator.py deleted file mode 100644 index c8986fb118..0000000000 --- a/packaging/NSIS/nsis-configurator.py +++ /dev/null @@ -1,78 +0,0 @@ -import shutil -import sys -from datetime import datetime - -from pathlib import Path - -from jinja2 import Template - -if __name__ == "__main__": - """ - - dist_loc: Location of distribution folder, as output by pyinstaller - - nsi_jinja_loc: Jinja2 template to use - - app_name: Should be "Ultimaker Cura". - - main_app: Name of executable, e.g. Ultimaker-Cura.exe? - - version_major: Major version number of Semver (e.g. 5). - - version_minor: Minor version number of Semver (e.g. 0). - - version_patch: Patch version number of Semver (e.g. 0). - - version_build: A version number that gets manually incremented at each build. - - company: Publisher of the application. Should be "Ultimaker B.V." - - web_site: Website to find more information. Should be "https://ultimaker.com". - - cura_license_file: Path to a license file in Cura. Should point to packaging/cura_license.txt in this repository. - - compression_method: Compression algorithm to use to compress the data inside the executable. Should be ZLIB, ZBIP2 or LZMA. - - cura_banner_img: Path to an image shown on the left in the installer. Should point to packaging/cura_banner_nsis.bmp in this repository. - - icon_path: Path to the icon to use on the installer - - destination: Where to put the installer after it's generated. -` """ - for i, v in enumerate(sys.argv): - print(f"{i} = {v}") - dist_loc = Path(sys.argv[1]) - instdir = Path("$INSTDIR") - dist_paths = [p.relative_to(dist_loc) for p in sorted(dist_loc.rglob("*")) if p.is_file()] - mapped_out_paths = {} - for dist_path in dist_paths: - if "__pycache__" not in dist_path.parts: - out_path = instdir.joinpath(dist_path).parent - if out_path not in mapped_out_paths: - mapped_out_paths[out_path] = [(dist_loc.joinpath(dist_path), instdir.joinpath(dist_path))] - else: - mapped_out_paths[out_path].append((dist_loc.joinpath(dist_path), instdir.joinpath(dist_path))) - - rmdir_paths = set() - for rmdir_f in mapped_out_paths.values(): - for _, rmdir_p in rmdir_f: - for rmdir in rmdir_p.parents: - rmdir_paths.add(rmdir) - - rmdir_paths = sorted(list(rmdir_paths), reverse = True)[:-2] - - jinja_template_path = Path(sys.argv[2]) - with open(jinja_template_path, "r") as f: - template = Template(f.read()) - - nsis_content = template.render( - app_name = sys.argv[3], - main_app = sys.argv[4], - version_major = sys.argv[5], - version_minor = sys.argv[6], - version_patch = sys.argv[7], - version_build = sys.argv[8], - company = sys.argv[9], - web_site = sys.argv[10], - year = datetime.now().year, - cura_license_file = Path(sys.argv[11]), - compression_method = sys.argv[12], # ZLIB, BZIP2 or LZMA - cura_banner_img = Path(sys.argv[13]), - cura_icon = Path(sys.argv[14]), - mapped_out_paths = mapped_out_paths, - rmdir_paths = rmdir_paths, - destination = Path(sys.argv[15]) - ) - - with open(dist_loc.parent.joinpath(jinja_template_path.stem), "w") as f: - f.write(nsis_content) - - shutil.copy(Path(__file__).absolute().parent.joinpath("fileassoc.nsh"), dist_loc.parent.joinpath("fileassoc.nsh")) - icon_path = Path(sys.argv[14]) - shutil.copy(icon_path, dist_loc.joinpath(icon_path.name)) - diff --git a/requirements-dev.txt b/requirements-dev.txt index e6f9471ec2..819943e8b7 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -2,3 +2,4 @@ pytest pyinstaller pyinstaller-hooks-contrib sip==6.5.1 +jinja2 diff --git a/resources/texts/change_log.txt b/resources/texts/change_log.txt index 731a517c36..79ba5b4d5a 100644 --- a/resources/texts/change_log.txt +++ b/resources/texts/change_log.txt @@ -2,6 +2,9 @@ * Improved toolpath simplification algorithm The algorithm that reduces the resolution of the print has been rewritten, providing a more constant resolution to allow for greater precision without causing buffer underruns. +* Added option to alternate wall direction +A new setting causes the direction of printing walls to alternate between layers and adjacent walls, which reduces warping in the print. + * Adjusted combing boundaries to reduce scarring Travel moves through the inside of the models are adjusted so that they should keep more distance from the model where possible, yet allowing travels through narrow parts without retractions. @@ -12,20 +15,37 @@ We added the option to disable acceleration and jerk commands for travel moves. Newly created project files will now store which packages they require from the Ultimaker Marketplace. If a project needs a material from there, the user will be prompted to download it. * Other new features and improvements: +- The interface to select the printing profile in Recommended Mode has been redesigned. +- Implemented multi-threaded slicing for MacOS, to bring it in line with other operating systems. - Cura now links toolpaths to project files in the Digital Factory. - Improved performance of loading STL files on Linux. - Packages from the Marketplace can now contain intent profiles. - The application now makes heavy use of Conan to make it easier and faster to build releases of Cura. - Start and end g-code can now refer to the currently active profile with replacement keys. +- To provide proper compatibility with both older and newer Linux distribution, this release contains two Linux builds. * Bug fixes: - Fix resetting configuration if it gets corrupt. - Monotonic ordering now works again for top surfaces. -- Fixed a bug where Remove Raft Inside Corners didn't always remove all corners. -- Fixed the position of the toolbar if the toolbar is too tall to fit. +- Fix a bug where Remove Raft Inside Corners didn't always remove all corners. +- Fix the position of the toolbar if the toolbar is too tall to fit. - Intents in the Recommended Mode now show a description again. - Remove Inside Corners and Raft Base Wall Count can now be changed per extruder, though they will affect the entire print. -- Fixed opening STL files with special characters in their header. +- Fix opening STL files with special characters in their header. +- Fix crash at start-up on newer Linux distributions. +- Fix priming when printing a raft with a different extruder for some of its layers. +- Fix a case where the inner wall ends up protruding through the outside of the model. +- Improve some details on dark mode colouring. +- Fix an error sometimes occurring when uninstalling plug-ins. +- Fix a rendering issue with pop-up dialogues on MacOS. +- Fix Discard or Keep Changes dialog showing an outdated setting value. +- Horizontal Scaling Shrinkage Compensation no longer adjusts the size of the build volume, allowing the full size of the build plate to be used. +- Fixed overextrusion when using gradual infill with thin strips of infill. +- Fix opening STL files with special characters in their file header. +- Fix slicing failure when using Randomize Infill Start in some cases. +- Restore reminder to sync materials with your printer when using cloud printers with custom materials. +- The tool bar should no longer show up in the monitor stage. +- Exporting materials should now retain settings unknown to Cura as well. * Printer definitions, profiles and materials: - Improved profiles for PVA and support for Ultimaker printers. @@ -37,6 +57,10 @@ Newly created project files will now store which packages they require from the - Add Trimarker Nebula Plus printer. - Various small profile improvements. +* Known critical issues: +- The placement of the seam has gotten more scattered than in previous releases. +- Support is sometimes missing in detailed parts, where previous releases supported them properly. + [5.0] Watch the launch event to learn more about Ultimaker Cura 5.0.