Merge branch 'main' into belt/baseChanges

This commit is contained in:
Joseph Robertson
2026-04-13 21:34:34 -05:00
committed by GitHub
94 changed files with 4309 additions and 375 deletions
+1 -1
View File
@@ -136,7 +136,7 @@ jobs:
files: "ctest_results.xml" files: "ctest_results.xml"
- name: Delete Test Artifact - name: Delete Test Artifact
if: success() if: success()
uses: geekyeggo/delete-artifact@v5 uses: geekyeggo/delete-artifact@v6
with: with:
name: ${{ github.sha }}-tests name: ${{ github.sha }}-tests
flatpak: flatpak:
+1 -1
View File
@@ -52,7 +52,7 @@ jobs:
- name: setup dev on Windows - name: setup dev on Windows
if: runner.os == 'Windows' if: runner.os == 'Windows'
uses: microsoft/setup-msbuild@v2 uses: microsoft/setup-msbuild@v3
- name: Get the date on Ubuntu and macOS - name: Get the date on Ubuntu and macOS
if: runner.os != 'Windows' if: runner.os != 'Windows'
+3 -2
View File
@@ -155,7 +155,7 @@ jobs:
- name: Delete intermediate per-arch artifacts - name: Delete intermediate per-arch artifacts
if: runner.os == 'macOS' && inputs.macos-combine-only if: runner.os == 'macOS' && inputs.macos-combine-only
uses: geekyeggo/delete-artifact@v5 uses: geekyeggo/delete-artifact@v6
with: with:
name: | name: |
OrcaSlicer_Mac_bundle_arm64_${{ github.sha }} OrcaSlicer_Mac_bundle_arm64_${{ github.sha }}
@@ -275,7 +275,7 @@ jobs:
# Windows # Windows
- name: setup MSVC - name: setup MSVC
if: runner.os == 'Windows' if: runner.os == 'Windows'
uses: microsoft/setup-msbuild@v2 uses: microsoft/setup-msbuild@v3
- name: Install nsis - name: Install nsis
if: runner.os == 'Windows' && !vars.SELF_HOSTED if: runner.os == 'Windows' && !vars.SELF_HOSTED
@@ -382,6 +382,7 @@ jobs:
shell: bash shell: bash
run: | run: |
./build_linux.sh -istrlL ./build_linux.sh -istrlL
./scripts/check_appimage_libs.sh ./build/package ./build/package/bin/orca-slicer
mv -n ./build/OrcaSlicer_Linux_V${{ env.ver_pure }}.AppImage ./build/OrcaSlicer_Linux_AppImage${{ env.ubuntu-ver-str }}_${{ env.ver }}.AppImage mv -n ./build/OrcaSlicer_Linux_V${{ env.ver_pure }}.AppImage ./build/OrcaSlicer_Linux_AppImage${{ env.ubuntu-ver-str }}_${{ env.ver }}.AppImage
chmod +x ./build/OrcaSlicer_Linux_AppImage${{ env.ubuntu-ver-str }}_${{ env.ver }}.AppImage chmod +x ./build/OrcaSlicer_Linux_AppImage${{ env.ubuntu-ver-str }}_${{ env.ver }}.AppImage
tar -cvpf build_tests.tar build/tests tar -cvpf build_tests.tar build/tests
+3 -13
View File
@@ -117,7 +117,7 @@ else()
set(SLIC3R_STATIC_INITIAL 1) set(SLIC3R_STATIC_INITIAL 1)
endif() endif()
option(SLIC3R_STATIC "Compile OrcaSlicer with static libraries (Boost, TBB, glew)" ${SLIC3R_STATIC_INITIAL}) option(SLIC3R_STATIC "Compile OrcaSlicer with static libraries (Boost, TBB)" ${SLIC3R_STATIC_INITIAL})
option(SLIC3R_GUI "Compile OrcaSlicer with GUI components (OpenGL, wxWidgets)" 1) option(SLIC3R_GUI "Compile OrcaSlicer with GUI components (OpenGL, wxWidgets)" 1)
option(SLIC3R_FHS "Assume OrcaSlicer is to be installed in a FHS directory structure" 0) option(SLIC3R_FHS "Assume OrcaSlicer is to be installed in a FHS directory structure" 0)
option(SLIC3R_PROFILE "Compile OrcaSlicer with an invasive Shiny profiler" 0) option(SLIC3R_PROFILE "Compile OrcaSlicer with an invasive Shiny profiler" 0)
@@ -694,16 +694,6 @@ if(APPLE AND CMAKE_VERSION VERSION_GREATER_EQUAL "4.0")
set(OPENGL_LIBRARIES "-framework OpenGL" CACHE STRING "OpenGL framework" FORCE) set(OPENGL_LIBRARIES "-framework OpenGL" CACHE STRING "OpenGL framework" FORCE)
endif() endif()
set(GLEW_ROOT "${CMAKE_PREFIX_PATH}")
message("GLEW_ROOT: ${GLEW_ROOT}")
# Find glew or use bundled version
if (SLIC3R_STATIC AND NOT SLIC3R_STATIC_EXCLUDE_GLEW)
set(GLEW_USE_STATIC_LIBS ON)
set(GLEW_VERBOSE ON)
endif()
find_package(GLEW REQUIRED)
find_package(glfw3 REQUIRED) find_package(glfw3 REQUIRED)
# Find the Cereal serialization library # Find the Cereal serialization library
@@ -919,7 +909,7 @@ elseif (SLIC3R_FHS)
install(DIRECTORY ${SLIC3R_RESOURCES_DIR}/ DESTINATION ${SLIC3R_FHS_RESOURCES} install(DIRECTORY ${SLIC3R_RESOURCES_DIR}/ DESTINATION ${SLIC3R_FHS_RESOURCES}
PATTERN "*/udev" EXCLUDE PATTERN "*/udev" EXCLUDE
) )
install(FILES src/dev-utils/platform/unix/OrcaSlicer.desktop DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/applications) install(FILES src/dev-utils/platform/unix/com.orcaslicer.OrcaSlicer.desktop DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/applications)
foreach(SIZE 32 128 192) foreach(SIZE 32 128 192)
install(FILES ${SLIC3R_RESOURCES_DIR}/images/OrcaSlicer_${SIZE}px.png install(FILES ${SLIC3R_RESOURCES_DIR}/images/OrcaSlicer_${SIZE}px.png
DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/icons/hicolor/${SIZE}x${SIZE}/apps RENAME OrcaSlicer.png DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/icons/hicolor/${SIZE}x${SIZE}/apps RENAME OrcaSlicer.png
@@ -928,7 +918,7 @@ elseif (SLIC3R_FHS)
elseif (CMAKE_MACOSX_BUNDLE) elseif (CMAKE_MACOSX_BUNDLE)
# install(DIRECTORY "${SLIC3R_RESOURCES_DIR}/" DESTINATION "${CMAKE_INSTALL_PREFIX}/OrcaSlicer.app/Contents/resources") # install(DIRECTORY "${SLIC3R_RESOURCES_DIR}/" DESTINATION "${CMAKE_INSTALL_PREFIX}/OrcaSlicer.app/Contents/resources")
else () else ()
install(FILES src/dev-utils/platform/unix/OrcaSlicer.desktop DESTINATION ${CMAKE_INSTALL_PREFIX}/resources/applications) install(FILES src/dev-utils/platform/unix/com.orcaslicer.OrcaSlicer.desktop DESTINATION ${CMAKE_INSTALL_PREFIX}/resources/applications)
install(DIRECTORY "${SLIC3R_RESOURCES_DIR}/" DESTINATION "${CMAKE_INSTALL_PREFIX}/resources") install(DIRECTORY "${SLIC3R_RESOURCES_DIR}/" DESTINATION "${CMAKE_INSTALL_PREFIX}/resources")
endif () endif ()
+304 -2
View File
@@ -8,7 +8,7 @@ SCRIPT_PATH=$(dirname "$(readlink -f "${0}")")
pushd "${SCRIPT_PATH}" > /dev/null pushd "${SCRIPT_PATH}" > /dev/null
function usage() { function usage() {
echo "Usage: ./${SCRIPT_NAME} [-1][-b][-c][-d][-D][-e][-h][-i][-j N][-p][-r][-s][-t][-u][-l][-L]" echo "Usage: ./${SCRIPT_NAME} [-1][-b][-c][-d][-D][-e][-F][-g][-h][-i][-j N][-p][-r][-s][-t][-u][-l][-L]"
echo " -1: limit builds to one core (where possible)" echo " -1: limit builds to one core (where possible)"
echo " -j N: limit builds to N cores (where possible)" echo " -j N: limit builds to N cores (where possible)"
echo " -b: build in Debug mode" echo " -b: build in Debug mode"
@@ -17,6 +17,8 @@ function usage() {
echo " -d: download and build dependencies in ./deps/ (build prerequisite)" echo " -d: download and build dependencies in ./deps/ (build prerequisite)"
echo " -D: dry run" echo " -D: dry run"
echo " -e: build in RelWithDebInfo mode" echo " -e: build in RelWithDebInfo mode"
echo " -F: rebuild the cached Docker/Podman runner image from scratch when used with -g"
echo " -g: run the requested build steps inside a Docker/Podman Ubuntu 24.04 container similar to the GitHub Actions Linux runner"
echo " -h: prints this help text" echo " -h: prints this help text"
echo " -i: build the Orca Slicer AppImage (optional)" echo " -i: build the Orca Slicer AppImage (optional)"
echo " -p: boost ccache hit rate by disabling precompiled headers (default: ON)" echo " -p: boost ccache hit rate by disabling precompiled headers (default: ON)"
@@ -28,6 +30,9 @@ function usage() {
echo " -L: use ld.lld as linker (if available)" echo " -L: use ld.lld as linker (if available)"
echo "For a first use, you want to './${SCRIPT_NAME} -u'" echo "For a first use, you want to './${SCRIPT_NAME} -u'"
echo " and then './${SCRIPT_NAME} -dsi'" echo " and then './${SCRIPT_NAME} -dsi'"
echo "For a GitHub Actions-like Linux build locally, use './${SCRIPT_NAME} -g -istrlL'"
echo "Use './${SCRIPT_NAME} -gF -istrlL' to rebuild the cached runner image first."
echo "Set ORCA_CONTAINER_CLI, ORCA_DOCKER_IMAGE, ORCA_DOCKER_BASE_IMAGE, or ORCA_DOCKER_CMAKE_VERSION to override the container runtime, cached image tag, base image, or CMake version."
} }
SLIC3R_PRECOMPILED_HEADERS="ON" SLIC3R_PRECOMPILED_HEADERS="ON"
@@ -35,60 +40,83 @@ SLIC3R_PRECOMPILED_HEADERS="ON"
unset name unset name
BUILD_DIR=build BUILD_DIR=build
BUILD_CONFIG=Release BUILD_CONFIG=Release
while getopts ":1j:bcCdDehiprstulL" opt ; do FORWARDED_ARGS=()
while getopts ":1j:bcCdDeFghiprstulL" opt ; do
case ${opt} in case ${opt} in
1 ) 1 )
export CMAKE_BUILD_PARALLEL_LEVEL=1 export CMAKE_BUILD_PARALLEL_LEVEL=1
FORWARDED_ARGS+=("-1")
;; ;;
j ) j )
export CMAKE_BUILD_PARALLEL_LEVEL=$OPTARG export CMAKE_BUILD_PARALLEL_LEVEL=$OPTARG
FORWARDED_ARGS+=("-j" "$OPTARG")
;; ;;
b ) b )
BUILD_DIR=build-dbg BUILD_DIR=build-dbg
BUILD_CONFIG=Debug BUILD_CONFIG=Debug
FORWARDED_ARGS+=("-b")
;; ;;
c ) c )
CLEAN_BUILD=1 CLEAN_BUILD=1
FORWARDED_ARGS+=("-c")
;; ;;
C ) C )
COLORED_OUTPUT="-DCOLORED_OUTPUT=ON" COLORED_OUTPUT="-DCOLORED_OUTPUT=ON"
FORWARDED_ARGS+=("-C")
;; ;;
d ) d )
BUILD_DEPS="1" BUILD_DEPS="1"
FORWARDED_ARGS+=("-d")
;; ;;
D ) D )
DRY_RUN="1" DRY_RUN="1"
FORWARDED_ARGS+=("-D")
;; ;;
e ) e )
BUILD_DIR=build-dbginfo BUILD_DIR=build-dbginfo
BUILD_CONFIG=RelWithDebInfo BUILD_CONFIG=RelWithDebInfo
FORWARDED_ARGS+=("-e")
;;
F )
CLEAN_DOCKER_IMAGE="1"
;;
g )
USE_DOCKER="1"
;; ;;
h ) usage h ) usage
exit 1 exit 1
;; ;;
i ) i )
BUILD_IMAGE="1" BUILD_IMAGE="1"
FORWARDED_ARGS+=("-i")
;; ;;
p ) p )
SLIC3R_PRECOMPILED_HEADERS="OFF" SLIC3R_PRECOMPILED_HEADERS="OFF"
FORWARDED_ARGS+=("-p")
;; ;;
r ) r )
SKIP_RAM_CHECK="1" SKIP_RAM_CHECK="1"
FORWARDED_ARGS+=("-r")
;; ;;
s ) s )
BUILD_ORCA="1" BUILD_ORCA="1"
FORWARDED_ARGS+=("-s")
;; ;;
t ) t )
BUILD_TESTS="1" BUILD_TESTS="1"
FORWARDED_ARGS+=("-t")
;; ;;
u ) u )
export UPDATE_LIB="1" export UPDATE_LIB="1"
FORWARDED_ARGS+=("-u")
;; ;;
l ) l )
USE_CLANG="1" USE_CLANG="1"
FORWARDED_ARGS+=("-l")
;; ;;
L ) L )
USE_LLD="1" USE_LLD="1"
FORWARDED_ARGS+=("-L")
;; ;;
* ) * )
echo "Unknown argument '${opt}', aborting." echo "Unknown argument '${opt}', aborting."
@@ -102,6 +130,11 @@ if [ ${OPTIND} -eq 1 ] ; then
exit 1 exit 1
fi fi
if [[ -n "${CLEAN_DOCKER_IMAGE}" ]] && [[ -z "${USE_DOCKER}" ]] ; then
echo "Error: -F requires -g."
exit 1
fi
function check_available_memory_and_disk() { function check_available_memory_and_disk() {
FREE_MEM_GB=$(free --gibi --total | grep 'Mem' | rev | cut --delimiter=" " --fields=1 | rev) FREE_MEM_GB=$(free --gibi --total | grep 'Mem' | rev | cut --delimiter=" " --fields=1 | rev)
MIN_MEM_GB=10 MIN_MEM_GB=10
@@ -139,6 +172,275 @@ function print_and_run() {
fi fi
} }
function resolve_container_cli() {
if [[ -n "${ORCA_CONTAINER_CLI}" ]] ; then
if ! command -v "${ORCA_CONTAINER_CLI}" >/dev/null 2>&1 ; then
echo "Error: container runtime '${ORCA_CONTAINER_CLI}' was not found." >&2
exit 1
fi
echo "${ORCA_CONTAINER_CLI}"
return
fi
if command -v docker >/dev/null 2>&1 ; then
echo "docker"
return
fi
if command -v podman >/dev/null 2>&1 ; then
echo "podman"
return
fi
echo "Error: neither docker nor podman is available. Install one of them or set ORCA_CONTAINER_CLI." >&2
exit 1
}
function get_docker_runner_image() {
local base_image
local docker_cmake_version
local recipe_hash
local sanitized_base_image
local sanitized_cmake_version
if [[ -n "${ORCA_DOCKER_IMAGE}" ]] ; then
echo "${ORCA_DOCKER_IMAGE}"
return
fi
base_image="${ORCA_DOCKER_BASE_IMAGE:-ubuntu:24.04}"
docker_cmake_version="${ORCA_DOCKER_CMAKE_VERSION-4.3.0}"
recipe_hash=$(find "${SCRIPT_PATH}/build_linux.sh" "${SCRIPT_PATH}/scripts/linux.d" -type f -print0 | sort -z | xargs -0 cat | sha256sum | cut -c1-12)
sanitized_base_image=$(echo "${base_image}" | tr '/:@' '---' | tr -cs 'A-Za-z0-9_.-' '-')
sanitized_cmake_version=$(echo "${docker_cmake_version:-system}" | tr -cs 'A-Za-z0-9_.-' '-')
echo "orcaslicer-linux-builder:${sanitized_base_image}-cmake-${sanitized_cmake_version}-${recipe_hash}"
}
function docker_runner_dockerfile() {
cat <<'EOF'
ARG BASE_IMAGE=ubuntu:24.04
FROM ${BASE_IMAGE}
ARG CMAKE_VERSION=4.3.0
ENV DEBIAN_FRONTEND=noninteractive
SHELL ["/bin/bash", "-c"]
RUN apt-get update && apt-get install -y sudo ca-certificates curl tar
COPY build_linux.sh /tmp/orcaslicer/build_linux.sh
COPY scripts/linux.d /tmp/orcaslicer/scripts/linux.d
WORKDIR /tmp/orcaslicer
RUN chmod +x ./build_linux.sh
RUN ./build_linux.sh -ur
RUN if [[ -n "${CMAKE_VERSION}" ]] ; then \
case "$(uname -m)" in \
x86_64|amd64) cmake_arch="x86_64" ;; \
aarch64|arm64) cmake_arch="aarch64" ;; \
*) cmake_arch="" ;; \
esac ; \
if [[ -n "${cmake_arch}" ]] ; then \
cmake_root="/opt/cmake-${CMAKE_VERSION}-linux-${cmake_arch}" ; \
if ! curl -fsSL "https://github.com/Kitware/CMake/releases/download/v${CMAKE_VERSION}/cmake-${CMAKE_VERSION}-linux-${cmake_arch}.tar.gz" | tar -xz -C /opt ; then \
echo "Warning: failed to install CMake ${CMAKE_VERSION}; falling back to the distro cmake package." ; \
elif [[ -d "${cmake_root}" ]] ; then \
ln -sf "${cmake_root}/bin/"* /usr/local/bin/ ; \
fi ; \
else \
echo "Skipping GitHub Actions CMake install for unsupported architecture $(uname -m)." ; \
fi ; \
fi
RUN rm -rf /var/lib/apt/lists/* /tmp/orcaslicer
EOF
}
function ensure_docker_runner_image() {
local container_cli
local base_image
local runner_image
local docker_cmake_version
local image_exists="0"
local force_rebuild="0"
local -a build_cmd
container_cli="$1"
runner_image="$2"
base_image="${ORCA_DOCKER_BASE_IMAGE:-ubuntu:24.04}"
docker_cmake_version="${ORCA_DOCKER_CMAKE_VERSION-4.3.0}"
if "${container_cli}" image inspect "${runner_image}" >/dev/null 2>&1 ; then
image_exists="1"
fi
if [[ -n "${CLEAN_DOCKER_IMAGE}" ]] ; then
force_rebuild="1"
if [[ "${image_exists}" == "1" ]] ; then
echo "Removing cached container image ${runner_image} ..."
if [[ -z "${DRY_RUN}" ]] ; then
"${container_cli}" image rm -f "${runner_image}" >/dev/null
else
printf '%q ' "${container_cli}" image rm -f "${runner_image}"
echo
fi
image_exists="0"
fi
fi
if [[ "${image_exists}" == "1" ]] ; then
echo "Using cached container image ${runner_image}"
return
fi
build_cmd=(
"${container_cli}" build --pull
-t "${runner_image}"
--build-arg "BASE_IMAGE=${base_image}"
--build-arg "CMAKE_VERSION=${docker_cmake_version}"
)
if [[ "${force_rebuild}" == "1" ]] ; then
build_cmd+=(--no-cache)
fi
build_cmd+=(-f - "${SCRIPT_PATH}")
printf '%q ' "${build_cmd[@]}"
echo
if [[ -n "${DRY_RUN}" ]] ; then
return
fi
docker_runner_dockerfile | "${build_cmd[@]}"
}
function run_in_docker() {
local container_cli
local runner_image
local container_workspace
local host_uid
local host_gid
local host_user
local -a build_args
local -a container_env
container_cli=$(resolve_container_cli)
runner_image=$(get_docker_runner_image)
host_uid=$(id -u)
host_gid=$(id -g)
host_user="${USER:-orca}"
container_workspace="/__w/OrcaSlicer/OrcaSlicer"
build_args=()
for item in "${FORWARDED_ARGS[@]}" ; do
if [[ "${item}" == "-u" ]] || [[ "${item}" == "-D" ]] ; then
continue
fi
build_args+=("${item}")
done
container_env=(
-e "CI=true"
-e "GITHUB_ACTIONS=true"
-e "GITHUB_WORKSPACE=${container_workspace}"
-e "RUNNER_OS=Linux"
-e "RUNNER_TEMP=/tmp"
-e "HOST_UID=${host_uid}"
-e "HOST_GID=${host_gid}"
-e "HOST_USER=${host_user}"
)
if [[ -n "${CMAKE_BUILD_PARALLEL_LEVEL}" ]] ; then
container_env+=( -e "CMAKE_BUILD_PARALLEL_LEVEL=${CMAKE_BUILD_PARALLEL_LEVEL}" )
fi
if [[ -n "${ORCA_UPDATER_SIG_KEY}" ]] ; then
container_env+=( -e "ORCA_UPDATER_SIG_KEY=${ORCA_UPDATER_SIG_KEY}" )
fi
ensure_docker_runner_image "${container_cli}" "${runner_image}"
printf '%q ' "${container_cli}" run --rm -i \
-v "${SCRIPT_PATH}:${container_workspace}" \
-w "${container_workspace}" \
"${container_env[@]}" \
"${runner_image}" \
bash -s -- "${build_args[@]}"
echo
if [[ -n "${DRY_RUN}" ]] ; then
return
fi
"${container_cli}" run --rm -i \
-v "${SCRIPT_PATH}:${container_workspace}" \
-w "${container_workspace}" \
"${container_env[@]}" \
"${runner_image}" \
bash -s -- "${build_args[@]}" <<'EOF'
set -e
function create_builder_user() {
if [[ "${HOST_UID}" == "0" ]] ; then
HOST_USER=root
return
fi
if getent group "${HOST_GID}" >/dev/null 2>&1 ; then
HOST_GROUP=$(getent group "${HOST_GID}" | cut -d: -f1)
else
HOST_GROUP="orca-builder"
if getent group "${HOST_GROUP}" >/dev/null 2>&1 ; then
HOST_GROUP="orca-builder-${HOST_GID}"
fi
groupadd -g "${HOST_GID}" "${HOST_GROUP}"
fi
if getent passwd "${HOST_UID}" >/dev/null 2>&1 ; then
HOST_USER=$(getent passwd "${HOST_UID}" | cut -d: -f1)
usermod -g "${HOST_GROUP}" "${HOST_USER}"
elif id -u "${HOST_USER}" >/dev/null 2>&1 ; then
usermod -u "${HOST_UID}" -g "${HOST_GROUP}" "${HOST_USER}"
else
useradd -m -u "${HOST_UID}" -g "${HOST_GROUP}" -s /bin/bash "${HOST_USER}"
fi
echo "${HOST_USER} ALL=(ALL) NOPASSWD:ALL" >/etc/sudoers.d/orcaslicer-builder
chmod 0440 /etc/sudoers.d/orcaslicer-builder
}
create_builder_user
mkdir -p "${GITHUB_WORKSPACE}/deps/build/destdir"
chown -R "${HOST_UID}:${HOST_GID}" "${GITHUB_WORKSPACE}/deps/build"
if [[ -d "${GITHUB_WORKSPACE}/build" ]] ; then
chown -R "${HOST_UID}:${HOST_GID}" "${GITHUB_WORKSPACE}/build"
fi
if [[ -d "${GITHUB_WORKSPACE}/build-dbg" ]] ; then
chown -R "${HOST_UID}:${HOST_GID}" "${GITHUB_WORKSPACE}/build-dbg"
fi
if [[ -d "${GITHUB_WORKSPACE}/build-dbginfo" ]] ; then
chown -R "${HOST_UID}:${HOST_GID}" "${GITHUB_WORKSPACE}/build-dbginfo"
fi
sudo -H -u "${HOST_USER}" env \
CMAKE_BUILD_PARALLEL_LEVEL="${CMAKE_BUILD_PARALLEL_LEVEL-}" \
GITHUB_WORKSPACE="${GITHUB_WORKSPACE}" \
ORCA_UPDATER_SIG_KEY="${ORCA_UPDATER_SIG_KEY-}" \
bash -c '
set -e
cd "${GITHUB_WORKSPACE}"
if [[ "$#" -gt 0 ]] ; then
./build_linux.sh "$@"
else
echo "No build steps were requested after container setup."
fi
' bash "$@"
EOF
}
if [[ -n "${USE_DOCKER}" ]] ; then
run_in_docker
popd > /dev/null # ${SCRIPT_PATH}
exit 0
fi
# cmake 4.x compatibility workaround # cmake 4.x compatibility workaround
export CMAKE_POLICY_VERSION_MINIMUM=3.5 export CMAKE_POLICY_VERSION_MINIMUM=3.5
+1
View File
@@ -18,6 +18,7 @@ orcaslicer_add_cmake_project(Boost
-DBOOST_EXCLUDE_LIBRARIES:STRING=contract|fiber|numpy|stacktrace|wave|test -DBOOST_EXCLUDE_LIBRARIES:STRING=contract|fiber|numpy|stacktrace|wave|test
-DBOOST_LOCALE_ENABLE_ICU:BOOL=OFF # do not link to libicu, breaks compatibility between distros -DBOOST_LOCALE_ENABLE_ICU:BOOL=OFF # do not link to libicu, breaks compatibility between distros
-DBUILD_TESTING:BOOL=OFF -DBUILD_TESTING:BOOL=OFF
-DBOOST_IOSTREAMS_ENABLE_BZIP2:BOOL=OFF # avoid libbz2 soname differences in AppImage builds
-DBOOST_IOSTREAMS_ENABLE_ZSTD:BOOL=OFF -DBOOST_IOSTREAMS_ENABLE_ZSTD:BOOL=OFF
"${_context_abi_line}" "${_context_abi_line}"
"${_context_arch_line}" "${_context_arch_line}"
+6 -8
View File
@@ -6,22 +6,20 @@ else()
set(_build_static ON) set(_build_static ON)
endif() endif()
set(_glfw_platform_args "")
if(CMAKE_SYSTEM_NAME STREQUAL "Linux") if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
set(_glfw_use_wayland "-DGLFW_USE_WAYLAND=ON") set(_glfw_platform_args -DGLFW_BUILD_WAYLAND=ON -DGLFW_BUILD_X11=ON)
else()
set(_glfw_use_wayland "-DGLFW_USE_WAYLAND=FF")
endif() endif()
orcaslicer_add_cmake_project(GLFW orcaslicer_add_cmake_project(GLFW
URL https://github.com/glfw/glfw/archive/refs/tags/3.3.7.zip URL https://github.com/glfw/glfw/archive/refs/tags/3.4.zip
URL_HASH SHA256=e02d956935e5b9fb4abf90e2c2e07c9a0526d7eacae8ee5353484c69a2a76cd0 URL_HASH SHA256=a133ddc3d3c66143eba9035621db8e0bcf34dba1ee9514a9e23e96afd39fd57a
#DEPENDS dep_Boost
CMAKE_ARGS CMAKE_ARGS
-DBUILD_SHARED_LIBS=${_build_shared} -DBUILD_SHARED_LIBS=${_build_shared}
-DGLFW_BUILD_DOCS=OFF -DGLFW_BUILD_DOCS=OFF
-DGLFW_BUILD_EXAMPLES=OFF -DGLFW_BUILD_EXAMPLES=OFF
-DGLFW_BUILD_TESTS=OFF -DGLFW_BUILD_TESTS=OFF
${_glfw_use_wayland} ${_glfw_platform_args}
) )
if (MSVC) if (MSVC)
+1 -1
View File
@@ -38,7 +38,7 @@ orcaslicer_add_cmake_project(
-DwxUSE_DETECT_SM=OFF -DwxUSE_DETECT_SM=OFF
-DwxUSE_PRIVATE_FONTS=ON -DwxUSE_PRIVATE_FONTS=ON
-DwxUSE_OPENGL=ON -DwxUSE_OPENGL=ON
-DwxUSE_GLCANVAS_EGL=OFF -DwxUSE_GLCANVAS_EGL=ON
-DwxUSE_WEBREQUEST=ON -DwxUSE_WEBREQUEST=ON
-DwxUSE_WEBVIEW=ON -DwxUSE_WEBVIEW=ON
${_wx_edge} ${_wx_edge}
+1 -1
View File
@@ -12435,7 +12435,7 @@ msgid ""
"Orca Slicer can upload G-code files to a printer host. This field should " "Orca Slicer can upload G-code files to a printer host. This field should "
"contain the API Key or the password required for authentication." "contain the API Key or the password required for authentication."
msgstr "" msgstr ""
"OrcaSlicer puede cargar archivos G-Cpde a un host de impresora. Este campo " "OrcaSlicer puede cargar archivos G-Code a un host de impresora. Este campo "
"debería contener una clave API o una contraseña requerida para la " "debería contener una clave API o una contraseña requerida para la "
"autenticación." "autenticación."
@@ -1,10 +0,0 @@
{
"type": "filament",
"name": "Elegoo PETG PRO @System",
"renamed_from": "Elegoo PETG Pro @System",
"inherits": "Elegoo PETG PRO @base",
"from": "system",
"setting_id": "OGFSE02_00",
"instantiation": "true",
"compatible_printers": []
}
@@ -1,74 +0,0 @@
{
"type": "filament",
"name": "Elegoo PETG PRO @base",
"inherits": "fdm_filament_pet",
"from": "system",
"filament_id": "OGFE02",
"instantiation": "false",
"filament_cost": [
"12.49"
],
"filament_density": [
"1.27"
],
"filament_flow_ratio": [
"0.98"
],
"filament_max_volumetric_speed": [
"12"
],
"filament_retraction_length": [
"0.8"
],
"filament_retraction_speed": [
"45"
],
"filament_deretraction_speed": [
"45"
],
"filament_vendor": [
"Elegoo"
],
"nozzle_temperature": [
"245"
],
"nozzle_temperature_initial_layer": [
"240"
],
"nozzle_temperature_range_high": [
"260"
],
"nozzle_temperature_range_low": [
"230"
],
"hot_plate_temp": [
"65"
],
"hot_plate_temp_initial_layer": [
"65"
],
"textured_plate_temp": [
"75"
],
"textured_plate_temp_initial_layer": [
"75"
],
"overhang_fan_speed": [
"90"
],
"fan_max_speed": [
"80"
],
"fan_min_speed": [
"20"
],
"fan_cooling_layer_time": [
"20"
],
"slow_down_layer_time": [
"10"
],
"slow_down_min_speed": [
"20"
]
}
+50
View File
@@ -0,0 +1,50 @@
#!/usr/bin/env bash
# Libraries that are safer to resolve from the host than bundle into the AppImage.
# Keep this list focused on the glibc/runtime loader and host-specific graphics/audio stacks.
appimage_is_host_library() {
local lib_name
lib_name="$(basename "$1")"
case "$lib_name" in
linux-vdso.so.*|linux-gate.so.*|ld-linux*.so*|ld64.so*|ld-musl-*.so*|libc.so*|libpthread.so*|libm.so*|libdl.so*|librt.so*|libresolv.so*|libutil.so*|libanl.so*|libnsl.so*|libBrokenLocale.so*|libcrypt.so*|libnss_*.so*|\
libGL.so*|libOpenGL.so*|libGLX*.so*|libGLU.so*|libEGL.so*|libGLES*.so*|libGLdispatch.so*|libdrm.so*|libdrm_*.so*|libgbm.so*|libwayland-*.so*|libxcb*.so*|libX11.so*|libX11-xcb.so*|libXau.so*|libXdmcp.so*|libXext.so*|libXdamage.so*|libXfixes.so*|libXcomposite.so*|libXrender.so*|libXrandr.so*|libXcursor.so*|libXi.so*|libXinerama.so*|libxshmfence.so*|libxkbcommon.so*|libxkbcommon-x11.so*|libSM.so*|libICE.so*|libudev.so*|libasound.so*|libpulse.so*|libpulsecommon*.so*|libjack.so*|libpipewire-*.so*|libvulkan.so*|libva.so*|libva-*.so*|\
libgtk-*.so*|libgdk-*.so*|libpango*.so*|libatk-bridge-*.so*|libatk*.so*|libatspi.so*|libcairo*.so*|libgdk_pixbuf-*.so*|libgio-2.0.so*|libgmodule-2.0.so*|libgobject-2.0.so*|libglib-2.0.so*|\
libgstreamer-1.0.so*|libgst*.so*|libsoup-*.so*|libwebkit2gtk-*.so*|libjavascriptcoregtk-*.so*|libsecret-1.so*|libmanette-0.2.so*|libenchant-2.so*|libhyphen.so*|libtasn1.so*|\
libfontconfig.so*|libfreetype.so*|libharfbuzz*.so*|libfribidi.so*|libgraphite2.so*|libthai.so*|libdatrie.so*|libepoxy.so*|libpixman-1.so*|\
libstdc++.so*|libgcc_s.so*|libatomic.so*|libdbus-1.so*|libuuid.so*|libffi.so*|libselinux.so*|libmount.so*|libblkid.so*|libpcre2-*.so*|libsystemd.so*|libcap.so*|libseccomp.so*|\
liborc-0.4.so*|libgudev-1.0.so*)
return 0
;;
*)
return 1
;;
esac
}
appimage_is_elf_file() {
file -b "$1" 2>/dev/null | grep -q '^ELF '
}
appimage_list_direct_dependencies() {
local target="$1"
local line dep
while IFS= read -r line; do
if [[ "$line" == *"=> not found"* ]]; then
echo "MISSING:${line%% *}"
continue
fi
dep=""
if [[ "$line" == *"=>"* ]]; then
dep="$(printf '%s\n' "$line" | sed -n 's/.*=> \(\/[^ ]*\).*/\1/p')"
elif [[ "$line" =~ ^[[:space:]]/ ]]; then
dep="$(printf '%s\n' "$line" | awk '{print $1}')"
fi
if [[ -n "$dep" ]]; then
echo "$dep"
fi
done < <(ldd "$target" 2>/dev/null || true)
}
+99
View File
@@ -0,0 +1,99 @@
#!/usr/bin/env bash
set -euo pipefail
SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)"
# shellcheck source=/dev/null
source "${SCRIPT_DIR}/appimage_lib_policy.sh"
usage() {
echo "Usage: $0 <appdir> [entrypoint]"
}
if [[ $# -lt 1 || $# -gt 2 ]]; then
usage
exit 1
fi
APPDIR="$1"
ENTRYPOINT="${2:-}"
if [[ ! -d "$APPDIR" ]]; then
echo "Error: AppDir does not exist: $APPDIR"
exit 1
fi
APPDIR="$(cd -- "$APPDIR" && pwd)"
if [[ -n "$ENTRYPOINT" ]]; then
if [[ ! -e "$ENTRYPOINT" ]]; then
echo "Error: entrypoint does not exist: $ENTRYPOINT"
exit 1
fi
ENTRYPOINT="$(cd -- "$(dirname -- "$ENTRYPOINT")" && pwd)/$(basename -- "$ENTRYPOINT")"
fi
declare -a lib_paths=(
"$APPDIR/lib/orca-runtime"
"$APPDIR/lib"
"$APPDIR/bin"
)
for candidate in \
"$APPDIR/lib/gstreamer-1.0" \
"$APPDIR/lib/gio/modules" \
"$APPDIR/lib/gdk-pixbuf-2.0/2.10.0/loaders"; do
if [[ -d "$candidate" ]]; then
lib_paths+=("$candidate")
fi
done
audit_ld_library_path="$(IFS=:; printf '%s' "${lib_paths[*]}")"
declare -a targets=()
declare -A seen_unresolved=()
declare -A seen_host=()
if [[ -n "$ENTRYPOINT" ]]; then
targets+=("$ENTRYPOINT")
fi
while IFS= read -r -d '' file; do
if appimage_is_elf_file "$file"; then
targets+=("$file")
fi
done < <(find "$APPDIR" -type f -print0)
for target in "${targets[@]}"; do
while IFS= read -r dep; do
if [[ "$dep" == MISSING:* ]]; then
seen_unresolved["$target -> ${dep#MISSING:}"]=1
continue
fi
dep="$(readlink -f "$dep" 2>/dev/null || printf '%s' "$dep")"
if [[ "$dep" == "$APPDIR"* ]]; then
continue
fi
if appimage_is_host_library "$dep"; then
continue
fi
seen_host["$target -> $dep"]=1
done < <(LD_LIBRARY_PATH="$audit_ld_library_path${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}" appimage_list_direct_dependencies "$target")
done
if (( ${#seen_unresolved[@]} > 0 )); then
echo "AppImage dependency audit failed: unresolved runtime libraries detected"
printf '%s\n' "${!seen_unresolved[@]}" | LC_ALL=C sort
exit 1
fi
if (( ${#seen_host[@]} > 0 )); then
echo "AppImage dependency audit failed: unexpected host libraries are still required"
printf '%s\n' "${!seen_host[@]}" | LC_ALL=C sort
exit 1
fi
echo "AppImage dependency audit passed: $APPDIR"
@@ -17,6 +17,7 @@ build-options:
finish-args: finish-args:
- --share=ipc - --share=ipc
- --socket=x11 - --socket=x11
- --socket=wayland
- --share=network - --share=network
- --device=all - --device=all
- --filesystem=home - --filesystem=home
@@ -99,7 +100,7 @@ modules:
- -DwxUSE_DETECT_SM=OFF - -DwxUSE_DETECT_SM=OFF
- -DwxUSE_PRIVATE_FONTS=ON - -DwxUSE_PRIVATE_FONTS=ON
- -DwxUSE_OPENGL=ON - -DwxUSE_OPENGL=ON
- -DwxUSE_GLCANVAS_EGL=OFF - -DwxUSE_GLCANVAS_EGL=ON
- -DwxUSE_WEBREQUEST=ON - -DwxUSE_WEBREQUEST=ON
- -DwxUSE_WEBVIEW=ON - -DwxUSE_WEBVIEW=ON
- -DwxUSE_WEBVIEW_EDGE=OFF - -DwxUSE_WEBVIEW_EDGE=OFF
@@ -186,10 +187,10 @@ modules:
sha256: a378e9a39e718e289102c20d45632f873bfdc58a7a5f924246ea4b176e185f1e sha256: a378e9a39e718e289102c20d45632f873bfdc58a7a5f924246ea4b176e185f1e
dest: external-packages/Qhull dest: external-packages/Qhull
# GLFW 3.3.7 # GLFW 3.4
- type: file - type: file
url: https://github.com/glfw/glfw/archive/refs/tags/3.3.7.zip url: https://github.com/glfw/glfw/archive/refs/tags/3.4.zip
sha256: e02d956935e5b9fb4abf90e2c2e07c9a0526d7eacae8ee5353484c69a2a76cd0 sha256: a133ddc3d3c66143eba9035621db8e0bcf34dba1ee9514a9e23e96afd39fd57a
dest: external-packages/GLFW dest: external-packages/GLFW
# OpenCSG 1.4.2 # OpenCSG 1.4.2
@@ -329,7 +330,6 @@ modules:
- | # Desktop integration files - | # Desktop integration files
install -Dm644 -t /app/share/icons/hicolor/scalable/apps/ resources/images/OrcaSlicer.svg install -Dm644 -t /app/share/icons/hicolor/scalable/apps/ resources/images/OrcaSlicer.svg
install -Dm644 ${FLATPAK_ID}.metainfo.xml /app/share/metainfo/${FLATPAK_ID}.metainfo.xml install -Dm644 ${FLATPAK_ID}.metainfo.xml /app/share/metainfo/${FLATPAK_ID}.metainfo.xml
mv /app/share/applications/OrcaSlicer.desktop /app/share/applications/${FLATPAK_ID}.desktop
desktop-file-edit --set-key=Exec --set-value="entrypoint %U" /app/share/applications/${FLATPAK_ID}.desktop desktop-file-edit --set-key=Exec --set-value="entrypoint %U" /app/share/applications/${FLATPAK_ID}.desktop
install -Dm755 entrypoint /app/bin install -Dm755 entrypoint /app/bin
install -Dm755 umount /app/bin install -Dm755 umount /app/bin
+1
View File
@@ -14,6 +14,7 @@ find_package(libnoise REQUIRED)
add_subdirectory(libslic3r) add_subdirectory(libslic3r)
if (SLIC3R_GUI) if (SLIC3R_GUI)
add_subdirectory(glad)
# imgui, imguizmo, and hidapi are now included from deps_src # imgui, imguizmo, and hidapi are now included from deps_src
add_subdirectory(libvgcode) add_subdirectory(libvgcode)
+41 -29
View File
@@ -88,7 +88,9 @@ using namespace nlohmann;
#include <GLFW/glfw3.h> #include <GLFW/glfw3.h>
#ifdef __WXGTK__ #ifdef __WXGTK__
#if __has_include(<X11/Xlib.h>)
#include <X11/Xlib.h> #include <X11/Xlib.h>
#endif
#include <unistd.h> #include <unistd.h>
#endif #endif
@@ -1183,30 +1185,42 @@ int CLI::run(int argc, char **argv)
save_main_thread_id(); save_main_thread_id();
#ifdef __WXGTK__ #ifdef __WXGTK__
// On Linux, wxGTK has no support for Wayland, and the app crashes on // Safety fallback: if wxWidgets was not built with EGL support, native
// startup if gtk3 is used. This env var has to be set explicitly to // Wayland will crash in wxGLCanvas::IsDisplaySupported() because the GLX
// instruct the window manager to fall back to X server mode. // backend cannot access an X11 display. Force X11 mode in that case.
::setenv("GDK_BACKEND", "x11", /* replace */ true); // NOTE: Do NOT remove this block even after enabling wxHAS_EGL
// in the build — it protects against builds where deps were not rebuilt.
#if !defined(wxHAS_EGL) || !wxHAS_EGL
{
const char* wayland_env = ::getenv("WAYLAND_DISPLAY");
if (wayland_env && *wayland_env) {
BOOST_LOG_TRIVIAL(warning) << "Wayland detected but wxWidgets has no EGL support (wxHAS_EGL is OFF). Forcing X11 backend.";
::setenv("GDK_BACKEND", "x11", true);
}
}
#endif
// WebKit2GTK's compositing mode can fail under XWayland, causing WebViews // WebKit2GTK compositing can fail under XWayland. Only disable it when
// (like the Setup Wizard) to render blank or freeze. Disabling compositing // both DISPLAY and WAYLAND_DISPLAY are set (i.e., XWayland is in use).
// mode forces software rendering, which works reliably on all backends. // On pure X11 or native Wayland, compositing is left enabled.
::setenv("WEBKIT_DISABLE_COMPOSITING_MODE", "1", /* replace */ false); {
const char* display_env_wk = ::getenv("DISPLAY");
// On Linux dual-GPU systems, request the high-performance discrete GPU. const char* wayland_env_wk = ::getenv("WAYLAND_DISPLAY");
// DRI_PRIME=1 handles AMD and nouveau (open-source NVIDIA) PRIME setups. if (display_env_wk && *display_env_wk && wayland_env_wk && *wayland_env_wk) {
::setenv("DRI_PRIME", "1", /* replace */ false); ::setenv("WEBKIT_DISABLE_COMPOSITING_MODE", "1", /* replace */ false);
}
// For NVIDIA proprietary driver PRIME render offload, set additional variables.
// Only set if the NVIDIA kernel module is loaded to avoid breaking systems without NVIDIA.
if (::access("/proc/driver/nvidia/version", F_OK) == 0) {
::setenv("__NV_PRIME_RENDER_OFFLOAD", "1", /* replace */ false);
::setenv("__GLX_VENDOR_LIBRARY_NAME", "nvidia", /* replace */ false);
} }
// Also on Linux, we need to tell Xlib that we will be using threads, // XInitThreads is needed before GStreamer may use Xlib. On native
// lest we crash when we fire up GStreamer. // Wayland without DISPLAY, GStreamer uses waylandsink (no Xlib).
XInitThreads(); #if __has_include(<X11/Xlib.h>)
{
const char* display_env = ::getenv("DISPLAY");
if (display_env && *display_env) {
XInitThreads();
}
}
#endif
#endif #endif
// Switch boost::filesystem to utf8. // Switch boost::filesystem to utf8.
@@ -1280,19 +1294,17 @@ int CLI::run(int argc, char **argv)
if (start_gui) { if (start_gui) {
BOOST_LOG_TRIVIAL(info) << "no action, start gui directly" << std::endl; BOOST_LOG_TRIVIAL(info) << "no action, start gui directly" << std::endl;
#ifdef SLIC3R_GUI #ifdef SLIC3R_GUI
/*#if !defined(_WIN32) && !defined(__APPLE__) #if !defined(_WIN32) && !defined(__APPLE__)
// likely some linux / unix system // likely some linux / unix system
const char *display = boost::nowide::getenv("DISPLAY"); const char *display = boost::nowide::getenv("DISPLAY");
// const char *wayland_display = boost::nowide::getenv("WAYLAND_DISPLAY"); const char *wayland_display = boost::nowide::getenv("WAYLAND_DISPLAY");
//if (! ((display && *display) || (wayland_display && *wayland_display))) { if (! ((display && *display) || (wayland_display && *wayland_display))) {
if (! (display && *display)) { boost::nowide::cerr << "Neither DISPLAY nor WAYLAND_DISPLAY set, GUI mode not available." << std::endl << std::endl;
// DISPLAY not set.
boost::nowide::cerr << "DISPLAY not set, GUI mode not available." << std::endl << std::endl;
this->print_help(false); this->print_help(false);
// Indicate an error. // Indicate an error.
return 1; return 1;
} }
#endif // some linux / unix system*/ #endif // some linux / unix system
Slic3r::GUI::GUI_InitParams params; Slic3r::GUI::GUI_InitParams params;
params.argc = argc; params.argc = argc;
params.argv = argv; params.argv = argv;
@@ -6453,7 +6465,7 @@ int CLI::run(int argc, char **argv)
BOOST_LOG_TRIVIAL(error) << "init opengl failed! skip thumbnail generating" << std::endl; BOOST_LOG_TRIVIAL(error) << "init opengl failed! skip thumbnail generating" << std::endl;
} }
else { else {
BOOST_LOG_TRIVIAL(info) << "glewInit Success." << std::endl; BOOST_LOG_TRIVIAL(info) << "gladLoadGL Success." << std::endl;
GLVolumeCollection glvolume_collection; GLVolumeCollection glvolume_collection;
Model &model = m_models[0]; Model &model = m_models[0];
int obj_extruder_id = 1, volume_extruder_id = 1; int obj_extruder_id = 1, volume_extruder_id = 1;
@@ -1,9 +0,0 @@
[Desktop Entry]
Name=Bambu GCode viewer
Exec=orca-slicer --gcodeviewer %F
Icon=OrcaSlicer-gcodeviewer
Terminal=false
Type=Application
MimeType=text/x.gcode;
Categories=Graphics;3DGraphics;
Keywords=3D;Printing;Slicer;
@@ -1,4 +1,4 @@
#!/bin/sh #!/usr/bin/env bash
APPIMAGETOOLURL="https://github.com/AppImage/appimagetool/releases/download/continuous/appimagetool-$(uname -m).AppImage" APPIMAGETOOLURL="https://github.com/AppImage/appimagetool/releases/download/continuous/appimagetool-$(uname -m).AppImage"
@@ -11,30 +11,37 @@ if [ -f /.dockerenv ] ; then # Only run if inside of a Docker Container
sed '0,/AI\x02/{s|AI\x02|\x00\x00\x00|}' -i ../appimagetool.AppImage sed '0,/AI\x02/{s|AI\x02|\x00\x00\x00|}' -i ../appimagetool.AppImage
fi fi
sed -i -e 's#/usr#././#g' bin/@SLIC3R_APP_CMD@
mv @SLIC3R_APP_CMD@ AppRun mv @SLIC3R_APP_CMD@ AppRun
chmod +x AppRun chmod +x AppRun
cp resources/images/@SLIC3R_APP_KEY@_192px.png @SLIC3R_APP_KEY@.png cp resources/images/@SLIC3R_APP_KEY@_192px.png @SLIC3R_APP_KEY@.png
mkdir -p usr/share/icons/hicolor/192x192/apps mkdir -p usr/share/icons/hicolor/192x192/apps
cp resources/images/@SLIC3R_APP_KEY@_192px.png usr/share/icons/hicolor/192x192/apps/@SLIC3R_APP_KEY@.png cp resources/images/@SLIC3R_APP_KEY@_192px.png usr/share/icons/hicolor/192x192/apps/@SLIC3R_APP_KEY@.png
cat <<EOF > @SLIC3R_APP_KEY@.desktop cat <<EOF > com.orcaslicer.@SLIC3R_APP_KEY@.desktop
[Desktop Entry] [Desktop Entry]
Name=@SLIC3R_APP_KEY@ Name=@SLIC3R_APP_KEY@
Exec=AppRun %F Exec=AppRun %F
Icon=@SLIC3R_APP_KEY@ Icon=@SLIC3R_APP_KEY@
Type=Application Type=Application
PrefersNonDefaultGPU=true
X-KDE-RunOnDiscreteGpu=true
Categories=Utility; Categories=Utility;
MimeType=model/stl;application/vnd.ms-3mfdocument;application/prs.wavefront-obj;application/x-amf; MimeType=model/stl;application/vnd.ms-3mfdocument;application/prs.wavefront-obj;application/x-amf;
EOF EOF
mkdir -p usr/share/applications
cp com.orcaslicer.@SLIC3R_APP_KEY@.desktop usr/share/applications/
mkdir -p usr/share/metainfo
cp @CMAKE_CURRENT_SOURCE_DIR@/scripts/flatpak/com.orcaslicer.@SLIC3R_APP_KEY@.metainfo.xml usr/share/metainfo/
export ARCH=$(uname -m) export ARCH=$(uname -m)
if [ -f /.dockerenv ] ; then # Only run if inside of a Docker Container if [ -f /.dockerenv ] ; then # Only run if inside of a Docker Container
../appimagetool.AppImage --appimage-extract-and-run . $([ ! -z "${container}" ] && echo '--appimage-extract-and-run') ../appimagetool.AppImage --appimage-extract-and-run . $([ -n "${container}" ] && echo '--appimage-extract-and-run')
else else
../appimagetool.AppImage . $([ ! -z "${container}" ] && echo '--appimage-extract-and-run') ../appimagetool.AppImage . $([ -n "${container}" ] && echo '--appimage-extract-and-run')
fi fi
mv @SLIC3R_APP_KEY@-$(uname -m).AppImage ${APP_IMAGE} mv @SLIC3R_APP_KEY@-$(uname -m).AppImage ${APP_IMAGE}
@@ -3,10 +3,25 @@
# Despite the script name, this doesn't necessarily create an "image"; # Despite the script name, this doesn't necessarily create an "image";
# it sets up a compatibility script wrapper for the binary and arranges some resources. # it sets up a compatibility script wrapper for the binary and arranges some resources.
set -e
export ROOT=$(echo $ROOT | grep . || pwd) export ROOT=$(echo $ROOT | grep . || pwd)
export NCORES=`nproc --all` export NCORES=$(nproc --all)
CONFIG=Release CONFIG=Release
SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)"
REPO_ROOT="$(cd -- "${SCRIPT_DIR}/../.." && pwd)"
POLICY_FILE="${REPO_ROOT}/scripts/appimage_lib_policy.sh"
CHECK_SCRIPT="${REPO_ROOT}/scripts/check_appimage_libs.sh"
if [ ! -f "${POLICY_FILE}" ]; then
echo "Error: missing AppImage helper ${POLICY_FILE}"
exit 1
fi
# shellcheck source=/dev/null
source "${POLICY_FILE}"
while getopts ":ihR:" opt; do while getopts ":ihR:" opt; do
case ${opt} in case ${opt} in
i ) i )
@@ -23,35 +38,324 @@ while getopts ":ihR:" opt; do
esac esac
done done
echo -n "[9/9] Generating Linux app..." copy_directory_if_present() {
#{ local src_dir="$1"
# create directory and copy into it local dst_dir="$2"
if [ -d "package" ]; then
rm -rf package if [ -n "$src_dir" ] && [ -d "$src_dir" ]; then
mkdir -p "$dst_dir"
cp -a "$src_dir"/. "$dst_dir"/
fi fi
mkdir -p package/bin }
# Copy Resources find_pkg_config_dir() {
cp -Rf ../resources package/resources local variable="$1"
shift
local module
for module in "$@"; do
if pkg-config --exists "$module" 2>/dev/null; then
pkg-config --variable="$variable" "$module" 2>/dev/null || true
return 0
fi
done
return 1
}
find_first_existing_file() {
local path
for path in "$@"; do
if [ -f "$path" ]; then
printf '%s\n' "$path"
return 0
fi
done
return 1
}
copy_shared_object_to_dir() {
local src="$1"
local dst_dir="$2"
local src_real dst_name soname
src_real="$(readlink -f "$src")"
dst_name="$(basename "$src_real")"
mkdir -p "$dst_dir"
cp -fL "$src_real" "$dst_dir/$dst_name"
if [ -L "$src" ]; then
ln -snf "$dst_name" "$dst_dir/$(basename "$src")"
fi
soname="$(objdump -p "$src_real" 2>/dev/null | awk '$1 == "SONAME" { print $2; exit }')"
if [ -n "$soname" ] && [ "$soname" != "$dst_name" ]; then
ln -snf "$dst_name" "$dst_dir/$soname"
fi
}
bundle_dependency_closure() {
local dst_dir="$1"
shift
local -a queue=("$@")
local target dep dep_real copied_path
declare -A seen=()
while [ ${#queue[@]} -gt 0 ]; do
target="${queue[0]}"
queue=("${queue[@]:1}")
if [ ! -e "$target" ] || ! appimage_is_elf_file "$target"; then
continue
fi
while IFS= read -r dep; do
if [[ "$dep" == MISSING:* ]]; then
echo "Error: missing runtime dependency ${dep#MISSING:} while bundling $target"
exit 1
fi
dep_real="$(readlink -f "$dep" 2>/dev/null || printf '%s' "$dep")"
if appimage_is_host_library "$dep_real"; then
continue
fi
if [ -n "${seen[$dep_real]}" ]; then
continue
fi
seen[$dep_real]=1
copy_shared_object_to_dir "$dep" "$dst_dir"
copied_path="$dst_dir/$(basename "$dep_real")"
if [ -e "$copied_path" ]; then
queue+=("$copied_path")
fi
done < <(appimage_list_direct_dependencies "$target")
done
}
echo -n "[9/9] Generating Linux app..."
# {
if [ -d "package" ]; then
rm -rf package
fi
APPDIR="package"
BIN_DIR="$APPDIR/bin"
LIB_DIR="$APPDIR/lib"
PRIVATE_LIB_DIR="$LIB_DIR/orca-runtime"
SHARE_DIR="$APPDIR/share"
LIBEXEC_DIR="$APPDIR/libexec"
BUNDLE_DESKTOP_STACK="${ORCA_BUNDLE_DESKTOP_STACK:-0}"
GST_PLUGIN_DIR="$LIB_DIR/gstreamer-1.0"
GIO_MODULE_DIR="$LIB_DIR/gio/modules"
GDK_PIXBUF_DIR="$LIB_DIR/gdk-pixbuf-2.0/2.10.0/loaders"
mkdir -p "$BIN_DIR" "$LIB_DIR" "$PRIVATE_LIB_DIR" "$SHARE_DIR" "$LIBEXEC_DIR"
if [ "$BUNDLE_DESKTOP_STACK" = "1" ]; then
mkdir -p "$GST_PLUGIN_DIR" "$GIO_MODULE_DIR" "$GDK_PIXBUF_DIR"
fi
cp -Rf ../resources "$APPDIR/resources"
# Find and hard link the @SLIC3R_APP_CMD@ binary from Multi-Config build
ORIGINAL_BINARY_LOCATION="" ORIGINAL_BINARY_LOCATION=""
if [ -f "src/${CONFIG}/@SLIC3R_APP_CMD@" ]; then if [ -f "src/${CONFIG}/@SLIC3R_APP_CMD@" ]; then
ORIGINAL_BINARY_LOCATION="$(realpath "src/${CONFIG}/@SLIC3R_APP_CMD@")" ORIGINAL_BINARY_LOCATION="$(realpath "src/${CONFIG}/@SLIC3R_APP_CMD@")"
elif [ -f "src/@SLIC3R_APP_CMD@" ]; then elif [ -f "src/@SLIC3R_APP_CMD@" ]; then
# Fallback for single-config builds
ORIGINAL_BINARY_LOCATION="$(realpath "src/@SLIC3R_APP_CMD@")" ORIGINAL_BINARY_LOCATION="$(realpath "src/@SLIC3R_APP_CMD@")"
else else
echo "Error: @SLIC3R_APP_CMD@ binary not found in any configuration directory" echo "Error: @SLIC3R_APP_CMD@ binary not found in any configuration directory"
exit 1 exit 1
fi fi
cp -fl "${ORIGINAL_BINARY_LOCATION}" package/bin/@SLIC3R_APP_CMD@ cp -fl "${ORIGINAL_BINARY_LOCATION}" "$BIN_DIR/@SLIC3R_APP_CMD@"
if [ "$BUNDLE_DESKTOP_STACK" = "1" ]; then
GSTREAMER_PLUGIN_SOURCE_DIR="$(find_pkg_config_dir pluginsdir gstreamer-1.0 || true)"
if [ -z "$GSTREAMER_PLUGIN_SOURCE_DIR" ]; then
GSTREAMER_PLUGIN_SOURCE_DIR="$(find /usr/lib /usr/lib64 -maxdepth 4 -type d -name gstreamer-1.0 2>/dev/null | head -n1)"
fi
copy_directory_if_present "$GSTREAMER_PLUGIN_SOURCE_DIR" "$GST_PLUGIN_DIR"
GIO_MODULE_SOURCE_DIR="$(find_pkg_config_dir giomoduledir gio-2.0 || true)"
if [ -z "$GIO_MODULE_SOURCE_DIR" ]; then
GIO_MODULE_SOURCE_DIR="$(find /usr/lib /usr/lib64 -maxdepth 5 -type d -path '*/gio/modules' 2>/dev/null | head -n1)"
fi
copy_directory_if_present "$GIO_MODULE_SOURCE_DIR" "$GIO_MODULE_DIR"
GDK_PIXBUF_SOURCE_DIR="$(find_pkg_config_dir gdk_pixbuf_moduledir gdk-pixbuf-2.0 || true)"
if [ -z "$GDK_PIXBUF_SOURCE_DIR" ]; then
GDK_PIXBUF_SOURCE_DIR="$(find /usr/lib /usr/lib64 -maxdepth 6 -type d -path '*/gdk-pixbuf-2.0/*/loaders' 2>/dev/null | head -n1)"
fi
copy_directory_if_present "$GDK_PIXBUF_SOURCE_DIR" "$GDK_PIXBUF_DIR"
GLIB_SCHEMAS_SOURCE_DIR="$(find_pkg_config_dir schemasdir gio-2.0 || true)"
if [ -z "$GLIB_SCHEMAS_SOURCE_DIR" ]; then
GLIB_SCHEMAS_SOURCE_DIR="/usr/share/glib-2.0/schemas"
fi
copy_directory_if_present "$GLIB_SCHEMAS_SOURCE_DIR" "$SHARE_DIR/glib-2.0/schemas"
if [ -d "$SHARE_DIR/glib-2.0/schemas" ] && command -v glib-compile-schemas >/dev/null 2>&1; then
glib-compile-schemas "$SHARE_DIR/glib-2.0/schemas"
fi
# Distros disagree on where helper executables live: pkg-config may point to libexec,
# Debian/Ubuntu often ship the scanner under a multiarch libdir, and RPM distros may use lib64.
GST_PLUGIN_SCANNER_SOURCE="$(find_first_existing_file \
"$(find_pkg_config_dir pluginscannerdir gstreamer-1.0 || true)/gst-plugin-scanner" \
/usr/libexec/gstreamer-1.0/gst-plugin-scanner \
/usr/lib/gstreamer1.0/gstreamer-1.0/gst-plugin-scanner \
/usr/lib/*/gstreamer1.0/gstreamer-1.0/gst-plugin-scanner \
/usr/lib64/gstreamer1.0/gstreamer-1.0/gst-plugin-scanner)" || true
if [ -n "$GST_PLUGIN_SCANNER_SOURCE" ]; then
mkdir -p "$LIBEXEC_DIR/gstreamer-1.0"
cp -fL "$GST_PLUGIN_SCANNER_SOURCE" "$LIBEXEC_DIR/gstreamer-1.0/gst-plugin-scanner"
fi
# Prefer the canonical pkg-config-reported helper path, but keep PATH-based fallbacks
# for distros exposing gdk-pixbuf-query-loaders or gdk-pixbuf-query-loaders-64 directly.
GDK_PIXBUF_QUERY_LOADERS_SOURCE="$(find_first_existing_file \
"$(pkg-config --variable=gdk_pixbuf_query_loaders gdk-pixbuf-2.0 2>/dev/null || true)" \
"$(command -v gdk-pixbuf-query-loaders 2>/dev/null || true)" \
"$(command -v gdk-pixbuf-query-loaders-64 2>/dev/null || true)")" || true
if [ -n "$GDK_PIXBUF_QUERY_LOADERS_SOURCE" ]; then
cp -fL "$GDK_PIXBUF_QUERY_LOADERS_SOURCE" "$LIBEXEC_DIR/gdk-pixbuf-query-loaders"
fi
fi
# WebKitGTK helper binaries are resolved from distro-specific absolute paths
# baked into libwebkit2gtk. Bundling Ubuntu's WebKitGTK inside an AppImage
# built with -g makes those helper paths unusable on Fedora and vice versa,
# so rely on the host WebKitGTK runtime instead of copying the helper stack.
mapfile -d '' BUNDLE_TARGETS < <(find "$BIN_DIR" "$LIB_DIR" "$LIBEXEC_DIR" -type f -print0 2>/dev/null)
bundle_dependency_closure "$PRIVATE_LIB_DIR" "${BUNDLE_TARGETS[@]}"
cat << EOF >"$LIBEXEC_DIR/@SLIC3R_APP_CMD@-env"
#!/bin/sh
set -e
SELF_DIR=\$(CDPATH= cd -- "\$(dirname -- "\$0")" && pwd)
APPDIR="\${APPDIR:-\$(CDPATH= cd -- "\$SELF_DIR/.." && pwd)}"
USE_BUNDLED_WEBKITGTK_STACK=0
if [ -e "\$APPDIR/lib/libwebkit2gtk-4.1.so.0" ] || [ -e "\$APPDIR/lib/libwebkit2gtk-4.0.so.0" ]; then
USE_BUNDLED_WEBKITGTK_STACK=1
fi
export APPDIR
PRIVATE_LIB_DIR="\$APPDIR/lib/orca-runtime"
if [ -d "\$PRIVATE_LIB_DIR" ]; then
export LD_LIBRARY_PATH="\$PRIVATE_LIB_DIR:\$APPDIR/bin\${LD_LIBRARY_PATH:+:\$LD_LIBRARY_PATH}"
else
export LD_LIBRARY_PATH="\$APPDIR/bin\${LD_LIBRARY_PATH:+:\$LD_LIBRARY_PATH}"
fi
has_host_runtime_library() {
local lib_name path
if command -v ldconfig >/dev/null 2>&1; then
if ldconfig -p 2>/dev/null | grep -Fq " \$lib_name"; then
return 0
fi
fi
for path in \
/lib /lib64 /usr/lib /usr/lib64 \
/usr/lib/* /usr/lib64/* /lib/* /lib64/*; do
if [ -e "\$path/\$lib_name" ]; then
return 0
fi
done
return 1
}
target_missing_runtime_library() {
local target_bin="\$1"
local lib_name="\$2"
if [ -z "\$target_bin" ] || [ ! -e "\$target_bin" ]; then
return 1
fi
if command -v ldd >/dev/null 2>&1; then
if ldd "\$target_bin" 2>/dev/null | grep -Fq "\$lib_name => not found"; then
return 0
fi
fi
return 1
}
TARGET_BIN="\$1"
if target_missing_runtime_library "\$TARGET_BIN" "libOpenGL.so.0" || ! has_host_runtime_library "libOpenGL.so.0"; then
echo "Error: missing host OpenGL runtime library libOpenGL.so.0." >&2
echo "On Ubuntu/Pop!_OS/Debian, install: libopengl0 and libglu1-mesa" >&2
echo "On Arch/CachyOS, install: libglvnd" >&2
exit 1
fi
if [ "\$USE_BUNDLED_WEBKITGTK_STACK" = "1" ]; then
export LD_LIBRARY_PATH="\$APPDIR/lib\${LD_LIBRARY_PATH:+:\$LD_LIBRARY_PATH}"
export GST_PLUGIN_SYSTEM_PATH=""
export GST_PLUGIN_PATH="\$APPDIR/lib/gstreamer-1.0\${GST_PLUGIN_PATH:+:\$GST_PLUGIN_PATH}"
export GIO_EXTRA_MODULES="\$APPDIR/lib/gio/modules\${GIO_EXTRA_MODULES:+:\$GIO_EXTRA_MODULES}"
export XDG_DATA_DIRS="\$APPDIR/share\${XDG_DATA_DIRS:+:\$XDG_DATA_DIRS}"
if [ -d "\$APPDIR/share/glib-2.0/schemas" ]; then
export GSETTINGS_SCHEMA_DIR="\$APPDIR/share/glib-2.0/schemas"
fi
if [ -x "\$APPDIR/libexec/gstreamer-1.0/gst-plugin-scanner" ]; then
export GST_PLUGIN_SCANNER="\$APPDIR/libexec/gstreamer-1.0/gst-plugin-scanner"
fi
if [ -d "\$APPDIR/lib/gdk-pixbuf-2.0/2.10.0/loaders" ]; then
export GDK_PIXBUF_MODULEDIR="\$APPDIR/lib/gdk-pixbuf-2.0/2.10.0/loaders"
if [ -x "\$APPDIR/libexec/gdk-pixbuf-query-loaders" ]; then
PIXBUF_CACHE_DIR="\${XDG_CACHE_HOME:-\$HOME/.cache}/@SLIC3R_APP_KEY@"
PIXBUF_CACHE_FILE="\$PIXBUF_CACHE_DIR/gdk-pixbuf-loaders.cache"
mkdir -p "\$PIXBUF_CACHE_DIR"
if [ ! -s "\$PIXBUF_CACHE_FILE" ] || find "\$APPDIR/lib/gdk-pixbuf-2.0/2.10.0/loaders" -type f -newer "\$PIXBUF_CACHE_FILE" | grep -q .; then
"\$APPDIR/libexec/gdk-pixbuf-query-loaders" "\$APPDIR/lib/gdk-pixbuf-2.0/2.10.0/loaders"/*.so > "\$PIXBUF_CACHE_FILE" 2>/dev/null || true
fi
if [ -s "\$PIXBUF_CACHE_FILE" ]; then
export GDK_PIXBUF_MODULE_FILE="\$PIXBUF_CACHE_FILE"
fi
fi
fi
if [ -d "\$APPDIR/lib/webkit2gtk-4.1" ]; then
export WEBKIT_EXEC_PATH="\$APPDIR/lib/webkit2gtk-4.1"
elif [ -d "\$APPDIR/lib/webkit2gtk-4.0" ]; then
export WEBKIT_EXEC_PATH="\$APPDIR/lib/webkit2gtk-4.0"
fi
if [ -d "\$APPDIR/lib/webkit2gtk-4.1/injected-bundle" ]; then
export WEBKIT_INJECTED_BUNDLE_PATH="\$APPDIR/lib/webkit2gtk-4.1/injected-bundle"
elif [ -d "\$APPDIR/lib/webkit2gtk-4.0/injected-bundle" ]; then
export WEBKIT_INJECTED_BUNDLE_PATH="\$APPDIR/lib/webkit2gtk-4.0/injected-bundle"
fi
else
if target_missing_runtime_library "\$TARGET_BIN" "libwebkit2gtk-4.1.so.0" || \
target_missing_runtime_library "\$TARGET_BIN" "libjavascriptcoregtk-4.1.so.0" || \
! has_host_runtime_library "libwebkit2gtk-4.1.so.0" || \
! has_host_runtime_library "libjavascriptcoregtk-4.1.so.0"; then
echo "Error: missing host WebKitGTK 4.1 runtime libraries." >&2
echo "Install the distro package providing libwebkit2gtk-4.1.so.0 and libjavascriptcoregtk-4.1.so.0." >&2
echo "On Arch/CachyOS, install: webkit2gtk-4.1" >&2
exit 1
fi
fi
exec "\$@"
EOF
chmod ug+x "$LIBEXEC_DIR/@SLIC3R_APP_CMD@-env"
# create bin
cat << EOF >@SLIC3R_APP_CMD@ cat << EOF >@SLIC3R_APP_CMD@
#!/bin/bash #!/bin/bash
DIR=\$(readlink -f "\$0" | xargs dirname) DIR=\$(dirname "\$(readlink -f "\$0")")
export LD_LIBRARY_PATH="\$DIR/bin:\$LD_LIBRARY_PATH" export APPDIR="\${APPDIR:-\$DIR}"
# FIXME: OrcaSlicer segfault workarounds # FIXME: OrcaSlicer segfault workarounds
# 1) OrcaSlicer will segfault on systems where locale info is not as expected (i.e. Holo-ISO arch-based distro) # 1) OrcaSlicer will segfault on systems where locale info is not as expected (i.e. Holo-ISO arch-based distro)
@@ -76,38 +380,33 @@ if [ "\$XDG_SESSION_TYPE" = "wayland" ] && [ "\$ZINK_DISABLE_OVERRIDE" != "1" ];
fi fi
fi fi
fi fi
exec "\$DIR/bin/@SLIC3R_APP_CMD@" "\$@" exec "\$DIR/libexec/@SLIC3R_APP_CMD@-env" "\$DIR/bin/@SLIC3R_APP_CMD@" "\$@"
EOF EOF
chmod ug+x @SLIC3R_APP_CMD@ chmod ug+x @SLIC3R_APP_CMD@
cp -fl @SLIC3R_APP_CMD@ package/@SLIC3R_APP_CMD@ cp -fl @SLIC3R_APP_CMD@ "$APPDIR/@SLIC3R_APP_CMD@"
# Nothing uses this tar? Remove if nobody has complained and it's been a while since this comment added.
# Original commit was https://github.com/OrcaSlicer/OrcaSlicer/commit/f5a4862da52fc68f77b5201ddf330a9800d83228 if [ -x "${CHECK_SCRIPT}" ] && [ -z "${ORCA_SKIP_APPIMAGE_AUDIT}" ]; then
# and it doesn't appear to have been used there either. "${CHECK_SCRIPT}" "$APPDIR" "$BIN_DIR/@SLIC3R_APP_CMD@"
#pushd package > /dev/null fi
#tar -cvf ../@SLIC3R_APP_KEY@.tar . &>/dev/null # } &> $ROOT/Build.log # Capture all command output
#popd > /dev/null
#} &> $ROOT/Build.log # Capture all command output
echo "done" echo "done"
if [[ -n "$BUILD_IMAGE" ]] if [[ -n "$BUILD_IMAGE" ]]
then then
echo -n "Creating Appimage for distribution..." echo -n "Creating Appimage for distribution..."
#{ # {
# AppImage script modifies files in place, so make a copy and clean up after.
rm -rf package_appimage rm -rf package_appimage
cp -Rf package package_appimage cp -Rf package package_appimage
pushd package_appimage > /dev/null pushd package_appimage > /dev/null
chmod +x ../build_appimage.sh chmod +x ../build_appimage.sh
if ../build_appimage.sh; then if ../build_appimage.sh; then
# Clean up on success. popd > /dev/null
popd > /dev/null mv package_appimage/"@SLIC3R_APP_KEY@_Linux_V@SoftFever_VERSION@.AppImage" "@SLIC3R_APP_KEY@_Linux_V@SoftFever_VERSION@.AppImage"
mv package_appimage/"@SLIC3R_APP_KEY@_Linux_V@SoftFever_VERSION@.AppImage" "@SLIC3R_APP_KEY@_Linux_V@SoftFever_VERSION@.AppImage" rm -fR package_appimage
rm -fR package_appimage
else else
# Leave files on failure so you can debug. popd > /dev/null
popd > /dev/null
fi fi
#} &> $ROOT/Build.log # Capture all command output # } &> $ROOT/Build.log # Capture all command output
echo "done" echo "done"
fi fi
@@ -5,6 +5,8 @@ Icon=OrcaSlicer
Exec=orca-slicer %U Exec=orca-slicer %U
Terminal=false Terminal=false
Type=Application Type=Application
PrefersNonDefaultGPU=true
X-KDE-RunOnDiscreteGpu=true
MimeType=model/stl;model/3mf;application/vnd.ms-3mfdocument;application/prs.wavefront-obj;application/x-amf;x-scheme-handler/orcaslicer;model/step; MimeType=model/stl;model/3mf;application/vnd.ms-3mfdocument;application/prs.wavefront-obj;application/x-amf;x-scheme-handler/orcaslicer;model/step;
Categories=Graphics;3DGraphics;Engineering; Categories=Graphics;3DGraphics;Engineering;
Keywords=3D;Printing;Slicer;slice;3D;printer;convert;gcode;stl;obj;amf;SLA Keywords=3D;Printing;Slicer;slice;3D;printer;convert;gcode;stl;obj;amf;SLA
+3
View File
@@ -0,0 +1,3 @@
add_library(glad STATIC src/gl.c)
target_include_directories(glad PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include)
target_link_libraries(glad PRIVATE ${CMAKE_DL_LIBS})
+311
View File
@@ -0,0 +1,311 @@
#ifndef __khrplatform_h_
#define __khrplatform_h_
/*
** Copyright (c) 2008-2018 The Khronos Group Inc.
**
** Permission is hereby granted, free of charge, to any person obtaining a
** copy of this software and/or associated documentation files (the
** "Materials"), to deal in the Materials without restriction, including
** without limitation the rights to use, copy, modify, merge, publish,
** distribute, sublicense, and/or sell copies of the Materials, and to
** permit persons to whom the Materials are furnished to do so, subject to
** the following conditions:
**
** The above copyright notice and this permission notice shall be included
** in all copies or substantial portions of the Materials.
**
** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
*/
/* Khronos platform-specific types and definitions.
*
* The master copy of khrplatform.h is maintained in the Khronos EGL
* Registry repository at https://github.com/KhronosGroup/EGL-Registry
* The last semantic modification to khrplatform.h was at commit ID:
* 67a3e0864c2d75ea5287b9f3d2eb74a745936692
*
* Adopters may modify this file to suit their platform. Adopters are
* encouraged to submit platform specific modifications to the Khronos
* group so that they can be included in future versions of this file.
* Please submit changes by filing pull requests or issues on
* the EGL Registry repository linked above.
*
*
* See the Implementer's Guidelines for information about where this file
* should be located on your system and for more details of its use:
* http://www.khronos.org/registry/implementers_guide.pdf
*
* This file should be included as
* #include <KHR/khrplatform.h>
* by Khronos client API header files that use its types and defines.
*
* The types in khrplatform.h should only be used to define API-specific types.
*
* Types defined in khrplatform.h:
* khronos_int8_t signed 8 bit
* khronos_uint8_t unsigned 8 bit
* khronos_int16_t signed 16 bit
* khronos_uint16_t unsigned 16 bit
* khronos_int32_t signed 32 bit
* khronos_uint32_t unsigned 32 bit
* khronos_int64_t signed 64 bit
* khronos_uint64_t unsigned 64 bit
* khronos_intptr_t signed same number of bits as a pointer
* khronos_uintptr_t unsigned same number of bits as a pointer
* khronos_ssize_t signed size
* khronos_usize_t unsigned size
* khronos_float_t signed 32 bit floating point
* khronos_time_ns_t unsigned 64 bit time in nanoseconds
* khronos_utime_nanoseconds_t unsigned time interval or absolute time in
* nanoseconds
* khronos_stime_nanoseconds_t signed time interval in nanoseconds
* khronos_boolean_enum_t enumerated boolean type. This should
* only be used as a base type when a client API's boolean type is
* an enum. Client APIs which use an integer or other type for
* booleans cannot use this as the base type for their boolean.
*
* Tokens defined in khrplatform.h:
*
* KHRONOS_FALSE, KHRONOS_TRUE Enumerated boolean false/true values.
*
* KHRONOS_SUPPORT_INT64 is 1 if 64 bit integers are supported; otherwise 0.
* KHRONOS_SUPPORT_FLOAT is 1 if floats are supported; otherwise 0.
*
* Calling convention macros defined in this file:
* KHRONOS_APICALL
* KHRONOS_APIENTRY
* KHRONOS_APIATTRIBUTES
*
* These may be used in function prototypes as:
*
* KHRONOS_APICALL void KHRONOS_APIENTRY funcname(
* int arg1,
* int arg2) KHRONOS_APIATTRIBUTES;
*/
#if defined(__SCITECH_SNAP__) && !defined(KHRONOS_STATIC)
# define KHRONOS_STATIC 1
#endif
/*-------------------------------------------------------------------------
* Definition of KHRONOS_APICALL
*-------------------------------------------------------------------------
* This precedes the return type of the function in the function prototype.
*/
#if defined(KHRONOS_STATIC)
/* If the preprocessor constant KHRONOS_STATIC is defined, make the
* header compatible with static linking. */
# define KHRONOS_APICALL
#elif defined(_WIN32)
# define KHRONOS_APICALL __declspec(dllimport)
#elif defined (__SYMBIAN32__)
# define KHRONOS_APICALL IMPORT_C
#elif defined(__ANDROID__)
# define KHRONOS_APICALL __attribute__((visibility("default")))
#else
# define KHRONOS_APICALL
#endif
/*-------------------------------------------------------------------------
* Definition of KHRONOS_APIENTRY
*-------------------------------------------------------------------------
* This follows the return type of the function and precedes the function
* name in the function prototype.
*/
#if defined(_WIN32) && !defined(_WIN32_WCE) && !defined(__SCITECH_SNAP__)
/* Win32 but not WinCE */
# define KHRONOS_APIENTRY __stdcall
#else
# define KHRONOS_APIENTRY
#endif
/*-------------------------------------------------------------------------
* Definition of KHRONOS_APIATTRIBUTES
*-------------------------------------------------------------------------
* This follows the closing parenthesis of the function prototype arguments.
*/
#if defined (__ARMCC_2__)
#define KHRONOS_APIATTRIBUTES __softfp
#else
#define KHRONOS_APIATTRIBUTES
#endif
/*-------------------------------------------------------------------------
* basic type definitions
*-----------------------------------------------------------------------*/
#if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || defined(__GNUC__) || defined(__SCO__) || defined(__USLC__)
/*
* Using <stdint.h>
*/
#include <stdint.h>
typedef int32_t khronos_int32_t;
typedef uint32_t khronos_uint32_t;
typedef int64_t khronos_int64_t;
typedef uint64_t khronos_uint64_t;
#define KHRONOS_SUPPORT_INT64 1
#define KHRONOS_SUPPORT_FLOAT 1
/*
* To support platform where unsigned long cannot be used interchangeably with
* inptr_t (e.g. CHERI-extended ISAs), we can use the stdint.h intptr_t.
* Ideally, we could just use (u)intptr_t everywhere, but this could result in
* ABI breakage if khronos_uintptr_t is changed from unsigned long to
* unsigned long long or similar (this results in different C++ name mangling).
* To avoid changes for existing platforms, we restrict usage of intptr_t to
* platforms where the size of a pointer is larger than the size of long.
*/
#if defined(__SIZEOF_LONG__) && defined(__SIZEOF_POINTER__)
#if __SIZEOF_POINTER__ > __SIZEOF_LONG__
#define KHRONOS_USE_INTPTR_T
#endif
#endif
#elif defined(__VMS ) || defined(__sgi)
/*
* Using <inttypes.h>
*/
#include <inttypes.h>
typedef int32_t khronos_int32_t;
typedef uint32_t khronos_uint32_t;
typedef int64_t khronos_int64_t;
typedef uint64_t khronos_uint64_t;
#define KHRONOS_SUPPORT_INT64 1
#define KHRONOS_SUPPORT_FLOAT 1
#elif defined(_WIN32) && !defined(__SCITECH_SNAP__)
/*
* Win32
*/
typedef __int32 khronos_int32_t;
typedef unsigned __int32 khronos_uint32_t;
typedef __int64 khronos_int64_t;
typedef unsigned __int64 khronos_uint64_t;
#define KHRONOS_SUPPORT_INT64 1
#define KHRONOS_SUPPORT_FLOAT 1
#elif defined(__sun__) || defined(__digital__)
/*
* Sun or Digital
*/
typedef int khronos_int32_t;
typedef unsigned int khronos_uint32_t;
#if defined(__arch64__) || defined(_LP64)
typedef long int khronos_int64_t;
typedef unsigned long int khronos_uint64_t;
#else
typedef long long int khronos_int64_t;
typedef unsigned long long int khronos_uint64_t;
#endif /* __arch64__ */
#define KHRONOS_SUPPORT_INT64 1
#define KHRONOS_SUPPORT_FLOAT 1
#elif 0
/*
* Hypothetical platform with no float or int64 support
*/
typedef int khronos_int32_t;
typedef unsigned int khronos_uint32_t;
#define KHRONOS_SUPPORT_INT64 0
#define KHRONOS_SUPPORT_FLOAT 0
#else
/*
* Generic fallback
*/
#include <stdint.h>
typedef int32_t khronos_int32_t;
typedef uint32_t khronos_uint32_t;
typedef int64_t khronos_int64_t;
typedef uint64_t khronos_uint64_t;
#define KHRONOS_SUPPORT_INT64 1
#define KHRONOS_SUPPORT_FLOAT 1
#endif
/*
* Types that are (so far) the same on all platforms
*/
typedef signed char khronos_int8_t;
typedef unsigned char khronos_uint8_t;
typedef signed short int khronos_int16_t;
typedef unsigned short int khronos_uint16_t;
/*
* Types that differ between LLP64 and LP64 architectures - in LLP64,
* pointers are 64 bits, but 'long' is still 32 bits. Win64 appears
* to be the only LLP64 architecture in current use.
*/
#ifdef KHRONOS_USE_INTPTR_T
typedef intptr_t khronos_intptr_t;
typedef uintptr_t khronos_uintptr_t;
#elif defined(_WIN64)
typedef signed long long int khronos_intptr_t;
typedef unsigned long long int khronos_uintptr_t;
#else
typedef signed long int khronos_intptr_t;
typedef unsigned long int khronos_uintptr_t;
#endif
#if defined(_WIN64)
typedef signed long long int khronos_ssize_t;
typedef unsigned long long int khronos_usize_t;
#else
typedef signed long int khronos_ssize_t;
typedef unsigned long int khronos_usize_t;
#endif
#if KHRONOS_SUPPORT_FLOAT
/*
* Float type
*/
typedef float khronos_float_t;
#endif
#if KHRONOS_SUPPORT_INT64
/* Time types
*
* These types can be used to represent a time interval in nanoseconds or
* an absolute Unadjusted System Time. Unadjusted System Time is the number
* of nanoseconds since some arbitrary system event (e.g. since the last
* time the system booted). The Unadjusted System Time is an unsigned
* 64 bit value that wraps back to 0 every 584 years. Time intervals
* may be either signed or unsigned.
*/
typedef khronos_uint64_t khronos_utime_nanoseconds_t;
typedef khronos_int64_t khronos_stime_nanoseconds_t;
#endif
/*
* Dummy value used to pad enum types to 32 bits.
*/
#ifndef KHRONOS_MAX_ENUM
#define KHRONOS_MAX_ENUM 0x7FFFFFFF
#endif
/*
* Enumerated boolean type
*
* Values other than zero should be considered to be true. Therefore
* comparisons should not be made against KHRONOS_TRUE.
*/
typedef enum {
KHRONOS_FALSE = 0,
KHRONOS_TRUE = 1,
KHRONOS_BOOLEAN_ENUM_FORCE_SIZE = KHRONOS_MAX_ENUM
} khronos_boolean_enum_t;
#endif /* __khrplatform_h_ */
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+7 -6
View File
@@ -9,11 +9,8 @@ if (EMSCRIPTEN OR SLIC3R_OPENGL_ES)
glad/src/gles2.c glad/src/gles2.c
) )
else () else ()
set(GLAD_SOURCES # Use shared GLAD library for GL; no local sources needed
glad/include/glad/gl.h set(GLAD_SOURCES "")
glad/include/KHR/khrplatform.h
glad/src/gl.c
)
endif () endif ()
set(LIBVGCODE_SOURCES set(LIBVGCODE_SOURCES
@@ -77,4 +74,8 @@ if (WIN32)
endif () endif ()
# glad includes # glad includes
include_directories(glad/include) if (EMSCRIPTEN OR SLIC3R_OPENGL_ES)
target_include_directories(libvgcode PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/glad/include)
else ()
target_link_libraries(libvgcode PUBLIC glad)
endif ()
+2 -2
View File
@@ -7,9 +7,9 @@
// OpenGL loader // OpenGL loader
#ifdef ENABLE_OPENGL_ES #ifdef ENABLE_OPENGL_ES
#include "../glad/include/glad/gles2.h" #include <glad/gles2.h>
#else #else
#include "../glad/include/glad/gl.h" #include <glad/gl.h>
#endif // ENABLE_OPENGL_ES #endif // ENABLE_OPENGL_ES
#include <string> #include <string>
+13 -3
View File
@@ -301,6 +301,8 @@ set(SLIC3R_GUI_SOURCES
GUI/KBShortcutsDialog.hpp GUI/KBShortcutsDialog.hpp
GUI/LibVGCode/LibVGCodeWrapper.hpp GUI/LibVGCode/LibVGCodeWrapper.hpp
GUI/LibVGCode/LibVGCodeWrapper.cpp GUI/LibVGCode/LibVGCodeWrapper.cpp
GUI/LinuxDisplayBackend.cpp
GUI/LinuxDisplayBackend.hpp
GUI/MainFrame.cpp GUI/MainFrame.cpp
GUI/MainFrame.hpp GUI/MainFrame.hpp
GUI/MarkdownTip.cpp GUI/MarkdownTip.cpp
@@ -736,7 +738,7 @@ else()
set(_opengl_link_lib OpenGL::GL) set(_opengl_link_lib OpenGL::GL)
endif() endif()
target_link_libraries(libslic3r_gui libslic3r cereal::cereal imgui imguizmo minilzo libvgcode md4c-html GLEW::GLEW OpenGL::GL hidapi ${wxWidgets_LIBRARIES} glfw libcurl OpenSSL::SSL OpenSSL::Crypto noise::noise) target_link_libraries(libslic3r_gui libslic3r cereal::cereal imgui imguizmo minilzo libvgcode md4c-html glad ${_opengl_link_lib} hidapi ${wxWidgets_LIBRARIES} glfw libcurl OpenSSL::SSL OpenSSL::Crypto noise::noise)
if (MSVC) if (MSVC)
@@ -787,16 +789,24 @@ if (UNIX AND NOT APPLE)
find_package(PkgConfig REQUIRED) find_package(PkgConfig REQUIRED)
find_package(GTK${SLIC3R_GTK} REQUIRED) find_package(GTK${SLIC3R_GTK} REQUIRED)
pkg_check_modules(LIBSECRET REQUIRED libsecret-1) pkg_check_modules(LIBSECRET REQUIRED libsecret-1)
pkg_check_modules(webkit2gtk REQUIRED webkit2gtk-4.1)
if (FLATPAK) if (FLATPAK)
# I don't know why this is needed, but for whatever reason slic3r isn't # I don't know why this is needed, but for whatever reason slic3r isn't
# linking to X11 and webkit2gtk. force it. # linking to X11 and webkit2gtk. force it.
find_package(X11 REQUIRED) find_package(X11 REQUIRED)
pkg_check_modules(webkit2gtk REQUIRED webkit2gtk-4.1)
target_link_libraries(libslic3r_gui ${X11_LIBRARIES} ${webkit2gtk_LIBRARIES}) target_link_libraries(libslic3r_gui ${X11_LIBRARIES} ${webkit2gtk_LIBRARIES})
endif() endif()
target_include_directories(libslic3r_gui SYSTEM PRIVATE ${GTK${SLIC3R_GTK}_INCLUDE_DIRS} ${LIBSECRET_INCLUDE_DIRS}) target_include_directories(libslic3r_gui SYSTEM PRIVATE ${GTK${SLIC3R_GTK}_INCLUDE_DIRS} ${LIBSECRET_INCLUDE_DIRS} ${webkit2gtk_INCLUDE_DIRS})
target_link_libraries(libslic3r_gui ${GTK${SLIC3R_GTK}_LIBRARIES} fontconfig ${LIBSECRET_LIBRARIES}) target_link_libraries(libslic3r_gui ${GTK${SLIC3R_GTK}_LIBRARIES} fontconfig ${LIBSECRET_LIBRARIES})
# Propagate GDK backend detection results as compile definitions so that
# LinuxDisplayBackend.cpp can include the right GDK headers.
if (wxHAVE_GDK_X11)
target_compile_definitions(libslic3r_gui PRIVATE wxHAVE_GDK_X11)
endif ()
if (wxHAVE_GDK_WAYLAND)
target_compile_definitions(libslic3r_gui PRIVATE wxHAVE_GDK_WAYLAND)
endif ()
# We add GStreamer for bambu:/// support. # We add GStreamer for bambu:/// support.
pkg_check_modules(GSTREAMER REQUIRED gstreamer-1.0) pkg_check_modules(GSTREAMER REQUIRED gstreamer-1.0)
+1 -1
View File
@@ -15,7 +15,7 @@
#include "Plater.hpp" #include "Plater.hpp"
#include "Camera.hpp" #include "Camera.hpp"
#include <GL/glew.h> #include <glad/gl.h>
#include <boost/algorithm/string/predicate.hpp> #include <boost/algorithm/string/predicate.hpp>
#include <boost/filesystem/operations.hpp> #include <boost/filesystem/operations.hpp>
+1 -1
View File
@@ -1,4 +1,4 @@
#include <GL/glew.h> #include <glad/gl.h>
#include "3DScene.hpp" #include "3DScene.hpp"
#include "GLShader.hpp" #include "GLShader.hpp"
+1 -1
View File
@@ -94,7 +94,7 @@ void CopyrightsDialog::fill_entries()
{ "Eigen3", "", "http://eigen.tuxfamily.org" }, { "Eigen3", "", "http://eigen.tuxfamily.org" },
{ "Expat", "", "http://www.libexpat.org" }, { "Expat", "", "http://www.libexpat.org" },
{ "fast_float", "", "https://github.com/fastfloat/fast_float" }, { "fast_float", "", "https://github.com/fastfloat/fast_float" },
{ "GLEW (The OpenGL Extension Wrangler Library)", "", "http://glew.sourceforge.net" }, { "GLAD (Multi-Language GL Loader-Generator)", "", "https://github.com/Dav1dde/glad" },
{ "GLFW", "", "https://www.glfw.org" }, { "GLFW", "", "https://www.glfw.org" },
{ "GNU gettext", "", "https://www.gnu.org/software/gettext" }, { "GNU gettext", "", "https://www.gnu.org/software/gettext" },
{ "ImGUI", "", "https://github.com/ocornut/imgui" }, { "ImGUI", "", "https://github.com/ocornut/imgui" },
+31 -8
View File
@@ -6,6 +6,9 @@
#include "I18N.hpp" #include "I18N.hpp"
#include "GUI_App.hpp" #include "GUI_App.hpp"
#include "GUI.hpp" #include "GUI.hpp"
#ifdef __WXGTK__
#include "LinuxDisplayBackend.hpp"
#endif
#include "wxExtensions.hpp" #include "wxExtensions.hpp"
#include "Plater.hpp" #include "Plater.hpp"
#include "MainFrame.hpp" #include "MainFrame.hpp"
@@ -56,9 +59,9 @@ CenteredTitle::CenteredTitle(wxWindow* parent)
wxString ellipsized = wxControl::Ellipsize(m_title, dc, wxELLIPSIZE_END, wxMax(0, rect.GetWidth() - FromDIP(8))); wxString ellipsized = wxControl::Ellipsize(m_title, dc, wxELLIPSIZE_END, wxMax(0, rect.GetWidth() - FromDIP(8)));
int y = rect.y + (rect.height - textHeight) / 2; int y = rect.y + (rect.height - textHeight) / 2;
int x = rect.x + (ellipsized != m_title) // is ellipsized int x = rect.x + ((ellipsized != m_title) // is ellipsized
? FromDIP(4) // align to left when clipped ? FromDIP(4) // align to left when clipped
: (rect.width - dc.GetTextExtent(m_title).GetWidth()) / 2; // centered when has available space : (rect.width - dc.GetTextExtent(m_title).GetWidth()) / 2); // centered when has available space
dc.DrawText(ellipsized, x, y); dc.DrawText(ellipsized, x, y);
}); });
@@ -346,6 +349,10 @@ void BBLTopbar::Init(wxFrame* parent)
this->Bind(wxEVT_LEFT_DCLICK, &BBLTopbar::OnMouseLeftDClock, this); this->Bind(wxEVT_LEFT_DCLICK, &BBLTopbar::OnMouseLeftDClock, this);
this->Bind(wxEVT_LEFT_DOWN, &BBLTopbar::OnMouseLeftDown, this); this->Bind(wxEVT_LEFT_DOWN, &BBLTopbar::OnMouseLeftDown, this);
this->Bind(wxEVT_LEFT_UP, &BBLTopbar::OnMouseLeftUp, this); this->Bind(wxEVT_LEFT_UP, &BBLTopbar::OnMouseLeftUp, this);
this->Bind(wxEVT_LEAVE_WINDOW, [this](wxMouseEvent& event) {
m_last_mouse_position = wxDefaultPosition;
event.Skip();
});
this->Bind(wxEVT_AUITOOLBAR_TOOL_DROPDOWN, &BBLTopbar::OnOpenProject, this, wxID_OPEN); this->Bind(wxEVT_AUITOOLBAR_TOOL_DROPDOWN, &BBLTopbar::OnOpenProject, this, wxID_OPEN);
this->Bind(wxEVT_AUITOOLBAR_TOOL_DROPDOWN, &BBLTopbar::OnSaveProject, this, wxID_SAVE); this->Bind(wxEVT_AUITOOLBAR_TOOL_DROPDOWN, &BBLTopbar::OnSaveProject, this, wxID_SAVE);
this->Bind(wxEVT_AUITOOLBAR_TOOL_DROPDOWN, &BBLTopbar::OnRedo, this, wxID_REDO); this->Bind(wxEVT_AUITOOLBAR_TOOL_DROPDOWN, &BBLTopbar::OnRedo, this, wxID_REDO);
@@ -589,8 +596,9 @@ void BBLTopbar::OnCloseFrame(wxAuiToolBarEvent& event)
void BBLTopbar::OnMouseLeftDClock(wxMouseEvent& mouse) void BBLTopbar::OnMouseLeftDClock(wxMouseEvent& mouse)
{ {
wxPoint mouse_pos = ::wxGetMousePosition(); m_last_mouse_position = mouse.GetPosition();
wxAuiToolBarItem* item = this->FindToolByCurrentPosition(); wxPoint mouse_pos = this->ClientToScreen(mouse.GetPosition());
wxAuiToolBarItem* item = this->FindToolByPosition(mouse.GetX(), mouse.GetY());
// check whether mouse is not on any tool item // check whether mouse is not on any tool item
if (item != NULL && item->GetWindow() != m_title_ctrl) { if (item != NULL && item->GetWindow() != m_title_ctrl) {
mouse.Skip(); mouse.Skip();
@@ -658,9 +666,12 @@ void BBLTopbar::OnCalibToolItem(wxAuiToolBarEvent &evt)
void BBLTopbar::OnMouseLeftDown(wxMouseEvent& event) void BBLTopbar::OnMouseLeftDown(wxMouseEvent& event)
{ {
wxPoint mouse_pos = ::wxGetMousePosition(); m_last_mouse_position = event.GetPosition();
// Use event-relative coords converted to screen, instead of wxGetMousePosition()
// which returns (0,0) on Wayland for global screen coordinates.
wxPoint mouse_pos = this->ClientToScreen(event.GetPosition());
wxPoint frame_pos = m_frame->GetScreenPosition(); wxPoint frame_pos = m_frame->GetScreenPosition();
wxAuiToolBarItem* item = this->FindToolByCurrentPosition(); wxAuiToolBarItem* item = this->FindToolByPosition(event.GetX(), event.GetY());
m_delta = mouse_pos - frame_pos; m_delta = mouse_pos - frame_pos;
if (item == NULL || item->GetWindow() == m_title_ctrl) if (item == NULL || item->GetWindow() == m_title_ctrl)
@@ -688,7 +699,8 @@ void BBLTopbar::OnMouseLeftDown(wxMouseEvent& event)
void BBLTopbar::OnMouseLeftUp(wxMouseEvent& event) void BBLTopbar::OnMouseLeftUp(wxMouseEvent& event)
{ {
wxPoint mouse_pos = ::wxGetMousePosition(); m_last_mouse_position = event.GetPosition();
wxPoint mouse_pos = this->ClientToScreen(event.GetPosition());
if (HasCapture()) if (HasCapture())
{ {
ReleaseMouse(); ReleaseMouse();
@@ -699,7 +711,10 @@ void BBLTopbar::OnMouseLeftUp(wxMouseEvent& event)
void BBLTopbar::OnMouseMotion(wxMouseEvent& event) void BBLTopbar::OnMouseMotion(wxMouseEvent& event)
{ {
wxPoint mouse_pos = ::wxGetMousePosition(); m_last_mouse_position = event.GetPosition();
// Use event-relative coords converted to screen, instead of wxGetMousePosition()
// which returns (0,0) on Wayland for global screen coordinates.
wxPoint mouse_pos = this->ClientToScreen(event.GetPosition());
if (!HasCapture()) { if (!HasCapture()) {
//m_frame->OnMouseMotion(event); //m_frame->OnMouseMotion(event);
@@ -743,6 +758,14 @@ void BBLTopbar::OnMenuClose(wxMenuEvent& event)
wxAuiToolBarItem* BBLTopbar::FindToolByCurrentPosition() wxAuiToolBarItem* BBLTopbar::FindToolByCurrentPosition()
{ {
if (m_last_mouse_position != wxDefaultPosition && GetClientRect().Contains(m_last_mouse_position))
return this->FindToolByPosition(m_last_mouse_position.x, m_last_mouse_position.y);
#ifdef __WXGTK__
if (Slic3r::GUI::is_running_on_wayland())
return nullptr;
#endif
wxPoint mouse_pos = ::wxGetMousePosition(); wxPoint mouse_pos = ::wxGetMousePosition();
wxPoint client_pos = this->ScreenToClient(mouse_pos); wxPoint client_pos = this->ScreenToClient(mouse_pos);
return this->FindToolByPosition(client_pos.x, client_pos.y); return this->FindToolByPosition(client_pos.x, client_pos.y);
+1
View File
@@ -85,6 +85,7 @@ private:
wxAuiToolBarItem* m_dropdown_menu_item; wxAuiToolBarItem* m_dropdown_menu_item;
wxRect m_normalRect; wxRect m_normalRect;
wxPoint m_delta; wxPoint m_delta;
wxPoint m_last_mouse_position{wxDefaultPosition};
wxMenu m_top_menu; wxMenu m_top_menu;
wxMenu* m_file_menu; wxMenu* m_file_menu;
wxMenu m_calib_menu; wxMenu m_calib_menu;
+1 -1
View File
@@ -13,7 +13,7 @@
#include <wx/mstream.h> #include <wx/mstream.h>
#include <wx/rawbmp.h> #include <wx/rawbmp.h>
#endif /* __WXGTK2__ */ #endif /* __WXGTK2__ */
#include <GL/glew.h> #include <glad/gl.h>
#define NANOSVG_IMPLEMENTATION #define NANOSVG_IMPLEMENTATION
#include "nanosvg/nanosvg.h" #include "nanosvg/nanosvg.h"
#define NANOSVGRAST_IMPLEMENTATION #define NANOSVGRAST_IMPLEMENTATION
+1 -1
View File
@@ -8,7 +8,7 @@
#include "Plater.hpp" #include "Plater.hpp"
#endif // ENABLE_CAMERA_STATISTICS #endif // ENABLE_CAMERA_STATISTICS
#include <GL/glew.h> #include <glad/gl.h>
namespace Slic3r { namespace Slic3r {
namespace GUI { namespace GUI {
+10 -6
View File
@@ -209,7 +209,7 @@ bool DesktopIntegrationDialog::is_integrated()
if (path.empty()) if (path.empty())
return false; return false;
// confirmation that OrcaSlicer.desktop exists // confirmation that com.orcaslicer.OrcaSlicer.desktop exists
struct stat buffer; struct stat buffer;
return (stat (path.c_str(), &buffer) == 0); return (stat (path.c_str(), &buffer) == 0);
} }
@@ -336,19 +336,21 @@ void DesktopIntegrationDialog::perform_desktop_integration()
"Exec=\"%3%\" %%F\n" "Exec=\"%3%\" %%F\n"
"Terminal=false\n" "Terminal=false\n"
"Type=Application\n" "Type=Application\n"
"PrefersNonDefaultGPU=true\n"
"X-KDE-RunOnDiscreteGpu=true\n"
"MimeType=model/stl;application/vnd.ms-3mfdocument;application/prs.wavefront-obj;application/x-amf;\n" "MimeType=model/stl;application/vnd.ms-3mfdocument;application/prs.wavefront-obj;application/x-amf;\n"
"Categories=Graphics;3DGraphics;Engineering;\n" "Categories=Graphics;3DGraphics;Engineering;\n"
"Keywords=3D;Printing;Slicer;slice;3D;printer;convert;gcode;stl;obj;amf;SLA\n" "Keywords=3D;Printing;Slicer;slice;3D;printer;convert;gcode;stl;obj;amf;SLA\n"
"StartupNotify=false\n" "StartupNotify=false\n"
"StartupWMClass=orca-slicer\n", name_suffix, version_suffix, excutable_path); "StartupWMClass=orca-slicer\n", name_suffix, version_suffix, excutable_path);
std::string path = GUI::format("%1%/applications/OrcaSlicer%2%.desktop", target_dir_desktop, version_suffix); std::string path = GUI::format("%1%/applications/com.orcaslicer.OrcaSlicer%2%.desktop", target_dir_desktop, version_suffix);
if (create_desktop_file(path, desktop_file)){ if (create_desktop_file(path, desktop_file)){
BOOST_LOG_TRIVIAL(debug) << "OrcaSlicer.desktop file installation success."; BOOST_LOG_TRIVIAL(debug) << "com.orcaslicer.OrcaSlicer.desktop file installation success.";
break; break;
} else { } else {
// write failed - try another path // write failed - try another path
BOOST_LOG_TRIVIAL(debug) << "Attempt to OrcaSlicer.desktop file installation failed. failed path: " << target_candidates[i]; BOOST_LOG_TRIVIAL(debug) << "Attempt to com.orcaslicer.OrcaSlicer.desktop file installation failed. failed path: " << target_candidates[i];
target_dir_desktop.clear(); target_dir_desktop.clear();
} }
// if all failed - try creating default home folder // if all failed - try creating default home folder
@@ -357,7 +359,7 @@ void DesktopIntegrationDialog::perform_desktop_integration()
create_path(into_u8(wxFileName::GetHomeDir()), ".local/share/applications"); create_path(into_u8(wxFileName::GetHomeDir()), ".local/share/applications");
// create desktop file // create desktop file
target_dir_desktop = GUI::format("%1%/.local/share",wxFileName::GetHomeDir()); target_dir_desktop = GUI::format("%1%/.local/share",wxFileName::GetHomeDir());
std::string path = GUI::format("%1%/applications/OrcaSlicer%2%.desktop", target_dir_desktop, version_suffix); std::string path = GUI::format("%1%/applications/com.orcaslicer.OrcaSlicer%2%.desktop", target_dir_desktop, version_suffix);
if (contains_path_dir(target_dir_desktop, "applications")) { if (contains_path_dir(target_dir_desktop, "applications")) {
if (!create_desktop_file(path, desktop_file)) { if (!create_desktop_file(path, desktop_file)) {
// Desktop file not written - end desktop integration // Desktop file not written - end desktop integration
@@ -379,7 +381,7 @@ void DesktopIntegrationDialog::perform_desktop_integration()
return; return;
} }
// save path to desktop file // save path to desktop file
app_config->set("desktop_integration_app_path", GUI::format("%1%/applications/OrcaSlicer%2%.desktop", target_dir_desktop, version_suffix)); app_config->set("desktop_integration_app_path", GUI::format("%1%/applications/com.orcaslicer.OrcaSlicer%2%.desktop", target_dir_desktop, version_suffix));
// Repeat for Gcode viewer - use same paths as for slicer files // Repeat for Gcode viewer - use same paths as for slicer files
// Do NOT add gcode viewer desktop file on ChromeOS // Do NOT add gcode viewer desktop file on ChromeOS
@@ -405,6 +407,8 @@ void DesktopIntegrationDialog::perform_desktop_integration()
"Exec=\"%3%\" --gcodeviewer %%F\n" "Exec=\"%3%\" --gcodeviewer %%F\n"
"Terminal=false\n" "Terminal=false\n"
"Type=Application\n" "Type=Application\n"
"PrefersNonDefaultGPU=true\n"
"X-KDE-RunOnDiscreteGpu=true\n"
"MimeType=text/x.gcode;\n" "MimeType=text/x.gcode;\n"
"Categories=Graphics;3DGraphics;\n" "Categories=Graphics;3DGraphics;\n"
"Keywords=3D;Printing;Slicer;\n" "Keywords=3D;Printing;Slicer;\n"
+1 -1
View File
@@ -18,7 +18,7 @@ public:
// methods that actually do / undo desktop integration. Static to be accesible from anywhere. // methods that actually do / undo desktop integration. Static to be accesible from anywhere.
// returns true if path to OrcaSlicer.desktop is stored in App Config and existence of desktop file. // returns true if path to com.orcaslicer.OrcaSlicer.desktop is stored in App Config and existence of desktop file.
// Does not check if desktop file leads to this binary or existence of icons and viewer desktop file. // Does not check if desktop file leads to this binary or existence of icons and viewer desktop file.
static bool is_integrated(); static bool is_integrated();
// true if appimage // true if appimage
+1 -1
View File
@@ -32,7 +32,7 @@
#endif // ENABLE_ACTUAL_SPEED_DEBUG #endif // ENABLE_ACTUAL_SPEED_DEBUG
#include <imgui/imgui_internal.h> #include <imgui/imgui_internal.h>
#include <GL/glew.h> #include <glad/gl.h>
#include <boost/log/trivial.hpp> #include <boost/log/trivial.hpp>
#include <boost/algorithm/string/split.hpp> #include <boost/algorithm/string/split.hpp>
#include <boost/nowide/cstdio.hpp> #include <boost/nowide/cstdio.hpp>
+52 -49
View File
@@ -44,7 +44,7 @@
#include "slic3r/Utils/RetinaHelper.hpp" #include "slic3r/Utils/RetinaHelper.hpp"
#endif #endif
#include <GL/glew.h> #include <glad/gl.h>
#include <wx/glcanvas.h> #include <wx/glcanvas.h>
#include <wx/bitmap.h> #include <wx/bitmap.h>
@@ -2194,8 +2194,12 @@ void GLCanvas3D::render(bool only_init)
wxGetApp().imgui()->render(); wxGetApp().imgui()->render();
m_canvas->SwapBuffers(); // On Wayland, eglSwapBuffers blocks when the canvas is hidden or
m_render_stats.increment_fps_counter(); // occluded. Skip the swap to avoid stalling the render loop.
if (m_canvas->IsShownOnScreen()) {
m_canvas->SwapBuffers();
m_render_stats.increment_fps_counter();
}
} }
void GLCanvas3D::render_thumbnail(ThumbnailData & thumbnail_data, void GLCanvas3D::render_thumbnail(ThumbnailData & thumbnail_data,
@@ -4824,14 +4828,13 @@ Vec2d GLCanvas3D::get_local_mouse_position() const
if (m_canvas == nullptr) if (m_canvas == nullptr)
return Vec2d::Zero(); return Vec2d::Zero();
wxPoint mouse_pos = m_canvas->ScreenToClient(wxGetMousePosition()); // Use the cached mouse position from event handlers (m_mouse.position)
const double factor = // instead of wxGetMousePosition() + ScreenToClient(), because
#if ENABLE_RETINA_GL // wxGetMousePosition() returns (0,0) on Wayland for global coords.
m_retina_helper->get_scale_factor(); // m_mouse.position already stores local canvas coordinates (set from
#else // event.GetX(), event.GetY()) and is already scaled by the retina factor
1.0; // in on_mouse(), so we can return it directly.
#endif return m_mouse.position;
return Vec2d(factor * mouse_pos.x, factor * mouse_pos.y);
} }
void GLCanvas3D::set_tooltip(const std::string& tooltip) void GLCanvas3D::set_tooltip(const std::string& tooltip)
@@ -6395,21 +6398,21 @@ void GLCanvas3D::render_thumbnail_framebuffer_ext(ThumbnailData& thumbnail_data,
// glsafe(::glEnable(GL_MULTISAMPLE)); // glsafe(::glEnable(GL_MULTISAMPLE));
GLint max_samples; GLint max_samples;
glsafe(::glGetIntegerv(GL_MAX_SAMPLES_EXT, &max_samples)); glsafe(::glGetIntegerv(GL_MAX_SAMPLES, &max_samples));
GLsizei num_samples = max_samples / 2; GLsizei num_samples = max_samples / 2;
GLuint render_fbo; GLuint render_fbo;
glsafe(::glGenFramebuffersEXT(1, &render_fbo)); glsafe(::glGenFramebuffers(1, &render_fbo));
glsafe(::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, render_fbo)); glsafe(::glBindFramebuffer(GL_FRAMEBUFFER, render_fbo));
GLuint render_tex = 0; GLuint render_tex = 0;
GLuint render_tex_buffer = 0; GLuint render_tex_buffer = 0;
if (multisample) { if (multisample) {
// use renderbuffer instead of texture to avoid the need to use glTexImage2DMultisample which is available only since OpenGL 3.2 // use renderbuffer instead of texture to avoid the need to use glTexImage2DMultisample which is available only since OpenGL 3.2
glsafe(::glGenRenderbuffersEXT(1, &render_tex_buffer)); glsafe(::glGenRenderbuffers(1, &render_tex_buffer));
glsafe(::glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, render_tex_buffer)); glsafe(::glBindRenderbuffer(GL_RENDERBUFFER, render_tex_buffer));
glsafe(::glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, num_samples, GL_RGBA8, w, h)); glsafe(::glRenderbufferStorageMultisample(GL_RENDERBUFFER, num_samples, GL_RGBA8, w, h));
glsafe(::glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_EXT, render_tex_buffer)); glsafe(::glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, render_tex_buffer));
} }
else { else {
glsafe(::glGenTextures(1, &render_tex)); glsafe(::glGenTextures(1, &render_tex));
@@ -6417,31 +6420,31 @@ void GLCanvas3D::render_thumbnail_framebuffer_ext(ThumbnailData& thumbnail_data,
glsafe(::glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr)); glsafe(::glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr));
glsafe(::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)); glsafe(::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
glsafe(::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)); glsafe(::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
glsafe(::glFramebufferTexture2D(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, render_tex, 0)); glsafe(::glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, render_tex, 0));
} }
GLuint render_depth; GLuint render_depth;
glsafe(::glGenRenderbuffersEXT(1, &render_depth)); glsafe(::glGenRenderbuffers(1, &render_depth));
glsafe(::glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, render_depth)); glsafe(::glBindRenderbuffer(GL_RENDERBUFFER, render_depth));
if (multisample) if (multisample)
glsafe(::glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, num_samples, GL_DEPTH_COMPONENT24, w, h)); glsafe(::glRenderbufferStorageMultisample(GL_RENDERBUFFER, num_samples, GL_DEPTH_COMPONENT24, w, h));
else else
glsafe(::glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, w, h)); glsafe(::glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, w, h));
glsafe(::glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, render_depth)); glsafe(::glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, render_depth));
GLenum drawBufs[] = { GL_COLOR_ATTACHMENT0 }; GLenum drawBufs[] = { GL_COLOR_ATTACHMENT0 };
glsafe(::glDrawBuffers(1, drawBufs)); glsafe(::glDrawBuffers(1, drawBufs));
if (::glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) == GL_FRAMEBUFFER_COMPLETE_EXT) { if (::glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE) {
render_thumbnail_internal(thumbnail_data, thumbnail_params, partplate_list, model_objects, volumes, extruder_colors, shader, camera_type, camera_view_angle_type, render_thumbnail_internal(thumbnail_data, thumbnail_params, partplate_list, model_objects, volumes, extruder_colors, shader, camera_type, camera_view_angle_type,
for_picking, for_picking,
ban_light); ban_light);
if (multisample) { if (multisample) {
GLuint resolve_fbo; GLuint resolve_fbo;
glsafe(::glGenFramebuffersEXT(1, &resolve_fbo)); glsafe(::glGenFramebuffers(1, &resolve_fbo));
glsafe(::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, resolve_fbo)); glsafe(::glBindFramebuffer(GL_FRAMEBUFFER, resolve_fbo));
GLuint resolve_tex; GLuint resolve_tex;
glsafe(::glGenTextures(1, &resolve_tex)); glsafe(::glGenTextures(1, &resolve_tex));
@@ -6449,21 +6452,21 @@ void GLCanvas3D::render_thumbnail_framebuffer_ext(ThumbnailData& thumbnail_data,
glsafe(::glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr)); glsafe(::glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr));
glsafe(::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)); glsafe(::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
glsafe(::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)); glsafe(::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
glsafe(::glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, resolve_tex, 0)); glsafe(::glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, resolve_tex, 0));
glsafe(::glDrawBuffers(1, drawBufs)); glsafe(::glDrawBuffers(1, drawBufs));
if (::glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) == GL_FRAMEBUFFER_COMPLETE_EXT) { if (::glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE) {
glsafe(::glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, render_fbo)); glsafe(::glBindFramebuffer(GL_READ_FRAMEBUFFER, render_fbo));
glsafe(::glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, resolve_fbo)); glsafe(::glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolve_fbo));
glsafe(::glBlitFramebufferEXT(0, 0, w, h, 0, 0, w, h, GL_COLOR_BUFFER_BIT, GL_LINEAR)); glsafe(::glBlitFramebuffer(0, 0, w, h, 0, 0, w, h, GL_COLOR_BUFFER_BIT, GL_LINEAR));
glsafe(::glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, resolve_fbo)); glsafe(::glBindFramebuffer(GL_READ_FRAMEBUFFER, resolve_fbo));
glsafe(::glReadPixels(0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, (void*)thumbnail_data.pixels.data())); glsafe(::glReadPixels(0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, (void*)thumbnail_data.pixels.data()));
} }
glsafe(::glDeleteTextures(1, &resolve_tex)); glsafe(::glDeleteTextures(1, &resolve_tex));
glsafe(::glDeleteFramebuffersEXT(1, &resolve_fbo)); glsafe(::glDeleteFramebuffers(1, &resolve_fbo));
} }
else else
glsafe(::glReadPixels(0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, (void*)thumbnail_data.pixels.data())); glsafe(::glReadPixels(0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, (void*)thumbnail_data.pixels.data()));
@@ -6473,13 +6476,13 @@ void GLCanvas3D::render_thumbnail_framebuffer_ext(ThumbnailData& thumbnail_data,
#endif // ENABLE_THUMBNAIL_GENERATOR_DEBUG_OUTPUT #endif // ENABLE_THUMBNAIL_GENERATOR_DEBUG_OUTPUT
} }
glsafe(::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0)); glsafe(::glBindFramebuffer(GL_FRAMEBUFFER, 0));
glsafe(::glDeleteRenderbuffersEXT(1, &render_depth)); glsafe(::glDeleteRenderbuffers(1, &render_depth));
if (render_tex_buffer != 0) if (render_tex_buffer != 0)
glsafe(::glDeleteRenderbuffersEXT(1, &render_tex_buffer)); glsafe(::glDeleteRenderbuffers(1, &render_tex_buffer));
if (render_tex != 0) if (render_tex != 0)
glsafe(::glDeleteTextures(1, &render_tex)); glsafe(::glDeleteTextures(1, &render_tex));
glsafe(::glDeleteFramebuffersEXT(1, &render_fbo)); glsafe(::glDeleteFramebuffers(1, &render_fbo));
//if (!multisample) //if (!multisample)
// glsafe(::glDisable(GL_MULTISAMPLE)); // glsafe(::glDisable(GL_MULTISAMPLE));
@@ -7256,8 +7259,8 @@ void GLCanvas3D::_rectangular_selection_picking_pass()
glsafe(::glBindFramebuffer(GL_FRAMEBUFFER, render_fbo)); glsafe(::glBindFramebuffer(GL_FRAMEBUFFER, render_fbo));
} }
else { else {
glsafe(::glGenFramebuffersEXT(1, &render_fbo)); glsafe(::glGenFramebuffers(1, &render_fbo));
glsafe(::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, render_fbo)); glsafe(::glBindFramebuffer(GL_FRAMEBUFFER, render_fbo));
} }
glsafe(::glGenTextures(1, &render_tex)); glsafe(::glGenTextures(1, &render_tex));
glsafe(::glBindTexture(GL_TEXTURE_2D, render_tex)); glsafe(::glBindTexture(GL_TEXTURE_2D, render_tex));
@@ -7272,11 +7275,11 @@ void GLCanvas3D::_rectangular_selection_picking_pass()
glsafe(::glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, render_depth)); glsafe(::glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, render_depth));
} }
else { else {
glsafe(::glFramebufferTexture2D(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, render_tex, 0)); glsafe(::glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, render_tex, 0));
glsafe(::glGenRenderbuffersEXT(1, &render_depth)); glsafe(::glGenRenderbuffers(1, &render_depth));
glsafe(::glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, render_depth)); glsafe(::glBindRenderbuffer(GL_RENDERBUFFER, render_depth));
glsafe(::glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, width, height)); glsafe(::glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, width, height));
glsafe(::glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, render_depth)); glsafe(::glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, render_depth));
} }
const GLenum drawBufs[] = { GL_COLOR_ATTACHMENT0 }; const GLenum drawBufs[] = { GL_COLOR_ATTACHMENT0 };
glsafe(::glDrawBuffers(1, drawBufs)); glsafe(::glDrawBuffers(1, drawBufs));
@@ -7285,7 +7288,7 @@ void GLCanvas3D::_rectangular_selection_picking_pass()
use_framebuffer = false; use_framebuffer = false;
} }
else { else {
if (::glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) != GL_FRAMEBUFFER_COMPLETE_EXT) if (::glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
use_framebuffer = false; use_framebuffer = false;
} }
} }
@@ -7396,11 +7399,11 @@ void GLCanvas3D::_rectangular_selection_picking_pass()
glsafe(::glDeleteFramebuffers(1, &render_fbo)); glsafe(::glDeleteFramebuffers(1, &render_fbo));
} }
else if (framebuffers_type == OpenGLManager::EFramebufferType::Ext) { else if (framebuffers_type == OpenGLManager::EFramebufferType::Ext) {
glsafe(::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0)); glsafe(::glBindFramebuffer(GL_FRAMEBUFFER, 0));
if (render_depth != 0) if (render_depth != 0)
glsafe(::glDeleteRenderbuffersEXT(1, &render_depth)); glsafe(::glDeleteRenderbuffers(1, &render_depth));
if (render_fbo != 0) if (render_fbo != 0)
glsafe(::glDeleteFramebuffersEXT(1, &render_fbo)); glsafe(::glDeleteFramebuffers(1, &render_fbo));
} }
if (render_tex != 0) if (render_tex != 0)
+1 -1
View File
@@ -954,7 +954,7 @@ public:
Camera::ViewAngleType camera_view_angle_type = Camera::ViewAngleType::Iso, Camera::ViewAngleType camera_view_angle_type = Camera::ViewAngleType::Iso,
bool for_picking = false, bool for_picking = false,
bool ban_light = false); bool ban_light = false);
// render thumbnail using an off-screen framebuffer when GLEW_EXT_framebuffer_object is supported // render thumbnail using an off-screen framebuffer when GL_EXT_framebuffer_object is supported
static void render_thumbnail_framebuffer_ext(ThumbnailData& thumbnail_data, unsigned int w, unsigned int h, const ThumbnailsParams& thumbnail_params, static void render_thumbnail_framebuffer_ext(ThumbnailData& thumbnail_data, unsigned int w, unsigned int h, const ThumbnailsParams& thumbnail_params,
PartPlateList& partplate_list, ModelObjectPtrs& model_objects, const GLVolumeCollection& volumes, std::vector<ColorRGBA>& extruder_colors, PartPlateList& partplate_list, ModelObjectPtrs& model_objects, const GLVolumeCollection& volumes, std::vector<ColorRGBA>& extruder_colors,
GLShaderProgram * shader, GLShaderProgram * shader,
+1 -1
View File
@@ -20,7 +20,7 @@
#include <igl/per_vertex_normals.h> #include <igl/per_vertex_normals.h>
#endif // ENABLE_SMOOTH_NORMALS #endif // ENABLE_SMOOTH_NORMALS
#include <GL/glew.h> #include <glad/gl.h>
namespace Slic3r { namespace Slic3r {
namespace GUI { namespace GUI {
+1 -1
View File
@@ -7,7 +7,7 @@
#include "Plater.hpp" #include "Plater.hpp"
#include <igl/project.h> #include <igl/project.h>
#include <GL/glew.h> #include <glad/gl.h>
namespace Slic3r { namespace Slic3r {
namespace GUI { namespace GUI {
+1 -1
View File
@@ -7,7 +7,7 @@
#include "libslic3r/Color.hpp" #include "libslic3r/Color.hpp"
#include <boost/nowide/fstream.hpp> #include <boost/nowide/fstream.hpp>
#include <GL/glew.h> #include <glad/gl.h>
#include <cassert> #include <cassert>
#include <boost/log/trivial.hpp> #include <boost/log/trivial.hpp>
+1 -1
View File
@@ -9,7 +9,7 @@
#include <string_view> #include <string_view>
using namespace std::literals; using namespace std::literals;
#include <GL/glew.h> #include <glad/gl.h>
namespace Slic3r { namespace Slic3r {
+1 -1
View File
@@ -11,7 +11,7 @@
#include "GUI_App.hpp" #include "GUI_App.hpp"
#include "GLModel.hpp" #include "GLModel.hpp"
#include <GL/glew.h> #include <glad/gl.h>
#include <wx/image.h> #include <wx/image.h>
#include <boost/filesystem.hpp> #include <boost/filesystem.hpp>
+28 -2
View File
@@ -161,6 +161,10 @@ typedef BOOL (WINAPI *LPFN_ISWOW64PROCESS2)(
#include <boost/nowide/fstream.hpp> #include <boost/nowide/fstream.hpp>
#endif // ENABLE_THUMBNAIL_GENERATOR_DEBUG #endif // ENABLE_THUMBNAIL_GENERATOR_DEBUG
#ifdef __WXGTK__
#include "LinuxDisplayBackend.hpp"
#endif
// Needed for forcing menu icons back under gtk2 and gtk3 // Needed for forcing menu icons back under gtk2 and gtk3
#if defined(__WXGTK20__) || defined(__WXGTK3__) #if defined(__WXGTK20__) || defined(__WXGTK3__)
#include <gtk/gtk.h> #include <gtk/gtk.h>
@@ -909,6 +913,8 @@ void GUI_App::post_init()
} }
else { else {
BOOST_LOG_TRIVIAL(warning) << __FUNCTION__ << "Found glcontext not ready, postpone the init"; BOOST_LOG_TRIVIAL(warning) << __FUNCTION__ << "Found glcontext not ready, postpone the init";
plater_->canvas3D()->enable_render(true);
plater_->canvas3D()->set_as_dirty();
} }
//#endif //#endif
if (is_editor()) if (is_editor())
@@ -2303,7 +2309,8 @@ bool GUI_App::init_opengl()
{ {
#ifdef __linux__ #ifdef __linux__
bool status = m_opengl_mgr.init_gl(); bool status = m_opengl_mgr.init_gl();
m_opengl_initialized = true; if (status)
m_opengl_initialized = true;
return status; return status;
#else #else
return m_opengl_mgr.init_gl(); return m_opengl_mgr.init_gl();
@@ -3091,6 +3098,20 @@ bool GUI_App::on_init_inner()
// Let the libslic3r know the callback, which will translate messages on demand. // Let the libslic3r know the callback, which will translate messages on demand.
Slic3r::I18N::set_translate_callback(libslic3r_translate_callback); Slic3r::I18N::set_translate_callback(libslic3r_translate_callback);
#if defined(__WXGTK__) && wxHAS_EGL
// Configure GL backend before any wxGLCanvas is created.
// On X11, prefer GLX for maximum driver compatibility.
// On Wayland, EGL is used by default (only option).
if (Slic3r::GUI::is_running_on_x11()) {
wxGLCanvas::PreferGLX();
BOOST_LOG_TRIVIAL(info) << "X11 detected, using GLX for OpenGL context";
} else if (Slic3r::GUI::is_running_on_wayland()) {
BOOST_LOG_TRIVIAL(info) << "Wayland detected, using EGL for OpenGL context";
} else {
BOOST_LOG_TRIVIAL(warning) << "Unknown display backend, defaulting to EGL";
}
#endif
BOOST_LOG_TRIVIAL(info) << "create the main window"; BOOST_LOG_TRIVIAL(info) << "create the main window";
mainframe = new MainFrame(); mainframe = new MainFrame();
// hide settings tabs after first Layout // hide settings tabs after first Layout
@@ -7708,7 +7729,12 @@ bool GUI_App::window_pos_restore(wxTopLevelWindow* window, const std::string &na
} }
const wxRect& rect = metrics->get_rect(); const wxRect& rect = metrics->get_rect();
window->SetPosition(rect.GetPosition()); #if defined(__WXGTK__)
// On Wayland, SetPosition() is a no-op for top-level windows.
// Only restore size and maximize state.
if (!Slic3r::GUI::is_running_on_wayland())
#endif
window->SetPosition(rect.GetPosition());
window->SetSize(rect.GetSize()); window->SetSize(rect.GetSize());
window->Maximize(metrics->get_maximized()); window->Maximize(metrics->get_maximized());
return true; return true;
+7
View File
@@ -1153,6 +1153,7 @@ void ObjectList::update_name_in_list(int obj_idx, int vol_idx) const
void ObjectList::selection_changed() void ObjectList::selection_changed()
{ {
if (wxGetApp().is_closing()) return;
if (m_prevent_list_events) return; if (m_prevent_list_events) return;
fix_multiselection_conflicts(); fix_multiselection_conflicts();
@@ -3456,6 +3457,9 @@ void ObjectList::changed_object(const int obj_idx/* = -1*/) const
void ObjectList::part_selection_changed() void ObjectList::part_selection_changed()
{ {
if (wxGetApp().is_closing())
return;
if (m_extruder_editor) m_extruder_editor->Hide(); if (m_extruder_editor) m_extruder_editor->Hide();
int obj_idx = -1; int obj_idx = -1;
int volume_id = -1; int volume_id = -1;
@@ -4656,6 +4660,9 @@ int ObjectList::get_selected_layers_range_idx() const
void ObjectList::update_selections() void ObjectList::update_selections()
{ {
if (wxGetApp().is_closing())
return;
const Selection& selection = scene_selection(); const Selection& selection = scene_selection();
wxDataViewItemArray sels; wxDataViewItemArray sels;
+3
View File
@@ -86,6 +86,9 @@ bool ObjectSettings::update_settings_list()
m_settings_list_sizer->Clear(true); m_settings_list_sizer->Clear(true);
m_og_settings.resize(0); m_og_settings.resize(0);
if (wxGetApp().is_closing())
return false;
auto objects_ctrl = wxGetApp().obj_list(); auto objects_ctrl = wxGetApp().obj_list();
auto objects_model = wxGetApp().obj_list()->GetModel(); auto objects_model = wxGetApp().obj_list()->GetModel();
auto config = wxGetApp().obj_list()->config(); auto config = wxGetApp().obj_list()->config();
+1 -1
View File
@@ -2,7 +2,7 @@
#include "GLGizmoAdvancedCut.hpp" #include "GLGizmoAdvancedCut.hpp"
#include "slic3r/GUI/GLCanvas3D.hpp" #include "slic3r/GUI/GLCanvas3D.hpp"
#include <GL/glew.h> #include <glad/gl.h>
#include <wx/button.h> #include <wx/button.h>
#include <wx/checkbox.h> #include <wx/checkbox.h>
+1 -1
View File
@@ -12,7 +12,7 @@
#include <numeric> #include <numeric>
#include <GL/glew.h> #include <glad/gl.h>
#include <tbb/parallel_for.h> #include <tbb/parallel_for.h>
#include <future> #include <future>
+1 -1
View File
@@ -1,7 +1,7 @@
#include "GLGizmoBase.hpp" #include "GLGizmoBase.hpp"
#include "slic3r/GUI/GLCanvas3D.hpp" #include "slic3r/GUI/GLCanvas3D.hpp"
#include <GL/glew.h> #include <glad/gl.h>
#include "slic3r/GUI/GUI_App.hpp" #include "slic3r/GUI/GUI_App.hpp"
#include "slic3r/GUI/Plater.hpp" #include "slic3r/GUI/Plater.hpp"
+1 -1
View File
@@ -1,5 +1,5 @@
#include "GLGizmoBrimEars.hpp" #include "GLGizmoBrimEars.hpp"
#include <GL/glew.h> #include <glad/gl.h>
#include "slic3r/GUI/GLCanvas3D.hpp" #include "slic3r/GUI/GLCanvas3D.hpp"
#include "slic3r/GUI/Camera.hpp" #include "slic3r/GUI/Camera.hpp"
#include "slic3r/GUI/Gizmos/GLGizmosCommon.hpp" #include "slic3r/GUI/Gizmos/GLGizmosCommon.hpp"
+1 -1
View File
@@ -1,7 +1,7 @@
#include "GLGizmoCut.hpp" #include "GLGizmoCut.hpp"
#include "slic3r/GUI/GLCanvas3D.hpp" #include "slic3r/GUI/GLCanvas3D.hpp"
#include <GL/glew.h> #include <glad/gl.h>
#include <algorithm> #include <algorithm>
+1 -1
View File
@@ -50,7 +50,7 @@
#include <cereal/types/string.hpp> #include <cereal/types/string.hpp>
#include <cereal/archives/binary.hpp> #include <cereal/archives/binary.hpp>
#include <GL/glew.h> #include <glad/gl.h>
#include <chrono> // measure enumeration of fonts #include <chrono> // measure enumeration of fonts
// uncomment for easier debug // uncomment for easier debug
+1 -1
View File
@@ -19,7 +19,7 @@
#include "libslic3r/TextConfiguration.hpp" #include "libslic3r/TextConfiguration.hpp"
#include <imgui/imgui.h> #include <imgui/imgui.h>
#include <GL/glew.h> #include <glad/gl.h>
class wxFont; class wxFont;
namespace Slic3r{ namespace Slic3r{
@@ -9,7 +9,7 @@
#include "slic3r/GUI/ImGuiWrapper.hpp" #include "slic3r/GUI/ImGuiWrapper.hpp"
#include "slic3r/GUI/Plater.hpp" #include "slic3r/GUI/Plater.hpp"
#include <GL/glew.h> #include <glad/gl.h>
#ifdef __WINDOWS__ #ifdef __WINDOWS__
#include <windows.h> #include <windows.h>
+1 -1
View File
@@ -15,7 +15,7 @@
#include "slic3r/GUI/GUI.hpp" #include "slic3r/GUI/GUI.hpp"
#include "slic3r/Utils/UndoRedo.hpp" #include "slic3r/Utils/UndoRedo.hpp"
#include <GL/glew.h> #include <glad/gl.h>
#include <boost/log/trivial.hpp> #include <boost/log/trivial.hpp>
+1 -1
View File
@@ -9,7 +9,7 @@
#include <numeric> #include <numeric>
#include <GL/glew.h> #include <glad/gl.h>
namespace Slic3r { namespace Slic3r {
namespace GUI { namespace GUI {
+1 -1
View File
@@ -11,7 +11,7 @@
#include "slic3r/GUI/Plater.hpp" #include "slic3r/GUI/Plater.hpp"
#include "slic3r/Utils/UndoRedo.hpp" #include "slic3r/Utils/UndoRedo.hpp"
#include <GL/glew.h> #include <glad/gl.h>
#include <algorithm> #include <algorithm>
namespace Slic3r::GUI { namespace Slic3r::GUI {
+1 -1
View File
@@ -3,7 +3,7 @@
#include "slic3r/GUI/Camera.hpp" #include "slic3r/GUI/Camera.hpp"
#include "slic3r/GUI/Gizmos/GLGizmosCommon.hpp" #include "slic3r/GUI/Gizmos/GLGizmosCommon.hpp"
#include <GL/glew.h> #include <glad/gl.h>
#include "slic3r/GUI/GUI_App.hpp" #include "slic3r/GUI/GUI_App.hpp"
#include "slic3r/GUI/GUI_ObjectSettings.hpp" #include "slic3r/GUI/GUI_ObjectSettings.hpp"
+1 -1
View File
@@ -12,7 +12,7 @@
#include <numeric> #include <numeric>
#include <GL/glew.h> #include <glad/gl.h>
#include <tbb/parallel_for.h> #include <tbb/parallel_for.h>
@@ -15,7 +15,7 @@
#include "slic3r/Utils/UndoRedo.hpp" #include "slic3r/Utils/UndoRedo.hpp"
#include <GL/glew.h> #include <glad/gl.h>
namespace Slic3r::GUI { namespace Slic3r::GUI {
+1 -1
View File
@@ -6,7 +6,7 @@
#include "libslic3r/AppConfig.hpp" #include "libslic3r/AppConfig.hpp"
#include <GL/glew.h> #include <glad/gl.h>
#include <wx/utils.h> #include <wx/utils.h>
+1 -1
View File
@@ -2,7 +2,7 @@
#include "slic3r/GUI/GLCanvas3D.hpp" #include "slic3r/GUI/GLCanvas3D.hpp"
#include "slic3r/GUI/Gizmos/GLGizmosCommon.hpp" #include "slic3r/GUI/Gizmos/GLGizmosCommon.hpp"
#include <GL/glew.h> #include <glad/gl.h>
#include "slic3r/GUI/GUI_App.hpp" #include "slic3r/GUI/GUI_App.hpp"
#include "slic3r/GUI/Camera.hpp" #include "slic3r/GUI/Camera.hpp"
+1 -1
View File
@@ -10,7 +10,7 @@
#include "libslic3r/Model.hpp" #include "libslic3r/Model.hpp"
#include <cereal/types/vector.hpp> #include <cereal/types/vector.hpp>
#include <GL/glew.h> #include <glad/gl.h>
#include <memory> #include <memory>
+1 -1
View File
@@ -9,7 +9,7 @@
#include "libslic3r/PresetBundle.hpp" #include "libslic3r/PresetBundle.hpp"
#include <GL/glew.h> #include <glad/gl.h>
namespace Slic3r { namespace Slic3r {
namespace GUI { namespace GUI {
+1 -1
View File
@@ -32,7 +32,7 @@
#include <wx/display.h> // detection of change DPI #include <wx/display.h> // detection of change DPI
#include <boost/log/trivial.hpp> #include <boost/log/trivial.hpp>
#include <GL/glew.h> #include <glad/gl.h>
#include <chrono> // measure enumeration of fonts #include <chrono> // measure enumeration of fonts
#include <sstream> // save for svg #include <sstream> // save for svg
#include <array> #include <array>
+1 -1
View File
@@ -19,7 +19,7 @@
#include "libslic3r/Model.hpp" #include "libslic3r/Model.hpp"
#include <imgui/imgui.h> #include <imgui/imgui.h>
#include <GL/glew.h> #include <glad/gl.h>
namespace Slic3r{ namespace Slic3r{
class ModelVolume; class ModelVolume;
+1 -1
View File
@@ -3,7 +3,7 @@
#include "slic3r/GUI/GUI_App.hpp" #include "slic3r/GUI/GUI_App.hpp"
#include "slic3r/GUI/Plater.hpp" #include "slic3r/GUI/Plater.hpp"
#include <GL/glew.h> #include <glad/gl.h>
#include <wx/utils.h> #include <wx/utils.h>
+1 -1
View File
@@ -11,7 +11,7 @@
#include "slic3r/GUI/GUI.hpp" #include "slic3r/GUI/GUI.hpp"
#include "slic3r/Utils/UndoRedo.hpp" #include "slic3r/Utils/UndoRedo.hpp"
#include <GL/glew.h> #include <glad/gl.h>
namespace Slic3r::GUI { namespace Slic3r::GUI {
+1 -1
View File
@@ -11,7 +11,7 @@
#include "libslic3r/Model.hpp" #include "libslic3r/Model.hpp"
#include "libslic3r/QuadricEdgeCollapse.hpp" #include "libslic3r/QuadricEdgeCollapse.hpp"
#include <GL/glew.h> #include <glad/gl.h>
#include <thread> #include <thread>
+1 -1
View File
@@ -6,7 +6,7 @@
#include "slic3r/GUI/MainFrame.hpp" #include "slic3r/GUI/MainFrame.hpp"
#include "slic3r/Utils/UndoRedo.hpp" #include "slic3r/Utils/UndoRedo.hpp"
#include <GL/glew.h> #include <glad/gl.h>
#include <wx/msgdlg.h> #include <wx/msgdlg.h>
#include <wx/settings.h> #include <wx/settings.h>
+1 -1
View File
@@ -16,7 +16,7 @@
#include <boost/log/trivial.hpp> #include <boost/log/trivial.hpp>
#include <GL/glew.h> #include <glad/gl.h>
#ifndef IMGUI_DEFINE_MATH_OPERATORS #ifndef IMGUI_DEFINE_MATH_OPERATORS
#define IMGUI_DEFINE_MATH_OPERATORS #define IMGUI_DEFINE_MATH_OPERATORS
+1 -1
View File
@@ -10,7 +10,7 @@
#include "libslic3r/PresetBundle.hpp" #include "libslic3r/PresetBundle.hpp"
#include <GL/glew.h> #include <glad/gl.h>
namespace Slic3r { namespace Slic3r {
namespace GUI { namespace GUI {
+2 -2
View File
@@ -1,7 +1,7 @@
#include "IMToolbar.hpp" #include "IMToolbar.hpp"
#include "3DScene.hpp" #include "3DScene.hpp"
#include <GL/glew.h> #include <glad/gl.h>
#include <imgui/imgui_internal.h> #include <imgui/imgui_internal.h>
#include <imgui/imgui.h> #include <imgui/imgui.h>
@@ -87,7 +87,7 @@ bool IMReturnToolbar::init()
glsafe(::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)); glsafe(::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
glsafe(::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)); glsafe(::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
glsafe(::glPixelStorei(GL_UNPACK_ROW_LENGTH, 0)); glsafe(::glPixelStorei(GL_UNPACK_ROW_LENGTH, 0));
if (compress && GLEW_EXT_texture_compression_s3tc) if (compress && GLAD_GL_EXT_texture_compression_s3tc)
glsafe(::glTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, data.width, data.height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels)); glsafe(::glTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, data.width, data.height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels));
else else
glsafe(::glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, data.width, data.height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels)); glsafe(::glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, data.width, data.height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels));
+1 -1
View File
@@ -9,7 +9,7 @@
#include "libslic3r/Utils.hpp" // ScopeGuard #include "libslic3r/Utils.hpp" // ScopeGuard
#include "3DScene.hpp" // glsafe #include "3DScene.hpp" // glsafe
#include "GL/glew.h" #include <glad/gl.h>
#define STB_RECT_PACK_IMPLEMENTATION #define STB_RECT_PACK_IMPLEMENTATION
#include "imgui/imstb_rectpack.h" // distribute rectangles #include "imgui/imstb_rectpack.h" // distribute rectangles
+2 -2
View File
@@ -18,7 +18,7 @@
#include <wx/clipbrd.h> #include <wx/clipbrd.h>
#include <wx/debug.h> #include <wx/debug.h>
#include <GL/glew.h> #include <glad/gl.h>
#ifndef IMGUI_DEFINE_MATH_OPERATORS #ifndef IMGUI_DEFINE_MATH_OPERATORS
#define IMGUI_DEFINE_MATH_OPERATORS #define IMGUI_DEFINE_MATH_OPERATORS
@@ -2839,7 +2839,7 @@ void ImGuiWrapper::init_font(bool compress)
glsafe(::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)); glsafe(::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
glsafe(::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)); glsafe(::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
glsafe(::glPixelStorei(GL_UNPACK_ROW_LENGTH, 0)); glsafe(::glPixelStorei(GL_UNPACK_ROW_LENGTH, 0));
if (compress && GLEW_EXT_texture_compression_s3tc) if (compress && GLAD_GL_EXT_texture_compression_s3tc)
glsafe(::glTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels)); glsafe(::glTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels));
else else
glsafe(::glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels)); glsafe(::glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels));
@@ -3,7 +3,7 @@
#include <vector> #include <vector>
#include <string> #include <string>
#include <GL/glew.h> #include <glad/gl.h>
#include <wx/string.h> #include <wx/string.h>
#include <wx/fontenc.h> #include <wx/fontenc.h>
#include "Job.hpp" #include "Job.hpp"
+53
View File
@@ -0,0 +1,53 @@
#include "LinuxDisplayBackend.hpp"
#if defined(__WXGTK__)
#include <gdk/gdk.h>
#ifdef wxHAVE_GDK_X11
#include <gdk/gdkx.h>
#endif
#ifdef wxHAVE_GDK_WAYLAND
#include <gdk/gdkwayland.h>
#endif
namespace Slic3r {
namespace GUI {
LinuxDisplayBackend get_linux_display_backend()
{
static const LinuxDisplayBackend backend = []() -> LinuxDisplayBackend {
GdkDisplay *display = gdk_display_get_default();
if (!display)
return LinuxDisplayBackend::Unknown;
#ifdef wxHAVE_GDK_WAYLAND
if (GDK_IS_WAYLAND_DISPLAY(display))
return LinuxDisplayBackend::Wayland;
#endif
#ifdef wxHAVE_GDK_X11
if (GDK_IS_X11_DISPLAY(display))
return LinuxDisplayBackend::X11;
#endif
return LinuxDisplayBackend::Unknown;
}();
return backend;
}
bool is_running_on_wayland()
{
return get_linux_display_backend() == LinuxDisplayBackend::Wayland;
}
bool is_running_on_x11()
{
return get_linux_display_backend() == LinuxDisplayBackend::X11;
}
} // namespace GUI
} // namespace Slic3r
#endif // defined(__WXGTK__)
+19
View File
@@ -0,0 +1,19 @@
#pragma once
namespace Slic3r {
namespace GUI {
#if defined(__WXGTK__)
enum class LinuxDisplayBackend { X11, Wayland, Unknown };
// Detect which display backend is in use at runtime.
// Must be called after gtk_init() / wxWidgets initialization.
LinuxDisplayBackend get_linux_display_backend();
// Convenience predicates.
bool is_running_on_wayland();
bool is_running_on_x11();
#endif // defined(__WXGTK__)
} // namespace GUI
} // namespace Slic3r
+2
View File
@@ -586,6 +586,8 @@ DPIFrame(NULL, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, BORDERLESS_FRAME_
#endif #endif
MarkdownTip::ExitTip(); MarkdownTip::ExitTip();
// Prevent queued selection/UI refresh work from running as normal during reset.
wxGetApp().set_closing(true);
m_plater->reset(); m_plater->reset();
this->shutdown(); this->shutdown();
+1 -1
View File
@@ -14,7 +14,7 @@
#include "slic3r/GUI/CameraUtils.hpp" #include "slic3r/GUI/CameraUtils.hpp"
#include <GL/glew.h> #include <glad/gl.h>
#include <igl/unproject.h> #include <igl/unproject.h>
+42 -21
View File
@@ -7,7 +7,7 @@
#include "libslic3r/Platform.hpp" #include "libslic3r/Platform.hpp"
#include <GL/glew.h> #include <glad/gl.h>
#include <boost/algorithm/string/split.hpp> #include <boost/algorithm/string/split.hpp>
#include <boost/algorithm/string/classification.hpp> #include <boost/algorithm/string/classification.hpp>
@@ -22,16 +22,11 @@
#include "../Utils/MacDarkMode.hpp" #include "../Utils/MacDarkMode.hpp"
#endif // __APPLE__ #endif // __APPLE__
// Verify GLEW and wxWidgets use the same OpenGL backend (EGL vs GLX). #ifdef __WXGTK__
// A mismatch causes rendering failures: GLEW's function loading must match #include "LinuxDisplayBackend.hpp"
// the context type created by wxWidgets. #ifdef wxHAS_EGL
#if defined(__linux__) #include <EGL/egl.h>
#if defined(GLEW_EGL) && (!defined(wxUSE_GLCANVAS_EGL) || !wxUSE_GLCANVAS_EGL) #endif
#error "OpenGL backend mismatch: GLEW has EGL support enabled but wxWidgets does not. Ensure GLEW_USE_EGL and wxUSE_GLCANVAS_EGL are both ON or both OFF."
#endif
#if !defined(GLEW_EGL) && defined(wxUSE_GLCANVAS_EGL) && wxUSE_GLCANVAS_EGL
#error "OpenGL backend mismatch: wxWidgets has EGL support enabled but GLEW does not. Ensure GLEW_USE_EGL and wxUSE_GLCANVAS_EGL are both ON or both OFF."
#endif
#endif #endif
namespace Slic3r { namespace Slic3r {
@@ -121,12 +116,12 @@ void OpenGLManager::GLInfo::detect() const
if (Slic3r::total_physical_memory() / (1024 * 1024 * 1024) < 6) if (Slic3r::total_physical_memory() / (1024 * 1024 * 1024) < 6)
*max_tex_size /= 2; *max_tex_size /= 2;
if (GLEW_EXT_texture_filter_anisotropic) { if (GLAD_GL_EXT_texture_filter_anisotropic) {
float* max_anisotropy = const_cast<float*>(&m_max_anisotropy); float* max_anisotropy = const_cast<float*>(&m_max_anisotropy);
glsafe(::glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, max_anisotropy)); glsafe(::glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, max_anisotropy));
} }
if (!GLEW_ARB_compatibility) if (!GLAD_GL_ARB_compatibility)
*const_cast<bool*>(&m_core_profile) = true; *const_cast<bool*>(&m_core_profile) = true;
*const_cast<bool*>(&m_detected) = true; *const_cast<bool*>(&m_detected) = true;
@@ -245,24 +240,36 @@ OpenGLManager::~OpenGLManager()
bool OpenGLManager::init_gl(bool popup_error) bool OpenGLManager::init_gl(bool popup_error)
{ {
if (!m_gl_initialized) { if (!m_gl_initialized) {
glewExperimental = true; int version = 0;
GLenum result = glewInit(); #if defined(__WXGTK__) && defined(wxHAS_EGL)
if (result != GLEW_OK) { if (is_running_on_wayland()) {
BOOST_LOG_TRIVIAL(error) << "Unable to init glew library, Error: " << glewGetErrorString(result); // On EGL/Wayland, gladLoaderLoadGL() dlopen's libGL.so then
// immediately dlclose's it. Since nothing else holds libGL.so
// open (unlike GLX where the context keeps it loaded), the
// library gets unmapped and all function pointers become invalid.
// Use eglGetProcAddress directly to avoid this.
version = gladLoadGL((GLADloadfunc)eglGetProcAddress);
} else
#endif
{
version = gladLoaderLoadGL();
}
if (version == 0) {
BOOST_LOG_TRIVIAL(error) << "Unable to init GLAD OpenGL loader";
return false; return false;
} }
//BOOST_LOG_TRIVIAL(info) << "glewInit Success."<< std::endl; BOOST_LOG_TRIVIAL(info) << "GLAD loaded OpenGL " << GLAD_VERSION_MAJOR(version) << "." << GLAD_VERSION_MINOR(version);
m_gl_initialized = true; m_gl_initialized = true;
if (GLEW_EXT_texture_compression_s3tc) if (GLAD_GL_EXT_texture_compression_s3tc)
s_compressed_textures_supported = true; s_compressed_textures_supported = true;
else else
s_compressed_textures_supported = false; s_compressed_textures_supported = false;
if (GLEW_ARB_framebuffer_object) { if (GLAD_GL_ARB_framebuffer_object) {
s_framebuffers_type = EFramebufferType::Arb; s_framebuffers_type = EFramebufferType::Arb;
BOOST_LOG_TRIVIAL(info) << "Found Framebuffer Type ARB."<< std::endl; BOOST_LOG_TRIVIAL(info) << "Found Framebuffer Type ARB."<< std::endl;
} }
else if (GLEW_EXT_framebuffer_object) { else if (GLAD_GL_EXT_framebuffer_object) {
BOOST_LOG_TRIVIAL(info) << "Found Framebuffer Type Ext."<< std::endl; BOOST_LOG_TRIVIAL(info) << "Found Framebuffer Type Ext."<< std::endl;
s_framebuffers_type = EFramebufferType::Ext; s_framebuffers_type = EFramebufferType::Ext;
} }
@@ -438,6 +445,20 @@ void OpenGLManager::detect_multisample(int* attribList)
{ {
int wxVersion = wxMAJOR_VERSION * 10000 + wxMINOR_VERSION * 100 + wxRELEASE_NUMBER; int wxVersion = wxMAJOR_VERSION * 10000 + wxMINOR_VERSION * 100 + wxRELEASE_NUMBER;
bool enable_multisample = wxVersion >= 30003; bool enable_multisample = wxVersion >= 30003;
#if defined(__WXGTK__)
// On Wayland, wxGLCanvas::IsDisplaySupported() requires the EGL backend.
// If wxWidgets was built without EGL, the GLX backend will crash trying
// to access a non-existent X11 display. Disable multisample in that case.
if (is_running_on_wayland()) {
#if !defined(wxHAS_EGL) || !wxHAS_EGL
BOOST_LOG_TRIVIAL(warning) << "Wayland without EGL: disabling multisample detection";
s_multisample = EMultisampleState::Disabled;
return;
#endif
}
#endif
s_multisample = s_multisample =
enable_multisample && enable_multisample &&
// Disable multi-sampling on ChromeOS, as the OpenGL virtualization swaps Red/Blue channels with multi-sampling enabled, // Disable multi-sampling on ChromeOS, as the OpenGL virtualization swaps Red/Blue channels with multi-sampling enabled,
+34 -8
View File
@@ -5,7 +5,7 @@
#include <string> #include <string>
#include <regex> #include <regex>
#include <future> #include <future>
#include <GL/glew.h> #include <glad/gl.h>
#include <boost/algorithm/string.hpp> #include <boost/algorithm/string.hpp>
#include <boost/optional.hpp> #include <boost/optional.hpp>
#include <boost/filesystem/path.hpp> #include <boost/filesystem/path.hpp>
@@ -1076,9 +1076,12 @@ void PartPlate::render_icon_texture(GLModel &buffer, GLTexture &texture)
void PartPlate::render_plate_name_texture() void PartPlate::render_plate_name_texture()
{ {
if (m_name_texture.get_id() == 0) if (m_plate_name_edit_icon.mesh_raycaster == nullptr)
generate_plate_name_texture(); generate_plate_name_texture();
if (m_name_texture.get_id() == 0)
return;
GLuint tex_id = (GLuint)m_name_texture.get_id(); GLuint tex_id = (GLuint)m_name_texture.get_id();
glsafe(::glBindTexture(GL_TEXTURE_2D, tex_id)); glsafe(::glBindTexture(GL_TEXTURE_2D, tex_id));
m_plate_name_icon.render(); m_plate_name_icon.render();
@@ -1469,6 +1472,9 @@ void PartPlate::render_right_arrow(const ColorRGBA render_color, bool use_lighti
static void register_model_for_picking(GLCanvas3D &canvas, PickingModel &model, int id) static void register_model_for_picking(GLCanvas3D &canvas, PickingModel &model, int id)
{ {
if (model.mesh_raycaster == nullptr)
return;
canvas.add_raycaster_for_picking(SceneRaycaster::EType::Bed, id, *model.mesh_raycaster, Transform3d::Identity()); canvas.add_raycaster_for_picking(SceneRaycaster::EType::Bed, id, *model.mesh_raycaster, Transform3d::Identity());
} }
@@ -1483,7 +1489,10 @@ void PartPlate::register_raycasters_for_picking(GLCanvas3D &canvas)
register_model_for_picking(canvas, m_plate_settings_icon, picking_id_component(5)); register_model_for_picking(canvas, m_plate_settings_icon, picking_id_component(5));
canvas.remove_raycasters_for_picking(SceneRaycaster::EType::Bed, picking_id_component(6)); canvas.remove_raycasters_for_picking(SceneRaycaster::EType::Bed, picking_id_component(6));
register_model_for_picking(canvas, m_plate_name_edit_icon, picking_id_component(6)); // Plate-name edit picking is built lazily together with the plate-name texture.
// During reset / reload_scene the icon may not have a raycaster yet, which is valid.
if (m_plate_name_edit_icon.mesh_raycaster != nullptr)
register_model_for_picking(canvas, m_plate_name_edit_icon, picking_id_component(6));
register_model_for_picking(canvas, m_move_front_icon, picking_id_component(7)); register_model_for_picking(canvas, m_move_front_icon, picking_id_component(7));
// Only register filament map button for H2D (dual-extruder Bambu Lab) printers // Only register filament map button for H2D (dual-extruder Bambu Lab) printers
@@ -2233,7 +2242,7 @@ void PartPlate::clear(bool clear_sliced_result)
m_ready_for_slice = true; m_ready_for_slice = true;
update_slice_result_valid_state(false); update_slice_result_valid_state(false);
} }
m_name_texture.reset(); invalidate_plate_name_texture();
return; return;
} }
@@ -2323,6 +2332,10 @@ Vec3d PartPlate::get_center_origin()
void PartPlate::generate_plate_name_texture() void PartPlate::generate_plate_name_texture()
{ {
auto canvas = this->m_partplate_list->m_plater->get_view3D_canvas3D();
if (canvas == nullptr)
return;
m_plate_name_icon.reset(); m_plate_name_icon.reset();
// generate m_name_texture texture from m_name with generate_from_text_string // generate m_name_texture texture from m_name with generate_from_text_string
@@ -2335,8 +2348,10 @@ void PartPlate::generate_plate_name_texture()
wxFont* font = &l; wxFont* font = &l;
wxColour foreground(0xf2, 0x75, 0x4e, 0xff); wxColour foreground(0xf2, 0x75, 0x4e, 0xff);
if (!m_name_texture.generate_from_text_string(text.ToUTF8().data(), *font, *wxBLACK, foreground)) if (!m_name_texture.generate_from_text_string(text.ToUTF8().data(), *font, *wxBLACK, foreground)) {
BOOST_LOG_TRIVIAL(error) << "PartPlate::generate_plate_name_texture(): generate_from_text_string() failed"; BOOST_LOG_TRIVIAL(error) << "PartPlate::generate_plate_name_texture(): generate_from_text_string() failed";
return;
}
ExPolygon poly; ExPolygon poly;
auto bed_ext = get_extents(m_shape); auto bed_ext = get_extents(m_shape);
@@ -2360,11 +2375,22 @@ void PartPlate::generate_plate_name_texture()
if (!init_model_from_poly(m_plate_name_icon, poly, GROUND_Z)) if (!init_model_from_poly(m_plate_name_icon, poly, GROUND_Z))
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << "Unable to generate geometry buffers for icons\n"; BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << "Unable to generate geometry buffers for icons\n";
auto canvas = this->m_partplate_list->m_plater->get_view3D_canvas3D();
canvas->remove_raycasters_for_picking(SceneRaycaster::EType::Bed, picking_id_component(6)); canvas->remove_raycasters_for_picking(SceneRaycaster::EType::Bed, picking_id_component(6));
calc_vertex_for_plate_name_edit_icon(&m_name_texture, 0, m_plate_name_edit_icon); calc_vertex_for_plate_name_edit_icon(&m_name_texture, 0, m_plate_name_edit_icon);
register_model_for_picking(*canvas, m_plate_name_edit_icon, picking_id_component(6)); register_model_for_picking(*canvas, m_plate_name_edit_icon, picking_id_component(6));
} }
void PartPlate::invalidate_plate_name_texture()
{
m_plate_name_edit_icon.mesh_raycaster.reset();
auto canvas = (m_plater != nullptr) ? m_plater->get_view3D_canvas3D() : nullptr;
if (canvas != nullptr) {
canvas->remove_raycasters_for_picking(SceneRaycaster::EType::Bed, picking_id_component(6));
canvas->set_as_dirty();
}
}
void PartPlate::set_plate_name(const std::string& name) void PartPlate::set_plate_name(const std::string& name)
{ {
// compare if name equal to m_name, case sensitive // compare if name equal to m_name, case sensitive
@@ -2375,7 +2401,7 @@ void PartPlate::set_plate_name(const std::string& name)
if (m_print != nullptr) if (m_print != nullptr)
m_print->set_plate_name(name); m_print->set_plate_name(name);
generate_plate_name_texture(); invalidate_plate_name_texture();
} }
//get the print's object, result and index //get the print's object, result and index
@@ -3148,7 +3174,7 @@ bool PartPlate::set_shape(const Pointfs& shape, const Pointfs& exclude_areas, co
calc_vertex_for_number(0, false, m_plate_idx_icon); calc_vertex_for_number(0, false, m_plate_idx_icon);
// calc vertex for plate name // calc vertex for plate name
generate_plate_name_texture(); invalidate_plate_name_texture();
} }
} }
+1
View File
@@ -200,6 +200,7 @@ private:
void render_icons(bool bottom, bool only_name = false, int hover_id = -1); void render_icons(bool bottom, bool only_name = false, int hover_id = -1);
void render_only_numbers(bool bottom); void render_only_numbers(bool bottom);
void render_plate_name_texture(); void render_plate_name_texture();
void invalidate_plate_name_texture();
void register_raycasters_for_picking(GLCanvas3D& canvas); void register_raycasters_for_picking(GLCanvas3D& canvas);
int picking_id_component(int idx) const; int picking_id_component(int idx) const;
+95 -9
View File
@@ -75,6 +75,9 @@
#include "GUI_App.hpp" #include "GUI_App.hpp"
#include "GuiColor.hpp" #include "GuiColor.hpp"
#include "GUI_ObjectList.hpp" #include "GUI_ObjectList.hpp"
#ifdef __WXGTK__
#include "LinuxDisplayBackend.hpp"
#endif
#include "GUI_Utils.hpp" #include "GUI_Utils.hpp"
#include "GUI_Factories.hpp" #include "GUI_Factories.hpp"
#include "wxExtensions.hpp" #include "wxExtensions.hpp"
@@ -348,6 +351,57 @@ void SlicedInfo::SetTextAndShow(SlicedInfoIdx idx, const wxString& text, const w
static wxString temp_dir; static wxString temp_dir;
namespace {
#ifdef __WXGTK__
wxString sanitize_window_layout_for_wayland(const wxString& layout, bool* removed_floating_state = nullptr)
{
if (!Slic3r::GUI::is_running_on_wayland() || layout.empty()) {
if (removed_floating_state != nullptr)
*removed_floating_state = false;
return layout;
}
static const std::regex state_pattern(R"(state=(\d+);)");
constexpr unsigned int disabled_wayland_flags =
static_cast<unsigned int>(wxAuiPaneInfo::optionFloating) |
static_cast<unsigned int>(wxAuiPaneInfo::optionFloatable);
const std::string input = layout.utf8_string();
std::string output;
output.reserve(input.size());
bool modified = false;
std::smatch match;
auto search_start = input.cbegin();
while (std::regex_search(search_start, input.cend(), match, state_pattern)) {
output.append(search_start, match[0].first);
try {
const unsigned long state = std::stoul(match[1].str());
const unsigned long sanitized_state = state & ~static_cast<unsigned long>(disabled_wayland_flags);
modified = modified || sanitized_state != state;
output += "state=" + std::to_string(sanitized_state) + ";";
} catch (const std::exception&) {
output += match[0].str();
}
search_start = match[0].second;
}
output.append(search_start, input.cend());
if (removed_floating_state != nullptr)
*removed_floating_state = modified;
return modified ? wxString::FromUTF8(output) : layout;
}
#endif
} // namespace
// Sidebar / private // Sidebar / private
enum class ActionButtonType : int { enum class ActionButtonType : int {
@@ -1781,7 +1835,11 @@ Sidebar::Sidebar(Plater *parent)
e.Skip(); e.Skip();
}); });
w->Bind(wxEVT_LEAVE_WINDOW, [this, panel_color](wxMouseEvent &e) { w->Bind(wxEVT_LEAVE_WINDOW, [this, panel_color](wxMouseEvent &e) {
wxWindow* next_w = wxFindWindowAtPoint(wxGetMousePosition()); // Use event-relative coords instead of wxGetMousePosition() which
// returns (0,0) on Wayland for global screen coordinates.
wxWindow* evtObj = dynamic_cast<wxWindow*>(e.GetEventObject());
wxPoint screenPos = evtObj ? evtObj->ClientToScreen(e.GetPosition()) : wxGetMousePosition();
wxWindow* next_w = wxFindWindowAtPoint(screenPos);
if (!next_w || !p->panel_printer_preset->IsDescendant(next_w)){ if (!next_w || !p->panel_printer_preset->IsDescendant(next_w)){
if(!p->combo_printer->HasFocus()) if(!p->combo_printer->HasFocus())
p->panel_printer_preset->SetBorderColor(panel_color.bd_normal); p->panel_printer_preset->SetBorderColor(panel_color.bd_normal);
@@ -1843,7 +1901,11 @@ Sidebar::Sidebar(Plater *parent)
e.Skip(); e.Skip();
}); });
w->Bind(wxEVT_LEAVE_WINDOW, [this, panel_color](wxMouseEvent &e) { w->Bind(wxEVT_LEAVE_WINDOW, [this, panel_color](wxMouseEvent &e) {
wxWindow* next_w = wxFindWindowAtPoint(wxGetMousePosition()); // Use event-relative coords instead of wxGetMousePosition() which
// returns (0,0) on Wayland for global screen coordinates.
wxWindow* evtObj = dynamic_cast<wxWindow*>(e.GetEventObject());
wxPoint screenPos = evtObj ? evtObj->ClientToScreen(e.GetPosition()) : wxGetMousePosition();
wxWindow* next_w = wxFindWindowAtPoint(screenPos);
if (!p->combo_nozzle_dia->HasFocus() && (!next_w || !p->panel_nozzle_dia->IsDescendant(next_w))) if (!p->combo_nozzle_dia->HasFocus() && (!next_w || !p->panel_nozzle_dia->IsDescendant(next_w)))
p->panel_nozzle_dia->SetBorderColor(panel_color.bd_normal); p->panel_nozzle_dia->SetBorderColor(panel_color.bd_normal);
e.Skip(); e.Skip();
@@ -1913,7 +1975,11 @@ Sidebar::Sidebar(Plater *parent)
e.Skip(); e.Skip();
}); });
w->Bind(wxEVT_LEAVE_WINDOW, [this, w, panel_color](wxMouseEvent &e) { w->Bind(wxEVT_LEAVE_WINDOW, [this, w, panel_color](wxMouseEvent &e) {
wxWindow* next_w = wxFindWindowAtPoint(wxGetMousePosition()); // Use event-relative coords instead of wxGetMousePosition() which
// returns (0,0) on Wayland for global screen coordinates.
wxWindow* evtObj = dynamic_cast<wxWindow*>(e.GetEventObject());
wxPoint screenPos = evtObj ? evtObj->ClientToScreen(e.GetPosition()) : wxGetMousePosition();
wxWindow* next_w = wxFindWindowAtPoint(screenPos);
if (!p->combo_printer_bed->HasFocus() && (!next_w || !p->panel_printer_bed->IsDescendant(next_w))) if (!p->combo_printer_bed->HasFocus() && (!next_w || !p->panel_printer_bed->IsDescendant(next_w)))
p->panel_printer_bed->SetBorderColor(panel_color.bd_normal); p->panel_printer_bed->SetBorderColor(panel_color.bd_normal);
if(w == p->image_printer_bed) if(w == p->image_printer_bed)
@@ -4835,8 +4901,16 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame)
{ {
m_is_dark = wxGetApp().app_config->get("dark_color_mode") == "1"; m_is_dark = wxGetApp().app_config->get("dark_color_mode") == "1";
#ifdef __WXGTK__
const bool disable_wayland_floating = Slic3r::GUI::is_running_on_wayland();
#endif
m_aui_mgr.SetManagedWindow(q); m_aui_mgr.SetManagedWindow(q);
m_aui_mgr.SetDockSizeConstraint(1, 1); m_aui_mgr.SetDockSizeConstraint(1, 1);
#ifdef __WXGTK__
if (disable_wayland_floating)
m_aui_mgr.SetFlags(m_aui_mgr.GetFlags() & ~wxAUI_MGR_ALLOW_FLOATING);
#endif
//m_aui_mgr.GetArtProvider()->SetMetric(wxAUI_DOCKART_PANE_BORDER_SIZE, 0); //m_aui_mgr.GetArtProvider()->SetMetric(wxAUI_DOCKART_PANE_BORDER_SIZE, 0);
//m_aui_mgr.GetArtProvider()->SetMetric(wxAUI_DOCKART_SASH_SIZE, 2); //m_aui_mgr.GetArtProvider()->SetMetric(wxAUI_DOCKART_SASH_SIZE, 2);
m_aui_mgr.GetArtProvider()->SetMetric(wxAUI_DOCKART_CAPTION_SIZE, 18); m_aui_mgr.GetArtProvider()->SetMetric(wxAUI_DOCKART_CAPTION_SIZE, 18);
@@ -4928,7 +5002,6 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame)
.CloseButton(false) .CloseButton(false)
.TopDockable(false) .TopDockable(false)
.BottomDockable(false) .BottomDockable(false)
.Floatable(true)
.BestSize(wxSize(39 * wxGetApp().em_unit(), 90 * wxGetApp().em_unit()))); .BestSize(wxSize(39 * wxGetApp().em_unit(), 90 * wxGetApp().em_unit())));
auto* panel_sizer = new wxBoxSizer(wxHORIZONTAL); auto* panel_sizer = new wxBoxSizer(wxHORIZONTAL);
@@ -4947,7 +5020,19 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame)
const auto cfg = wxGetApp().app_config; const auto cfg = wxGetApp().app_config;
wxString layout = wxString::FromUTF8(cfg->get("window_layout")); wxString layout = wxString::FromUTF8(cfg->get("window_layout"));
if (!layout.empty()) { if (!layout.empty()) {
m_aui_mgr.LoadPerspective(layout, false); bool removed_floating_state = false;
#ifdef __WXGTK__
if (disable_wayland_floating)
layout = sanitize_window_layout_for_wayland(layout, &removed_floating_state);
#endif
if (!m_aui_mgr.LoadPerspective(layout, false)) {
BOOST_LOG_TRIVIAL(warning) << "Failed to restore saved window layout";
m_aui_mgr.LoadPerspective(m_default_window_layout, false);
} else if (removed_floating_state) {
BOOST_LOG_TRIVIAL(info) << "Removed floating AUI state from saved window layout for Wayland";
}
sidebar_layout.is_collapsed = !sidebar.IsShown(); sidebar_layout.is_collapsed = !sidebar.IsShown();
} }
@@ -8886,11 +8971,9 @@ void Plater::priv::set_current_panel(wxPanel* panel, bool no_slice)
wxPanel* old_panel = current_panel; wxPanel* old_panel = current_panel;
//#if BBL_HAS_FIRST_PAGE //#if BBL_HAS_FIRST_PAGE
if (!old_panel) { if (!old_panel) {
//BBS: only switch to the first panel when visible // Wayland may report the first canvas as not yet shown while the frame is still mapping.
// Keep the panel switch anyway so handlers are bound and the first paint can initialize GL later.
panel->Show(); panel->Show();
//dynamic_cast<View3D *>(panel)->get_canvas3d()->render();
if (!panel->IsShownOnScreen())
return;
} }
//#endif //#endif
current_panel = panel; current_panel = panel;
@@ -10050,6 +10133,9 @@ void Plater::priv::on_action_split_volumes(SimpleEvent&)
void Plater::priv::on_object_select(SimpleEvent& evt) void Plater::priv::on_object_select(SimpleEvent& evt)
{ {
if (wxGetApp().is_closing())
return;
wxGetApp().obj_list()->update_selections(); wxGetApp().obj_list()->update_selections();
selection_changed(); selection_changed();
} }
+12
View File
@@ -15,6 +15,10 @@
#include <slic3r/GUI/Widgets/WebView.hpp> #include <slic3r/GUI/Widgets/WebView.hpp>
#include <wx/webview.h> #include <wx/webview.h>
#ifdef __linux__
#include <webkit2/webkit2.h>
#endif
namespace pt = boost::property_tree; namespace pt = boost::property_tree;
namespace Slic3r { namespace Slic3r {
@@ -33,6 +37,14 @@ PrinterWebView::PrinterWebView(wxWindow *parent)
return; return;
} }
#ifdef __linux__
auto cookiesPath = boost::filesystem::path(data_dir() + "/cache/cookies.db");
auto wv = static_cast<WebKitWebView*>(m_browser->GetNativeBackend());
auto wv_ctx = webkit_web_view_get_context(wv);
auto cookieManager = webkit_web_context_get_cookie_manager(wv_ctx);
webkit_cookie_manager_set_persistent_storage(cookieManager, cookiesPath.c_str(), WEBKIT_COOKIE_PERSISTENT_STORAGE_SQLITE);
#endif
m_browser->Bind(wxEVT_WEBVIEW_ERROR, &PrinterWebView::OnError, this); m_browser->Bind(wxEVT_WEBVIEW_ERROR, &PrinterWebView::OnError, this);
m_browser->Bind(wxEVT_WEBVIEW_LOADED, &PrinterWebView::OnLoaded, this); m_browser->Bind(wxEVT_WEBVIEW_LOADED, &PrinterWebView::OnLoaded, this);
+47 -6
View File
@@ -22,6 +22,10 @@
#include "imgui/imconfig.h" #include "imgui/imconfig.h"
#if defined(__WXGTK__)
#include "LinuxDisplayBackend.hpp"
#endif
using boost::optional; using boost::optional;
namespace Slic3r { namespace Slic3r {
@@ -33,6 +37,17 @@ wxDEFINE_EVENT(wxCUSTOMEVT_JUMP_TO_OBJECT, wxCommandEvent);
using GUI::from_u8; using GUI::from_u8;
using GUI::into_u8; using GUI::into_u8;
namespace {
bool focus_left_popup(wxWindow* popup, wxWindow* focus_window, wxWindow* related_window_1 = nullptr,
wxWindow* related_window_2 = nullptr, wxWindow* related_window_3 = nullptr)
{
return focus_window != popup && !popup->IsDescendant(focus_window) && focus_window != related_window_1 &&
focus_window != related_window_2 && focus_window != related_window_3;
}
} // namespace
namespace Search { namespace Search {
static char marker_by_type(Preset::Type type, PrinterTechnology pt) static char marker_by_type(Preset::Type type, PrinterTechnology pt)
@@ -674,11 +689,24 @@ void SearchDialog::OnDismiss() { }
void SearchDialog::Dismiss() void SearchDialog::Dismiss()
{ {
auto pos = wxGetMousePosition();
auto focus_window = wxWindow::FindFocus(); auto focus_window = wxWindow::FindFocus();
if (!focus_window) if (!focus_window) {
Die(); Die();
else if (!m_event_tag->GetScreenRect().Contains(pos) && !this->GetScreenRect().Contains(pos) && !m_search_item_tag->GetScreenRect().Contains(pos)) { return;
}
#if defined(__WXGTK__)
// On Wayland, wxGetMousePosition() returns unreliable global coords.
// Rely on focus tracking instead: if focus moved to a window outside
// this dialog and its related controls, dismiss.
if (Slic3r::GUI::is_running_on_wayland()) {
if (focus_left_popup(this, focus_window, m_event_tag, m_search_item_tag, search_line)) {
Die();
}
return;
}
#endif
auto pos = wxGetMousePosition();
if (!m_event_tag->GetScreenRect().Contains(pos) && !this->GetScreenRect().Contains(pos) && !m_search_item_tag->GetScreenRect().Contains(pos)) {
Die(); Die();
} }
} }
@@ -904,11 +932,24 @@ void SearchObjectDialog::OnDismiss() {}
void SearchObjectDialog::Dismiss() void SearchObjectDialog::Dismiss()
{ {
auto pos = wxGetMousePosition();
auto focus_window = wxWindow::FindFocus(); auto focus_window = wxWindow::FindFocus();
if (!focus_window) if (!focus_window) {
Die(); Die();
else if (!search_line->GetScreenRect().Contains(pos) && !this->GetScreenRect().Contains(pos)) { return;
}
#if defined(__WXGTK__)
// On Wayland, wxGetMousePosition() returns unreliable global coords.
// Rely on focus tracking instead: if focus moved to a window outside
// this dialog and its related controls, dismiss.
if (Slic3r::GUI::is_running_on_wayland()) {
if (focus_left_popup(this, focus_window, search_line)) {
Die();
}
return;
}
#endif
auto pos = wxGetMousePosition();
if (!search_line->GetScreenRect().Contains(pos) && !this->GetScreenRect().Contains(pos)) {
Die(); Die();
} }
} }
+1 -1
View File
@@ -18,7 +18,7 @@
#include "libslic3r/BuildVolume.hpp" #include "libslic3r/BuildVolume.hpp"
#endif // ENABLE_ENHANCED_PRINT_VOLUME_FIT #endif // ENABLE_ENHANCED_PRINT_VOLUME_FIT
#include <GL/glew.h> #include <glad/gl.h>
#include <boost/algorithm/string/predicate.hpp> #include <boost/algorithm/string/predicate.hpp>
#include <boost/log/trivial.hpp> #include <boost/log/trivial.hpp>
+26 -1
View File
@@ -17,6 +17,9 @@
#include "GUI_App.hpp" #include "GUI_App.hpp"
#include "GUI_Utils.hpp" #include "GUI_Utils.hpp"
#include "I18N.hpp" #include "I18N.hpp"
#ifdef __WXGTK__
#include "LinuxDisplayBackend.hpp"
#endif
#include "MainFrame.hpp" #include "MainFrame.hpp"
#include "MsgDialog.hpp" #include "MsgDialog.hpp"
#include "OpenGLManager.hpp" #include "OpenGLManager.hpp"
@@ -28,7 +31,7 @@
#include <boost/property_tree/json_parser.hpp> #include <boost/property_tree/json_parser.hpp>
#include <boost/uuid/detail/md5.hpp> #include <boost/uuid/detail/md5.hpp>
#include "GL/glew.h" #include <glad/gl.h>
#include <wx/display.h> #include <wx/display.h>
#include <wx/htmllbox.h> #include <wx/htmllbox.h>
@@ -420,6 +423,28 @@ static std::string generate_system_info_json()
data_node.put("Linux_DistroID", distro_id); data_node.put("Linux_DistroID", distro_id);
data_node.put("Linux_DistroVer", distro_ver); data_node.put("Linux_DistroVer", distro_ver);
data_node.put("Linux_Wayland", wxGetEnv("WAYLAND_DISPLAY", nullptr)); data_node.put("Linux_Wayland", wxGetEnv("WAYLAND_DISPLAY", nullptr));
#ifdef __WXGTK__
const LinuxDisplayBackend display_backend = get_linux_display_backend();
const char* display_backend_name = "unknown";
const char* gl_backend_hint = "Unknown";
switch (display_backend) {
case LinuxDisplayBackend::Wayland:
display_backend_name = "wayland";
gl_backend_hint = "EGL";
break;
case LinuxDisplayBackend::X11:
display_backend_name = "x11";
gl_backend_hint = "GLX";
break;
default:
break;
}
data_node.put("Linux_DisplayBackend", display_backend_name);
data_node.put("Linux_GLBackendHint", gl_backend_hint);
#else
data_node.put("Linux_DisplayBackend", "unknown");
data_node.put("Linux_GLBackendHint", "Unknown");
#endif
#endif #endif
data_node.put("wxWidgets", wxVERSION_NUM_DOT_STRING); data_node.put("wxWidgets", wxVERSION_NUM_DOT_STRING);
#ifdef __WXGTK__ #ifdef __WXGTK__
+1 -1
View File
@@ -1,4 +1,4 @@
#include <GL/glew.h> #include <glad/gl.h>
#include "SkipPartCanvas.hpp" #include "SkipPartCanvas.hpp"
#include <opencv2/opencv.hpp> #include <opencv2/opencv.hpp>
+1 -1
View File
@@ -1,6 +1,6 @@
#include "TextLines.hpp" #include "TextLines.hpp"
#include <GL/glew.h> #include <glad/gl.h>
#include "libslic3r/Model.hpp" #include "libslic3r/Model.hpp"
+3 -1
View File
@@ -516,7 +516,9 @@ void Button::OnParentMotion(wxMouseEvent& event)
tipWindow->SetLabel(tip); tipWindow->SetLabel(tip);
} }
tipWindow->Position(wxGetMousePosition(), wxSize(0, 0)); // Position tooltip relative to the button widget itself rather than
// using wxGetMousePosition() which returns (0,0) on Wayland.
tipWindow->Position(this->ClientToScreen(wxPoint(0, 0)), this->GetSize());
tipWindow->Popup(); tipWindow->Popup();
} }
else else
+1 -1
View File
@@ -1,6 +1,6 @@
#include "EmbossStyleManager.hpp" #include "EmbossStyleManager.hpp"
#include <optional> #include <optional>
#include <GL/glew.h> // Imgui texture #include <glad/gl.h> // Imgui texture
#include <imgui/imgui_internal.h> // ImTextCharFromUtf8 #include <imgui/imgui_internal.h> // ImTextCharFromUtf8
#include <libslic3r/AppConfig.hpp> #include <libslic3r/AppConfig.hpp>
#include <libslic3r/Utils.hpp> // ScopeGuard #include <libslic3r/Utils.hpp> // ScopeGuard
+1 -1
View File
@@ -7,7 +7,7 @@
#include <functional> #include <functional>
#include <imgui/imgui.h> #include <imgui/imgui.h>
#include <wx/font.h> #include <wx/font.h>
#include <GL/glew.h> #include <glad/gl.h>
#include <libslic3r/BoundingBox.hpp> #include <libslic3r/BoundingBox.hpp>
#include <libslic3r/Emboss.hpp> #include <libslic3r/Emboss.hpp>
#include <libslic3r/TextConfiguration.hpp> #include <libslic3r/TextConfiguration.hpp>