mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-09-28 03:11:47 +00:00
Merge branch 'main' into feat/printer-agent-impl
This commit is contained in:
@@ -149,9 +149,9 @@ jobs:
|
|||||||
working-directory: ${{ github.workspace }}
|
working-directory: ${{ github.workspace }}
|
||||||
run: |
|
run: |
|
||||||
if [ -z "${{ vars.SELF_HOSTED }}" ]; then
|
if [ -z "${{ vars.SELF_HOSTED }}" ]; then
|
||||||
brew install automake texinfo libtool
|
brew install automake texinfo libtool pkgconf yasm nasm
|
||||||
fi
|
fi
|
||||||
./build_release_macos.sh -dx ${{ !vars.SELF_HOSTED && '-1' || '' }} -a ${{ inputs.arch }} -t 10.15
|
./build_release_macos.sh -dx ${{ !vars.SELF_HOSTED && '-j 3' || '' }} -a ${{ inputs.arch }} -t 10.15
|
||||||
(cd "${{ github.workspace }}/deps/build/${{ inputs.arch }}" && \
|
(cd "${{ github.workspace }}/deps/build/${{ inputs.arch }}" && \
|
||||||
find . -mindepth 1 -maxdepth 1 ! -name 'OrcaSlicer_dep' -exec rm -rf {} +)
|
find . -mindepth 1 -maxdepth 1 ! -name 'OrcaSlicer_dep' -exec rm -rf {} +)
|
||||||
|
|
||||||
|
|||||||
@@ -145,7 +145,7 @@ jobs:
|
|||||||
env:
|
env:
|
||||||
ORCA_TESTS_BUILD_ONLY: ${{ inputs.arch == 'arm64' && '1' || '' }}
|
ORCA_TESTS_BUILD_ONLY: ${{ inputs.arch == 'arm64' && '1' || '' }}
|
||||||
run: |
|
run: |
|
||||||
./build_release_macos.sh -s -n -x ${{ !vars.SELF_HOSTED && '-1' || '' }} -a ${{ inputs.arch }} -t 10.15 ${{ inputs.arch == 'arm64' && '-T' || '' }}
|
./build_release_macos.sh -s -n -x ${{ !vars.SELF_HOSTED && '-j 3' || '' }} -a ${{ inputs.arch }} -t 10.15 ${{ inputs.arch == 'arm64' && '-T' || '' }}
|
||||||
|
|
||||||
- name: Pack unit tests mac
|
- name: Pack unit tests mac
|
||||||
if: runner.os == 'macOS' && !inputs.macos-combine-only && inputs.arch == 'arm64'
|
if: runner.os == 'macOS' && !inputs.macos-combine-only && inputs.arch == 'arm64'
|
||||||
@@ -204,7 +204,7 @@ jobs:
|
|||||||
if: runner.os == 'macOS' && inputs.macos-combine-only
|
if: runner.os == 'macOS' && inputs.macos-combine-only
|
||||||
working-directory: ${{ github.workspace }}
|
working-directory: ${{ github.workspace }}
|
||||||
run: |
|
run: |
|
||||||
./build_release_macos.sh -u -x ${{ !vars.SELF_HOSTED && '-1' || '' }} -a universal -t 10.15
|
./build_release_macos.sh -u -x ${{ !vars.SELF_HOSTED && '-j 3' || '' }} -a universal -t 10.15
|
||||||
|
|
||||||
# Thanks to RaySajuuk, it's working now
|
# Thanks to RaySajuuk, it's working now
|
||||||
- name: Sign app and notary
|
- name: Sign app and notary
|
||||||
|
|||||||
+67
-1
@@ -298,6 +298,8 @@ if (APPLE)
|
|||||||
SET(CMAKE_XCODE_ATTRIBUTE_PRODUCT_BUNDLE_IDENTIFIER "com.orcaslicer.OrcaSlicer")
|
SET(CMAKE_XCODE_ATTRIBUTE_PRODUCT_BUNDLE_IDENTIFIER "com.orcaslicer.OrcaSlicer")
|
||||||
|
|
||||||
message(STATUS "Orca: IS_CROSS_COMPILE: ${IS_CROSS_COMPILE}")
|
message(STATUS "Orca: IS_CROSS_COMPILE: ${IS_CROSS_COMPILE}")
|
||||||
|
elseif (CMAKE_SYSTEM_NAME STREQUAL "Linux")
|
||||||
|
set(CMAKE_INSTALL_RPATH "$ORIGIN")
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
# Proposal for C++ unit tests and sandboxes
|
# Proposal for C++ unit tests and sandboxes
|
||||||
@@ -1065,6 +1067,10 @@ function(orcaslicer_copy_dlls target config postfix output_dlls)
|
|||||||
${CMAKE_PREFIX_PATH}/bin/occt/TKXDESTEP.dll
|
${CMAKE_PREFIX_PATH}/bin/occt/TKXDESTEP.dll
|
||||||
${CMAKE_PREFIX_PATH}/bin/occt/TKXSBase.dll
|
${CMAKE_PREFIX_PATH}/bin/occt/TKXSBase.dll
|
||||||
${CMAKE_PREFIX_PATH}/bin/freetype.dll
|
${CMAKE_PREFIX_PATH}/bin/freetype.dll
|
||||||
|
${CMAKE_PREFIX_PATH}/bin/avcodec-61.dll
|
||||||
|
${CMAKE_PREFIX_PATH}/bin/swresample-5.dll
|
||||||
|
${CMAKE_PREFIX_PATH}/bin/swscale-8.dll
|
||||||
|
${CMAKE_PREFIX_PATH}/bin/avutil-59.dll
|
||||||
DESTINATION ${_out_dir})
|
DESTINATION ${_out_dir})
|
||||||
|
|
||||||
set(${output_dlls}
|
set(${output_dlls}
|
||||||
@@ -1100,12 +1106,58 @@ function(orcaslicer_copy_dlls target config postfix output_dlls)
|
|||||||
${_out_dir}/TKXSBase.dll
|
${_out_dir}/TKXSBase.dll
|
||||||
|
|
||||||
${_out_dir}/freetype.dll
|
${_out_dir}/freetype.dll
|
||||||
|
${_out_dir}/avcodec-61.dll
|
||||||
|
${_out_dir}/swresample-5.dll
|
||||||
|
${_out_dir}/swscale-8.dll
|
||||||
|
${_out_dir}/avutil-59.dll
|
||||||
PARENT_SCOPE
|
PARENT_SCOPE
|
||||||
)
|
)
|
||||||
|
|
||||||
endfunction()
|
endfunction()
|
||||||
|
|
||||||
|
function(orcaslicer_copy_sos target config postfix output_sos)
|
||||||
|
|
||||||
|
get_property(_is_multi GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
|
||||||
|
get_target_property(_alt_out_dir ${target} RUNTIME_OUTPUT_DIRECTORY)
|
||||||
|
|
||||||
|
if (_alt_out_dir)
|
||||||
|
set(_out_dir "${_alt_out_dir}")
|
||||||
|
elseif (_is_multi)
|
||||||
|
set(_out_dir "${CMAKE_CURRENT_BINARY_DIR}/${config}")
|
||||||
|
else ()
|
||||||
|
set(_out_dir "${CMAKE_CURRENT_BINARY_DIR}")
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
file(COPY ${CMAKE_PREFIX_PATH}/lib/libavcodec.so
|
||||||
|
${CMAKE_PREFIX_PATH}/lib/libavcodec.so.61
|
||||||
|
${CMAKE_PREFIX_PATH}/lib/libavcodec.so.61.3.100
|
||||||
|
${CMAKE_PREFIX_PATH}/lib/libavutil.so
|
||||||
|
${CMAKE_PREFIX_PATH}/lib/libavutil.so.59
|
||||||
|
${CMAKE_PREFIX_PATH}/lib/libavutil.so.59.8.100
|
||||||
|
${CMAKE_PREFIX_PATH}/lib/libswscale.so
|
||||||
|
${CMAKE_PREFIX_PATH}/lib/libswscale.so.8
|
||||||
|
${CMAKE_PREFIX_PATH}/lib/libswscale.so.8.1.100
|
||||||
|
${CMAKE_PREFIX_PATH}/lib/libswresample.so
|
||||||
|
${CMAKE_PREFIX_PATH}/lib/libswresample.so.5
|
||||||
|
${CMAKE_PREFIX_PATH}/lib/libswresample.so.5.1.100
|
||||||
|
DESTINATION ${_out_dir})
|
||||||
|
|
||||||
|
set(${output_sos}
|
||||||
|
${_out_dir}/libavcodec.so
|
||||||
|
${_out_dir}/libavcodec.so.61
|
||||||
|
${_out_dir}/libavcodec.so.61.3.100
|
||||||
|
${_out_dir}/libavutil.so
|
||||||
|
${_out_dir}/libavutil.so.59
|
||||||
|
${_out_dir}/libavutil.so.59.8.100
|
||||||
|
${_out_dir}/libswscale.so
|
||||||
|
${_out_dir}/libswscale.so.8
|
||||||
|
${_out_dir}/libswscale.so.8.1.100
|
||||||
|
${_out_dir}/libswresample.so
|
||||||
|
${_out_dir}/libswresample.so.5
|
||||||
|
${_out_dir}/libswresample.so.5.1.100
|
||||||
|
PARENT_SCOPE
|
||||||
|
)
|
||||||
|
endfunction()
|
||||||
|
|
||||||
# Bundled sources set their own warning flags, and a plain -Wall there means /Wall
|
# Bundled sources set their own warning flags, and a plain -Wall there means /Wall
|
||||||
# (= -Weverything) under clang-cl. Target options are applied after the ones a target
|
# (= -Weverything) under clang-cl. Target options are applied after the ones a target
|
||||||
@@ -1217,6 +1269,20 @@ else ()
|
|||||||
endif()
|
endif()
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
|
if (CMAKE_SYSTEM_NAME STREQUAL "Linux")
|
||||||
|
set(LIBRARY_FILES
|
||||||
|
${LIBDIR_BIN}/libavcodec.so.61
|
||||||
|
${LIBDIR_BIN}/libavcodec.so.61.3.100
|
||||||
|
${LIBDIR_BIN}/libavutil.so.59
|
||||||
|
${LIBDIR_BIN}/libavutil.so.59.8.100
|
||||||
|
${LIBDIR_BIN}/libswresample.so.5
|
||||||
|
${LIBDIR_BIN}/libswresample.so.5.1.100
|
||||||
|
${LIBDIR_BIN}/libswscale.so.8
|
||||||
|
${LIBDIR_BIN}/libswscale.so.8.1.100
|
||||||
|
)
|
||||||
|
install(FILES ${LIBRARY_FILES} DESTINATION "${CMAKE_INSTALL_PREFIX}/bin")
|
||||||
|
endif ()
|
||||||
|
|
||||||
install(FILES ${CMAKE_SOURCE_DIR}/LICENSE.txt DESTINATION ".")
|
install(FILES ${CMAKE_SOURCE_DIR}/LICENSE.txt DESTINATION ".")
|
||||||
configure_file(${LIBDIR}/dev-utils/platform/unix/fhs.hpp.in ${LIBDIR_BIN}/dev-utils/platform/unix/fhs.hpp)
|
configure_file(${LIBDIR}/dev-utils/platform/unix/fhs.hpp.in ${LIBDIR_BIN}/dev-utils/platform/unix/fhs.hpp)
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ set -e
|
|||||||
set -o pipefail
|
set -o pipefail
|
||||||
SECONDS=0
|
SECONDS=0
|
||||||
|
|
||||||
while getopts ":dpa:snt:xbc:i:1Tuh" opt; do
|
while getopts ":dpa:snt:xbc:i:j:Tuh" opt; do
|
||||||
case "${opt}" in
|
case "${opt}" in
|
||||||
d )
|
d )
|
||||||
export BUILD_TARGET="deps"
|
export BUILD_TARGET="deps"
|
||||||
@@ -38,8 +38,8 @@ while getopts ":dpa:snt:xbc:i:1Tuh" opt; do
|
|||||||
i )
|
i )
|
||||||
export CMAKE_IGNORE_PREFIX_PATH="${CMAKE_IGNORE_PREFIX_PATH:+$CMAKE_IGNORE_PREFIX_PATH;}$OPTARG"
|
export CMAKE_IGNORE_PREFIX_PATH="${CMAKE_IGNORE_PREFIX_PATH:+$CMAKE_IGNORE_PREFIX_PATH;}$OPTARG"
|
||||||
;;
|
;;
|
||||||
1 )
|
j )
|
||||||
export CMAKE_BUILD_PARALLEL_LEVEL=1
|
export CMAKE_BUILD_PARALLEL_LEVEL="$OPTARG"
|
||||||
;;
|
;;
|
||||||
T )
|
T )
|
||||||
export BUILD_TESTS="1"
|
export BUILD_TESTS="1"
|
||||||
@@ -58,7 +58,7 @@ while getopts ":dpa:snt:xbc:i:1Tuh" opt; do
|
|||||||
echo " -b: Build without reconfiguring CMake"
|
echo " -b: Build without reconfiguring CMake"
|
||||||
echo " -c: Set CMake build configuration, default is Release"
|
echo " -c: Set CMake build configuration, default is Release"
|
||||||
echo " -i: Add a prefix to ignore during CMake dependency discovery (repeatable), defaults to /opt/local:/usr/local:/opt/homebrew"
|
echo " -i: Add a prefix to ignore during CMake dependency discovery (repeatable), defaults to /opt/local:/usr/local:/opt/homebrew"
|
||||||
echo " -1: Use single job for building"
|
echo " -j: Set the number of parallel build jobs (CMAKE_BUILD_PARALLEL_LEVEL)"
|
||||||
echo " -T: Build and run tests (set ORCA_TESTS_BUILD_ONLY=1 to build without running)"
|
echo " -T: Build and run tests (set ORCA_TESTS_BUILD_ONLY=1 to build without running)"
|
||||||
exit 0
|
exit 0
|
||||||
;;
|
;;
|
||||||
|
|||||||
+16
-3
@@ -20,6 +20,18 @@ for %%a in (%*) do (
|
|||||||
if "%%a"=="-x" set USE_NINJA=1
|
if "%%a"=="-x" set USE_NINJA=1
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@REM Check for clang-cl option (-l). Combined with -x it also builds the deps with
|
||||||
|
@REM clang-cl; on the Visual Studio generator it applies to the slicer only, because
|
||||||
|
@REM the dependency sub-builds have no toolset to inherit and stay on MSVC.
|
||||||
|
set CLANG_ARG=
|
||||||
|
set TOOLSET_ARG=
|
||||||
|
for %%a in (%*) do (
|
||||||
|
if "%%a"=="-l" (
|
||||||
|
set CLANG_ARG=-DCMAKE_C_COMPILER=clang-cl -DCMAKE_CXX_COMPILER=clang-cl
|
||||||
|
set TOOLSET_ARG=-T ClangCL
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
@REM Check for unit-tests option ("tests")
|
@REM Check for unit-tests option ("tests")
|
||||||
set BUILD_TESTS=OFF
|
set BUILD_TESTS=OFF
|
||||||
for %%a in (%*) do (
|
for %%a in (%*) do (
|
||||||
@@ -127,12 +139,13 @@ if "%1"=="slicer" (
|
|||||||
GOTO :slicer
|
GOTO :slicer
|
||||||
)
|
)
|
||||||
echo "building deps.."
|
echo "building deps.."
|
||||||
|
if defined CLANG_ARG if "%USE_NINJA%"=="0" echo Note: -l needs -x for the dependencies; building them with MSVC.
|
||||||
|
|
||||||
echo on
|
echo on
|
||||||
REM Set minimum CMake policy to avoid <3.5 errors
|
REM Set minimum CMake policy to avoid <3.5 errors
|
||||||
set CMAKE_POLICY_VERSION_MINIMUM=3.5
|
set CMAKE_POLICY_VERSION_MINIMUM=3.5
|
||||||
if "%USE_NINJA%"=="1" (
|
if "%USE_NINJA%"=="1" (
|
||||||
cmake ../ -G %CMAKE_GENERATOR% -DCMAKE_BUILD_TYPE=%build_type%
|
cmake ../ -G %CMAKE_GENERATOR% %CLANG_ARG% -DCMAKE_BUILD_TYPE=%build_type%
|
||||||
cmake --build . --config %build_type% --target deps
|
cmake --build . --config %build_type% --target deps
|
||||||
) else (
|
) else (
|
||||||
cmake ../ -G %CMAKE_GENERATOR% -A %arch% -DCMAKE_BUILD_TYPE=%build_type%
|
cmake ../ -G %CMAKE_GENERATOR% -A %arch% -DCMAKE_BUILD_TYPE=%build_type%
|
||||||
@@ -151,10 +164,10 @@ cd %build_dir%
|
|||||||
echo on
|
echo on
|
||||||
set CMAKE_POLICY_VERSION_MINIMUM=3.5
|
set CMAKE_POLICY_VERSION_MINIMUM=3.5
|
||||||
if "%USE_NINJA%"=="1" (
|
if "%USE_NINJA%"=="1" (
|
||||||
cmake .. -G %CMAKE_GENERATOR% -DORCA_TOOLS=ON %SIG_FLAG% -DBUILD_TESTS=%BUILD_TESTS% -DCMAKE_BUILD_TYPE=%build_type%
|
cmake .. -G %CMAKE_GENERATOR% %CLANG_ARG% -DORCA_TOOLS=ON %SIG_FLAG% -DBUILD_TESTS=%BUILD_TESTS% -DCMAKE_BUILD_TYPE=%build_type%
|
||||||
cmake --build . --config %build_type% --target all
|
cmake --build . --config %build_type% --target all
|
||||||
) else (
|
) else (
|
||||||
cmake .. -G %CMAKE_GENERATOR% -A %arch% -DORCA_TOOLS=ON %SIG_FLAG% -DBUILD_TESTS=%BUILD_TESTS% -DCMAKE_BUILD_TYPE=%build_type%
|
cmake .. -G %CMAKE_GENERATOR% -A %arch% %TOOLSET_ARG% -DORCA_TOOLS=ON %SIG_FLAG% -DBUILD_TESTS=%BUILD_TESTS% -DCMAKE_BUILD_TYPE=%build_type%
|
||||||
cmake --build . --config %build_type% --target ALL_BUILD -- -m
|
cmake --build . --config %build_type% --target ALL_BUILD -- -m
|
||||||
)
|
)
|
||||||
@echo off
|
@echo off
|
||||||
|
|||||||
Vendored
+3
@@ -21,6 +21,9 @@ orcaslicer_add_cmake_project(Assimp
|
|||||||
URL ${_assimp_url}
|
URL ${_assimp_url}
|
||||||
URL_HASH ${_assimp_hash}
|
URL_HASH ${_assimp_hash}
|
||||||
CMAKE_ARGS
|
CMAKE_ARGS
|
||||||
|
# Assimp's ccache support sets the global RULE_LAUNCH_COMPILE, which breaks
|
||||||
|
# the Ninja RC rule. The superbuild forwards CMAKE_<LANG>_COMPILER_LAUNCHER.
|
||||||
|
-DASSIMP_BUILD_USE_CCACHE=OFF
|
||||||
-DASSIMP_BUILD_TESTS=OFF
|
-DASSIMP_BUILD_TESTS=OFF
|
||||||
-DASSIMP_BUILD_SAMPLES=OFF
|
-DASSIMP_BUILD_SAMPLES=OFF
|
||||||
-DASSIMP_BUILD_ASSIMP_TOOLS=OFF
|
-DASSIMP_BUILD_ASSIMP_TOOLS=OFF
|
||||||
|
|||||||
Vendored
+8
@@ -24,6 +24,13 @@ if (MSVC AND DEP_DEBUG)
|
|||||||
set(_options "FORWARD_CONFIG")
|
set(_options "FORWARD_CONFIG")
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
|
# Boost.Container's bundled dlmalloc passes int* where the Win32 Interlocked API
|
||||||
|
# takes volatile long*; cl compiles that with a warning, clang errors out.
|
||||||
|
set(_boost_c_flags_line "")
|
||||||
|
if (MSVC AND CMAKE_C_COMPILER_ID STREQUAL "Clang")
|
||||||
|
set(_boost_c_flags_line "-DCMAKE_C_FLAGS:STRING=-Wno-incompatible-pointer-types")
|
||||||
|
endif ()
|
||||||
|
|
||||||
orcaslicer_add_cmake_project(Boost
|
orcaslicer_add_cmake_project(Boost
|
||||||
${_options}
|
${_options}
|
||||||
URL "https://github.com/boostorg/boost/releases/download/boost-1.84.0/boost-1.84.0.tar.gz"
|
URL "https://github.com/boostorg/boost/releases/download/boost-1.84.0/boost-1.84.0.tar.gz"
|
||||||
@@ -38,6 +45,7 @@ orcaslicer_add_cmake_project(Boost
|
|||||||
"${_context_abi_line}"
|
"${_context_abi_line}"
|
||||||
"${_context_arch_line}"
|
"${_context_arch_line}"
|
||||||
"${_context_impl_line}"
|
"${_context_impl_line}"
|
||||||
|
"${_boost_c_flags_line}"
|
||||||
)
|
)
|
||||||
|
|
||||||
set(DEP_Boost_DEPENDS ZLIB)
|
set(DEP_Boost_DEPENDS ZLIB)
|
||||||
Vendored
+13
-4
@@ -157,8 +157,16 @@ endif ()
|
|||||||
function(orcaslicer_add_cmake_project projectname)
|
function(orcaslicer_add_cmake_project projectname)
|
||||||
cmake_parse_arguments(P_ARGS "FORWARD_CONFIG" "INSTALL_DIR;BUILD_COMMAND;INSTALL_COMMAND" "CMAKE_ARGS" ${ARGN})
|
cmake_parse_arguments(P_ARGS "FORWARD_CONFIG" "INSTALL_DIR;BUILD_COMMAND;INSTALL_COMMAND" "CMAKE_ARGS" ${ARGN})
|
||||||
|
|
||||||
|
# MSVC is true for clang-cl as well, so the sub-build toolchain has to key on the
|
||||||
|
# generator. A non-Visual-Studio superbuild passes its own generator down, and with
|
||||||
|
# it the CMAKE_C_COMPILER / CMAKE_CXX_COMPILER forwarded below.
|
||||||
|
set(_dep_msvc_gen FALSE)
|
||||||
|
if (MSVC AND CMAKE_GENERATOR MATCHES "Visual Studio")
|
||||||
|
set(_dep_msvc_gen TRUE)
|
||||||
|
endif ()
|
||||||
|
|
||||||
set(_configs_line -DCMAKE_BUILD_TYPE:STRING=${CMAKE_BUILD_TYPE})
|
set(_configs_line -DCMAKE_BUILD_TYPE:STRING=${CMAKE_BUILD_TYPE})
|
||||||
if (_is_multi OR MSVC)
|
if (_is_multi OR _dep_msvc_gen)
|
||||||
if (P_ARGS_FORWARD_CONFIG)
|
if (P_ARGS_FORWARD_CONFIG)
|
||||||
set(_configs_line -DCMAKE_BUILD_TYPE:STRING=${CMAKE_BUILD_TYPE})
|
set(_configs_line -DCMAKE_BUILD_TYPE:STRING=${CMAKE_BUILD_TYPE})
|
||||||
elseif (ORCA_INCLUDE_DEBUG_INFO AND NOT DEP_DEBUG)
|
elseif (ORCA_INCLUDE_DEBUG_INFO AND NOT DEP_DEBUG)
|
||||||
@@ -174,7 +182,7 @@ function(orcaslicer_add_cmake_project projectname)
|
|||||||
set(_target_config "Release")
|
set(_target_config "Release")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (MSVC)
|
if (_dep_msvc_gen)
|
||||||
set(_gen CMAKE_GENERATOR "${DEP_MSVC_GEN}" CMAKE_GENERATOR_PLATFORM "${DEP_PLATFORM}")
|
set(_gen CMAKE_GENERATOR "${DEP_MSVC_GEN}" CMAKE_GENERATOR_PLATFORM "${DEP_PLATFORM}")
|
||||||
else()
|
else()
|
||||||
set(_gen "")
|
set(_gen "")
|
||||||
@@ -182,7 +190,7 @@ function(orcaslicer_add_cmake_project projectname)
|
|||||||
|
|
||||||
if ($ENV{CMAKE_BUILD_PARALLEL_LEVEL})
|
if ($ENV{CMAKE_BUILD_PARALLEL_LEVEL})
|
||||||
set(_build_j "") # assume environment will control --build parallel setting
|
set(_build_j "") # assume environment will control --build parallel setting
|
||||||
elseif(MSVC)
|
elseif(_dep_msvc_gen)
|
||||||
set(_build_j "/m")
|
set(_build_j "/m")
|
||||||
else()
|
else()
|
||||||
set(_build_j "-j${NPROC}")
|
set(_build_j "-j${NPROC}")
|
||||||
@@ -367,7 +375,7 @@ include(libnoise/libnoise.cmake)
|
|||||||
|
|
||||||
include(Draco/Draco.cmake)
|
include(Draco/Draco.cmake)
|
||||||
|
|
||||||
# Assimp: glTF/GLB/FBX import for the texture-to-color feature.
|
include(FFMPEG/FFMPEG.cmake)
|
||||||
include(Assimp/Assimp.cmake)
|
include(Assimp/Assimp.cmake)
|
||||||
|
|
||||||
|
|
||||||
@@ -451,6 +459,7 @@ set(_dep_list
|
|||||||
dep_libnoise
|
dep_libnoise
|
||||||
dep_python3
|
dep_python3
|
||||||
dep_wxInspector
|
dep_wxInspector
|
||||||
|
dep_FFMPEG
|
||||||
dep_Assimp
|
dep_Assimp
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
Vendored
+14
@@ -56,6 +56,18 @@ else()
|
|||||||
set(_curl_static ON)
|
set(_curl_static ON)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
# curl 7.75's configure probes and code rely on C laxness cl allows but clang
|
||||||
|
# errors on (implicit function declarations, int* vs u_long* in ioctlsocket),
|
||||||
|
# which flips probe results and misconfigures nonblock.c into the AmigaOS
|
||||||
|
# IoctlSocket branch. Relax both diagnostics so the probes behave like cl, and
|
||||||
|
# pin the camel-case probes off since they only "pass" by implicit declaration.
|
||||||
|
set(_curl_c_flags_line "")
|
||||||
|
set(_curl_probe_overrides "")
|
||||||
|
if (MSVC AND CMAKE_C_COMPILER_ID STREQUAL "Clang")
|
||||||
|
set(_curl_c_flags_line "-DCMAKE_C_FLAGS:STRING=-Wno-implicit-function-declaration -Wno-incompatible-pointer-types")
|
||||||
|
set(_curl_probe_overrides -DHAVE_IOCTLSOCKET_CAMEL=0 -DHAVE_IOCTLSOCKET_CAMEL_FIONBIO=0)
|
||||||
|
endif ()
|
||||||
|
|
||||||
orcaslicer_add_cmake_project(CURL
|
orcaslicer_add_cmake_project(CURL
|
||||||
# GIT_REPOSITORY https://github.com/curl/curl.git
|
# GIT_REPOSITORY https://github.com/curl/curl.git
|
||||||
# GIT_TAG curl-7_75_0
|
# GIT_TAG curl-7_75_0
|
||||||
@@ -69,6 +81,8 @@ orcaslicer_add_cmake_project(CURL
|
|||||||
-DBUILD_CURL_EXE:BOOL=OFF
|
-DBUILD_CURL_EXE:BOOL=OFF
|
||||||
-DCMAKE_POSITION_INDEPENDENT_CODE=ON
|
-DCMAKE_POSITION_INDEPENDENT_CODE=ON
|
||||||
-DCURL_STATICLIB=${_curl_static}
|
-DCURL_STATICLIB=${_curl_static}
|
||||||
|
"${_curl_c_flags_line}"
|
||||||
|
${_curl_probe_overrides}
|
||||||
${_curl_platform_flags}
|
${_curl_platform_flags}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
Vendored
+15
@@ -7,5 +7,20 @@ orcaslicer_add_cmake_project(Eigen
|
|||||||
URL https://gitlab.com/libeigen/eigen/-/archive/5.0.1/eigen-5.0.1.zip
|
URL https://gitlab.com/libeigen/eigen/-/archive/5.0.1/eigen-5.0.1.zip
|
||||||
URL_HASH SHA256=0dbb1f9e3aaad66f352c03227d8c983f6f0b49e0b07e71a7300f4abcc01aee12
|
URL_HASH SHA256=0dbb1f9e3aaad66f352c03227d8c983f6f0b49e0b07e71a7300f4abcc01aee12
|
||||||
CMAKE_ARGS "${_eigen_extra_flags}"
|
CMAKE_ARGS "${_eigen_extra_flags}"
|
||||||
|
# Only the headers are consumed here. Everything below builds nothing we
|
||||||
|
# use, and all three enable_language(Fortran): test/CMakeLists.txt:9,
|
||||||
|
# lapack/CMakeLists.txt:6 and blas/testing/CMakeLists.txt:2. They default
|
||||||
|
# to ON because the dependency configures as its own top-level project.
|
||||||
|
#
|
||||||
|
# Whether that probe is harmless depends on what CMake finds. The Visual
|
||||||
|
# Studio generator supports no Fortran, so it finds nothing; clang-cl sits
|
||||||
|
# next to the LLVM toolset's flang, which works. MSVC with Ninja finds
|
||||||
|
# Strawberry Perl's MinGW gfortran instead, which the deps build already
|
||||||
|
# requires for OpenSSL, and hands it the MSVC-style /machine:x64 that
|
||||||
|
# MinGW's ld reads as a missing input file. The configure dies there and
|
||||||
|
# takes the rest of the superbuild with it.
|
||||||
|
-DEIGEN_BUILD_TESTING=OFF
|
||||||
|
-DEIGEN_BUILD_BLAS=OFF
|
||||||
|
-DEIGEN_BUILD_LAPACK=OFF
|
||||||
DEPENDS dep_Boost dep_GMP dep_MPFR
|
DEPENDS dep_Boost dep_GMP dep_MPFR
|
||||||
)
|
)
|
||||||
|
|||||||
Vendored
+87
@@ -0,0 +1,87 @@
|
|||||||
|
set(_conf_cmd ./configure)
|
||||||
|
|
||||||
|
if (MSVC)
|
||||||
|
set(_source_dir "${CMAKE_BINARY_DIR}/dep_FFMPEG-prefix/src/dep_FFMPEG")
|
||||||
|
|
||||||
|
set(PREBUILD_URL_arm64 "https://github.com/Noisyfox/FFmpeg-Builds-Orca/releases/download/autobuild-2026-07-17-14-28/ffmpeg-n7.0.3-31-g9b6ffd74b5-winarm64-orca-shared-7.0.zip")
|
||||||
|
set(PREBUILD_HASH_arm64 "12f4140279f2f8469885e1b5b2e8be9d788882914c21523cacd56989f3548054")
|
||||||
|
set(PREBUILD_URL_x64 "https://github.com/Noisyfox/FFmpeg-Builds-Orca/releases/download/autobuild-2026-07-17-14-28/ffmpeg-n7.0.3-31-g9b6ffd74b5-win64-orca-shared-7.0.zip")
|
||||||
|
set(PREBUILD_HASH_x64 "e65916020ddb9ef84b2666dfbcbfc9b1d67f69d15b4a66db53754637bf2d498c")
|
||||||
|
|
||||||
|
ExternalProject_Add(dep_FFMPEG
|
||||||
|
URL ${PREBUILD_URL_${DEPS_ARCH}}
|
||||||
|
URL_HASH SHA256=${PREBUILD_HASH_${DEPS_ARCH}}
|
||||||
|
DOWNLOAD_DIR ${DEP_DOWNLOAD_DIR}/FFMPEG
|
||||||
|
CONFIGURE_COMMAND ""
|
||||||
|
BUILD_COMMAND ""
|
||||||
|
INSTALL_COMMAND
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E copy_directory "${_source_dir}/bin" "${DESTDIR}/bin"
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E copy_directory "${_source_dir}/lib" "${DESTDIR}/lib"
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E copy_directory "${_source_dir}/include" "${DESTDIR}/include"
|
||||||
|
)
|
||||||
|
|
||||||
|
else ()
|
||||||
|
if (APPLE)
|
||||||
|
set(_minos_cmd
|
||||||
|
"--extra-cflags=-mmacosx-version-min=${DEP_OSX_TARGET}"
|
||||||
|
"--extra-ldflags=-mmacosx-version-min=${DEP_OSX_TARGET}"
|
||||||
|
)
|
||||||
|
# Static FFmpeg: nothing to bundle into the .app, no rpath handling.
|
||||||
|
# Disable the VideoToolbox/AudioToolbox HW-accel paths: the player decodes
|
||||||
|
# in software (swscale), and the auto-detected HW objects would drag in
|
||||||
|
# system frameworks that the static libs would then depend on.
|
||||||
|
set(_link_cmd --enable-static --disable-shared --disable-videotoolbox --disable-audiotoolbox)
|
||||||
|
if (IS_CROSS_COMPILE)
|
||||||
|
set(_cross_cmd --enable-cross-compile)
|
||||||
|
set(_pic_cmd --enable-pic)
|
||||||
|
if (${CMAKE_SYSTEM_PROCESSOR} MATCHES "x86_64")
|
||||||
|
set(_arch_cmd --arch=arm64)
|
||||||
|
set(_cc_cmd "--cc=clang -arch arm64")
|
||||||
|
else()
|
||||||
|
set(_arch_cmd --arch=x86_64)
|
||||||
|
set(_cc_cmd "--cc=clang -arch x86_64")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
else ()
|
||||||
|
set(_link_cmd --enable-shared)
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
set(_build_j -j)
|
||||||
|
if(DEFINED ENV{CMAKE_BUILD_PARALLEL_LEVEL})
|
||||||
|
set(_build_j "-j$ENV{CMAKE_BUILD_PARALLEL_LEVEL}")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
ExternalProject_Add(dep_FFMPEG
|
||||||
|
URL https://github.com/FFmpeg/FFmpeg/archive/refs/tags/n7.0.3.tar.gz
|
||||||
|
URL_HASH SHA256=DEEDCABE339165214A3637DF4C86A507AEF0D793CF8774FF68735F4737E8DDBC
|
||||||
|
DOWNLOAD_DIR ${DEP_DOWNLOAD_DIR}/FFMPEG
|
||||||
|
CONFIGURE_COMMAND ${_conf_cmd}
|
||||||
|
${_cross_cmd}
|
||||||
|
${_pic_cmd}
|
||||||
|
${_arch_cmd}
|
||||||
|
${_cc_cmd}
|
||||||
|
"--prefix=${DESTDIR}"
|
||||||
|
${_link_cmd}
|
||||||
|
${_minos_cmd}
|
||||||
|
--disable-doc
|
||||||
|
--enable-small
|
||||||
|
--disable-outdevs
|
||||||
|
--disable-filters
|
||||||
|
--enable-filter=*null*,afade,*fifo,*format,*resample,aeval,allrgb,allyuv,atempo,pan,*bars,color,*key,crop,draw*,eq*,framerate,*_qsv,*_vaapi,*v4l2*,hw*,scale,volume,test*
|
||||||
|
--disable-protocols
|
||||||
|
--enable-protocol=file,fd,pipe,rtp,udp
|
||||||
|
--disable-muxers
|
||||||
|
--enable-muxer=rtp
|
||||||
|
--disable-encoders
|
||||||
|
--disable-decoders
|
||||||
|
--enable-decoder=*aac*,h264*,mp3*,mjpeg,rv*
|
||||||
|
--disable-demuxers
|
||||||
|
--enable-demuxer=h264,mp3,mov
|
||||||
|
--disable-zlib
|
||||||
|
--disable-avdevice
|
||||||
|
BUILD_IN_SOURCE ON
|
||||||
|
BUILD_COMMAND make ${_build_j}
|
||||||
|
INSTALL_COMMAND make install
|
||||||
|
)
|
||||||
|
|
||||||
|
endif()
|
||||||
Vendored
+43
@@ -1,3 +1,20 @@
|
|||||||
|
diff --git a/adm/cmake/occt_defs_flags.cmake b/adm/cmake/occt_defs_flags.cmake
|
||||||
|
index 00000000..00000001 100644
|
||||||
|
--- a/adm/cmake/occt_defs_flags.cmake
|
||||||
|
+++ b/adm/cmake/occt_defs_flags.cmake
|
||||||
|
@@ -134,7 +134,11 @@
|
||||||
|
set (CMAKE_CXX_FLAGS "-std=c++0x ${CMAKE_CXX_FLAGS}")
|
||||||
|
endif()
|
||||||
|
# Optimize size of binaries
|
||||||
|
- set (CMAKE_SHARED_LINKER_FLAGS "-Wl,-s ${CMAKE_SHARED_LINKER_FLAGS}")
|
||||||
|
+ # clang-cl reports the Clang compiler ID, and OCCT builds shared on Windows,
|
||||||
|
+ # where the MSVC-style linker gets this flag as an argument it does not know.
|
||||||
|
+ if (NOT WIN32)
|
||||||
|
+ set (CMAKE_SHARED_LINKER_FLAGS "-Wl,-s ${CMAKE_SHARED_LINKER_FLAGS}")
|
||||||
|
+ endif()
|
||||||
|
elseif(MINGW)
|
||||||
|
add_definitions(-D_WIN32_WINNT=0x0601)
|
||||||
|
# _WIN32_WINNT=0x0601 (use Windows 7 SDK)
|
||||||
diff --git a/CMakeLists.txt b/CMakeLists.txt
|
diff --git a/CMakeLists.txt b/CMakeLists.txt
|
||||||
index d98acc0f..28eb8eb4 100644
|
index d98acc0f..28eb8eb4 100644
|
||||||
--- a/CMakeLists.txt
|
--- a/CMakeLists.txt
|
||||||
@@ -168,6 +185,32 @@ index d98acc0f..28eb8eb4 100644
|
|||||||
endforeach()
|
endforeach()
|
||||||
|
|
||||||
if (BUILD_SAMPLES_QT)
|
if (BUILD_SAMPLES_QT)
|
||||||
|
diff --git a/adm/cmake/occt_macros.cmake b/adm/cmake/occt_macros.cmake
|
||||||
|
index 224c96b1..8c94a1c5 100644
|
||||||
|
--- a/adm/cmake/occt_macros.cmake
|
||||||
|
+++ b/adm/cmake/occt_macros.cmake
|
||||||
|
@@ -608,7 +608,7 @@ macro (OCCT_INSERT_CODE_FOR_TARGET)
|
||||||
|
install(CODE "if (\"\${CMAKE_INSTALL_CONFIG_NAME}\" MATCHES \"^([Rr][Ee][Ll][Ee][Aa][Ss][Ee])$\")
|
||||||
|
set (OCCT_INSTALL_BIN_LETTER \"\")
|
||||||
|
elseif (\"\${CMAKE_INSTALL_CONFIG_NAME}\" MATCHES \"^([Rr][Ee][Ll][Ww][Ii][Tt][Hh][Dd][Ee][Bb][Ii][Nn][Ff][Oo])$\")
|
||||||
|
- set (OCCT_INSTALL_BIN_LETTER \"i\")
|
||||||
|
+ set (OCCT_INSTALL_BIN_LETTER \"\")
|
||||||
|
elseif (\"\${CMAKE_INSTALL_CONFIG_NAME}\" MATCHES \"^([Dd][Ee][Bb][Uu][Gg])$\")
|
||||||
|
set (OCCT_INSTALL_BIN_LETTER \"d\")
|
||||||
|
endif()")
|
||||||
|
diff --git a/adm/cmake/occt_toolkit.cmake b/adm/cmake/occt_toolkit.cmake
|
||||||
|
index 550e0e2f..7ac1a3b8 100644
|
||||||
|
--- a/adm/cmake/occt_toolkit.cmake
|
||||||
|
+++ b/adm/cmake/occt_toolkit.cmake
|
||||||
|
@@ -241,7 +241,7 @@
|
||||||
|
else()
|
||||||
|
set (aReleasePdbConf)
|
||||||
|
endif()
|
||||||
|
- install (FILES ${CMAKE_BINARY_DIR}/${OS_WITH_BIT}/${COMPILER}/bin\${OCCT_INSTALL_BIN_LETTER}/${PROJECT_NAME}.pdb
|
||||||
|
+ install (FILES $<TARGET_PDB_FILE:${PROJECT_NAME}>
|
||||||
|
CONFIGURATIONS Debug ${aReleasePdbConf} RelWithDebInfo
|
||||||
|
DESTINATION "${INSTALL_DIR_BIN}\${OCCT_INSTALL_BIN_LETTER}")
|
||||||
|
endif()
|
||||||
diff --git a/src/Font/Font_FTFont.cxx b/src/Font/Font_FTFont.cxx
|
diff --git a/src/Font/Font_FTFont.cxx b/src/Font/Font_FTFont.cxx
|
||||||
index 5ae9899f..0a17372b 100644
|
index 5ae9899f..0a17372b 100644
|
||||||
--- a/src/Font/Font_FTFont.cxx
|
--- a/src/Font/Font_FTFont.cxx
|
||||||
|
|||||||
Vendored
+13
-3
@@ -17,10 +17,20 @@ else()
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(WIN32)
|
if(WIN32)
|
||||||
set(_conf_cmd perl Configure )
|
set(_openssl_msvc_env CC=cl CXX=cl RC=rc CL=/FS)
|
||||||
|
# OpenSSL's perl Configure honors the CC environment variable, but the
|
||||||
|
# VC-WIN64A makefile only works with cl (an unquoted clang-cl path with
|
||||||
|
# spaces, e.g. exported by CLion, silently produces no .obj files and the
|
||||||
|
# lib step fails with LNK1181). Pin the upstream toolchain.
|
||||||
|
# Keep rc.exe resolved from the MSVC developer environment as well. The
|
||||||
|
# absolute Windows SDK path contains spaces and OpenSSL 1.1.1 writes it to
|
||||||
|
# the generated nmake file without quoting, which skips .res generation.
|
||||||
|
# /FS serializes access to OpenSSL's shared generated PDB when cl is
|
||||||
|
# driven through nmake from a Ninja configure step.
|
||||||
|
set(_conf_cmd ${CMAKE_COMMAND} -E env ${_openssl_msvc_env} perl Configure )
|
||||||
set(_cross_comp_prefix_line "")
|
set(_cross_comp_prefix_line "")
|
||||||
set(_make_cmd nmake)
|
set(_make_cmd ${CMAKE_COMMAND} -E env ${_openssl_msvc_env} nmake)
|
||||||
set(_install_cmd nmake install_sw )
|
set(_install_cmd ${CMAKE_COMMAND} -E env ${_openssl_msvc_env} nmake install_sw )
|
||||||
else()
|
else()
|
||||||
if(APPLE)
|
if(APPLE)
|
||||||
set(_conf_cmd export MACOSX_DEPLOYMENT_TARGET=${CMAKE_OSX_DEPLOYMENT_TARGET} && ./Configure -mmacosx-version-min=${CMAKE_OSX_DEPLOYMENT_TARGET})
|
set(_conf_cmd export MACOSX_DEPLOYMENT_TARGET=${CMAKE_OSX_DEPLOYMENT_TARGET} && ./Configure -mmacosx-version-min=${CMAKE_OSX_DEPLOYMENT_TARGET})
|
||||||
|
|||||||
Vendored
+24
@@ -1,3 +1,26 @@
|
|||||||
|
# wxInspector finds wxWidgets through CMake's FindwxWidgets module, which only
|
||||||
|
# searches lib/vc*_lib because _WX_TOOL is hardcoded to "vc". A superbuild driven
|
||||||
|
# by clang-cl installs wxWidgets into lib/clang_x64_lib, so hand the module the
|
||||||
|
# directory wxWidgets actually used, derived the same way wxWidgetsConfig.cmake
|
||||||
|
# derives it.
|
||||||
|
set(_wxinspector_wx_hints "")
|
||||||
|
if (MSVC)
|
||||||
|
if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
|
||||||
|
set(_wx_compiler_prefix "clang")
|
||||||
|
else ()
|
||||||
|
set(_wx_compiler_prefix "vc")
|
||||||
|
endif ()
|
||||||
|
set(_wx_arch_suffix "")
|
||||||
|
if (CMAKE_GENERATOR_PLATFORM AND NOT CMAKE_GENERATOR_PLATFORM STREQUAL "Win32")
|
||||||
|
string(TOLOWER "_${CMAKE_GENERATOR_PLATFORM}" _wx_arch_suffix)
|
||||||
|
elseif (CMAKE_SIZEOF_VOID_P EQUAL 8)
|
||||||
|
set(_wx_arch_suffix "_x64")
|
||||||
|
endif ()
|
||||||
|
set(_wxinspector_wx_hints
|
||||||
|
"-DwxWidgets_ROOT_DIR=${DESTDIR}"
|
||||||
|
"-DwxWidgets_LIB_DIR=${DESTDIR}/lib/${_wx_compiler_prefix}${_wx_arch_suffix}_lib")
|
||||||
|
endif ()
|
||||||
|
|
||||||
orcaslicer_add_cmake_project(
|
orcaslicer_add_cmake_project(
|
||||||
wxInspector
|
wxInspector
|
||||||
URL https://github.com/Noisyfox/wxInspector/archive/refs/tags/v1.0.0.zip
|
URL https://github.com/Noisyfox/wxInspector/archive/refs/tags/v1.0.0.zip
|
||||||
@@ -6,6 +29,7 @@ orcaslicer_add_cmake_project(
|
|||||||
CMAKE_ARGS
|
CMAKE_ARGS
|
||||||
-DCMAKE_CXX_FLAGS="-DwxDEBUG_LEVEL=0"
|
-DCMAKE_CXX_FLAGS="-DwxDEBUG_LEVEL=0"
|
||||||
-DCMAKE_POSITION_INDEPENDENT_CODE=ON
|
-DCMAKE_POSITION_INDEPENDENT_CODE=ON
|
||||||
|
${_wxinspector_wx_hints}
|
||||||
)
|
)
|
||||||
|
|
||||||
if (MSVC)
|
if (MSVC)
|
||||||
|
|||||||
-28
@@ -1,28 +0,0 @@
|
|||||||
---
|
|
||||||
build/cmake/wxWidgetsConfig.cmake.in | 10 +++++++++-
|
|
||||||
1 file changed, 10 insertions(+), 1 deletion(-)
|
|
||||||
|
|
||||||
diff --git a/build/cmake/wxWidgetsConfig.cmake.in b/build/cmake/wxWidgetsConfig.cmake.in
|
|
||||||
index 1a83f36..70ad8a4 100644
|
|
||||||
--- a/build/cmake/wxWidgetsConfig.cmake.in
|
|
||||||
+++ b/build/cmake/wxWidgetsConfig.cmake.in
|
|
||||||
@@ -58,7 +58,16 @@ if(WIN32_MSVC_NAMING)
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
-include("${CMAKE_CURRENT_LIST_DIR}${wxPLATFORM_LIB_DIR}/@PROJECT_NAME@Targets.cmake")
|
|
||||||
+if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang" AND CMAKE_CXX_COMPILER_FRONTEND_VARIANT STREQUAL "MSVC")
|
|
||||||
+ if (CMAKE_GENERATOR_PLATFORM STREQUAL "ARM64" OR CMAKE_VS_PLATFORM_NAME STREQUAL "ARM64" OR CMAKE_SYSTEM_PROCESSOR MATCHES "^(ARM64|arm64|aarch64)$")
|
|
||||||
+ set(_wx_clang_msvc_lib_dir "vc_arm64_lib")
|
|
||||||
+ else()
|
|
||||||
+ set(_wx_clang_msvc_lib_dir "vc_x64_lib")
|
|
||||||
+ endif()
|
|
||||||
+ include("${CMAKE_CURRENT_LIST_DIR}${wxPLATFORM_LIB_DIR}/${_wx_clang_msvc_lib_dir}/@PROJECT_NAME@Targets.cmake")
|
|
||||||
+else()
|
|
||||||
+ include("${CMAKE_CURRENT_LIST_DIR}${wxPLATFORM_LIB_DIR}/@PROJECT_NAME@Targets.cmake")
|
|
||||||
+endif()
|
|
||||||
|
|
||||||
macro(wx_inherit_property source dest name)
|
|
||||||
# property name without _<CONFIG>
|
|
||||||
--
|
|
||||||
2.43.0
|
|
||||||
Vendored
-1
@@ -28,7 +28,6 @@ orcaslicer_add_cmake_project(
|
|||||||
GIT_SHALLOW ON
|
GIT_SHALLOW ON
|
||||||
GIT_SUBMODULES 3rdparty/catch 3rdparty/pcre 3rdparty/libwebp
|
GIT_SUBMODULES 3rdparty/catch 3rdparty/pcre 3rdparty/libwebp
|
||||||
DEPENDS ${PNG_PKG} ${ZLIB_PKG} ${EXPAT_PKG} ${JPEG_PKG}
|
DEPENDS ${PNG_PKG} ${ZLIB_PKG} ${EXPAT_PKG} ${JPEG_PKG}
|
||||||
PATCH_COMMAND git apply --verbose --ignore-space-change --whitespace=fix ${CMAKE_CURRENT_LIST_DIR}/0001-Clang-CL-fix.patch
|
|
||||||
CMAKE_ARGS
|
CMAKE_ARGS
|
||||||
-DwxBUILD_PRECOMP=ON
|
-DwxBUILD_PRECOMP=ON
|
||||||
${_wx_toolkit}
|
${_wx_toolkit}
|
||||||
|
|||||||
@@ -0,0 +1,376 @@
|
|||||||
|
# macOS FFmpeg Media Player Implementation Plan
|
||||||
|
|
||||||
|
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
|
||||||
|
|
||||||
|
**Goal:** Make macOS use the same FFmpeg-based media player (`wxMediaCtrl3` + `AVVideoDecoder`) as Windows/Linux, linking the static FFmpeg libraries from the deps build, and remove the old `wxMediaCtrl2.mm` BambuPlayer-based player.
|
||||||
|
|
||||||
|
**Architecture:** The new player is platform-neutral C++ already used on Linux/Windows. Enabling it on macOS is pure build wiring: compile `wxMediaCtrl3.cpp` + `AVVideoDecoder.cpp` on macOS, drop the `__WXMAC__` alias that redirects `wxMediaCtrl3` to the old `wxMediaCtrl2`, and link static FFmpeg (`libavcodec.a`/`libswscale.a`/`libavutil.a`) from the deps install. The Bambu stream API is dlsym'd at runtime from the network plugin (`libBambuSource.dylib`), which already exports it — no plugin changes needed. Rendering reuses the existing `wxImage` → `DrawBitmap` paint path (same as Linux).
|
||||||
|
|
||||||
|
**Tech Stack:** C++17, wxWidgets, CMake, FFmpeg 7.0.3 (libavcodec/libswscale/libavutil), macOS (Xcode generator), `deps/` ExternalProject build system.
|
||||||
|
|
||||||
|
## Global Constraints
|
||||||
|
|
||||||
|
- Branch: `dev/ffmpeg-player-macos`. Commit after every task.
|
||||||
|
- **Linux and Windows builds must not change** — the FFmpeg deps flag change is guarded by `APPLE`; Linux keeps `--enable-shared`, Windows keeps its prebuilt DLL zips.
|
||||||
|
- Static FFmpeg only on macOS: deps produce `libavcodec.a`/`libswscale.a`/`libavutil.a`; the app links those explicitly — the app binary must have **no** `libav*` dylib references (`otool -L` check).
|
||||||
|
- Follow existing code style: PascalCase classes, snake_case functions, C++17.
|
||||||
|
- No changes to `StatusPanel.cpp`, `MediaPlayCtrl.*`, or the BambuTunnel interface — the app already creates `wxMediaCtrl3` and uses only its public interface.
|
||||||
|
- The player cannot be unit-tested (hardware/plugin-dependent GUI code); verification is build-level, link-level, and manual runtime on a Mac.
|
||||||
|
- `localization/i18n/list.txt` references only `wxMediaCtrl2.cpp` (Win/Linux, stays) — no translation-list changes needed.
|
||||||
|
- Build dirs on the dev machine: main app = `build_arm64/` (Xcode generator, multi-config), deps = `deps/build/arm64/` (Unix Makefiles). App target name: `OrcaSlicer`. Substitute your own configured build dirs where noted.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Task 1: Enable wxMediaCtrl3 on macOS and link static FFmpeg
|
||||||
|
|
||||||
|
**Files:**
|
||||||
|
- Modify: `src/slic3r/GUI/wxMediaCtrl3.h` (lines 18–22: the `#ifdef __WXMAC__` alias branch)
|
||||||
|
- Modify: `src/slic3r/GUI/wxMediaCtrl3.cpp:13` (uncomment the event define)
|
||||||
|
- Modify: `src/slic3r/GUI/wxMediaCtrl2.cpp:101` (remove the event define)
|
||||||
|
- Modify: `src/slic3r/CMakeLists.txt` (APPLE source list ~lines 779–792; FFmpeg link block ~lines 905–910)
|
||||||
|
|
||||||
|
**Interfaces:**
|
||||||
|
- Consumes: nothing new (all classes already exist).
|
||||||
|
- Produces: `wxMediaCtrl3` class compiled on macOS with the same interface as Linux/Windows — `Load(wxURI)`, `Play()`, `Stop()`, `SetIdleImage(wxString)`, `GetState()`, `GetLastError()`, `GetVideoSize()`, event `EVT_MEDIA_CTRL_STAT` defined once in the lib (from `wxMediaCtrl3.cpp`).
|
||||||
|
|
||||||
|
- [ ] **Step 1: Remove the macOS alias in wxMediaCtrl3.h**
|
||||||
|
|
||||||
|
Current (lines 16–23 of `src/slic3r/GUI/wxMediaCtrl3.h`):
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
void wxMediaCtrl_OnSize(wxWindow * ctrl, wxSize const & videoSize, int width, int height);
|
||||||
|
|
||||||
|
#ifdef __WXMAC__
|
||||||
|
|
||||||
|
#include "wxMediaCtrl2.h"
|
||||||
|
#define wxMediaCtrl3 wxMediaCtrl2
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#define BAMBU_DYNAMIC
|
||||||
|
```
|
||||||
|
|
||||||
|
New:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
void wxMediaCtrl_OnSize(wxWindow * ctrl, wxSize const & videoSize, int width, int height);
|
||||||
|
|
||||||
|
#define BAMBU_DYNAMIC
|
||||||
|
```
|
||||||
|
|
||||||
|
Also remove the matching `#endif` that closed the `#else` branch (the one before the final `#endif /* wxMediaCtrl3_h */`), so the file's `#ifndef`/`#endif` guard pair stays balanced.
|
||||||
|
|
||||||
|
- [ ] **Step 2: Move the EVT_MEDIA_CTRL_STAT definition into wxMediaCtrl3.cpp**
|
||||||
|
|
||||||
|
In `src/slic3r/GUI/wxMediaCtrl3.cpp:13`, uncomment:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
//wxDEFINE_EVENT(EVT_MEDIA_CTRL_STAT, wxCommandEvent);
|
||||||
|
```
|
||||||
|
|
||||||
|
becomes:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
wxDEFINE_EVENT(EVT_MEDIA_CTRL_STAT, wxCommandEvent);
|
||||||
|
```
|
||||||
|
|
||||||
|
In `src/slic3r/GUI/wxMediaCtrl2.cpp:101`, delete:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
wxDEFINE_EVENT(EVT_MEDIA_CTRL_STAT, wxCommandEvent);
|
||||||
|
```
|
||||||
|
|
||||||
|
(One definition total in the lib — `MediaPlayCtrl.cpp:59` binds this event on the media ctrl.)
|
||||||
|
|
||||||
|
- [ ] **Step 3: Update the APPLE source list in CMakeLists.txt**
|
||||||
|
|
||||||
|
In `src/slic3r/CMakeLists.txt`, the APPLE branch (currently compiles `wxMediaCtrl2.mm`, which becomes dead on macOS):
|
||||||
|
|
||||||
|
```cmake
|
||||||
|
GUI/wxMediaCtrl2.mm
|
||||||
|
GUI/wxMediaCtrl2.h
|
||||||
|
GUI/wxMediaCtrl3.h
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
becomes:
|
||||||
|
|
||||||
|
```cmake
|
||||||
|
GUI/AVVideoDecoder.cpp
|
||||||
|
GUI/AVVideoDecoder.hpp
|
||||||
|
GUI/wxMediaCtrl3.cpp
|
||||||
|
GUI/wxMediaCtrl3.h
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
(The `else ()` branch — Win/Linux — stays exactly as it is.)
|
||||||
|
|
||||||
|
- [ ] **Step 4: Link static FFmpeg on macOS**
|
||||||
|
|
||||||
|
In `src/slic3r/CMakeLists.txt`, the FFmpeg block (currently `if (NOT APPLE)`):
|
||||||
|
|
||||||
|
```cmake
|
||||||
|
if (NOT APPLE)
|
||||||
|
pkg_check_modules(LIBAV REQUIRED IMPORTED_TARGET
|
||||||
|
libavcodec
|
||||||
|
libswscale
|
||||||
|
libavutil
|
||||||
|
)
|
||||||
|
target_link_libraries(libslic3r_gui PkgConfig::LIBAV)
|
||||||
|
endif()
|
||||||
|
```
|
||||||
|
|
||||||
|
becomes:
|
||||||
|
|
||||||
|
```cmake
|
||||||
|
if (APPLE)
|
||||||
|
# Static FFmpeg from the deps install: nothing to bundle into the .app,
|
||||||
|
# no rpath/install_name handling. Order matters: avcodec -> swscale -> avutil.
|
||||||
|
find_library(LIBAVCODEC_LIBRARY NAMES libavcodec.a PATHS ${CMAKE_PREFIX_PATH}/lib NO_DEFAULT_PATH)
|
||||||
|
find_library(LIBSWSCALE_LIBRARY NAMES libswscale.a PATHS ${CMAKE_PREFIX_PATH}/lib NO_DEFAULT_PATH)
|
||||||
|
find_library(LIBAVUTIL_LIBRARY NAMES libavutil.a PATHS ${CMAKE_PREFIX_PATH}/lib NO_DEFAULT_PATH)
|
||||||
|
target_link_libraries(libslic3r_gui ${LIBAVCODEC_LIBRARY} ${LIBSWSCALE_LIBRARY} ${LIBAVUTIL_LIBRARY})
|
||||||
|
target_include_directories(libslic3r_gui SYSTEM PRIVATE ${CMAKE_PREFIX_PATH}/include)
|
||||||
|
else ()
|
||||||
|
pkg_check_modules(LIBAV REQUIRED IMPORTED_TARGET
|
||||||
|
libavcodec
|
||||||
|
libswscale
|
||||||
|
libavutil
|
||||||
|
)
|
||||||
|
target_link_libraries(libslic3r_gui PkgConfig::LIBAV)
|
||||||
|
endif()
|
||||||
|
```
|
||||||
|
|
||||||
|
The deps install (`${CMAKE_PREFIX_PATH}/lib`) already contains the three `.a` files from the existing arm64 deps build — no deps rebuild needed for this task.
|
||||||
|
|
||||||
|
- [ ] **Step 5: Reconfigure and build the app**
|
||||||
|
|
||||||
|
Run (Xcode generator; `cmake` re-runs automatically on build):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cmake --build build_arm64 --config RelWithDebInfo --target OrcaSlicer
|
||||||
|
```
|
||||||
|
|
||||||
|
Expected: configure succeeds (no `pkg_check_modules` errors on macOS, `find_library` finds all three `.a` files), compile succeeds (`wxMediaCtrl3.cpp` and `AVVideoDecoder.cpp` compile on macOS without changes), link succeeds.
|
||||||
|
|
||||||
|
If CMake complains that `wxMediaCtrl3.h` is included but not in the source list or similar IDE-only warnings — ignore; headers in the list are cosmetic.
|
||||||
|
|
||||||
|
- [ ] **Step 6: Verify no dynamic FFmpeg dependency**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
otool -L build_arm64/src/RelWithDebInfo/OrcaSlicer.app/Contents/MacOS/OrcaSlicer | grep -i "libav" || echo "OK: no dynamic FFmpeg"
|
||||||
|
```
|
||||||
|
|
||||||
|
Expected: prints `OK: no dynamic FFmpeg` (empty grep output). This is the whole point of static linking — nothing to bundle into the `.app`.
|
||||||
|
|
||||||
|
- [ ] **Step 7: Quick sanity — macOS unit tests still pass**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
ctest --test-dir build_arm64/tests/libslic3r --output-on-failure
|
||||||
|
```
|
||||||
|
|
||||||
|
Expected: passes (add `-C RelWithDebInfo` if the multi-config generator requires it). If no tests were built in this build dir, build target `tests` first (`cmake --build build_arm64 --config RelWithDebInfo --target tests`).
|
||||||
|
|
||||||
|
- [ ] **Step 8: Commit**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git add src/slic3r/CMakeLists.txt src/slic3r/GUI/wxMediaCtrl3.h src/slic3r/GUI/wxMediaCtrl3.cpp src/slic3r/GUI/wxMediaCtrl2.cpp
|
||||||
|
git commit -m "feat: use FFmpeg media player on macOS with static FFmpeg"
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Task 2: Static-only FFmpeg in the macOS deps build
|
||||||
|
|
||||||
|
**Files:**
|
||||||
|
- Modify: `deps/FFMPEG/FFMPEG.cmake` (non-MSVC branch, APPLE section and CONFIGURE_COMMAND)
|
||||||
|
|
||||||
|
**Interfaces:**
|
||||||
|
- Consumes: nothing.
|
||||||
|
- Produces: a deps install on macOS containing only `libavcodec.a`, `libswscale.a`, `libavutil.a` (+ headers) — no `libav*` dylibs, so no bundling/rpath machinery is ever needed on macOS. Linux and Windows output are unchanged.
|
||||||
|
|
||||||
|
- [ ] **Step 1: Add the static flag variable**
|
||||||
|
|
||||||
|
In `deps/FFMPEG/FFMPEG.cmake`, inside the non-MSVC `else ()` branch, in the existing `if (APPLE)` block:
|
||||||
|
|
||||||
|
```cmake
|
||||||
|
if (APPLE)
|
||||||
|
set(_minos_cmd
|
||||||
|
"CFLAGS=-mmacosx-version-min=${DEP_OSX_TARGET}"
|
||||||
|
"LDFLAGS=-mmacosx-version-min=${DEP_OSX_TARGET}"
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
add after the `_minos_cmd` set:
|
||||||
|
|
||||||
|
```cmake
|
||||||
|
# Static FFmpeg: nothing to bundle into the .app, no rpath handling.
|
||||||
|
# Shared flags must come AFTER --enable-shared below so they win.
|
||||||
|
set(_link_cmd --enable-static --disable-shared)
|
||||||
|
```
|
||||||
|
|
||||||
|
and add a matching `else ()` after the `if (IS_CROSS_COMPILE) ... endif()` block inside that `if (APPLE)`, so non-Apple Unix keeps shared:
|
||||||
|
|
||||||
|
```cmake
|
||||||
|
else ()
|
||||||
|
set(_link_cmd --enable-shared)
|
||||||
|
endif ()
|
||||||
|
```
|
||||||
|
|
||||||
|
(If the existing `if (IS_CROSS_COMPILE)` block is the last thing inside `if (APPLE)`, the new `else ()` closes the `if (APPLE)` itself.)
|
||||||
|
|
||||||
|
- [ ] **Step 2: Use the variable in CONFIGURE_COMMAND**
|
||||||
|
|
||||||
|
In the `ExternalProject_Add(dep_FFMPEG ...)` configure command:
|
||||||
|
|
||||||
|
```cmake
|
||||||
|
"--prefix=${DESTDIR}"
|
||||||
|
--enable-shared
|
||||||
|
```
|
||||||
|
|
||||||
|
becomes:
|
||||||
|
|
||||||
|
```cmake
|
||||||
|
"--prefix=${DESTDIR}"
|
||||||
|
--enable-shared
|
||||||
|
${_link_cmd}
|
||||||
|
```
|
||||||
|
|
||||||
|
Order matters: `--enable-shared` comes first, then `--enable-static --disable-shared` (APPLE) or `--enable-shared` (Linux) — the last flag wins in FFmpeg configure.
|
||||||
|
|
||||||
|
- [ ] **Step 3: Rebuild the FFmpeg dep (slow — several minutes, run in background)**
|
||||||
|
|
||||||
|
The changed CONFIGURE_COMMAND invalidates the ExternalProject stamp, so this re-configures and rebuilds FFmpeg:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cmake --build deps/build/arm64 --target dep_FFMPEG
|
||||||
|
```
|
||||||
|
|
||||||
|
For a fully clean static-only check (removes the previous shared build tree, which can leave stale `.dylib` files behind in the in-source build):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
rm -rf deps/build/arm64/dep_FFMPEG-prefix
|
||||||
|
cmake --build deps/build/arm64 --target dep_FFMPEG
|
||||||
|
```
|
||||||
|
|
||||||
|
- [ ] **Step 4: Verify the artifacts**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
ls deps/build/arm64/dep_FFMPEG-prefix/src/dep_FFMPEG/libavcodec/*.a
|
||||||
|
ls deps/build/arm64/dep_FFMPEG-prefix/src/dep_FFMPEG/libavcodec/*.dylib 2>/dev/null || echo "OK: no dylibs"
|
||||||
|
```
|
||||||
|
|
||||||
|
Expected: `libavcodec.a` present, second command prints `OK: no dylibs`. Check `libavutil` and `libswscale` the same way.
|
||||||
|
|
||||||
|
- [ ] **Step 5: Verify the app still links against the static libs**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cmake --build build_arm64 --config RelWithDebInfo --target OrcaSlicer
|
||||||
|
otool -L build_arm64/src/RelWithDebInfo/OrcaSlicer.app/Contents/MacOS/OrcaSlicer | grep -i "libav" || echo "OK: no dynamic FFmpeg"
|
||||||
|
```
|
||||||
|
|
||||||
|
Expected: build succeeds, `OK: no dynamic FFmpeg`.
|
||||||
|
|
||||||
|
- [ ] **Step 6: Commit**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git add deps/FFMPEG/FFMPEG.cmake
|
||||||
|
git commit -m "build: build static-only FFmpeg for macOS deps"
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Task 3: Remove the old macOS player
|
||||||
|
|
||||||
|
**Files:**
|
||||||
|
- Delete: `src/slic3r/GUI/wxMediaCtrl2.mm`
|
||||||
|
- Delete: `src/slic3r/GUI/BambuPlayer/BambuPlayer.h` (and the empty `BambuPlayer/` dir)
|
||||||
|
- Modify: `src/slic3r/GUI/wxMediaCtrl2.h` (remove the `#ifdef __WXMAC__` section, lines 22–60)
|
||||||
|
|
||||||
|
**Interfaces:**
|
||||||
|
- Consumes: Task 1 (macOS no longer references `wxMediaCtrl2` — nothing includes `wxMediaCtrl2.h` on macOS anymore; `wxMediaCtrl2` is never instantiated on any platform).
|
||||||
|
- Produces: a clean tree where the old BambuPlayer-based player is gone from macOS. The `BambuPlayer` ObjC class itself remains inside the network plugin (external prebuilt binary) — only the GUI-side consumer is removed.
|
||||||
|
|
||||||
|
- [ ] **Step 1: Delete the old player files**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git rm src/slic3r/GUI/wxMediaCtrl2.mm
|
||||||
|
git rm src/slic3r/GUI/BambuPlayer/BambuPlayer.h
|
||||||
|
rmdir src/slic3r/GUI/BambuPlayer 2>/dev/null || true
|
||||||
|
```
|
||||||
|
|
||||||
|
- [ ] **Step 2: Strip the __WXMAC__ section from wxMediaCtrl2.h**
|
||||||
|
|
||||||
|
In `src/slic3r/GUI/wxMediaCtrl2.h`, remove the entire macOS branch of the `#ifdef __WXMAC__` guard — from `#ifdef __WXMAC__` (line 22) through the closing `};` of the mac class (line 60), and the `#else` marker — leaving only the non-mac `class wxMediaCtrl2 : public wxMediaCtrl { ... };` definition followed by the final `#endif /* wxMediaCtrl2_h */`. The resulting file keeps its `#ifndef`/`#endif` include guard pair balanced.
|
||||||
|
|
||||||
|
The file stays on disk because Win/Linux compile `wxMediaCtrl2.cpp`, which includes it.
|
||||||
|
|
||||||
|
- [ ] **Step 3: Grep for leftover references**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
grep -rn "wxMediaCtrl2.mm\|BambuPlayer/BambuPlayer.h\|BambuPlayer" src/slic3r --include="*.cpp" --include="*.h" --include="*.mm" --include="*.txt"
|
||||||
|
```
|
||||||
|
|
||||||
|
Expected: no hits in `src/slic3r/GUI` (ignore `localization/i18n/list.txt:196`, which lists the Win/Linux `wxMediaCtrl2.cpp` and stays).
|
||||||
|
|
||||||
|
- [ ] **Step 4: Rebuild the app**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cmake --build build_arm64 --config RelWithDebInfo --target OrcaSlicer
|
||||||
|
```
|
||||||
|
|
||||||
|
Expected: configure + compile + link succeed with the deleted files gone.
|
||||||
|
|
||||||
|
- [ ] **Step 5: Commit**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git add -A src/slic3r/GUI
|
||||||
|
git commit -m "refactor: remove old BambuPlayer-based media player from macOS"
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Task 4: Runtime verification on hardware
|
||||||
|
|
||||||
|
**Files:** none — manual verification.
|
||||||
|
|
||||||
|
**Interfaces:** consumes all prior tasks. Final gate: the new player must actually stream on a Mac.
|
||||||
|
|
||||||
|
- [ ] **Step 1: Launch the freshly built app**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
open build_arm64/src/RelWithDebInfo/OrcaSlicer.app
|
||||||
|
```
|
||||||
|
|
||||||
|
Expected: app launches normally; no crash in the network/device subsystem.
|
||||||
|
|
||||||
|
- [ ] **Step 2: Load the network plugin and open the Device tab**
|
||||||
|
|
||||||
|
Log in / ensure the network plugin (`libBambuSource.dylib`) loads, select a printer, open the Device tab (camera monitoring panel).
|
||||||
|
|
||||||
|
Expected: the camera preview area shows the idle image initially (no crash — this exercises `wxMediaCtrl3::SetIdleImage` and the `wxImage` load path on macOS for the first time).
|
||||||
|
|
||||||
|
- [ ] **Step 3: Start the stream and watch it render**
|
||||||
|
|
||||||
|
Click play / wait for `MediaPlayCtrl` to start the stream.
|
||||||
|
|
||||||
|
Expected: live video renders in the panel. Check the console/log output (`BOOST_LOG` goes to the terminal if run from it, or check the log file):
|
||||||
|
- `stat_log ...` lines appear (the `EVT_MEDIA_CTRL_STAT` path is live — proves the Bambu C API dlsym worked from `libBambuSource.dylib`);
|
||||||
|
- no repeated decode/error messages like `AVVideoDecoder: ...` or `can not find function ...` (proves `StaticBambuLib::get` resolved all Bambu functions);
|
||||||
|
- Stop/Play toggle works; idle image reappears on stop;
|
||||||
|
- window resize keeps aspect ratio (exercises `DoSetSize`/`adjust_frame_size`/`paintEvent`).
|
||||||
|
|
||||||
|
- [ ] **Step 4: Confirm the old player is really gone**
|
||||||
|
|
||||||
|
Expected: nothing in the logs references `BambuPlayer` (the ObjC class is no longer dlsym'd); the video path is entirely `wxMediaCtrl3` + `AVVideoDecoder`.
|
||||||
|
|
||||||
|
If a printer is unavailable, at minimum verify Steps 1–2 (launch + idle image) and note in the PR that live-stream verification needs hardware.
|
||||||
|
|
||||||
|
- [ ] **Step 5: Final review pass**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git log --oneline -6
|
||||||
|
git show --stat HEAD # and each of the three task commits
|
||||||
|
```
|
||||||
|
|
||||||
|
Expected: the last 4 commits are the design doc + the 3 implementation tasks (each task commit touches only its listed files). Review the diff for scope: no Linux/Windows changes beyond the two `EVT_MEDIA_CTRL_STAT` lines in Task 1, no `StatusPanel`/`MediaPlayCtrl` changes.
|
||||||
@@ -0,0 +1,110 @@
|
|||||||
|
# FFmpeg Media Player for macOS — Design
|
||||||
|
|
||||||
|
Date: 2026-08-14
|
||||||
|
Branch: `dev/ffmpeg-player-macos`
|
||||||
|
|
||||||
|
## Problem
|
||||||
|
|
||||||
|
The branch's new FFmpeg-based media player (`wxMediaCtrl3` + `AVVideoDecoder`) is used on
|
||||||
|
Windows and Linux, but macOS still runs the old player: `wxMediaCtrl2.mm`, an ObjC
|
||||||
|
`BambuPlayer` class dlsym'd from the Bambu network plugin that renders via CALayer.
|
||||||
|
On macOS, `wxMediaCtrl3` is currently aliased to `wxMediaCtrl2` and FFmpeg is not linked
|
||||||
|
into the app at all.
|
||||||
|
|
||||||
|
Goal: make macOS use the same FFmpeg player as Windows/Linux, linking the **static**
|
||||||
|
FFmpeg libraries from the deps build instead of dynamic ones.
|
||||||
|
|
||||||
|
## Current state (verified)
|
||||||
|
|
||||||
|
- New player (Win/Linux): `GUI/wxMediaCtrl3.cpp` + `GUI/AVVideoDecoder.cpp`. Decodes with
|
||||||
|
FFmpeg (libavcodec/libswscale/libavutil), renders frames into `wxImage` (non-Windows) /
|
||||||
|
`wxBitmap` (Windows) drawn in a `paintEvent`, feeds via the `Bambu_*` C API
|
||||||
|
(`BambuTunnel.h`, `BAMBU_DYNAMIC`) dlsym'd from the network plugin through
|
||||||
|
`StaticBambuLib::get()` (`GUI/Printer/PrinterFileSystem.cpp`, compiled on all platforms).
|
||||||
|
- Old player (macOS): `GUI/wxMediaCtrl2.mm` uses the ObjC `BambuPlayer` class found via
|
||||||
|
`dlsym(module, "OBJC_CLASS_$_BambuPlayer")` in `libBambuSource.dylib`.
|
||||||
|
- The macOS network plugin `libBambuSource.dylib` already exports the full Bambu C API
|
||||||
|
(verified with `nm`), so the new player needs zero plugin changes.
|
||||||
|
- FFmpeg linking in `src/slic3r/CMakeLists.txt` is guarded by `if (NOT APPLE)` —
|
||||||
|
macOS currently does not link FFmpeg.
|
||||||
|
- `deps/FFMPEG/FFMPEG.cmake`: non-MSVC branch builds FFmpeg from source with
|
||||||
|
`--enable-shared`. The existing arm64 deps build on the dev machine happened to be
|
||||||
|
configured with both static and shared enabled, so `libavcodec.a` / `libswscale.a` /
|
||||||
|
`libavutil.a` are already present at
|
||||||
|
`deps/build/arm64/OrcaSlicer_dep/usr/local/lib/`.
|
||||||
|
- `EVT_MEDIA_CTRL_STAT` is `wxDEFINE_EVENT`'d in `wxMediaCtrl2.cpp` (Win/Linux) and
|
||||||
|
`wxMediaCtrl2.mm` (macOS); the define in `wxMediaCtrl3.cpp` is commented out.
|
||||||
|
- `wxMediaCtrl2` is never instantiated anywhere on any platform — dead code.
|
||||||
|
- `StatusPanel` already creates `wxMediaCtrl3`; `MediaPlayCtrl` only uses the
|
||||||
|
`wxMediaCtrl3` interface (`Load/Play/Stop/GetState/GetVideoSize/GetLastError/SetIdleImage`),
|
||||||
|
so no UI-side changes are needed.
|
||||||
|
|
||||||
|
## Approach (approved)
|
||||||
|
|
||||||
|
**Reuse the shared player on macOS.** Compile the existing `wxMediaCtrl3.cpp` +
|
||||||
|
`AVVideoDecoder.cpp` on macOS so all three platforms run one implementation.
|
||||||
|
Rendering uses the existing `wxImage` → `DrawBitmap` paint path, identical to Linux.
|
||||||
|
Known trade-off: frames are scaled to the widget's logical (1x) size, so Retina is
|
||||||
|
slightly soft compared to the old CALayer player. Accepted for now; a Retina-aware
|
||||||
|
scaling follow-up is possible later.
|
||||||
|
|
||||||
|
Rejected alternative: a native CGImage/CALayer renderer for macOS — faster and
|
||||||
|
Retina-crisp, but adds a second render implementation to maintain.
|
||||||
|
|
||||||
|
## Changes
|
||||||
|
|
||||||
|
### 1. Enable the FFmpeg player on macOS (source)
|
||||||
|
|
||||||
|
- `GUI/wxMediaCtrl3.h`: remove the `#ifdef __WXMAC__` branch (lines 18–22) that aliases
|
||||||
|
`wxMediaCtrl3` → `wxMediaCtrl2`. macOS then compiles the real `wxMediaCtrl3` class,
|
||||||
|
including the `BAMBU_DYNAMIC` BambuTunnel path used on Linux.
|
||||||
|
- Event symbol fix: move `wxDEFINE_EVENT(EVT_MEDIA_CTRL_STAT, wxCommandEvent)` into
|
||||||
|
`wxMediaCtrl3.cpp` (uncomment the existing line) and remove it from
|
||||||
|
`wxMediaCtrl2.cpp`. One definition total in the lib; all three platforms resolve it.
|
||||||
|
|
||||||
|
### 2. Static FFmpeg linking (deps + app)
|
||||||
|
|
||||||
|
- `deps/FFMPEG/FFMPEG.cmake`: in the non-MSVC branch, pass
|
||||||
|
`--disable-shared --enable-static` when `APPLE`. Linux keeps `--enable-shared`;
|
||||||
|
Windows keeps its prebuilt shared DLL zips. Fresh macOS deps builds install only
|
||||||
|
`libavcodec.a` / `libswscale.a` / `libavutil.a` — no dylibs to bundle, no
|
||||||
|
rpath/install_name handling. (The existing local arm64 deps build already contains
|
||||||
|
the `.a` files, so no deps rebuild is strictly needed to try the change locally,
|
||||||
|
but a fresh CI deps build must produce them.)
|
||||||
|
- `src/slic3r/CMakeLists.txt`:
|
||||||
|
- APPLE branch of `SLIC3R_GUI_SOURCES`: add `GUI/wxMediaCtrl3.cpp`,
|
||||||
|
`GUI/wxMediaCtrl3.h`, `GUI/AVVideoDecoder.cpp`, `GUI/AVVideoDecoder.hpp`;
|
||||||
|
remove `GUI/wxMediaCtrl2.mm` and `GUI/wxMediaCtrl2.h` (the `.h` stays on
|
||||||
|
disk for the Win/Linux build of `wxMediaCtrl2.cpp`, but nothing on macOS
|
||||||
|
includes it after this change).
|
||||||
|
- Add an APPLE mirror of the `NOT APPLE` FFmpeg block: `find_library` for
|
||||||
|
`libavcodec.a`, `libswscale.a`, `libavutil.a` under `${CMAKE_PREFIX_PATH}/lib`
|
||||||
|
with `NO_DEFAULT_PATH`, link them (order avcodec → swscale → avutil), and add
|
||||||
|
`${CMAKE_PREFIX_PATH}/include` as a SYSTEM include directory. Deps are built with
|
||||||
|
`--disable-zlib` and no external codecs, so the three static libs link cleanly.
|
||||||
|
|
||||||
|
### 3. Remove the old player
|
||||||
|
|
||||||
|
- Delete `GUI/wxMediaCtrl2.mm` and `GUI/BambuPlayer/BambuPlayer.h` (header used only
|
||||||
|
by the `.mm`; the real `BambuPlayer` lives inside the network plugin).
|
||||||
|
- Remove the now-dead `__WXMAC__` section of `GUI/wxMediaCtrl2.h`.
|
||||||
|
- `wxMediaCtrl2.cpp` (Win/Linux) stays in the build as-is (dead but harmless; out of
|
||||||
|
scope to remove on this branch).
|
||||||
|
|
||||||
|
### 4. Verification
|
||||||
|
|
||||||
|
- Build on macOS: `cmake --build build_arm64` (or `build/arm64`).
|
||||||
|
- Confirm no dynamic FFmpeg dependency: `otool -L` on the app binary shows no `libav*`
|
||||||
|
dylib references.
|
||||||
|
- Runtime: with the network plugin loaded, the Device tab camera preview streams via
|
||||||
|
the FFmpeg player (check the device page / `MediaPlayCtrl`).
|
||||||
|
- macOS `ctest` still passes — static linking means no test-executable `.so` copying
|
||||||
|
hacks (unlike the Linux shared-lib setup).
|
||||||
|
|
||||||
|
## Out of scope
|
||||||
|
|
||||||
|
- Linux (shared libs, AppImage/flatpak bundling) and Windows (prebuilt DLL zips)
|
||||||
|
keep their current FFmpeg setup.
|
||||||
|
- Retina-aware frame scaling / native CGImage rendering (follow-up if visual quality
|
||||||
|
is judged insufficient).
|
||||||
|
- Audio streaming (neither player plays audio in this UI path).
|
||||||
@@ -193,7 +193,6 @@ src/slic3r/GUI/ObjColorDialog.cpp
|
|||||||
src/slic3r/GUI/SyncAmsInfoDialog.cpp
|
src/slic3r/GUI/SyncAmsInfoDialog.cpp
|
||||||
src/slic3r/GUI/WipeTowerDialog.cpp
|
src/slic3r/GUI/WipeTowerDialog.cpp
|
||||||
src/slic3r/GUI/wxExtensions.cpp
|
src/slic3r/GUI/wxExtensions.cpp
|
||||||
src/slic3r/GUI/wxMediaCtrl2.cpp
|
|
||||||
src/slic3r/GUI/WebUserLoginDialog.cpp
|
src/slic3r/GUI/WebUserLoginDialog.cpp
|
||||||
src/slic3r/GUI/WebGuideDialog.cpp
|
src/slic3r/GUI/WebGuideDialog.cpp
|
||||||
src/slic3r/GUI/KBShortcutsDialog.hpp
|
src/slic3r/GUI/KBShortcutsDialog.hpp
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 171 KiB After Width: | Height: | Size: 579 KiB |
@@ -318,6 +318,12 @@ modules:
|
|||||||
sha256: 0ba163956f2d468b19a91b96c5aba66ee9610843ea41dda628ea44cdafde7db7
|
sha256: 0ba163956f2d468b19a91b96c5aba66ee9610843ea41dda628ea44cdafde7db7
|
||||||
dest: external-packages/wxInspector
|
dest: external-packages/wxInspector
|
||||||
|
|
||||||
|
# FFmpeg n7.0.3
|
||||||
|
- type: file
|
||||||
|
url: https://github.com/FFmpeg/FFmpeg/archive/refs/tags/n7.0.3.tar.gz
|
||||||
|
sha256: deedcabe339165214a3637df4c86a507aef0d793cf8774ff68735f4737e8ddbc
|
||||||
|
dest: external-packages/FFMPEG
|
||||||
|
|
||||||
# ---------------------------------------------------------------
|
# ---------------------------------------------------------------
|
||||||
# Fallback archives for deps normally provided by the GNOME SDK.
|
# Fallback archives for deps normally provided by the GNOME SDK.
|
||||||
# These are only used if find_package() fails to locate them.
|
# These are only used if find_package() fails to locate them.
|
||||||
|
|||||||
@@ -25,6 +25,9 @@ export REQUIRED_DEV_PACKAGES=(
|
|||||||
wayland-protocols
|
wayland-protocols
|
||||||
webkit2gtk-4.1
|
webkit2gtk-4.1
|
||||||
wget
|
wget
|
||||||
|
pkgconf
|
||||||
|
yasm
|
||||||
|
nasm
|
||||||
)
|
)
|
||||||
|
|
||||||
if [[ -n "$UPDATE_LIB" ]]
|
if [[ -n "$UPDATE_LIB" ]]
|
||||||
|
|||||||
@@ -25,6 +25,9 @@ export REQUIRED_DEV_PACKAGES=(
|
|||||||
wayland-protocols
|
wayland-protocols
|
||||||
webkit2gtk
|
webkit2gtk
|
||||||
wget
|
wget
|
||||||
|
pkgconf
|
||||||
|
yasm
|
||||||
|
nasm
|
||||||
)
|
)
|
||||||
|
|
||||||
if [[ -n "$UPDATE_LIB" ]]
|
if [[ -n "$UPDATE_LIB" ]]
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ export REQUIRED_BUNDLES=(
|
|||||||
perl-basic
|
perl-basic
|
||||||
texinfo
|
texinfo
|
||||||
wget
|
wget
|
||||||
|
nasm
|
||||||
)
|
)
|
||||||
|
|
||||||
if [[ -n "$UPDATE_LIB" ]]
|
if [[ -n "$UPDATE_LIB" ]]
|
||||||
|
|||||||
@@ -27,6 +27,9 @@ REQUIRED_DEV_PACKAGES=(
|
|||||||
ninja-build
|
ninja-build
|
||||||
texinfo
|
texinfo
|
||||||
wget
|
wget
|
||||||
|
pkgconf
|
||||||
|
yasm
|
||||||
|
nasm
|
||||||
)
|
)
|
||||||
|
|
||||||
if [[ -n "$UPDATE_LIB" ]]
|
if [[ -n "$UPDATE_LIB" ]]
|
||||||
|
|||||||
@@ -31,6 +31,9 @@ REQUIRED_DEV_PACKAGES=(
|
|||||||
webkit2gtk4.1-devel
|
webkit2gtk4.1-devel
|
||||||
wget
|
wget
|
||||||
libcurl-devel
|
libcurl-devel
|
||||||
|
pkgconf
|
||||||
|
yasm
|
||||||
|
nasm
|
||||||
)
|
)
|
||||||
|
|
||||||
if [[ -n "$UPDATE_LIB" ]]
|
if [[ -n "$UPDATE_LIB" ]]
|
||||||
|
|||||||
@@ -32,6 +32,9 @@ REQUIRED_DEV_PACKAGES=(
|
|||||||
sys-devel/m4
|
sys-devel/m4
|
||||||
virtual/libudev
|
virtual/libudev
|
||||||
x11-libs/gtk+:3
|
x11-libs/gtk+:3
|
||||||
|
dev-util/pkgconf
|
||||||
|
dev-lang/yasm
|
||||||
|
dev-lang/nasm
|
||||||
)
|
)
|
||||||
|
|
||||||
if [[ -n "$UPDATE_LIB" ]]
|
if [[ -n "$UPDATE_LIB" ]]
|
||||||
|
|||||||
@@ -30,6 +30,9 @@ REQUIRED_DEV_PACKAGES=(
|
|||||||
webkit2gtk4-devel
|
webkit2gtk4-devel
|
||||||
wget
|
wget
|
||||||
libcurl-devel
|
libcurl-devel
|
||||||
|
pkgconf
|
||||||
|
yasm
|
||||||
|
nasm
|
||||||
)
|
)
|
||||||
|
|
||||||
if [[ -n "$UPDATE_LIB" ]]
|
if [[ -n "$UPDATE_LIB" ]]
|
||||||
|
|||||||
@@ -294,6 +294,16 @@ if (WIN32)
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
else ()
|
else ()
|
||||||
|
if (NOT APPLE)
|
||||||
|
set(output_sos_Release "")
|
||||||
|
set(output_sos_Debug "")
|
||||||
|
add_custom_target(OrcaSlicerSosCopy ALL DEPENDS OrcaSlicer)
|
||||||
|
if ("${CMAKE_BUILD_TYPE}" STREQUAL "Debug")
|
||||||
|
orcaslicer_copy_sos(OrcaSlicerSosCopy "Debug" "d" output_sos_Debug)
|
||||||
|
else()
|
||||||
|
orcaslicer_copy_sos(OrcaSlicerSosCopy "Release" "" output_sos_Release)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
if (APPLE AND NOT CMAKE_MACOSX_BUNDLE)
|
if (APPLE AND NOT CMAKE_MACOSX_BUNDLE)
|
||||||
# On OSX, the name of the binary matches the name of the Application.
|
# On OSX, the name of the binary matches the name of the Application.
|
||||||
add_custom_command(TARGET OrcaSlicer POST_BUILD
|
add_custom_command(TARGET OrcaSlicer POST_BUILD
|
||||||
@@ -372,5 +382,9 @@ if (WIN32)
|
|||||||
install(FILES ${output_dlls_${build_type}} DESTINATION ".")
|
install(FILES ${output_dlls_${build_type}} DESTINATION ".")
|
||||||
install(DIRECTORY "${CMAKE_PREFIX_PATH}/libpython/" DESTINATION "python")
|
install(DIRECTORY "${CMAKE_PREFIX_PATH}/libpython/" DESTINATION "python")
|
||||||
else ()
|
else ()
|
||||||
|
if (APPLE)
|
||||||
|
else()
|
||||||
|
install(FILES ${output_sos_${build_type}} DESTINATION "${CMAKE_INSTALL_PREFIX}")
|
||||||
|
endif()
|
||||||
install(TARGETS OrcaSlicer RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}" BUNDLE DESTINATION ${CMAKE_INSTALL_BINDIR})
|
install(TARGETS OrcaSlicer RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}" BUNDLE DESTINATION ${CMAKE_INSTALL_BINDIR})
|
||||||
endif ()
|
endif ()
|
||||||
|
|||||||
@@ -83,6 +83,10 @@ copy_shared_object_to_dir() {
|
|||||||
src_real="$(readlink -f "$src")"
|
src_real="$(readlink -f "$src")"
|
||||||
dst_name="$(basename "$src_real")"
|
dst_name="$(basename "$src_real")"
|
||||||
mkdir -p "$dst_dir"
|
mkdir -p "$dst_dir"
|
||||||
|
if [ "$src_real" = "$dst_dir/$dst_name" ]; then
|
||||||
|
# Already bundled; the dependency resolved from the bundle directory.
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
cp -fL "$src_real" "$dst_dir/$dst_name"
|
cp -fL "$src_real" "$dst_dir/$dst_name"
|
||||||
|
|
||||||
if [ -L "$src" ]; then
|
if [ -L "$src" ]; then
|
||||||
@@ -96,12 +100,23 @@ copy_shared_object_to_dir() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bundle_dependency_closure() {
|
bundle_dependency_closure() {
|
||||||
local dst_dir="$1"
|
local dst_dir
|
||||||
|
dst_dir="$(cd -- "$1" && pwd)"
|
||||||
shift
|
shift
|
||||||
|
|
||||||
local -a queue=("$@")
|
local -a queue=("$@")
|
||||||
local target dep dep_real copied_path
|
local target dep dep_real dep_key copied_path
|
||||||
declare -A seen=()
|
declare -A seen=()
|
||||||
|
# Dependencies are resolved with ldd, which only searches the default
|
||||||
|
# loader path. Deps-built shared libraries (e.g. the FFmpeg stack) are not
|
||||||
|
# installed there and carry no RUNPATH of their own, so once copied into
|
||||||
|
# the bundle ldd can no longer resolve one sibling from another
|
||||||
|
# (libavcodec -> libavutil) and reports it as missing. Extend the loader
|
||||||
|
# path with the bundle directory plus the source directories of files
|
||||||
|
# already bundled, so every library that was resolved once keeps resolving
|
||||||
|
# for its own dependencies. The audit script does the same
|
||||||
|
# (scripts/check_appimage_libs.sh).
|
||||||
|
local -a search_dirs=("$dst_dir")
|
||||||
|
|
||||||
while [ ${#queue[@]} -gt 0 ]; do
|
while [ ${#queue[@]} -gt 0 ]; do
|
||||||
target="${queue[0]}"
|
target="${queue[0]}"
|
||||||
@@ -122,17 +137,24 @@ bundle_dependency_closure() {
|
|||||||
continue
|
continue
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ -n "${seen[$dep_real]}" ]; then
|
# Key dedup on the bundled file rather than the source path: once
|
||||||
|
# ldd resolves a library from the bundle directory (via the
|
||||||
|
# LD_LIBRARY_PATH above) its path is a dst_dir path, which differs
|
||||||
|
# from the source path the first resolution returned. Keying on
|
||||||
|
# the source path would re-copy the file onto itself.
|
||||||
|
dep_key="$dst_dir/$(basename "$dep_real")"
|
||||||
|
if [ -n "${seen[$dep_key]}" ]; then
|
||||||
continue
|
continue
|
||||||
fi
|
fi
|
||||||
|
|
||||||
seen[$dep_real]=1
|
seen[$dep_key]=1
|
||||||
copy_shared_object_to_dir "$dep" "$dst_dir"
|
copy_shared_object_to_dir "$dep" "$dst_dir"
|
||||||
|
search_dirs+=("$(dirname "$dep_real")")
|
||||||
copied_path="$dst_dir/$(basename "$dep_real")"
|
copied_path="$dst_dir/$(basename "$dep_real")"
|
||||||
if [ -e "$copied_path" ]; then
|
if [ -e "$copied_path" ]; then
|
||||||
queue+=("$copied_path")
|
queue+=("$copied_path")
|
||||||
fi
|
fi
|
||||||
done < <(appimage_list_direct_dependencies "$target")
|
done < <(LD_LIBRARY_PATH="$(IFS=:; printf '%s' "${search_dirs[*]}")${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}" appimage_list_direct_dependencies "$target")
|
||||||
done
|
done
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -229,7 +229,7 @@ public:
|
|||||||
m_bbox(bbox.min - Point(SCALED_EPSILON, SCALED_EPSILON), bbox.max + Point(SCALED_EPSILON, SCALED_EPSILON)) {}
|
m_bbox(bbox.min - Point(SCALED_EPSILON, SCALED_EPSILON), bbox.max + Point(SCALED_EPSILON, SCALED_EPSILON)) {}
|
||||||
size_t idx() const { return m_idx; }
|
size_t idx() const { return m_idx; }
|
||||||
const BoundingBox& bbox() const { return m_bbox; }
|
const BoundingBox& bbox() const { return m_bbox; }
|
||||||
Point centroid() const { return (m_bbox.min() + m_bbox.max() / 2); }
|
Point centroid() const { return (m_bbox.min() + m_bbox.max()) / 2; }
|
||||||
private:
|
private:
|
||||||
size_t m_idx;
|
size_t m_idx;
|
||||||
BoundingBox m_bbox;
|
BoundingBox m_bbox;
|
||||||
|
|||||||
@@ -57,24 +57,24 @@ void ArcFitter::do_arc_fitting(const Points& points, std::vector<PathFittingData
|
|||||||
//BBS: can be fit as arc, then save arc data temperarily
|
//BBS: can be fit as arc, then save arc data temperarily
|
||||||
last_arc = target_arc;
|
last_arc = target_arc;
|
||||||
if (back_index == points.size() - 1) {
|
if (back_index == points.size() - 1) {
|
||||||
result.emplace_back(std::move(PathFittingData{ front_index,
|
result.emplace_back(PathFittingData{ front_index,
|
||||||
back_index,
|
back_index,
|
||||||
last_arc.direction == ArcDirection::Arc_Dir_CCW ? EMovePathType::Arc_move_ccw : EMovePathType::Arc_move_cw,
|
last_arc.direction == ArcDirection::Arc_Dir_CCW ? EMovePathType::Arc_move_ccw : EMovePathType::Arc_move_cw,
|
||||||
last_arc }));
|
last_arc });
|
||||||
front_index = back_index;
|
front_index = back_index;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (back_index - front_index > 2) {
|
if (back_index - front_index > 2) {
|
||||||
//BBS: althought current point_stack can't be fit as arc,
|
//BBS: althought current point_stack can't be fit as arc,
|
||||||
//but previous must can be fit if removing the top in stack, so save last arc
|
//but previous must can be fit if removing the top in stack, so save last arc
|
||||||
result.emplace_back(std::move(PathFittingData{ front_index,
|
result.emplace_back(PathFittingData{ front_index,
|
||||||
back_index - 1,
|
back_index - 1,
|
||||||
last_arc.direction == ArcDirection::Arc_Dir_CCW ? EMovePathType::Arc_move_ccw : EMovePathType::Arc_move_cw,
|
last_arc.direction == ArcDirection::Arc_Dir_CCW ? EMovePathType::Arc_move_ccw : EMovePathType::Arc_move_cw,
|
||||||
last_arc }));
|
last_arc });
|
||||||
} else {
|
} else {
|
||||||
//BBS: save the first segment as line move when 3 point-line can't be fit as arc move
|
//BBS: save the first segment as line move when 3 point-line can't be fit as arc move
|
||||||
if (result.empty() || result.back().path_type != EMovePathType::Linear_move)
|
if (result.empty() || result.back().path_type != EMovePathType::Linear_move)
|
||||||
result.emplace_back(std::move(PathFittingData{front_index, front_index + 1, EMovePathType::Linear_move, ArcSegment()}));
|
result.emplace_back(PathFittingData{front_index, front_index + 1, EMovePathType::Linear_move, ArcSegment()});
|
||||||
else if(result.back().path_type == EMovePathType::Linear_move)
|
else if(result.back().path_type == EMovePathType::Linear_move)
|
||||||
result.back().end_point_index = front_index + 1;
|
result.back().end_point_index = front_index + 1;
|
||||||
}
|
}
|
||||||
@@ -87,7 +87,7 @@ void ArcFitter::do_arc_fitting(const Points& points, std::vector<PathFittingData
|
|||||||
//BBS: handle the remain data
|
//BBS: handle the remain data
|
||||||
if (front_index != back_index) {
|
if (front_index != back_index) {
|
||||||
if (result.empty() || result.back().path_type != EMovePathType::Linear_move)
|
if (result.empty() || result.back().path_type != EMovePathType::Linear_move)
|
||||||
result.emplace_back(std::move(PathFittingData{front_index, back_index, EMovePathType::Linear_move, ArcSegment()}));
|
result.emplace_back(PathFittingData{front_index, back_index, EMovePathType::Linear_move, ArcSegment()});
|
||||||
else if (result.back().path_type == EMovePathType::Linear_move)
|
else if (result.back().path_type == EMovePathType::Linear_move)
|
||||||
result.back().end_point_index = back_index;
|
result.back().end_point_index = back_index;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,8 +13,8 @@ Slic3r::Polylines Paths64_to_polylines(const Clipper2Lib::Paths64& in)
|
|||||||
Slic3r::Points points;
|
Slic3r::Points points;
|
||||||
points.reserve(path64.size());
|
points.reserve(path64.size());
|
||||||
for (const Clipper2Lib::Point64& point64 : path64)
|
for (const Clipper2Lib::Point64& point64 : path64)
|
||||||
points.emplace_back(std::move(Slic3r::Point(point64.x, point64.y)));
|
points.emplace_back(Slic3r::Point(point64.x, point64.y));
|
||||||
out.emplace_back(std::move(Slic3r::Polyline(points)));
|
out.emplace_back(Slic3r::Polyline(points));
|
||||||
}
|
}
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
@@ -29,7 +29,7 @@ Clipper2Lib::Paths64 Slic3rPoints_to_Paths64(const Container& in)
|
|||||||
Clipper2Lib::Path64 path;
|
Clipper2Lib::Path64 path;
|
||||||
path.reserve(item.size());
|
path.reserve(item.size());
|
||||||
for (const Slic3r::Point& point : item.points)
|
for (const Slic3r::Point& point : item.points)
|
||||||
path.emplace_back(std::move(Clipper2Lib::Point64(point.x(), point.y())));
|
path.emplace_back(Clipper2Lib::Point64(point.x(), point.y()));
|
||||||
out.emplace_back(std::move(path));
|
out.emplace_back(std::move(path));
|
||||||
}
|
}
|
||||||
return out;
|
return out;
|
||||||
@@ -44,7 +44,7 @@ Points Path64ToPoints(const Clipper2Lib::Path64& path64)
|
|||||||
{
|
{
|
||||||
Points points;
|
Points points;
|
||||||
points.reserve(path64.size());
|
points.reserve(path64.size());
|
||||||
for (const Clipper2Lib::Point64 &point64 : path64) points.emplace_back(std::move(Slic3r::Point(point64.x, point64.y)));
|
for (const Clipper2Lib::Point64 &point64 : path64) points.emplace_back(Slic3r::Point(point64.x, point64.y));
|
||||||
return points;
|
return points;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -99,7 +99,7 @@ Clipper2Lib::Paths64 Slic3rPolygons_to_Paths64(const Polygons &in)
|
|||||||
for (const Polygon &poly : in) {
|
for (const Polygon &poly : in) {
|
||||||
Clipper2Lib::Path64 path;
|
Clipper2Lib::Path64 path;
|
||||||
path.reserve(poly.points.size());
|
path.reserve(poly.points.size());
|
||||||
for (const Slic3r::Point &point : poly.points) path.emplace_back(std::move(Clipper2Lib::Point64(point.x(), point.y())));
|
for (const Slic3r::Point &point : poly.points) path.emplace_back(Clipper2Lib::Point64(point.x(), point.y()));
|
||||||
out.emplace_back(std::move(path));
|
out.emplace_back(std::move(path));
|
||||||
}
|
}
|
||||||
return out;
|
return out;
|
||||||
@@ -114,7 +114,7 @@ Clipper2Lib::Paths64 Slic3rExPolygons_to_Paths64(const ExPolygons& in)
|
|||||||
const auto &poly = expolygon.contour_or_hole(i);
|
const auto &poly = expolygon.contour_or_hole(i);
|
||||||
Clipper2Lib::Path64 path;
|
Clipper2Lib::Path64 path;
|
||||||
path.reserve(poly.points.size());
|
path.reserve(poly.points.size());
|
||||||
for (const Slic3r::Point &point : poly.points) path.emplace_back(std::move(Clipper2Lib::Point64(point.x(), point.y())));
|
for (const Slic3r::Point &point : poly.points) path.emplace_back(Clipper2Lib::Point64(point.x(), point.y()));
|
||||||
out.emplace_back(std::move(path));
|
out.emplace_back(std::move(path));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -134,8 +134,8 @@ Polylines _clipper2_pl_open(Clipper2Lib::ClipType clipType, const Slic3r::Polyli
|
|||||||
|
|
||||||
Slic3r::Polylines out;
|
Slic3r::Polylines out;
|
||||||
out.reserve(solution.size() + solution_open.size());
|
out.reserve(solution.size() + solution_open.size());
|
||||||
polylines_append(out, std::move(Paths64_to_polylines(solution)));
|
polylines_append(out, Paths64_to_polylines(solution));
|
||||||
polylines_append(out, std::move(Paths64_to_polylines(solution_open)));
|
polylines_append(out, Paths64_to_polylines(solution_open));
|
||||||
|
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -55,9 +55,9 @@ bool load_obj(const char *path, TriangleMesh *meshptr, ObjInfo& obj_info, std::s
|
|||||||
boost::filesystem::path temp_mtl_path(mtl_file);
|
boost::filesystem::path temp_mtl_path(mtl_file);
|
||||||
mtl_path = temp_mtl_path;
|
mtl_path = temp_mtl_path;
|
||||||
}
|
}
|
||||||
auto _mtl_path = mtl_name_is_path ? mtl_abs_path.string().c_str() : mtl_path.string().c_str();
|
const std::string _mtl_path = (mtl_name_is_path ? mtl_abs_path : mtl_path).string();
|
||||||
if (boost::filesystem::exists(mtl_name_is_path ? mtl_abs_path : mtl_path)) {
|
if (boost::filesystem::exists(mtl_name_is_path ? mtl_abs_path : mtl_path)) {
|
||||||
if (!ObjParser::mtlparse(_mtl_path, mtl_data)) {
|
if (!ObjParser::mtlparse(_mtl_path.c_str(), mtl_data)) {
|
||||||
BOOST_LOG_TRIVIAL(error) << "load_obj:load_mtl: failed to parse " << _mtl_path;
|
BOOST_LOG_TRIVIAL(error) << "load_obj:load_mtl: failed to parse " << _mtl_path;
|
||||||
message = _L("load mtl in obj: failed to parse");
|
message = _L("load mtl in obj: failed to parse");
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -111,14 +111,19 @@ bool StepPreProcessor::isUtf8File(const char* path)
|
|||||||
bool StepPreProcessor::isUtf8(const std::string str)
|
bool StepPreProcessor::isUtf8(const std::string str)
|
||||||
{
|
{
|
||||||
size_t num = 0;
|
size_t num = 0;
|
||||||
int i = 0;
|
size_t i = 0;
|
||||||
while (i < str.length()) {
|
while (i < str.length()) {
|
||||||
if ((str[i] & 0x80) == 0x00) {
|
const unsigned char lead = static_cast<unsigned char>(str[i]);
|
||||||
|
if ((lead & 0x80) == 0x00) {
|
||||||
i++;
|
i++;
|
||||||
} else if ((num = preNum(str[i])) > 2) {
|
// preNum() counts the leading 1 bits, and a multi-byte sequence is 2 to 4
|
||||||
|
// bytes long, so anything outside that range is not a lead byte.
|
||||||
|
} else if ((num = preNum(lead)) >= 2 && num <= 4) {
|
||||||
|
if (i + num > str.length())
|
||||||
|
return false;
|
||||||
i++;
|
i++;
|
||||||
for (int j = 0; j < num - 1; j++) {
|
for (size_t j = 0; j < num - 1; j++) {
|
||||||
if ((str[i] & 0xc0) != 0x80)
|
if ((static_cast<unsigned char>(str[i]) & 0xc0) != 0x80)
|
||||||
return false;
|
return false;
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
@@ -132,15 +137,20 @@ bool StepPreProcessor::isUtf8(const std::string str)
|
|||||||
bool StepPreProcessor::isGBK(const std::string str) {
|
bool StepPreProcessor::isGBK(const std::string str) {
|
||||||
size_t i = 0;
|
size_t i = 0;
|
||||||
while (i < str.length()) {
|
while (i < str.length()) {
|
||||||
if (str[i] <= 0x7f) {
|
// char is signed here, so every byte compares <= 0x7f unless widened first.
|
||||||
|
const unsigned char lead = static_cast<unsigned char>(str[i]);
|
||||||
|
if (lead <= 0x7f) {
|
||||||
i++;
|
i++;
|
||||||
continue;
|
continue;
|
||||||
} else {
|
} else {
|
||||||
if (str[i] >= 0x81 &&
|
if (i + 1 >= str.length())
|
||||||
str[i] <= 0xfe &&
|
return false;
|
||||||
str[i + 1] >= 0x40 &&
|
const unsigned char trail = static_cast<unsigned char>(str[i + 1]);
|
||||||
str[i + 1] <= 0xfe &&
|
if (lead >= 0x81 &&
|
||||||
str[i + 1] != 0xf7) {
|
lead <= 0xfe &&
|
||||||
|
trail >= 0x40 &&
|
||||||
|
trail <= 0xfe &&
|
||||||
|
trail != 0xf7) {
|
||||||
i += 2;
|
i += 2;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -586,7 +596,7 @@ Step::Step_Status Step::mesh(Model* model,
|
|||||||
for (Standard_Integer aNodeIter = 1; aNodeIter <= aTriangulation->NbNodes(); ++aNodeIter) {
|
for (Standard_Integer aNodeIter = 1; aNodeIter <= aTriangulation->NbNodes(); ++aNodeIter) {
|
||||||
gp_Pnt aPnt = aTriangulation->Node(aNodeIter);
|
gp_Pnt aPnt = aTriangulation->Node(aNodeIter);
|
||||||
aPnt.Transform(aTrsf);
|
aPnt.Transform(aTrsf);
|
||||||
points.emplace_back(std::move(Vec3f(aPnt.X(), aPnt.Y(), aPnt.Z())));
|
points.emplace_back(Vec3f(aPnt.X(), aPnt.Y(), aPnt.Z()));
|
||||||
}
|
}
|
||||||
// BBS: copy triangles
|
// BBS: copy triangles
|
||||||
const TopAbs_Orientation anOrientation = anExpSF.Current().Orientation();
|
const TopAbs_Orientation anOrientation = anExpSF.Current().Orientation();
|
||||||
|
|||||||
@@ -8963,7 +8963,7 @@ private:
|
|||||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << " inital and interval = " << m_interval;
|
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << " inital and interval = " << m_interval;
|
||||||
m_next_backup = boost::get_system_time() + boost::posix_time::seconds(m_interval);
|
m_next_backup = boost::get_system_time() + boost::posix_time::seconds(m_interval);
|
||||||
boost::unique_lock lock(m_mutex);
|
boost::unique_lock lock(m_mutex);
|
||||||
m_thread = std::move(boost::thread(boost::ref(*this)));
|
m_thread = boost::thread(boost::ref(*this));
|
||||||
}
|
}
|
||||||
|
|
||||||
~_BBS_Backup_Manager() {
|
~_BBS_Backup_Manager() {
|
||||||
|
|||||||
@@ -352,7 +352,7 @@ bool load_svg(const char *path, Model *model, std::string &message)
|
|||||||
for (Standard_Integer aNodeIter = 1; aNodeIter <= aTriangulation->NbNodes(); ++aNodeIter) {
|
for (Standard_Integer aNodeIter = 1; aNodeIter <= aTriangulation->NbNodes(); ++aNodeIter) {
|
||||||
gp_Pnt aPnt = aTriangulation->Node(aNodeIter);
|
gp_Pnt aPnt = aTriangulation->Node(aNodeIter);
|
||||||
aPnt.Transform(aTrsf);
|
aPnt.Transform(aTrsf);
|
||||||
points.emplace_back(std::move(Vec3f(aPnt.X(), aPnt.Y(), aPnt.Z())));
|
points.emplace_back(Vec3f(aPnt.X(), aPnt.Y(), aPnt.Z()));
|
||||||
}
|
}
|
||||||
// BBS: copy triangles
|
// BBS: copy triangles
|
||||||
const TopAbs_Orientation anOrientation = anExpSF.Current().Orientation();
|
const TopAbs_Orientation anOrientation = anExpSF.Current().Orientation();
|
||||||
|
|||||||
@@ -9079,7 +9079,7 @@ bool GCode::needs_retraction(const Polyline &travel, ExtrusionRole role, LiftTyp
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
Polygons temp;
|
Polygons temp;
|
||||||
temp.emplace_back(std::move(instance_bbox.polygon()));
|
temp.emplace_back(instance_bbox.polygon());
|
||||||
if (intersection_pl(travel, temp).empty())
|
if (intersection_pl(travel, temp).empty())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
|||||||
@@ -78,7 +78,7 @@ struct PlateBBoxData
|
|||||||
int first_extruder = 0;
|
int first_extruder = 0;
|
||||||
float nozzle_diameter = 0.4;
|
float nozzle_diameter = 0.4;
|
||||||
std::string bed_type;
|
std::string bed_type;
|
||||||
float first_layer_time;
|
float first_layer_time = 0.0f;
|
||||||
// version 1: use view type ColorPrint (filament color)
|
// version 1: use view type ColorPrint (filament color)
|
||||||
// version 2: use view type FilamentId (filament id)
|
// version 2: use view type FilamentId (filament id)
|
||||||
int version = 2;
|
int version = 2;
|
||||||
|
|||||||
@@ -165,7 +165,6 @@ public:
|
|||||||
|
|
||||||
|
|
||||||
//BBS
|
//BBS
|
||||||
unsigned int m_last_additional_fan_speed;
|
|
||||||
int m_last_bed_temperature;
|
int m_last_bed_temperature;
|
||||||
bool m_last_bed_temperature_reached;
|
bool m_last_bed_temperature_reached;
|
||||||
double m_lifted;
|
double m_lifted;
|
||||||
|
|||||||
@@ -352,7 +352,7 @@ void segment(CGALMesh& src, std::vector<CGALMesh>& dst, double smoothing_alpha =
|
|||||||
//}
|
//}
|
||||||
//else
|
//else
|
||||||
{
|
{
|
||||||
dst.emplace_back(std::move(CGALMesh(out)));
|
dst.emplace_back(CGALMesh(out));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//if (mesh_merged.is_empty() == false) {
|
//if (mesh_merged.is_empty() == false) {
|
||||||
@@ -371,7 +371,7 @@ std::vector<TriangleMesh> segment(const TriangleMesh& src, double smoothing_alph
|
|||||||
std::vector<TriangleMesh> out_meshes;
|
std::vector<TriangleMesh> out_meshes;
|
||||||
for (auto& outf_cgal_mesh: out_cgal_meshes)
|
for (auto& outf_cgal_mesh: out_cgal_meshes)
|
||||||
{
|
{
|
||||||
out_meshes.emplace_back(std::move(cgal_to_triangle_mesh(outf_cgal_mesh.m)));
|
out_meshes.emplace_back(cgal_to_triangle_mesh(outf_cgal_mesh.m));
|
||||||
}
|
}
|
||||||
|
|
||||||
return out_meshes;
|
return out_meshes;
|
||||||
|
|||||||
@@ -261,7 +261,7 @@ static void add_textured_mesh_to_model(Model& model, const TexturedMesh& tex_mes
|
|||||||
its_remove_degenerate_faces(its);
|
its_remove_degenerate_faces(its);
|
||||||
its_compactify_vertices(its);
|
its_compactify_vertices(its);
|
||||||
|
|
||||||
model.add_object(object_name.c_str(), input_file.c_str(), std::move(TriangleMesh(std::move(its))));
|
model.add_object(object_name.c_str(), input_file.c_str(), TriangleMesh(std::move(its)));
|
||||||
}
|
}
|
||||||
|
|
||||||
Model Model::read_from_file(const std::string& input_file,
|
Model Model::read_from_file(const std::string& input_file,
|
||||||
|
|||||||
@@ -3790,7 +3790,7 @@ std::vector<Polygons> Print::get_extruder_printable_polygons() const
|
|||||||
Polygons ploys = {Polygon::new_scale(e_printable_area)};
|
Polygons ploys = {Polygon::new_scale(e_printable_area)};
|
||||||
extruder_printable_polys.emplace_back(ploys);
|
extruder_printable_polys.emplace_back(ploys);
|
||||||
}
|
}
|
||||||
return std::move(extruder_printable_polys);
|
return extruder_printable_polys;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<Polygons> Print::get_extruder_unprintable_polygons() const
|
std::vector<Polygons> Print::get_extruder_unprintable_polygons() const
|
||||||
@@ -3803,7 +3803,7 @@ std::vector<Polygons> Print::get_extruder_unprintable_polygons() const
|
|||||||
Polygons ploys = diff(printable_poly, Polygon::new_scale(e_printable_area));
|
Polygons ploys = diff(printable_poly, Polygon::new_scale(e_printable_area));
|
||||||
extruder_unprintable_polys.emplace_back(ploys);
|
extruder_unprintable_polys.emplace_back(ploys);
|
||||||
}
|
}
|
||||||
return std::move(extruder_unprintable_polys);
|
return extruder_unprintable_polys;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t Print::get_extruder_id(unsigned int filament_id) const
|
size_t Print::get_extruder_id(unsigned int filament_id) const
|
||||||
|
|||||||
@@ -906,7 +906,7 @@ void PrintObject::detect_overhangs_for_lift()
|
|||||||
Layer& lower_layer = *layer.lower_layer;
|
Layer& lower_layer = *layer.lower_layer;
|
||||||
|
|
||||||
ExPolygons overhangs = diff_ex(layer.lslices, offset_ex(lower_layer.lslices, scale_(min_overlap)));
|
ExPolygons overhangs = diff_ex(layer.lslices, offset_ex(lower_layer.lslices, scale_(min_overlap)));
|
||||||
layer.loverhangs = std::move(offset2_ex(overhangs, -0.1f * scale_(line_width), 0.1f * scale_(line_width)));
|
layer.loverhangs = offset2_ex(overhangs, -0.1f * scale_(line_width), 0.1f * scale_(line_width));
|
||||||
layer.loverhangs_bbox = get_extents(layer.loverhangs);
|
layer.loverhangs_bbox = get_extents(layer.loverhangs);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -199,7 +199,7 @@ static void MakeMesh(TopoDS_Shape& theSolid, TriangleMesh& theMesh)
|
|||||||
for (Standard_Integer aNodeIter = 1; aNodeIter <= aTriangulation->NbNodes(); ++aNodeIter) {
|
for (Standard_Integer aNodeIter = 1; aNodeIter <= aTriangulation->NbNodes(); ++aNodeIter) {
|
||||||
gp_Pnt aPnt = aTriangulation->Node(aNodeIter);
|
gp_Pnt aPnt = aTriangulation->Node(aNodeIter);
|
||||||
aPnt.Transform(aTrsf);
|
aPnt.Transform(aTrsf);
|
||||||
points.emplace_back(std::move(Vec3f(aPnt.X(), aPnt.Y(), aPnt.Z())));
|
points.emplace_back(Vec3f(aPnt.X(), aPnt.Y(), aPnt.Z()));
|
||||||
}
|
}
|
||||||
//BBS: copy triangles
|
//BBS: copy triangles
|
||||||
const TopAbs_Orientation anOrientation = anExpSF.Current().Orientation();
|
const TopAbs_Orientation anOrientation = anExpSF.Current().Orientation();
|
||||||
|
|||||||
@@ -842,7 +842,7 @@ void TreeSupport::detect_overhangs(bool check_support_necessity/* = false*/)
|
|||||||
|
|
||||||
// normal overhang
|
// normal overhang
|
||||||
ExPolygons lower_layer_offseted = offset_ex(lower_polys, support_offset_scaled, SUPPORT_SURFACES_OFFSET_PARAMETERS);
|
ExPolygons lower_layer_offseted = offset_ex(lower_polys, support_offset_scaled, SUPPORT_SURFACES_OFFSET_PARAMETERS);
|
||||||
overhangs_all_layers[layer_nr] = std::move(diff_ex(curr_polys, lower_layer_offseted));
|
overhangs_all_layers[layer_nr] = diff_ex(curr_polys, lower_layer_offseted);
|
||||||
|
|
||||||
double duration{ std::chrono::duration_cast<second_>(clock_::now() - t0).count() };
|
double duration{ std::chrono::duration_cast<second_>(clock_::now() - t0).count() };
|
||||||
if (duration > 30 || overhangs_all_layers[layer_nr].size() > 100) {
|
if (duration > 30 || overhangs_all_layers[layer_nr].size() > 100) {
|
||||||
@@ -1396,7 +1396,7 @@ void TreeSupport::generate_toolpaths()
|
|||||||
raft_areas.push_back(expoly);
|
raft_areas.push_back(expoly);
|
||||||
}
|
}
|
||||||
|
|
||||||
raft_areas = std::move(offset_ex(raft_areas, scale_(object_config.raft_first_layer_expansion)));
|
raft_areas = offset_ex(raft_areas, scale_(object_config.raft_first_layer_expansion));
|
||||||
|
|
||||||
size_t layer_nr = 0;
|
size_t layer_nr = 0;
|
||||||
for (; layer_nr < m_slicing_params.base_raft_layers; layer_nr++) {
|
for (; layer_nr < m_slicing_params.base_raft_layers; layer_nr++) {
|
||||||
@@ -1522,9 +1522,9 @@ void TreeSupport::generate_toolpaths()
|
|||||||
erSupportMaterialInterface : erSupportMaterial;
|
erSupportMaterialInterface : erSupportMaterial;
|
||||||
make_perimeter_and_inner_brim(ts_layer->support_fills.entities, poly, wall_count, flow,
|
make_perimeter_and_inner_brim(ts_layer->support_fills.entities, poly, wall_count, flow,
|
||||||
brim_role);
|
brim_role);
|
||||||
polys = std::move(offset_ex(poly, -flow.scaled_spacing()));
|
polys = offset_ex(poly, -flow.scaled_spacing());
|
||||||
} else if (area_group.type == SupportLayer::Roof1stLayer) {
|
} else if (area_group.type == SupportLayer::Roof1stLayer) {
|
||||||
polys = std::move(offset_ex(poly, 0.5*support_flow.scaled_width()));
|
polys = offset_ex(poly, 0.5*support_flow.scaled_width());
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
polys.push_back(poly);
|
polys.push_back(poly);
|
||||||
@@ -2269,7 +2269,7 @@ void TreeSupport::draw_circles()
|
|||||||
// Inside the gap: remove only the part overlapping the contact surface, keep the rest.
|
// Inside the gap: remove only the part overlapping the contact surface, keep the rest.
|
||||||
if (bottom_gap_height > EPSILON && layer_bottom_z < band_gap_top - EPSILON) {
|
if (bottom_gap_height > EPSILON && layer_bottom_z < band_gap_top - EPSILON) {
|
||||||
any_gap_cleared = true;
|
any_gap_cleared = true;
|
||||||
comp_poly = std::move(diff_ex(comp_poly, band.surfaces));
|
comp_poly = diff_ex(comp_poly, band.surfaces);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Overlaps interface band
|
// Overlaps interface band
|
||||||
@@ -2304,7 +2304,7 @@ void TreeSupport::draw_circles()
|
|||||||
ExPolygons comp_interface = band_ex.empty() ? ExPolygons {} : intersection_ex(comp_poly, band_ex);
|
ExPolygons comp_interface = band_ex.empty() ? ExPolygons {} : intersection_ex(comp_poly, band_ex);
|
||||||
if (!comp_interface.empty()) {
|
if (!comp_interface.empty()) {
|
||||||
append(new_floor_areas, comp_interface);
|
append(new_floor_areas, comp_interface);
|
||||||
comp_poly = std::move(diff_ex(comp_poly, offset_ex(comp_interface, 10)));
|
comp_poly = diff_ex(comp_poly, offset_ex(comp_interface, 10));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2396,7 +2396,7 @@ void TreeSupport::draw_circles()
|
|||||||
ts_layer->lslices.emplace_back(*expoly);
|
ts_layer->lslices.emplace_back(*expoly);
|
||||||
}
|
}
|
||||||
|
|
||||||
ts_layer->lslices = std::move(union_ex(ts_layer->lslices));
|
ts_layer->lslices = union_ex(ts_layer->lslices);
|
||||||
//Must update bounding box which is used in avoid crossing perimeter
|
//Must update bounding box which is used in avoid crossing perimeter
|
||||||
ts_layer->lslices_bboxes.clear();
|
ts_layer->lslices_bboxes.clear();
|
||||||
ts_layer->lslices_bboxes.reserve(ts_layer->lslices.size());
|
ts_layer->lslices_bboxes.reserve(ts_layer->lslices.size());
|
||||||
@@ -2474,7 +2474,7 @@ void TreeSupport::draw_circles()
|
|||||||
if (global_lightning_infill)
|
if (global_lightning_infill)
|
||||||
{
|
{
|
||||||
//search overhangs globally
|
//search overhangs globally
|
||||||
overhang = std::move(diff_ex(offset_ex(base_areas_lower, -2.0 * scale_(support_extrusion_width)), base_areas));
|
overhang = diff_ex(offset_ex(base_areas_lower, -2.0 * scale_(support_extrusion_width)), base_areas);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -2485,13 +2485,13 @@ void TreeSupport::draw_circles()
|
|||||||
Polygon rev_hole = hole;
|
Polygon rev_hole = hole;
|
||||||
rev_hole.make_counter_clockwise();
|
rev_hole.make_counter_clockwise();
|
||||||
ExPolygons ex_hole;
|
ExPolygons ex_hole;
|
||||||
ex_hole.emplace_back(std::move(ExPolygon(rev_hole)));
|
ex_hole.emplace_back(ExPolygon(rev_hole));
|
||||||
for (auto& other_area : base_areas)
|
for (auto& other_area : base_areas)
|
||||||
//if (&other_area != &base_area)
|
//if (&other_area != &base_area)
|
||||||
ex_hole = std::move(diff_ex(ex_hole, other_area));
|
ex_hole = diff_ex(ex_hole, other_area);
|
||||||
overhang = std::move(union_ex(overhang, ex_hole));
|
overhang = union_ex(overhang, ex_hole);
|
||||||
}
|
}
|
||||||
overhang = std::move(intersection_ex(overhang, offset_ex(base_areas_lower, -0.5 * scale_(support_extrusion_width))));
|
overhang = intersection_ex(overhang, offset_ex(base_areas_lower, -0.5 * scale_(support_extrusion_width)));
|
||||||
}
|
}
|
||||||
|
|
||||||
overhangs.emplace_back(to_polygons(overhang));
|
overhangs.emplace_back(to_polygons(overhang));
|
||||||
@@ -2746,7 +2746,7 @@ void TreeSupport::drop_nodes()
|
|||||||
|
|
||||||
m_object->print()->set_status(60 + int(10 * (1 - float(layer_nr) / contact_nodes.size())), _u8L("Generating support"));// (boost::format(_u8L("Support: propagate branches at layer %d")) % layer_nr).str());
|
m_object->print()->set_status(60 + int(10 * (1 - float(layer_nr) / contact_nodes.size())), _u8L("Generating support"));// (boost::format(_u8L("Support: propagate branches at layer %d")) % layer_nr).str());
|
||||||
|
|
||||||
Polygons layer_contours = std::move(m_ts_data->get_contours_with_holes(obj_layer_nr));
|
Polygons layer_contours = m_ts_data->get_contours_with_holes(obj_layer_nr);
|
||||||
//std::unordered_map<Line, bool, LineHash>& mst_line_x_layer_contour_cache = m_mst_line_x_layer_contour_caches[layer_nr];
|
//std::unordered_map<Line, bool, LineHash>& mst_line_x_layer_contour_cache = m_mst_line_x_layer_contour_caches[layer_nr];
|
||||||
tbb::concurrent_unordered_map<Line, bool, LineHash> mst_line_x_layer_contour_cache;
|
tbb::concurrent_unordered_map<Line, bool, LineHash> mst_line_x_layer_contour_cache;
|
||||||
auto is_line_cut_by_contour = [&mst_line_x_layer_contour_cache,&layer_contours](Point a, Point b)
|
auto is_line_cut_by_contour = [&mst_line_x_layer_contour_cache,&layer_contours](Point a, Point b)
|
||||||
@@ -3763,7 +3763,7 @@ const ExPolygons& TreeSupportData::calculate_avoidance(const RadiusLayerPair& ke
|
|||||||
}
|
}
|
||||||
const ExPolygons &collision = get_collision(radius, layer_nr);
|
const ExPolygons &collision = get_collision(radius, layer_nr);
|
||||||
avoidance_areas.insert(avoidance_areas.end(), collision.begin(), collision.end());
|
avoidance_areas.insert(avoidance_areas.end(), collision.begin(), collision.end());
|
||||||
avoidance_areas = std::move(union_ex(avoidance_areas));
|
avoidance_areas = union_ex(avoidance_areas);
|
||||||
auto ret = m_avoidance_cache.insert({key, std::move(avoidance_areas)});
|
auto ret = m_avoidance_cache.insert({key, std::move(avoidance_areas)});
|
||||||
//assert(ret.second);
|
//assert(ret.second);
|
||||||
return ret.first->second;
|
return ret.first->second;
|
||||||
|
|||||||
+36
-18
@@ -38,6 +38,8 @@ set(SLIC3R_GUI_SOURCES
|
|||||||
GUI/AuxiliaryDataViewModel.hpp
|
GUI/AuxiliaryDataViewModel.hpp
|
||||||
GUI/AuxiliaryDialog.cpp
|
GUI/AuxiliaryDialog.cpp
|
||||||
GUI/AuxiliaryDialog.hpp
|
GUI/AuxiliaryDialog.hpp
|
||||||
|
GUI/AVVideoDecoder.cpp
|
||||||
|
GUI/AVVideoDecoder.hpp
|
||||||
GUI/Auxiliary.hpp
|
GUI/Auxiliary.hpp
|
||||||
GUI/BackgroundSlicingProcess.cpp
|
GUI/BackgroundSlicingProcess.cpp
|
||||||
GUI/BackgroundSlicingProcess.hpp
|
GUI/BackgroundSlicingProcess.hpp
|
||||||
@@ -611,6 +613,8 @@ set(SLIC3R_GUI_SOURCES
|
|||||||
GUI/WipeTowerDialog.cpp
|
GUI/WipeTowerDialog.cpp
|
||||||
GUI/wxExtensions.cpp
|
GUI/wxExtensions.cpp
|
||||||
GUI/wxExtensions.hpp
|
GUI/wxExtensions.hpp
|
||||||
|
GUI/wxMediaCtrl3.cpp
|
||||||
|
GUI/wxMediaCtrl3.h
|
||||||
plugin/PythonInterpreter.cpp
|
plugin/PythonInterpreter.cpp
|
||||||
plugin/PythonInterpreter.hpp
|
plugin/PythonInterpreter.hpp
|
||||||
plugin/PythonPluginBridge.cpp
|
plugin/PythonPluginBridge.cpp
|
||||||
@@ -799,21 +803,8 @@ if (APPLE)
|
|||||||
GUI/DeepLinkHandlerMac.mm
|
GUI/DeepLinkHandlerMac.mm
|
||||||
GUI/DeepLinkHandlerMac.h
|
GUI/DeepLinkHandlerMac.h
|
||||||
GUI/GUI_UtilsMac.mm
|
GUI/GUI_UtilsMac.mm
|
||||||
GUI/wxMediaCtrl2.mm
|
|
||||||
GUI/wxMediaCtrl2.h
|
|
||||||
)
|
)
|
||||||
FIND_LIBRARY(DISKARBITRATION_LIBRARY DiskArbitration)
|
FIND_LIBRARY(DISKARBITRATION_LIBRARY DiskArbitration)
|
||||||
else ()
|
|
||||||
list(APPEND SLIC3R_GUI_SOURCES
|
|
||||||
GUI/wxMediaCtrl2.cpp
|
|
||||||
GUI/wxMediaCtrl2.h
|
|
||||||
)
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
if (UNIX AND NOT APPLE)
|
|
||||||
list(APPEND SLIC3R_GUI_SOURCES
|
|
||||||
GUI/Printer/gstbambusrc.c
|
|
||||||
)
|
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
set(ORCA_UPDATER_SIG_KEY_B64 "${ORCA_UPDATER_SIG_KEY}")
|
set(ORCA_UPDATER_SIG_KEY_B64 "${ORCA_UPDATER_SIG_KEY}")
|
||||||
@@ -913,6 +904,38 @@ if (SLIC3R_PCH AND NOT SLIC3R_SYNTAXONLY)
|
|||||||
add_precompiled_header(libslic3r_gui pchheader.hpp FORCEINCLUDE)
|
add_precompiled_header(libslic3r_gui pchheader.hpp FORCEINCLUDE)
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
|
if (APPLE)
|
||||||
|
# Static FFmpeg from the deps install: nothing to bundle into the .app,
|
||||||
|
# no rpath/install_name handling. Order matters: avcodec -> swscale -> avutil.
|
||||||
|
find_library(LIBAVCODEC_LIBRARY NAMES libavcodec.a PATHS ${CMAKE_PREFIX_PATH}/lib NO_DEFAULT_PATH)
|
||||||
|
find_library(LIBSWSCALE_LIBRARY NAMES libswscale.a PATHS ${CMAKE_PREFIX_PATH}/lib NO_DEFAULT_PATH)
|
||||||
|
find_library(LIBAVUTIL_LIBRARY NAMES libavutil.a PATHS ${CMAKE_PREFIX_PATH}/lib NO_DEFAULT_PATH)
|
||||||
|
if (NOT LIBAVCODEC_LIBRARY OR NOT LIBSWSCALE_LIBRARY OR NOT LIBAVUTIL_LIBRARY)
|
||||||
|
message(FATAL_ERROR "Static FFmpeg (libavcodec.a/libswscale.a/libavutil.a) not found under ${CMAKE_PREFIX_PATH}/lib. Rebuild the deps — FFMPEG builds static-only on macOS.")
|
||||||
|
endif ()
|
||||||
|
target_link_libraries(libslic3r_gui ${LIBAVCODEC_LIBRARY} ${LIBSWSCALE_LIBRARY} ${LIBAVUTIL_LIBRARY})
|
||||||
|
target_include_directories(libslic3r_gui SYSTEM PRIVATE ${CMAKE_PREFIX_PATH}/include)
|
||||||
|
elseif (WIN32)
|
||||||
|
# Prebuilt shared FFmpeg from the deps install. Windows has no pkg-config,
|
||||||
|
# so resolve the import libraries out of the deps prefix directly; the DLLs
|
||||||
|
# are copied next to the executable by the top level CMakeLists.
|
||||||
|
find_library(LIBAVCODEC_LIBRARY NAMES avcodec PATHS ${CMAKE_PREFIX_PATH}/lib NO_DEFAULT_PATH)
|
||||||
|
find_library(LIBSWSCALE_LIBRARY NAMES swscale PATHS ${CMAKE_PREFIX_PATH}/lib NO_DEFAULT_PATH)
|
||||||
|
find_library(LIBAVUTIL_LIBRARY NAMES avutil PATHS ${CMAKE_PREFIX_PATH}/lib NO_DEFAULT_PATH)
|
||||||
|
if (NOT LIBAVCODEC_LIBRARY OR NOT LIBSWSCALE_LIBRARY OR NOT LIBAVUTIL_LIBRARY)
|
||||||
|
message(FATAL_ERROR "FFmpeg (avcodec/swscale/avutil) not found under ${CMAKE_PREFIX_PATH}/lib. Rebuild the deps.")
|
||||||
|
endif ()
|
||||||
|
target_link_libraries(libslic3r_gui ${LIBAVCODEC_LIBRARY} ${LIBSWSCALE_LIBRARY} ${LIBAVUTIL_LIBRARY})
|
||||||
|
target_include_directories(libslic3r_gui SYSTEM PRIVATE ${CMAKE_PREFIX_PATH}/include)
|
||||||
|
else ()
|
||||||
|
pkg_check_modules(LIBAV REQUIRED IMPORTED_TARGET
|
||||||
|
libavcodec
|
||||||
|
libswscale
|
||||||
|
libavutil
|
||||||
|
)
|
||||||
|
target_link_libraries(libslic3r_gui PkgConfig::LIBAV)
|
||||||
|
endif()
|
||||||
|
|
||||||
# We need to implement some hacks for wxWidgets and touch the underlying GTK
|
# We need to implement some hacks for wxWidgets and touch the underlying GTK
|
||||||
# layer and sub-libraries. This forces us to use the include locations and
|
# layer and sub-libraries. This forces us to use the include locations and
|
||||||
# link these libraries.
|
# link these libraries.
|
||||||
@@ -939,11 +962,6 @@ if (UNIX AND NOT APPLE)
|
|||||||
target_compile_definitions(libslic3r_gui PRIVATE wxHAVE_GDK_WAYLAND)
|
target_compile_definitions(libslic3r_gui PRIVATE wxHAVE_GDK_WAYLAND)
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
# We add GStreamer for bambu:/// support.
|
|
||||||
pkg_check_modules(GSTREAMER REQUIRED gstreamer-1.0)
|
|
||||||
pkg_check_modules(GST_BASE REQUIRED gstreamer-base-1.0)
|
|
||||||
target_link_libraries(libslic3r_gui ${GSTREAMER_LIBRARIES} ${GST_BASE_LIBRARIES})
|
|
||||||
target_include_directories(libslic3r_gui SYSTEM PRIVATE ${GSTREAMER_INCLUDE_DIRS} ${GST_BASE_INCLUDE_DIRS})
|
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
# Add a definition so that we can tell we are compiling slic3r.
|
# Add a definition so that we can tell we are compiling slic3r.
|
||||||
|
|||||||
@@ -55,7 +55,6 @@ private:
|
|||||||
|
|
||||||
Label* m_text_label;
|
Label* m_text_label;
|
||||||
wxStaticBitmap* m_icon_bitmap;
|
wxStaticBitmap* m_icon_bitmap;
|
||||||
int m_target_size;
|
|
||||||
std::string m_icon_name;
|
std::string m_icon_name;
|
||||||
ScalableBitmap m_icon;
|
ScalableBitmap m_icon;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -0,0 +1,170 @@
|
|||||||
|
#include "AVVideoDecoder.hpp"
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
#include <libavutil/avutil.h>
|
||||||
|
#include <libavutil/imgutils.h>
|
||||||
|
}
|
||||||
|
|
||||||
|
AVVideoDecoder::AVVideoDecoder()
|
||||||
|
{
|
||||||
|
codec_ctx_ = avcodec_alloc_context3(nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
AVVideoDecoder::~AVVideoDecoder()
|
||||||
|
{
|
||||||
|
if (sws_ctx_)
|
||||||
|
sws_freeContext(sws_ctx_);
|
||||||
|
if (frame_)
|
||||||
|
av_frame_free(&frame_);
|
||||||
|
if (codec_ctx_)
|
||||||
|
avcodec_free_context(&codec_ctx_);
|
||||||
|
}
|
||||||
|
|
||||||
|
int AVVideoDecoder::open(Bambu_StreamInfo const &info)
|
||||||
|
{
|
||||||
|
auto codec_id = info.sub_type == AVC1 ? AV_CODEC_ID_H264 : AV_CODEC_ID_MJPEG;
|
||||||
|
auto codec = avcodec_find_decoder(codec_id);
|
||||||
|
if (codec == nullptr) {
|
||||||
|
fprintf(stderr, "AVVideoDecoder: unsupported codec!\n");
|
||||||
|
return -1; // Codec not found
|
||||||
|
}
|
||||||
|
/* open the coderc */
|
||||||
|
if (avcodec_open2(codec_ctx_, codec, nullptr) < 0) {
|
||||||
|
fprintf(stderr, "AVVideoDecoder: could not open codec\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Allocate an AVFrame structure
|
||||||
|
frame_ = av_frame_alloc();
|
||||||
|
if (frame_ == nullptr)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int AVVideoDecoder::decode(const Bambu_Sample &sample)
|
||||||
|
{
|
||||||
|
int ret = -1;
|
||||||
|
AVPacket *pkt = av_packet_alloc();
|
||||||
|
if (!pkt) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = av_new_packet(pkt, sample.size);
|
||||||
|
if (ret != 0) {
|
||||||
|
av_packet_free(&pkt);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(pkt->data, sample.buffer, size_t(sample.size));
|
||||||
|
|
||||||
|
ret = avcodec_send_packet(codec_ctx_, pkt);
|
||||||
|
if (ret == 0) {
|
||||||
|
got_frame_ = avcodec_receive_frame(codec_ctx_, frame_) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
av_packet_unref(pkt);
|
||||||
|
av_packet_free(&pkt);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int AVVideoDecoder::flush()
|
||||||
|
{
|
||||||
|
int ret = avcodec_send_packet(codec_ctx_, nullptr);
|
||||||
|
got_frame_ = avcodec_receive_frame(codec_ctx_, frame_) == 0;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AVVideoDecoder::close()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AVVideoDecoder::toWxImage(wxImage &image, wxSize const &size2)
|
||||||
|
{
|
||||||
|
if (!got_frame_)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
auto size1 = size2;
|
||||||
|
if (!size1.IsFullySpecified())
|
||||||
|
size1 = {frame_->width, frame_->height };
|
||||||
|
auto size = size1;
|
||||||
|
if (size.GetWidth() & 0x0f) {
|
||||||
|
size.SetWidth((size.GetWidth() & ~0x0f) + 0x10);
|
||||||
|
if (size.GetWidth() != width_) {
|
||||||
|
std::fill(bits_.begin(), bits_.end(), 0);
|
||||||
|
width_ = size.GetWidth();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
AVPixelFormat wxFmt = AV_PIX_FMT_RGB24;
|
||||||
|
sws_ctx_ = sws_getCachedContext(sws_ctx_,
|
||||||
|
frame_->width, frame_->height, AVPixelFormat(frame_->format),
|
||||||
|
size1.GetWidth(), size1.GetHeight(), wxFmt,
|
||||||
|
SWS_GAUSS,
|
||||||
|
nullptr, nullptr, nullptr);
|
||||||
|
if (sws_ctx_ == nullptr)
|
||||||
|
return false;
|
||||||
|
int length = size.GetWidth() * size.GetHeight() * 3;
|
||||||
|
if (bits_.size() < length)
|
||||||
|
bits_.resize(length);
|
||||||
|
uint8_t * datas[] = { bits_.data() };
|
||||||
|
int strides[] = { size.GetWidth() * 3 };
|
||||||
|
int result_h = sws_scale(sws_ctx_, frame_->data, frame_->linesize, 0, frame_->height, datas, strides);
|
||||||
|
if (result_h != size.GetHeight()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// Copy: the frame outlives this decoder and is painted by the GUI thread while the
|
||||||
|
// next sws_scale is already overwriting bits_, so it must own its pixels. The Windows
|
||||||
|
// path below needs no equivalent, wxBitmap copies the bits into GDI.
|
||||||
|
image = wxImage(size.GetWidth(), size.GetHeight(), bits_.data(), true).Copy();
|
||||||
|
if (!image.IsOk()) {
|
||||||
|
fprintf(stderr, "AVVideoDecoder: image not ok %dx%d\n", size.GetWidth(), size.GetHeight());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AVVideoDecoder::toWxBitmap(wxBitmap &bitmap, wxSize const &size2)
|
||||||
|
{
|
||||||
|
if (!got_frame_)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
auto size1 = size2;
|
||||||
|
if (!size1.IsFullySpecified())
|
||||||
|
size1 = {frame_->width, frame_->height };
|
||||||
|
auto size = size1;
|
||||||
|
if (size.GetWidth() & 0x0f) {
|
||||||
|
size.SetWidth((size.GetWidth() & ~0x0f) + 0x10);
|
||||||
|
if (size.GetWidth() != width_) {
|
||||||
|
std::fill(bits_.begin(), bits_.end(), 0);
|
||||||
|
width_ = size.GetWidth();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
AVPixelFormat wxFmt = AV_PIX_FMT_RGB32;
|
||||||
|
sws_ctx_ = sws_getCachedContext(sws_ctx_,
|
||||||
|
frame_->width, frame_->height, AVPixelFormat(frame_->format),
|
||||||
|
size1.GetWidth(), size1.GetHeight(), wxFmt,
|
||||||
|
SWS_GAUSS,
|
||||||
|
nullptr, nullptr, nullptr);
|
||||||
|
if (sws_ctx_ == nullptr)
|
||||||
|
return false;
|
||||||
|
int length = size.GetWidth() * size.GetHeight() * 4;
|
||||||
|
if (bits_.size() < length)
|
||||||
|
bits_.resize(length);
|
||||||
|
uint8_t *datas[] = { bits_.data() };
|
||||||
|
int strides[] = { size.GetWidth() * 4 };
|
||||||
|
int result_h = sws_scale(sws_ctx_, frame_->data, frame_->linesize, 0, frame_->height, datas, strides);
|
||||||
|
if (result_h != size.GetHeight()) {
|
||||||
|
fprintf(stderr, "AVVideoDecoder: result_h %d %d\n", result_h, size.GetHeight());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
bitmap = wxBitmap((char const *) bits_.data(), size.GetWidth(), size.GetHeight(), 32);
|
||||||
|
assert(bitmap.IsOk());
|
||||||
|
if (!bitmap.IsOk()) {
|
||||||
|
fprintf(stderr, "AVVideoDecoder: bitmap not ok %dx%d\n", size.GetWidth(), size.GetHeight());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
#ifndef AVVIDEODECODER_HPP
|
||||||
|
#define AVVIDEODECODER_HPP
|
||||||
|
|
||||||
|
#include "Printer/BambuTunnel.h"
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
#include <libavcodec/avcodec.h>
|
||||||
|
#include <libswscale/swscale.h>
|
||||||
|
}
|
||||||
|
#include <vector>
|
||||||
|
#include <wx/bitmap.h>
|
||||||
|
#include <wx/gdicmn.h>
|
||||||
|
#include <wx/image.h>
|
||||||
|
|
||||||
|
class wxBitmap;
|
||||||
|
|
||||||
|
class AVVideoDecoder
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
AVVideoDecoder();
|
||||||
|
|
||||||
|
~AVVideoDecoder();
|
||||||
|
|
||||||
|
public:
|
||||||
|
int open(Bambu_StreamInfo const &info);
|
||||||
|
|
||||||
|
int decode(Bambu_Sample const &sample);
|
||||||
|
|
||||||
|
int flush();
|
||||||
|
|
||||||
|
void close();
|
||||||
|
|
||||||
|
bool toWxImage(wxImage &image, wxSize const &size);
|
||||||
|
|
||||||
|
bool toWxBitmap(wxBitmap &bitmap, wxSize const & size);
|
||||||
|
|
||||||
|
private:
|
||||||
|
AVCodecContext *codec_ctx_ = nullptr;
|
||||||
|
AVFrame * frame_ = nullptr;
|
||||||
|
SwsContext * sws_ctx_ = nullptr;
|
||||||
|
bool got_frame_ = false;
|
||||||
|
int width_ { 0 }; // scale result width
|
||||||
|
std::vector<uint8_t> bits_;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // AVVIDEODECODER_HPP
|
||||||
@@ -60,7 +60,6 @@ class AboutDialog : public DPIDialog
|
|||||||
wxHtmlWindow* m_html;
|
wxHtmlWindow* m_html;
|
||||||
wxStaticBitmap* m_logo;
|
wxStaticBitmap* m_logo;
|
||||||
int m_copy_rights_btn_id { wxID_ANY };
|
int m_copy_rights_btn_id { wxID_ANY };
|
||||||
int m_copy_version_btn_id { wxID_ANY };
|
|
||||||
public:
|
public:
|
||||||
AboutDialog();
|
AboutDialog();
|
||||||
|
|
||||||
|
|||||||
@@ -93,7 +93,6 @@ private:
|
|||||||
CenteredTitle* m_title_ctrl { nullptr };
|
CenteredTitle* m_title_ctrl { nullptr };
|
||||||
wxString m_titleText;
|
wxString m_titleText;
|
||||||
|
|
||||||
wxAuiToolBarItem* m_account_item;
|
|
||||||
wxAuiToolBarItem* m_model_store_item;
|
wxAuiToolBarItem* m_model_store_item;
|
||||||
|
|
||||||
//wxAuiToolBarItem *m_publish_item;
|
//wxAuiToolBarItem *m_publish_item;
|
||||||
|
|||||||
@@ -1,30 +0,0 @@
|
|||||||
//
|
|
||||||
// BambuPlayer.h
|
|
||||||
// BambuPlayer
|
|
||||||
//
|
|
||||||
// Created by cmguo on 2021/12/6.
|
|
||||||
//
|
|
||||||
|
|
||||||
#import <Foundation/Foundation.h>
|
|
||||||
#import <AVFoundation/AVSampleBufferDisplayLayer.h>
|
|
||||||
#import <Cocoa/Cocoa.h>
|
|
||||||
|
|
||||||
NS_ASSUME_NONNULL_BEGIN
|
|
||||||
|
|
||||||
@interface BambuPlayer : NSObject
|
|
||||||
|
|
||||||
+ (void) initialize;
|
|
||||||
|
|
||||||
- (instancetype) initWithDisplayLayer: (AVSampleBufferDisplayLayer*) layer;
|
|
||||||
- (instancetype) initWithImageView: (NSView*) view;
|
|
||||||
- (int) open: (char const *) url;
|
|
||||||
- (NSSize) videoSize;
|
|
||||||
- (int) play;
|
|
||||||
- (void) stop;
|
|
||||||
- (void) close;
|
|
||||||
|
|
||||||
- (void) setLogger: (void (*)(void const * context, int level, char const * msg)) logger withContext: (void const *) context;
|
|
||||||
|
|
||||||
@end
|
|
||||||
|
|
||||||
NS_ASSUME_NONNULL_END
|
|
||||||
@@ -74,12 +74,10 @@ private:
|
|||||||
std::unordered_set<std::string> m_system_filament_types_set;
|
std::unordered_set<std::string> m_system_filament_types_set;
|
||||||
std::set<std::string> m_visible_printers;
|
std::set<std::string> m_visible_printers;
|
||||||
CreateType m_create_type;
|
CreateType m_create_type;
|
||||||
Button * m_button_create = nullptr;
|
|
||||||
Button * m_button_cancel = nullptr;
|
Button * m_button_cancel = nullptr;
|
||||||
ComboBox * m_filament_vendor_combobox = nullptr;
|
ComboBox * m_filament_vendor_combobox = nullptr;
|
||||||
::CheckBox * m_can_not_find_vendor_checkbox = nullptr;
|
::CheckBox * m_can_not_find_vendor_checkbox = nullptr;
|
||||||
ComboBox * m_filament_type_combobox = nullptr;
|
ComboBox * m_filament_type_combobox = nullptr;
|
||||||
ComboBox * m_exist_vendor_combobox = nullptr;
|
|
||||||
ComboBox * m_filament_preset_combobox = nullptr;
|
ComboBox * m_filament_preset_combobox = nullptr;
|
||||||
TextInput * m_filament_custom_vendor_input = nullptr;
|
TextInput * m_filament_custom_vendor_input = nullptr;
|
||||||
wxGridSizer * m_filament_presets_sizer = nullptr;
|
wxGridSizer * m_filament_presets_sizer = nullptr;
|
||||||
|
|||||||
@@ -16,24 +16,27 @@ namespace Slic3r
|
|||||||
// This block is never executed at runtime.
|
// This block is never executed at runtime.
|
||||||
static void _toolhead_translation_markers()
|
static void _toolhead_translation_markers()
|
||||||
{
|
{
|
||||||
// Dynamic toolhead display names from JSON config — xgettext cannot scan these
|
// Possible runtime values of tool_head_display_names, marked for extraction.
|
||||||
L("Main Extruder"); L("Main extruder"); L("main extruder");
|
static const char *const markers[] = {
|
||||||
L("Auxiliary Extruder"); L("Auxiliary extruder"); L("auxiliary extruder");
|
L("Main Extruder"), L("Main extruder"), L("main extruder"),
|
||||||
L("Left Extruder"); L("Left extruder"); L("left extruder");
|
L("Auxiliary Extruder"), L("Auxiliary extruder"), L("auxiliary extruder"),
|
||||||
L("Right Extruder"); L("Right extruder"); L("right extruder");
|
L("Left Extruder"), L("Left extruder"), L("left extruder"),
|
||||||
L("Main Nozzle"); L("Main nozzle"); L("main nozzle");
|
L("Right Extruder"), L("Right extruder"), L("right extruder"),
|
||||||
L("Auxiliary Nozzle"); L("Auxiliary nozzle"); L("auxiliary nozzle");
|
L("Main Nozzle"), L("Main nozzle"), L("main nozzle"),
|
||||||
L("Left Nozzle"); L("Left nozzle"); L("left nozzle");
|
L("Auxiliary Nozzle"), L("Auxiliary nozzle"), L("auxiliary nozzle"),
|
||||||
L("Right Nozzle"); L("Right nozzle"); L("right nozzle");
|
L("Left Nozzle"), L("Left nozzle"), L("left nozzle"),
|
||||||
L("Main Hotend"); L("Main hotend"); L("main hotend");
|
L("Right Nozzle"), L("Right nozzle"), L("right nozzle"),
|
||||||
L("Auxiliary Hotend"); L("Auxiliary hotend"); L("auxiliary hotend");
|
L("Main Hotend"), L("Main hotend"), L("main hotend"),
|
||||||
L("Left Hotend"); L("Left hotend"); L("left hotend");
|
L("Auxiliary Hotend"), L("Auxiliary hotend"), L("auxiliary hotend"),
|
||||||
L("Right Hotend"); L("Right hotend"); L("right hotend");
|
L("Left Hotend"), L("Left hotend"), L("left hotend"),
|
||||||
|
L("Right Hotend"), L("Right hotend"), L("right hotend"),
|
||||||
// standalone position words (short_name=true runtime results)
|
// standalone position words (short_name=true runtime results)
|
||||||
L("main"); L("auxiliary");
|
L("main"), L("auxiliary"),
|
||||||
L("Main"); L("Auxiliary");
|
L("Main"), L("Auxiliary"),
|
||||||
L("left"); L("right");
|
L("left"), L("right"),
|
||||||
L("Left"); L("Right");
|
L("Left"), L("Right"),
|
||||||
|
};
|
||||||
|
(void) markers;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string DevPrinterConfigUtil::m_resource_file_path = "";
|
std::string DevPrinterConfigUtil::m_resource_file_path = "";
|
||||||
|
|||||||
@@ -199,7 +199,6 @@ private:
|
|||||||
void OnRefreshButton(wxCommandEvent& event);
|
void OnRefreshButton(wxCommandEvent& event);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int saveTimes{0};
|
|
||||||
wxBoxSizer* mainSizer{nullptr};
|
wxBoxSizer* mainSizer{nullptr};
|
||||||
wxPanel* textPanel{nullptr};
|
wxPanel* textPanel{nullptr};
|
||||||
wxBoxSizer* textSizer{nullptr};
|
wxBoxSizer* textSizer{nullptr};
|
||||||
|
|||||||
@@ -122,7 +122,6 @@ private:
|
|||||||
private:
|
private:
|
||||||
int m_ext_nozzle_id = -1;
|
int m_ext_nozzle_id = -1;
|
||||||
int m_rack_nozzle_id = -1;
|
int m_rack_nozzle_id = -1;
|
||||||
bool m_isRefreshFinish = false;
|
|
||||||
bool findNozzleImage = false;
|
bool findNozzleImage = false;
|
||||||
|
|
||||||
NozzleStatus m_nozzle_status = NOZZLE_STATUS_DC;
|
NozzleStatus m_nozzle_status = NOZZLE_STATUS_DC;
|
||||||
@@ -154,7 +153,6 @@ private:
|
|||||||
Label* m_diameter_label;
|
Label* m_diameter_label;
|
||||||
Label* m_flowtype_label;
|
Label* m_flowtype_label;
|
||||||
Label* m_type_label;
|
Label* m_type_label;
|
||||||
ScalableButton* m_error_button{ nullptr };
|
|
||||||
|
|
||||||
Label* m_sn_label;
|
Label* m_sn_label;
|
||||||
Label* m_version_label;
|
Label* m_version_label;
|
||||||
|
|||||||
@@ -266,7 +266,7 @@ void wgtDeviceNozzleRackSelect::OnNozzleItemSelected(wxCommandEvent &evt)
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto *item = dynamic_cast<wgtDeviceNozzleRackNozzleItem *>(evt.GetEventObject());
|
auto *item = dynamic_cast<wgtDeviceNozzleRackNozzleItem *>(evt.GetEventObject());
|
||||||
if (item; auto ptr = m_nozzle_rack.lock()) {
|
if (auto ptr = m_nozzle_rack.lock(); item && ptr) {
|
||||||
int to_select_pos_id = sGetNozzlePosId(item, m_toolhead_nozzle_l, m_toolhead_nozzle_r);
|
int to_select_pos_id = sGetNozzlePosId(item, m_toolhead_nozzle_l, m_toolhead_nozzle_r);
|
||||||
if (to_select_pos_id > -1 && to_select_pos_id != GetSelectedNozzlePosID()) {
|
if (to_select_pos_id > -1 && to_select_pos_id != GetSelectedNozzlePosID()) {
|
||||||
SetSelectedNozzle(ptr->GetNozzleSystem()->GetNozzleByPosId(to_select_pos_id));
|
SetSelectedNozzle(ptr->GetNozzleSystem()->GetNozzleByPosId(to_select_pos_id));
|
||||||
|
|||||||
@@ -72,7 +72,6 @@ public:
|
|||||||
float m_model_z_offset{ 0.5f };
|
float m_model_z_offset{ 0.5f };
|
||||||
bool m_visible{ true };
|
bool m_visible{ true };
|
||||||
bool m_is_dark = false;
|
bool m_is_dark = false;
|
||||||
bool m_fixed_screen_size{ false };
|
|
||||||
float m_scale_factor{ 1.0f };
|
float m_scale_factor{ 1.0f };
|
||||||
#if ENABLE_ACTUAL_SPEED_DEBUG
|
#if ENABLE_ACTUAL_SPEED_DEBUG
|
||||||
ActualSpeedImguiWidget m_actual_speed_imgui_widget;
|
ActualSpeedImguiWidget m_actual_speed_imgui_widget;
|
||||||
|
|||||||
@@ -327,7 +327,6 @@ private:
|
|||||||
GLTexture m_icons_texture;
|
GLTexture m_icons_texture;
|
||||||
bool m_icons_texture_dirty;
|
bool m_icons_texture_dirty;
|
||||||
mutable GLTexture m_images_texture;
|
mutable GLTexture m_images_texture;
|
||||||
mutable bool m_images_texture_dirty;
|
|
||||||
BackgroundTexture m_background_texture;
|
BackgroundTexture m_background_texture;
|
||||||
GLTexture m_arrow_texture;
|
GLTexture m_arrow_texture;
|
||||||
Layout m_layout;
|
Layout m_layout;
|
||||||
|
|||||||
@@ -86,7 +86,6 @@ private:
|
|||||||
boost::thread m_thread;
|
boost::thread m_thread;
|
||||||
// Mutex and condition variable to synchronize m_thread with the UI thread.
|
// Mutex and condition variable to synchronize m_thread with the UI thread.
|
||||||
std::mutex m_mutex;
|
std::mutex m_mutex;
|
||||||
int m_generate_count;
|
|
||||||
|
|
||||||
// This map holds all translated description texts, so they can be easily referenced during layout calculations
|
// This map holds all translated description texts, so they can be easily referenced during layout calculations
|
||||||
// etc. When language changes, GUI is recreated and this class constructed again, so the change takes effect.
|
// etc. When language changes, GUI is recreated and this class constructed again, so the change takes effect.
|
||||||
|
|||||||
@@ -176,7 +176,6 @@ private:
|
|||||||
// Use those values to disable selection of active extruders
|
// Use those values to disable selection of active extruders
|
||||||
bool m_is_dark = false;
|
bool m_is_dark = false;
|
||||||
|
|
||||||
bool is_osx{false};
|
|
||||||
int m_min_value;
|
int m_min_value;
|
||||||
int m_max_value;
|
int m_max_value;
|
||||||
int m_lower_value;
|
int m_lower_value;
|
||||||
@@ -201,10 +200,6 @@ private:
|
|||||||
void *m_one_layer_on_hover_id;
|
void *m_one_layer_on_hover_id;
|
||||||
void *m_one_layer_off_id;
|
void *m_one_layer_off_id;
|
||||||
void *m_one_layer_off_hover_id;
|
void *m_one_layer_off_hover_id;
|
||||||
void* m_one_layer_on_light_id;
|
|
||||||
void* m_one_layer_on_hover_light_id;
|
|
||||||
void* m_one_layer_off_light_id;
|
|
||||||
void* m_one_layer_off_hover_light_id;
|
|
||||||
void* m_one_layer_on_dark_id;
|
void* m_one_layer_on_dark_id;
|
||||||
void* m_one_layer_on_hover_dark_id;
|
void* m_one_layer_on_hover_dark_id;
|
||||||
void* m_one_layer_off_dark_id;
|
void* m_one_layer_off_dark_id;
|
||||||
|
|||||||
@@ -2482,6 +2482,19 @@ static const ImWchar ranges_keyboard_shortcuts[] =
|
|||||||
};
|
};
|
||||||
#endif // __APPLE__
|
#endif // __APPLE__
|
||||||
|
|
||||||
|
// Names drawn through the atlas come from file names and CAD data, not from the UI language.
|
||||||
|
// GetGlyphRangesDefault() already gives every language the CJK ideographs, which is why a
|
||||||
|
// Chinese file name renders under an English UI; these are the alphabetic scripts it omits.
|
||||||
|
// Codepoints the font lacks are skipped at build time, so only existing glyphs cost anything.
|
||||||
|
static const ImWchar ranges_language_independent[] =
|
||||||
|
{
|
||||||
|
0x0100, 0x024F, // Latin Extended-A and Extended-B
|
||||||
|
0x0370, 0x03FF, // Greek and Coptic
|
||||||
|
0x0400, 0x04FF, // Cyrillic
|
||||||
|
0x1E00, 0x1EFF, // Latin Extended Additional (Vietnamese)
|
||||||
|
0,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
std::vector<unsigned char> ImGuiWrapper::load_svg(const std::string& bitmap_name, unsigned target_width, unsigned target_height, unsigned *outwidth, unsigned *outheight)
|
std::vector<unsigned char> ImGuiWrapper::load_svg(const std::string& bitmap_name, unsigned target_width, unsigned target_height, unsigned *outwidth, unsigned *outheight)
|
||||||
{
|
{
|
||||||
@@ -2792,6 +2805,7 @@ void ImGuiWrapper::init_font(bool compress)
|
|||||||
ImFontAtlas::GlyphRangesBuilder builder;
|
ImFontAtlas::GlyphRangesBuilder builder;
|
||||||
builder.AddRanges(m_glyph_ranges);
|
builder.AddRanges(m_glyph_ranges);
|
||||||
builder.AddRanges(ImGui::GetIO().Fonts->GetGlyphRangesDefault());
|
builder.AddRanges(ImGui::GetIO().Fonts->GetGlyphRangesDefault());
|
||||||
|
builder.AddRanges(ranges_language_independent);
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
if (m_font_cjk)
|
if (m_font_cjk)
|
||||||
// Apple keyboard shortcuts are only contained in the CJK fonts.
|
// Apple keyboard shortcuts are only contained in the CJK fonts.
|
||||||
@@ -2813,12 +2827,17 @@ void ImGuiWrapper::init_font(bool compress)
|
|||||||
// Orca: temp fix for Korean font
|
// Orca: temp fix for Korean font
|
||||||
auto font_name_regular = "HarmonyOS_Sans_SC_Regular.ttf";
|
auto font_name_regular = "HarmonyOS_Sans_SC_Regular.ttf";
|
||||||
auto font_name_bold = "HarmonyOS_Sans_SC_Bold.ttf";
|
auto font_name_bold = "HarmonyOS_Sans_SC_Bold.ttf";
|
||||||
|
// The Korean and Thai fonts cover their own script and little else, so they need the
|
||||||
|
// default font merged in behind them to reach the full range.
|
||||||
|
bool needs_glyph_fallback = false;
|
||||||
if(m_glyph_ranges == ImGui::GetIO().Fonts->GetGlyphRangesKorean()) {
|
if(m_glyph_ranges == ImGui::GetIO().Fonts->GetGlyphRangesKorean()) {
|
||||||
font_name_regular = "NanumGothic-Regular.ttf";
|
font_name_regular = "NanumGothic-Regular.ttf";
|
||||||
font_name_bold = "NanumGothic-Bold.ttf";
|
font_name_bold = "NanumGothic-Bold.ttf";
|
||||||
|
needs_glyph_fallback = true;
|
||||||
} else if (m_glyph_ranges == ImGui::GetIO().Fonts->GetGlyphRangesThai()) {
|
} else if (m_glyph_ranges == ImGui::GetIO().Fonts->GetGlyphRangesThai()) {
|
||||||
font_name_regular = "Sarabun-Medium.ttf";
|
font_name_regular = "Sarabun-Medium.ttf";
|
||||||
font_name_bold = "Sarabun-SemiBold.ttf";
|
font_name_bold = "Sarabun-SemiBold.ttf";
|
||||||
|
needs_glyph_fallback = true;
|
||||||
}
|
}
|
||||||
default_font = io.Fonts->AddFontFromFileTTF((Slic3r::resources_dir() + "/fonts/" + font_name_regular).c_str(), m_font_size, &cfg, ranges.Data);
|
default_font = io.Fonts->AddFontFromFileTTF((Slic3r::resources_dir() + "/fonts/" + font_name_regular).c_str(), m_font_size, &cfg, ranges.Data);
|
||||||
if (default_font == nullptr) {
|
if (default_font == nullptr) {
|
||||||
@@ -2828,11 +2847,12 @@ void ImGuiWrapper::init_font(bool compress)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_glyph_ranges == ImGui::GetIO().Fonts->GetGlyphRangesThai()) {
|
// A merged font only supplies glyphs the font ahead of it lacks, so this fills the gaps
|
||||||
|
// without restyling anything the script font already covers.
|
||||||
|
if (needs_glyph_fallback) {
|
||||||
ImFontConfig fallback_cfg = cfg;
|
ImFontConfig fallback_cfg = cfg;
|
||||||
fallback_cfg.MergeMode = true;
|
fallback_cfg.MergeMode = true;
|
||||||
static constexpr ImWchar celsius_range[] = { 0x2103, 0x2103, 0 };
|
io.Fonts->AddFontFromFileTTF((Slic3r::resources_dir() + "/fonts/HarmonyOS_Sans_SC_Regular.ttf").c_str(), m_font_size, &fallback_cfg, ranges.Data);
|
||||||
io.Fonts->AddFontFromFileTTF((Slic3r::resources_dir() + "/fonts/HarmonyOS_Sans_SC_Regular.ttf").c_str(), m_font_size, &fallback_cfg, celsius_range);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bold_font = io.Fonts->AddFontFromFileTTF((Slic3r::resources_dir() + "/fonts/" + font_name_bold).c_str(), m_font_size, &cfg, ranges.Data);
|
bold_font = io.Fonts->AddFontFromFileTTF((Slic3r::resources_dir() + "/fonts/" + font_name_bold).c_str(), m_font_size, &cfg, ranges.Data);
|
||||||
@@ -2841,11 +2861,10 @@ void ImGuiWrapper::init_font(bool compress)
|
|||||||
if (bold_font == nullptr) { throw Slic3r::RuntimeError("ImGui: Could not load deafult font"); }
|
if (bold_font == nullptr) { throw Slic3r::RuntimeError("ImGui: Could not load deafult font"); }
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_glyph_ranges == ImGui::GetIO().Fonts->GetGlyphRangesThai()) {
|
if (needs_glyph_fallback) {
|
||||||
ImFontConfig fallback_cfg = cfg;
|
ImFontConfig fallback_cfg = cfg;
|
||||||
fallback_cfg.MergeMode = true;
|
fallback_cfg.MergeMode = true;
|
||||||
static constexpr ImWchar celsius_range[] = { 0x2103, 0x2103, 0 };
|
io.Fonts->AddFontFromFileTTF((Slic3r::resources_dir() + "/fonts/HarmonyOS_Sans_SC_Bold.ttf").c_str(), m_font_size, &fallback_cfg, ranges.Data);
|
||||||
io.Fonts->AddFontFromFileTTF((Slic3r::resources_dir() + "/fonts/HarmonyOS_Sans_SC_Bold.ttf").c_str(), m_font_size, &fallback_cfg, celsius_range);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_glyph_ranges == ImGui::GetIO().Fonts->GetGlyphRangesThai()) {
|
if (m_glyph_ranges == ImGui::GetIO().Fonts->GetGlyphRangesThai()) {
|
||||||
@@ -2897,13 +2916,18 @@ void ImGuiWrapper::init_font(bool compress)
|
|||||||
glsafe(::glGetIntegerv(GL_MAX_TEXTURE_SIZE, &gl_max_tex_size));
|
glsafe(::glGetIntegerv(GL_MAX_TEXTURE_SIZE, &gl_max_tex_size));
|
||||||
constexpr int max_retries = 6;
|
constexpr int max_retries = 6;
|
||||||
for (int attempt = 0; attempt < max_retries && io.Fonts->TexHeight > gl_max_tex_size; ++attempt) {
|
for (int attempt = 0; attempt < max_retries && io.Fonts->TexHeight > gl_max_tex_size; ++attempt) {
|
||||||
io.Fonts->TexDesiredWidth = (io.Fonts->TexDesiredWidth > 0 ? io.Fonts->TexDesiredWidth : io.Fonts->TexWidth) * 2;
|
const int width = io.Fonts->TexDesiredWidth > 0 ? io.Fonts->TexDesiredWidth : io.Fonts->TexWidth;
|
||||||
|
// Both dimensions share the same limit, so widening past it would only trade an
|
||||||
|
// illegal height for an illegal width.
|
||||||
|
if (width * 2 > gl_max_tex_size)
|
||||||
|
break;
|
||||||
|
io.Fonts->TexDesiredWidth = width * 2;
|
||||||
io.Fonts->Build();
|
io.Fonts->Build();
|
||||||
}
|
}
|
||||||
if (io.Fonts->TexHeight > gl_max_tex_size) {
|
if (io.Fonts->TexHeight > gl_max_tex_size) {
|
||||||
// Shouldn't really happen
|
// Needs both a very large glyph set and a small GL_MAX_TEXTURE_SIZE.
|
||||||
BOOST_LOG_TRIVIAL(error) << "Font atlas height " << io.Fonts->TexHeight
|
BOOST_LOG_TRIVIAL(error) << "Font atlas " << io.Fonts->TexWidth << "x" << io.Fonts->TexHeight
|
||||||
<< " still exceeds GL_MAX_TEXTURE_SIZE (" << gl_max_tex_size << ")"
|
<< " does not fit GL_MAX_TEXTURE_SIZE (" << gl_max_tex_size << ")"
|
||||||
<< " after " << max_retries << " attempts; rendering may be incomplete";
|
<< " after " << max_retries << " attempts; rendering may be incomplete";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -74,7 +74,7 @@ bool ImageDPIFrame::Show(bool show)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ImageDPIFrame::set_bitmap(const wxBitmap &bit_map) {
|
void ImageDPIFrame::set_bitmap(const wxBitmap &bit_map) {
|
||||||
if (&bit_map && bit_map.IsOk()) {
|
if (bit_map.IsOk()) {
|
||||||
m_bitmap->SetBitmap(bit_map);
|
m_bitmap->SetBitmap(bit_map);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -61,7 +61,6 @@ private:
|
|||||||
::Button *m_button_year = nullptr;
|
::Button *m_button_year = nullptr;
|
||||||
::Button *m_button_month = nullptr;
|
::Button *m_button_month = nullptr;
|
||||||
::Button *m_button_all = nullptr;
|
::Button *m_button_all = nullptr;
|
||||||
::Label *m_switch_label = nullptr;
|
|
||||||
|
|
||||||
::StaticBox * m_type_panel = nullptr;
|
::StaticBox * m_type_panel = nullptr;
|
||||||
::Button * m_button_video = nullptr;
|
::Button * m_button_video = nullptr;
|
||||||
|
|||||||
@@ -40,13 +40,14 @@ static std::map<int, std::string> error_messages = {
|
|||||||
namespace Slic3r {
|
namespace Slic3r {
|
||||||
namespace GUI {
|
namespace GUI {
|
||||||
|
|
||||||
MediaPlayCtrl::MediaPlayCtrl(wxWindow *parent, wxMediaCtrl2 *media_ctrl, const wxPoint &pos, const wxSize &size)
|
MediaPlayCtrl::MediaPlayCtrl(wxWindow *parent, wxMediaCtrl3 *media_ctrl, const wxPoint &pos, const wxSize &size)
|
||||||
: wxPanel(parent, wxID_ANY, pos, size)
|
: wxPanel(parent, wxID_ANY, pos, size)
|
||||||
, m_media_ctrl(media_ctrl)
|
, m_media_ctrl(media_ctrl)
|
||||||
{
|
{
|
||||||
SetLabel("MediaPlayCtrl");
|
SetLabel("MediaPlayCtrl");
|
||||||
SetBackgroundColour(*wxWHITE);
|
SetBackgroundColour(*wxWHITE);
|
||||||
m_media_ctrl->Bind(wxEVT_MEDIA_STATECHANGED, &MediaPlayCtrl::onStateChanged, this);
|
m_media_ctrl->Bind(wxEVT_MEDIA_STATECHANGED, &MediaPlayCtrl::onStateChanged, this);
|
||||||
|
m_media_ctrl->SetIdleImage(from_u8(resources_dir() + "/images/live_stream_default.png"));
|
||||||
|
|
||||||
m_button_play = new Button(this, "", "media_play", wxBORDER_NONE);
|
m_button_play = new Button(this, "", "media_play", wxBORDER_NONE);
|
||||||
m_button_play->SetCanFocus(false);
|
m_button_play->SetCanFocus(false);
|
||||||
@@ -178,13 +179,6 @@ void MediaPlayCtrl::SetMachineObject(MachineObject* obj)
|
|||||||
if (machine == m_machine) {
|
if (machine == m_machine) {
|
||||||
if (m_last_state == MEDIASTATE_IDLE && IsEnabled())
|
if (m_last_state == MEDIASTATE_IDLE && IsEnabled())
|
||||||
Play();
|
Play();
|
||||||
else if (m_last_state == MEDIASTATE_LOADING && m_tutk_state == "disable"
|
|
||||||
&& m_last_user_play + wxTimeSpan::Seconds(3) < wxDateTime::Now()) {
|
|
||||||
// resend ttcode to printer
|
|
||||||
if (auto agent = wxGetApp().getAgent())
|
|
||||||
agent->get_camera_url(machine, [](auto) {}, wxGetApp().get_printer_cloud_provider());
|
|
||||||
m_last_user_play = wxDateTime::Now();
|
|
||||||
}
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
m_machine = machine;
|
m_machine = machine;
|
||||||
@@ -716,7 +710,9 @@ void MediaPlayCtrl::media_proc()
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else if (url == "<play>") {
|
else if (url == "<play>") {
|
||||||
|
BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl: start play";
|
||||||
m_media_ctrl->Play();
|
m_media_ctrl->Play();
|
||||||
|
BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl: end play";
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl: start load";
|
BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl: start load";
|
||||||
@@ -831,27 +827,16 @@ bool MediaPlayCtrl::get_stream_url(std::string *url)
|
|||||||
|
|
||||||
}}
|
}}
|
||||||
|
|
||||||
void wxMediaCtrl2::DoSetSize(int x, int y, int width, int height, int sizeFlags)
|
void wxMediaCtrl_OnSize(wxWindow * ctrl, wxSize const & videoSize, int width, int height)
|
||||||
{
|
{
|
||||||
#ifdef __WXMAC__
|
wxSize size = videoSize;
|
||||||
wxWindow::DoSetSize(x, y, width, height, sizeFlags);
|
if (!size.IsFullySpecified()) size = {16, 9};
|
||||||
#else
|
|
||||||
wxMediaCtrl::DoSetSize(x, y, width, height, sizeFlags);
|
|
||||||
#endif
|
|
||||||
#if defined(__LINUX__) && defined(__WXGTK__)
|
|
||||||
if (m_gtk_video_window) {
|
|
||||||
const wxSize client_size = GetClientSize();
|
|
||||||
m_gtk_video_window->SetSize(0, 0, client_size.GetWidth(), client_size.GetHeight());
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
if (sizeFlags & wxSIZE_USE_EXISTING) return;
|
|
||||||
wxSize size = m_video_size;
|
|
||||||
int maxHeight = (width * size.GetHeight() + size.GetHeight() - 1) / size.GetWidth();
|
int maxHeight = (width * size.GetHeight() + size.GetHeight() - 1) / size.GetWidth();
|
||||||
if (maxHeight != GetMaxHeight()) {
|
if (maxHeight != ctrl->GetMaxHeight()) {
|
||||||
// BOOST_LOG_TRIVIAL(info) << "wxMediaCtrl2::DoSetSize: width: " << width << ", height: " << height << ", maxHeight: " << maxHeight;
|
// BOOST_LOG_TRIVIAL(info) << "wxMediaCtrl_OnSize: width: " << width << ", height: " << height << ", maxHeight: " << maxHeight;
|
||||||
SetMaxSize({-1, maxHeight});
|
ctrl->SetMaxSize({-1, maxHeight});
|
||||||
CallAfter([this] {
|
ctrl->CallAfter([ctrl] {
|
||||||
if (auto p = GetParent()) {
|
if (auto p = ctrl->GetParent()) {
|
||||||
p->Layout();
|
p->Layout();
|
||||||
p->Refresh();
|
p->Refresh();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
#ifndef MediaPlayCtrl_h
|
#ifndef MediaPlayCtrl_h
|
||||||
#define MediaPlayCtrl_h
|
#define MediaPlayCtrl_h
|
||||||
|
|
||||||
#include "wxMediaCtrl2.h"
|
#include "wxMediaCtrl3.h"
|
||||||
|
|
||||||
#include <wx/panel.h>
|
#include <wx/panel.h>
|
||||||
|
|
||||||
@@ -30,7 +30,7 @@ namespace GUI {
|
|||||||
class MediaPlayCtrl : public wxPanel
|
class MediaPlayCtrl : public wxPanel
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
MediaPlayCtrl(wxWindow *parent, wxMediaCtrl2 *media_ctrl, const wxPoint &pos = wxDefaultPosition, const wxSize &size = wxDefaultSize);
|
MediaPlayCtrl(wxWindow *parent, wxMediaCtrl3 *media_ctrl, const wxPoint &pos = wxDefaultPosition, const wxSize &size = wxDefaultSize);
|
||||||
|
|
||||||
~MediaPlayCtrl();
|
~MediaPlayCtrl();
|
||||||
|
|
||||||
@@ -75,7 +75,7 @@ private:
|
|||||||
// token
|
// token
|
||||||
std::shared_ptr<int> m_token = std::make_shared<int>(0);
|
std::shared_ptr<int> m_token = std::make_shared<int>(0);
|
||||||
|
|
||||||
wxMediaCtrl2 * m_media_ctrl;
|
wxMediaCtrl3 * m_media_ctrl;
|
||||||
wxMediaState m_last_state = MEDIASTATE_IDLE;
|
wxMediaState m_last_state = MEDIASTATE_IDLE;
|
||||||
std::string m_machine;
|
std::string m_machine;
|
||||||
int m_lan_proto = 0;
|
int m_lan_proto = 0;
|
||||||
|
|||||||
@@ -86,11 +86,8 @@ private:
|
|||||||
|
|
||||||
/* side tools */
|
/* side tools */
|
||||||
SideTools* m_side_tools{nullptr};
|
SideTools* m_side_tools{nullptr};
|
||||||
wxStaticBitmap* m_bitmap_printer_type;
|
|
||||||
wxStaticBitmap* m_bitmap_arrow;
|
wxStaticBitmap* m_bitmap_arrow;
|
||||||
wxStaticText* m_staticText_printer_name;
|
|
||||||
wxStaticBitmap* m_bitmap_wifi_signal;
|
wxStaticBitmap* m_bitmap_wifi_signal;
|
||||||
wxBoxSizer * m_side_tools_sizer;
|
|
||||||
SelectMachinePopup m_select_machine;
|
SelectMachinePopup m_select_machine;
|
||||||
|
|
||||||
/* images */
|
/* images */
|
||||||
@@ -101,7 +98,6 @@ private:
|
|||||||
wxBitmap m_printer_img;
|
wxBitmap m_printer_img;
|
||||||
wxBitmap m_arrow_img;
|
wxBitmap m_arrow_img;
|
||||||
|
|
||||||
int last_wifi_signal = -1;
|
|
||||||
int last_status;
|
int last_status;
|
||||||
bool m_initialized { false };
|
bool m_initialized { false };
|
||||||
bool update_flag{false};
|
bool update_flag{false};
|
||||||
|
|||||||
@@ -34,7 +34,6 @@
|
|||||||
#include "Widgets/AxisCtrlButton.hpp"
|
#include "Widgets/AxisCtrlButton.hpp"
|
||||||
#include "Widgets/TextInput.hpp"
|
#include "Widgets/TextInput.hpp"
|
||||||
#include "Widgets/StaticLine.hpp"
|
#include "Widgets/StaticLine.hpp"
|
||||||
#include "wxMediaCtrl2.h"
|
|
||||||
#include "MediaPlayCtrl.h"
|
#include "MediaPlayCtrl.h"
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
|||||||
@@ -88,7 +88,6 @@ private:
|
|||||||
Button* m_task_name{ nullptr };
|
Button* m_task_name{ nullptr };
|
||||||
Button* m_status{ nullptr };
|
Button* m_status{ nullptr };
|
||||||
Button* m_action{ nullptr };
|
Button* m_action{ nullptr };
|
||||||
Button* m_stop_all_botton{nullptr};
|
|
||||||
|
|
||||||
// tip when no device
|
// tip when no device
|
||||||
wxStaticText* m_tip_text{ nullptr };
|
wxStaticText* m_tip_text{ nullptr };
|
||||||
|
|||||||
@@ -79,7 +79,6 @@ private:
|
|||||||
std::vector<wxBoxSizer *> m_row_col_boxsizer_list;
|
std::vector<wxBoxSizer *> m_row_col_boxsizer_list;
|
||||||
std::vector<ButtonState*> m_result_icon_list;
|
std::vector<ButtonState*> m_result_icon_list;
|
||||||
int m_last_cluster_num{-1};
|
int m_last_cluster_num{-1};
|
||||||
const int m_combox_width{50};
|
|
||||||
int m_combox_icon_width;
|
int m_combox_icon_width;
|
||||||
int m_combox_icon_height;
|
int m_combox_icon_height;
|
||||||
wxButton * m_image_button = nullptr;
|
wxButton * m_image_button = nullptr;
|
||||||
|
|||||||
@@ -6470,7 +6470,7 @@ int PartPlateList::store_to_3mf_structure(PlateDataPtrs& plate_data_list, bool w
|
|||||||
plate_data_item->filament_change_sequence = m_plate_list[i]->m_gcode_result->filament_change_sequence;
|
plate_data_item->filament_change_sequence = m_plate_list[i]->m_gcode_result->filament_change_sequence;
|
||||||
plate_data_item->nozzle_change_sequence = m_plate_list[i]->m_gcode_result->nozzle_change_sequence;
|
plate_data_item->nozzle_change_sequence = m_plate_list[i]->m_gcode_result->nozzle_change_sequence;
|
||||||
plate_data_item->optimal_assignment = m_plate_list[i]->m_gcode_result->optimal_assignment;
|
plate_data_item->optimal_assignment = m_plate_list[i]->m_gcode_result->optimal_assignment;
|
||||||
plate_data_item->first_layer_time = std::to_string(m_plate_list[i]->cali_bboxes_data.first_layer_time);
|
plate_data_item->first_layer_time = std::to_string(m_plate_list[i]->get_slice_result()->initial_layer_time);
|
||||||
Print *print = nullptr;
|
Print *print = nullptr;
|
||||||
m_plate_list[i]->get_print((PrintBase **) &print, nullptr, nullptr);
|
m_plate_list[i]->get_print((PrintBase **) &print, nullptr, nullptr);
|
||||||
if (print) {
|
if (print) {
|
||||||
|
|||||||
@@ -128,7 +128,6 @@ private:
|
|||||||
bool is_drag_mode();
|
bool is_drag_mode();
|
||||||
|
|
||||||
boost::shared_ptr<PrinterFileSystem> m_file_sys;
|
boost::shared_ptr<PrinterFileSystem> m_file_sys;
|
||||||
bool m_file_sys_result{false};
|
|
||||||
std::string m_timestamp;
|
std::string m_timestamp;
|
||||||
std::string m_tmp_path;
|
std::string m_tmp_path;
|
||||||
std::vector<string> m_local_paths;
|
std::vector<string> m_local_paths;
|
||||||
|
|||||||
@@ -33,7 +33,6 @@ class PhysicalPrinterDialog : public DPIDialog
|
|||||||
Button* m_printhost_test_btn {nullptr};
|
Button* m_printhost_test_btn {nullptr};
|
||||||
Button* m_printhost_logout_btn {nullptr};
|
Button* m_printhost_logout_btn {nullptr};
|
||||||
Button* m_printhost_cafile_browse_btn {nullptr};
|
Button* m_printhost_cafile_browse_btn {nullptr};
|
||||||
Button* m_printhost_client_cert_browse_btn {nullptr};
|
|
||||||
Button* m_printhost_port_browse_btn {nullptr};
|
Button* m_printhost_port_browse_btn {nullptr};
|
||||||
|
|
||||||
RoundedRectangle* m_input_area {nullptr};
|
RoundedRectangle* m_input_area {nullptr};
|
||||||
|
|||||||
@@ -3870,7 +3870,7 @@ bool Sidebar::reset_bed_type_combox_choices(bool is_sidebar_init)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
m_last_combo_bedtype_count = p->combo_printer_bed->GetCount();
|
m_last_combo_bedtype_count = p->combo_printer_bed->GetCount();
|
||||||
if (!is_sidebar_init && &p->plater->get_partplate_list()) {
|
if (!is_sidebar_init) {
|
||||||
p->plater->get_partplate_list().check_all_plate_local_bed_type(m_cur_combox_bed_types);
|
p->plater->get_partplate_list().check_all_plate_local_bed_type(m_cur_combox_bed_types);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@@ -21688,7 +21688,7 @@ void Plater::show_object_info()
|
|||||||
auto mesh_errors = p->sidebar->obj_list()->get_mesh_errors_info(&info_manifold, &non_manifold_edges);
|
auto mesh_errors = p->sidebar->obj_list()->get_mesh_errors_info(&info_manifold, &non_manifold_edges);
|
||||||
|
|
||||||
if (non_manifold_edges > 0) {
|
if (non_manifold_edges > 0) {
|
||||||
info_manifold += into_u8("\n" + _L("Tips:") + "\n" + _L("Use \"Fix Model\" to repair the mesh."));
|
info_manifold += "\n" + _L("Tips:") + "\n" + _L("Use \"Fix Model\" to repair the mesh.");
|
||||||
}
|
}
|
||||||
|
|
||||||
info_manifold = "<Error>" + info_manifold + "</Error>";
|
info_manifold = "<Error>" + info_manifold + "</Error>";
|
||||||
|
|||||||
@@ -662,10 +662,10 @@ PrinterFileSystem::File const &PrinterFileSystem::GetFile(size_t index, bool &se
|
|||||||
void PrinterFileSystem::Attached()
|
void PrinterFileSystem::Attached()
|
||||||
{
|
{
|
||||||
boost::unique_lock lock(m_mutex);
|
boost::unique_lock lock(m_mutex);
|
||||||
m_recv_thread = std::move(boost::thread([w = weak_from_this()] {
|
m_recv_thread = boost::thread([w = weak_from_this()] {
|
||||||
boost::shared_ptr<PrinterFileSystem> s = w.lock();
|
boost::shared_ptr<PrinterFileSystem> s = w.lock();
|
||||||
if (s) s->RecvMessageThread();
|
if (s) s->RecvMessageThread();
|
||||||
}));
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void PrinterFileSystem::Start()
|
void PrinterFileSystem::Start()
|
||||||
|
|||||||
@@ -1,657 +0,0 @@
|
|||||||
/* bambusrc for gstreamer
|
|
||||||
* integration with proprietary Bambu Lab blob for getting raw h.264 video
|
|
||||||
*
|
|
||||||
* Copyright (C) 2023 Joshua Wise <joshua@accelerated.tech>
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
|
||||||
* copy of this software and associated documentation files (the "Software"),
|
|
||||||
* to deal in the Software without restriction, including without limitation
|
|
||||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
||||||
* and/or sell copies of the Software, and to permit persons to whom the
|
|
||||||
* Software is 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 Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS 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 SOFTWARE OR THE USE OR OTHER
|
|
||||||
* DEALINGS IN THE SOFTWARE.
|
|
||||||
*
|
|
||||||
* Alternatively, the contents of this file may be used under the
|
|
||||||
* GNU Lesser General Public License Version 2.1 (the "LGPL"), in
|
|
||||||
* which case the following provisions apply instead of the ones
|
|
||||||
* mentioned above:
|
|
||||||
*
|
|
||||||
* This library is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU Library General Public
|
|
||||||
* License as published by the Free Software Foundation; either
|
|
||||||
* version 2 of the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This library is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* Library General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Library General Public
|
|
||||||
* License along with this library; if not, write to the
|
|
||||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
|
||||||
* Boston, MA 02111-1307, USA.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
|
||||||
# include <config.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <gst/gst.h>
|
|
||||||
|
|
||||||
#include "gstbambusrc.h"
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#ifndef EXTERNAL_GST_PLUGIN
|
|
||||||
#define BAMBU_DYNAMIC
|
|
||||||
#endif
|
|
||||||
#include "BambuTunnel.h"
|
|
||||||
|
|
||||||
#ifdef BAMBU_DYNAMIC
|
|
||||||
// From PrinterFileSystem.
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C"
|
|
||||||
#else
|
|
||||||
extern
|
|
||||||
#endif
|
|
||||||
BambuLib *bambulib_get();
|
|
||||||
BambuLib *_lib = NULL;
|
|
||||||
#define BAMBULIB(x) (_lib->x)
|
|
||||||
|
|
||||||
#else
|
|
||||||
#define BAMBULIB(x) (x)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
GST_DEBUG_CATEGORY_STATIC (gst_bambusrc_debug);
|
|
||||||
#define GST_CAT_DEFAULT gst_bambusrc_debug
|
|
||||||
|
|
||||||
static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src",
|
|
||||||
GST_PAD_SRC,
|
|
||||||
GST_PAD_ALWAYS,
|
|
||||||
GST_STATIC_CAPS_ANY);
|
|
||||||
//GST_STATIC_CAPS("video/x-h264,framerate=0/1,parsed=(boolean)false,stream-format=(string)byte-stream"));
|
|
||||||
|
|
||||||
enum
|
|
||||||
{
|
|
||||||
PROP_0,
|
|
||||||
PROP_LOCATION,
|
|
||||||
};
|
|
||||||
|
|
||||||
static void gst_bambusrc_uri_handler_init (gpointer g_iface,
|
|
||||||
gpointer iface_data);
|
|
||||||
static void gst_bambusrc_finalize (GObject * gobject);
|
|
||||||
static void gst_bambusrc_dispose (GObject * gobject);
|
|
||||||
|
|
||||||
static void gst_bambusrc_set_property (GObject * object, guint prop_id,
|
|
||||||
const GValue * value, GParamSpec * pspec);
|
|
||||||
static void gst_bambusrc_get_property (GObject * object, guint prop_id,
|
|
||||||
GValue * value, GParamSpec * pspec);
|
|
||||||
|
|
||||||
static GstStateChangeReturn gst_bambusrc_change_state (GstElement *
|
|
||||||
element, GstStateChange transition);
|
|
||||||
static GstFlowReturn gst_bambusrc_create (GstPushSrc * psrc,
|
|
||||||
GstBuffer ** outbuf);
|
|
||||||
static gboolean gst_bambusrc_start (GstBaseSrc * bsrc);
|
|
||||||
static gboolean gst_bambusrc_stop (GstBaseSrc * bsrc);
|
|
||||||
static gboolean gst_bambusrc_is_seekable (GstBaseSrc * bsrc);
|
|
||||||
static gboolean gst_bambusrc_query (GstBaseSrc * bsrc, GstQuery * query);
|
|
||||||
static gboolean gst_bambusrc_unlock (GstBaseSrc * bsrc);
|
|
||||||
static gboolean gst_bambusrc_unlock_stop (GstBaseSrc * bsrc);
|
|
||||||
static gboolean gst_bambusrc_set_location (GstBambuSrc * src,
|
|
||||||
const gchar * uri, GError ** error);
|
|
||||||
|
|
||||||
#define gst_bambusrc_parent_class parent_class
|
|
||||||
G_DEFINE_TYPE_WITH_CODE (GstBambuSrc, gst_bambusrc, GST_TYPE_PUSH_SRC,
|
|
||||||
G_IMPLEMENT_INTERFACE (GST_TYPE_URI_HANDLER,
|
|
||||||
gst_bambusrc_uri_handler_init));
|
|
||||||
|
|
||||||
static void
|
|
||||||
gst_bambusrc_class_init (GstBambuSrcClass * klass)
|
|
||||||
{
|
|
||||||
GObjectClass *gobject_class;
|
|
||||||
GstElementClass *gstelement_class;
|
|
||||||
GstBaseSrcClass *gstbasesrc_class;
|
|
||||||
GstPushSrcClass *gstpushsrc_class;
|
|
||||||
|
|
||||||
gobject_class = (GObjectClass *) klass;
|
|
||||||
gstelement_class = (GstElementClass *) klass;
|
|
||||||
gstbasesrc_class = (GstBaseSrcClass *) klass;
|
|
||||||
gstpushsrc_class = (GstPushSrcClass *) klass;
|
|
||||||
|
|
||||||
gobject_class->set_property = gst_bambusrc_set_property;
|
|
||||||
gobject_class->get_property = gst_bambusrc_get_property;
|
|
||||||
gobject_class->finalize = gst_bambusrc_finalize;
|
|
||||||
gobject_class->dispose = gst_bambusrc_dispose;
|
|
||||||
|
|
||||||
g_object_class_install_property (gobject_class,
|
|
||||||
PROP_LOCATION,
|
|
||||||
g_param_spec_string ("location", "Location",
|
|
||||||
"URI to pass to Bambu Lab blobs", "",
|
|
||||||
(GParamFlags)(G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
|
|
||||||
|
|
||||||
gst_element_class_add_static_pad_template (gstelement_class, &srctemplate);
|
|
||||||
|
|
||||||
gst_element_class_set_static_metadata (gstelement_class, "Bambu Lab source",
|
|
||||||
"Source/Network",
|
|
||||||
"Receive data as a client over the network using the proprietary Bambu Lab blobs",
|
|
||||||
"Joshua Wise <joshua@accelerated.tech>");
|
|
||||||
gstelement_class->change_state =
|
|
||||||
GST_DEBUG_FUNCPTR (gst_bambusrc_change_state);
|
|
||||||
|
|
||||||
gstbasesrc_class->start = GST_DEBUG_FUNCPTR (gst_bambusrc_start);
|
|
||||||
gstbasesrc_class->stop = GST_DEBUG_FUNCPTR (gst_bambusrc_stop);
|
|
||||||
gstbasesrc_class->unlock = GST_DEBUG_FUNCPTR (gst_bambusrc_unlock);
|
|
||||||
gstbasesrc_class->unlock_stop =
|
|
||||||
GST_DEBUG_FUNCPTR (gst_bambusrc_unlock_stop);
|
|
||||||
gstbasesrc_class->is_seekable =
|
|
||||||
GST_DEBUG_FUNCPTR (gst_bambusrc_is_seekable);
|
|
||||||
gstbasesrc_class->query = GST_DEBUG_FUNCPTR (gst_bambusrc_query);
|
|
||||||
|
|
||||||
gstpushsrc_class->create = GST_DEBUG_FUNCPTR (gst_bambusrc_create);
|
|
||||||
|
|
||||||
GST_DEBUG_CATEGORY_INIT (gst_bambusrc_debug, "bambusrc", 0,
|
|
||||||
"Bambu Lab src");
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
gst_bambusrc_reset (GstBambuSrc * src)
|
|
||||||
{
|
|
||||||
gst_caps_replace (&src->src_caps, NULL);
|
|
||||||
if (src->tnl) {
|
|
||||||
BAMBULIB(Bambu_Close)(src->tnl);
|
|
||||||
BAMBULIB(Bambu_Destroy)(src->tnl);
|
|
||||||
src->tnl = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
gst_bambusrc_init (GstBambuSrc * src)
|
|
||||||
{
|
|
||||||
src->location = NULL;
|
|
||||||
src->tnl = NULL;
|
|
||||||
|
|
||||||
gst_base_src_set_automatic_eos (GST_BASE_SRC (src), FALSE);
|
|
||||||
gst_base_src_set_live(GST_BASE_SRC(src), TRUE);
|
|
||||||
|
|
||||||
gst_bambusrc_reset (src);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
gst_bambusrc_dispose (GObject * gobject)
|
|
||||||
{
|
|
||||||
GstBambuSrc *src = GST_BAMBUSRC (gobject);
|
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (src, "dispose");
|
|
||||||
|
|
||||||
G_OBJECT_CLASS (parent_class)->dispose (gobject);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
gst_bambusrc_finalize (GObject * gobject)
|
|
||||||
{
|
|
||||||
GstBambuSrc *src = GST_BAMBUSRC (gobject);
|
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (src, "finalize");
|
|
||||||
|
|
||||||
g_free (src->location);
|
|
||||||
if (src->tnl) {
|
|
||||||
BAMBULIB(Bambu_Close)(src->tnl);
|
|
||||||
BAMBULIB(Bambu_Destroy)(src->tnl);
|
|
||||||
}
|
|
||||||
|
|
||||||
G_OBJECT_CLASS (parent_class)->finalize (gobject);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
gst_bambusrc_set_property (GObject * object, guint prop_id,
|
|
||||||
const GValue * value, GParamSpec * pspec)
|
|
||||||
{
|
|
||||||
GstBambuSrc *src = GST_BAMBUSRC (object);
|
|
||||||
|
|
||||||
switch (prop_id) {
|
|
||||||
case PROP_LOCATION:
|
|
||||||
{
|
|
||||||
const gchar *location;
|
|
||||||
|
|
||||||
location = g_value_get_string (value);
|
|
||||||
|
|
||||||
if (location == NULL) {
|
|
||||||
GST_WARNING ("location property cannot be NULL");
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
if (!gst_bambusrc_set_location (src, location, NULL)) {
|
|
||||||
GST_WARNING ("badly formatted location");
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
done:
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
gst_bambusrc_get_property (GObject * object, guint prop_id,
|
|
||||||
GValue * value, GParamSpec * pspec)
|
|
||||||
{
|
|
||||||
GstBambuSrc *src = GST_BAMBUSRC (object);
|
|
||||||
|
|
||||||
switch (prop_id) {
|
|
||||||
case PROP_LOCATION:
|
|
||||||
g_value_set_string (value, src->location);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int gst_bambu_last_error = 0;
|
|
||||||
|
|
||||||
static GstFlowReturn
|
|
||||||
gst_bambusrc_create (GstPushSrc * psrc, GstBuffer ** outbuf)
|
|
||||||
{
|
|
||||||
GstBambuSrc *src;
|
|
||||||
|
|
||||||
src = GST_BAMBUSRC (psrc);
|
|
||||||
|
|
||||||
(void) src;
|
|
||||||
GST_DEBUG_OBJECT (src, "create()");
|
|
||||||
|
|
||||||
int rv;
|
|
||||||
Bambu_Sample sample;
|
|
||||||
|
|
||||||
if (!src->tnl) {
|
|
||||||
return GST_FLOW_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
while ((rv = BAMBULIB(Bambu_ReadSample)(src->tnl, &sample)) == Bambu_would_block) {
|
|
||||||
GST_DEBUG_OBJECT(src, "create would block");
|
|
||||||
usleep(33333); /* 30Hz */
|
|
||||||
}
|
|
||||||
|
|
||||||
if (rv == Bambu_stream_end) {
|
|
||||||
return GST_FLOW_EOS;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (rv != Bambu_success) {
|
|
||||||
gst_bambu_last_error = rv;
|
|
||||||
return GST_FLOW_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if GLIB_CHECK_VERSION(2,68,0)
|
|
||||||
gpointer sbuf = g_memdup2(sample.buffer, sample.size);
|
|
||||||
#else
|
|
||||||
gpointer sbuf = g_memdup(sample.buffer, sample.size);
|
|
||||||
#endif
|
|
||||||
*outbuf = gst_buffer_new_wrapped_full(0, sbuf, sample.size, 0, sample.size, sbuf, g_free);
|
|
||||||
|
|
||||||
/* Synthesize monotonic timestamps at the announced frame rate, anchored
|
|
||||||
* to the first frame's arrival time. The X1C's RTSPS server emits
|
|
||||||
* unreliable decode timestamps (wildly non-monotonic jumps, or sometimes
|
|
||||||
* none at all); forwarding them directly froze the pipeline after a few
|
|
||||||
* seconds. Pacing on a synthesized clock — the same trick mpv uses when
|
|
||||||
* it reports "No video PTS! Making something up." — gives smooth
|
|
||||||
* playback regardless of network jitter, and only drops late frames if
|
|
||||||
* the printer can't keep up. A snap-back resets the anchor if real
|
|
||||||
* arrival drifts more than two frame periods from the synthesized
|
|
||||||
* timeline (e.g. announced framerate was wrong).
|
|
||||||
*/
|
|
||||||
GstClock *clock = GST_ELEMENT_CLOCK(psrc);
|
|
||||||
GstClockTime base_time = gst_element_get_base_time((GstElement *)psrc);
|
|
||||||
GstClockTime running_now = GST_CLOCK_TIME_NONE;
|
|
||||||
if (clock) {
|
|
||||||
GstClockTime now = gst_clock_get_time(clock);
|
|
||||||
if (now != GST_CLOCK_TIME_NONE && now >= base_time)
|
|
||||||
running_now = now - base_time;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Adapt the period to actual inter-arrival time via EWMA. The announced
|
|
||||||
* frame_rate is unreliable on Bambu printers (X1C announces 30 but
|
|
||||||
* delivers ~28), so trusting it causes the synthesized timeline to drift
|
|
||||||
* relative to real time, which makes the sink consider frames late and
|
|
||||||
* skip pacing entirely. Measuring the real rate keeps PTS in step with
|
|
||||||
* arrival on average, so the sink can pace inside bursts while still
|
|
||||||
* tracking the printer's actual frame cadence.
|
|
||||||
*/
|
|
||||||
if (src->avg_period == 0) {
|
|
||||||
int fps = src->frame_rate > 0 ? src->frame_rate : 30;
|
|
||||||
src->avg_period = GST_SECOND / fps;
|
|
||||||
}
|
|
||||||
if (running_now != GST_CLOCK_TIME_NONE && src->last_arrival != 0) {
|
|
||||||
GstClockTimeDiff delta = GST_CLOCK_DIFF(src->last_arrival, running_now);
|
|
||||||
/* clamp to plausible video frame periods (5..200 ms) so a one-off
|
|
||||||
* burst-of-zero or long stall doesn't poison the average */
|
|
||||||
if (delta > 5 * GST_MSECOND && delta < 200 * GST_MSECOND) {
|
|
||||||
src->avg_period = (src->avg_period * 15 + (GstClockTime)delta) / 16;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
src->last_arrival = (running_now != GST_CLOCK_TIME_NONE) ? running_now : src->last_arrival;
|
|
||||||
GstClockTime period = src->avg_period;
|
|
||||||
|
|
||||||
/* Lead time: schedule frames a few periods in the future of their
|
|
||||||
* arrival, so the sink has a small jitter buffer. Without this, frames
|
|
||||||
* arriving slightly later than expected land behind the running clock
|
|
||||||
* and the sink renders them immediately, producing visible stutter.
|
|
||||||
* 100ms is invisible for a live print-monitor view.
|
|
||||||
*/
|
|
||||||
const GstClockTime LEAD = 100 * GST_MSECOND;
|
|
||||||
|
|
||||||
if (!src->sttime) {
|
|
||||||
src->sttime = (running_now != GST_CLOCK_TIME_NONE) ? running_now + LEAD : LEAD;
|
|
||||||
src->frame_count = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
GstClockTime pts = src->sttime + src->frame_count * period;
|
|
||||||
|
|
||||||
/* Safety net: with the lead applied, expected drift is roughly -LEAD
|
|
||||||
* (pts sits LEAD ns ahead of running_now). Re-anchor only if the
|
|
||||||
* synthesized timeline diverges from that expectation by several frame
|
|
||||||
* periods, which indicates a real disturbance (printer paused, stream
|
|
||||||
* resumed, large fps change) rather than ordinary jitter.
|
|
||||||
*/
|
|
||||||
if (running_now != GST_CLOCK_TIME_NONE) {
|
|
||||||
GstClockTimeDiff drift = GST_CLOCK_DIFF(pts, running_now);
|
|
||||||
GstClockTimeDiff expected = -(GstClockTimeDiff)LEAD;
|
|
||||||
GstClockTimeDiff slack = (GstClockTimeDiff)(4 * period);
|
|
||||||
if (drift > expected + slack || drift < expected - slack) {
|
|
||||||
GST_DEBUG_OBJECT(src, "ts drift %" G_GINT64_FORMAT " ns; re-anchoring", drift);
|
|
||||||
src->sttime = running_now + LEAD;
|
|
||||||
src->frame_count = 0;
|
|
||||||
pts = src->sttime;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
GST_BUFFER_PTS(*outbuf) = pts;
|
|
||||||
GST_BUFFER_DTS(*outbuf) = pts;
|
|
||||||
GST_BUFFER_DURATION(*outbuf) = period;
|
|
||||||
src->frame_count++;
|
|
||||||
GST_DEBUG_OBJECT(src,
|
|
||||||
"sttime:%lu, DTS:%lu, PTS: %lu~",
|
|
||||||
src->sttime, GST_BUFFER_DTS(*outbuf), GST_BUFFER_PTS(*outbuf));
|
|
||||||
|
|
||||||
return GST_FLOW_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void _log(void *ctx, int lvl, const char *msg) {
|
|
||||||
GstBambuSrc *src = (GstBambuSrc *) ctx;
|
|
||||||
GST_DEBUG_OBJECT(src, "bambu: %s", msg);
|
|
||||||
BAMBULIB(Bambu_FreeLogMsg)(msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
static gboolean
|
|
||||||
gst_bambusrc_start (GstBaseSrc * bsrc)
|
|
||||||
{
|
|
||||||
GstBambuSrc *src = GST_BAMBUSRC (bsrc);
|
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (src, "start(\"%s\")", src->location);
|
|
||||||
|
|
||||||
if (src->tnl) {
|
|
||||||
BAMBULIB(Bambu_Close)(src->tnl);
|
|
||||||
BAMBULIB(Bambu_Destroy)(src->tnl);
|
|
||||||
src->tnl = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef BAMBU_DYNAMIC
|
|
||||||
if (!_lib) {
|
|
||||||
_lib = bambulib_get();
|
|
||||||
if (!_lib->Bambu_Open) {
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
if (BAMBULIB(Bambu_Create)(&src->tnl, src->location) != Bambu_success) {
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
int rv = 0;
|
|
||||||
BAMBULIB(Bambu_SetLogger)(src->tnl, _log, (void *)src);
|
|
||||||
if ((rv = BAMBULIB(Bambu_Open)(src->tnl)) != Bambu_success) {
|
|
||||||
BAMBULIB(Bambu_Destroy)(src->tnl);
|
|
||||||
src->tnl = NULL;
|
|
||||||
gst_bambu_last_error = rv;
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
int n = 0;
|
|
||||||
while ((rv = BAMBULIB(Bambu_StartStream)(src->tnl, 1 /* video */)) == Bambu_would_block) {
|
|
||||||
usleep(100000);
|
|
||||||
}
|
|
||||||
if (rv != Bambu_success) {
|
|
||||||
BAMBULIB(Bambu_Close)(src->tnl);
|
|
||||||
BAMBULIB(Bambu_Destroy)(src->tnl);
|
|
||||||
src->tnl = NULL;
|
|
||||||
gst_bambu_last_error = rv;
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
src->video_type = AVC1;
|
|
||||||
n = BAMBULIB(Bambu_GetStreamCount)(src->tnl);
|
|
||||||
GST_INFO_OBJECT (src, "Bambu_GetStreamCount returned stream count=%d",n);
|
|
||||||
for (int i = 0; i < n; ++i) {
|
|
||||||
Bambu_StreamInfo info;
|
|
||||||
BAMBULIB(Bambu_GetStreamInfo)(src->tnl, i, &info);
|
|
||||||
|
|
||||||
GST_INFO_OBJECT (src, "stream %d type=%d, sub_type=%d", i, info.type, info.sub_type);
|
|
||||||
if (info.type == VIDE) {
|
|
||||||
src->video_type = info.sub_type;
|
|
||||||
src->frame_rate = info.format.video.frame_rate;
|
|
||||||
GST_INFO_OBJECT (src, " width %d height=%d, frame_rate=%d",
|
|
||||||
info.format.video.width, info.format.video.height, info.format.video.frame_rate);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
src->sttime = 0;
|
|
||||||
src->frame_count = 0;
|
|
||||||
src->last_arrival = 0;
|
|
||||||
src->avg_period = 0;
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static gboolean
|
|
||||||
gst_bambusrc_stop (GstBaseSrc * bsrc)
|
|
||||||
{
|
|
||||||
GstBambuSrc *src;
|
|
||||||
|
|
||||||
src = GST_BAMBUSRC (bsrc);
|
|
||||||
GST_DEBUG_OBJECT (src, "stop()");
|
|
||||||
if (src->tnl) {
|
|
||||||
BAMBULIB(Bambu_Close)(src->tnl);
|
|
||||||
BAMBULIB(Bambu_Destroy)(src->tnl);
|
|
||||||
src->tnl = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static GstStateChangeReturn
|
|
||||||
gst_bambusrc_change_state (GstElement * element, GstStateChange transition)
|
|
||||||
{
|
|
||||||
GstStateChangeReturn ret;
|
|
||||||
GstBambuSrc *src;
|
|
||||||
|
|
||||||
src = GST_BAMBUSRC (element);
|
|
||||||
|
|
||||||
(void) src;
|
|
||||||
|
|
||||||
switch (transition) {
|
|
||||||
case GST_STATE_CHANGE_READY_TO_NULL:
|
|
||||||
//gst_bambusrc_session_close (src);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Interrupt a blocking request. */
|
|
||||||
static gboolean
|
|
||||||
gst_bambusrc_unlock (GstBaseSrc * bsrc)
|
|
||||||
{
|
|
||||||
GstBambuSrc *src;
|
|
||||||
|
|
||||||
src = GST_BAMBUSRC (bsrc);
|
|
||||||
GST_DEBUG_OBJECT (src, "unlock()");
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Interrupt interrupt. */
|
|
||||||
static gboolean
|
|
||||||
gst_bambusrc_unlock_stop (GstBaseSrc * bsrc)
|
|
||||||
{
|
|
||||||
GstBambuSrc *src;
|
|
||||||
|
|
||||||
src = GST_BAMBUSRC (bsrc);
|
|
||||||
GST_DEBUG_OBJECT (src, "unlock_stop()");
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static gboolean
|
|
||||||
gst_bambusrc_is_seekable (GstBaseSrc * bsrc)
|
|
||||||
{
|
|
||||||
GstBambuSrc *src = GST_BAMBUSRC (bsrc);
|
|
||||||
|
|
||||||
(void) src;
|
|
||||||
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static gboolean
|
|
||||||
gst_bambusrc_query (GstBaseSrc * bsrc, GstQuery * query)
|
|
||||||
{
|
|
||||||
GstBambuSrc *src = GST_BAMBUSRC (bsrc);
|
|
||||||
gboolean ret;
|
|
||||||
GstSchedulingFlags flags;
|
|
||||||
gint minsize, maxsize, align;
|
|
||||||
|
|
||||||
switch (GST_QUERY_TYPE (query)) {
|
|
||||||
case GST_QUERY_URI:
|
|
||||||
gst_query_set_uri (query, src->location);
|
|
||||||
ret = TRUE;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
ret = FALSE;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!ret)
|
|
||||||
ret = GST_BASE_SRC_CLASS (parent_class)->query (bsrc, query);
|
|
||||||
|
|
||||||
switch (GST_QUERY_TYPE (query)) {
|
|
||||||
case GST_QUERY_SCHEDULING:
|
|
||||||
gst_query_parse_scheduling (query, &flags, &minsize, &maxsize, &align);
|
|
||||||
flags = (GstSchedulingFlags)((int)flags | (int)GST_SCHEDULING_FLAG_SEQUENTIAL);
|
|
||||||
gst_query_set_scheduling (query, flags, minsize, maxsize, align);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static gboolean
|
|
||||||
gst_bambusrc_set_location (GstBambuSrc * src, const gchar * uri,
|
|
||||||
GError ** error)
|
|
||||||
{
|
|
||||||
if (src->location) {
|
|
||||||
g_free (src->location);
|
|
||||||
src->location = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (uri == NULL)
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
src->location = g_strdup (uri);
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static GstURIType
|
|
||||||
gst_bambusrc_uri_get_type (GType type)
|
|
||||||
{
|
|
||||||
return GST_URI_SRC;
|
|
||||||
}
|
|
||||||
|
|
||||||
static const gchar *const *
|
|
||||||
gst_bambusrc_uri_get_protocols (GType type)
|
|
||||||
{
|
|
||||||
static const gchar *protocols[] = { "bambu", NULL };
|
|
||||||
|
|
||||||
return protocols;
|
|
||||||
}
|
|
||||||
|
|
||||||
static gchar *
|
|
||||||
gst_bambusrc_uri_get_uri (GstURIHandler * handler)
|
|
||||||
{
|
|
||||||
GstBambuSrc *src = GST_BAMBUSRC (handler);
|
|
||||||
|
|
||||||
/* FIXME: make thread-safe */
|
|
||||||
return g_strdup (src->location);
|
|
||||||
}
|
|
||||||
|
|
||||||
static gboolean
|
|
||||||
gst_bambusrc_uri_set_uri (GstURIHandler * handler, const gchar * uri,
|
|
||||||
GError ** error)
|
|
||||||
{
|
|
||||||
GstBambuSrc *src = GST_BAMBUSRC (handler);
|
|
||||||
|
|
||||||
return gst_bambusrc_set_location (src, uri, error);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
gst_bambusrc_uri_handler_init (gpointer g_iface, gpointer iface_data)
|
|
||||||
{
|
|
||||||
GstURIHandlerInterface *iface = (GstURIHandlerInterface *) g_iface;
|
|
||||||
|
|
||||||
iface->get_type = gst_bambusrc_uri_get_type;
|
|
||||||
iface->get_protocols = gst_bambusrc_uri_get_protocols;
|
|
||||||
iface->get_uri = gst_bambusrc_uri_get_uri;
|
|
||||||
iface->set_uri = gst_bambusrc_uri_set_uri;
|
|
||||||
}
|
|
||||||
|
|
||||||
static gboolean gstbambusrc_init(GstPlugin *plugin)
|
|
||||||
{
|
|
||||||
return gst_element_register(plugin, "bambusrc", GST_RANK_PRIMARY, GST_TYPE_BAMBUSRC);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef EXTERNAL_GST_PLUGIN
|
|
||||||
|
|
||||||
// for use inside of Bambu Slicer
|
|
||||||
void gstbambusrc_register()
|
|
||||||
{
|
|
||||||
static int did_register = 0;
|
|
||||||
if (did_register)
|
|
||||||
return;
|
|
||||||
did_register = 1;
|
|
||||||
|
|
||||||
gst_plugin_register_static(GST_VERSION_MAJOR, GST_VERSION_MINOR, "bambusrc", "Bambu Lab source", gstbambusrc_init, "0.0.1", "GPL", "BambuStudio", "BambuStudio", "https://github.com/bambulab/BambuStudio");
|
|
||||||
}
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
#ifndef PACKAGE
|
|
||||||
#define PACKAGE "bambusrc"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, GST_VERSION_MINOR, bambusrc, "Bambu Lab source", gstbambusrc_init, "0.0.1", "GPL", "BambuStudio", "https://github.com/bambulab/BambuStudio")
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,78 +0,0 @@
|
|||||||
/* bambusrc for gstreamer
|
|
||||||
* integration with proprietary Bambu Lab blob for getting raw h.264 video
|
|
||||||
*
|
|
||||||
* Copyright (C) 2023 Joshua Wise <joshua@accelerated.tech>
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
|
||||||
* copy of this software and associated documentation files (the "Software"),
|
|
||||||
* to deal in the Software without restriction, including without limitation
|
|
||||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
||||||
* and/or sell copies of the Software, and to permit persons to whom the
|
|
||||||
* Software is 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 Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS 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 SOFTWARE OR THE USE OR OTHER
|
|
||||||
* DEALINGS IN THE SOFTWARE.
|
|
||||||
*
|
|
||||||
* Alternatively, the contents of this file may be used under the
|
|
||||||
* GNU Lesser General Public License Version 2.1 (the "LGPL"), in
|
|
||||||
* which case the following provisions apply instead of the ones
|
|
||||||
* mentioned above:
|
|
||||||
*
|
|
||||||
* This library is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU Library General Public
|
|
||||||
* License as published by the Free Software Foundation; either
|
|
||||||
* version 2 of the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This library is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* Library General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Library General Public
|
|
||||||
* License along with this library; if not, write to the
|
|
||||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
|
||||||
* Boston, MA 02111-1307, USA.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef __GST_BAMBUSRC_H__
|
|
||||||
#define __GST_BAMBUSRC_H__
|
|
||||||
|
|
||||||
#include <gst/gst.h>
|
|
||||||
#include <gst/base/gstpushsrc.h>
|
|
||||||
#include <glib.h>
|
|
||||||
|
|
||||||
G_BEGIN_DECLS
|
|
||||||
|
|
||||||
#define GST_TYPE_BAMBUSRC (gst_bambusrc_get_type())
|
|
||||||
G_DECLARE_FINAL_TYPE (GstBambuSrc, gst_bambusrc,
|
|
||||||
GST, BAMBUSRC, GstPushSrc)
|
|
||||||
|
|
||||||
typedef void *Bambu_Tunnel;
|
|
||||||
|
|
||||||
struct _GstBambuSrc
|
|
||||||
{
|
|
||||||
GstPushSrc element;
|
|
||||||
GstCaps *src_caps;
|
|
||||||
gchar *location;
|
|
||||||
Bambu_Tunnel tnl;
|
|
||||||
GstClockTime sttime;
|
|
||||||
int video_type;
|
|
||||||
int frame_rate;
|
|
||||||
guint64 frame_count;
|
|
||||||
GstClockTime last_arrival;
|
|
||||||
GstClockTime avg_period;
|
|
||||||
};
|
|
||||||
|
|
||||||
extern void gstbambusrc_register();
|
|
||||||
|
|
||||||
G_END_DECLS
|
|
||||||
|
|
||||||
#endif /* __GST_BAMBUSRC_H__ */
|
|
||||||
@@ -63,7 +63,6 @@ class ProjectPanel : public wxPanel
|
|||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
std::atomic<bool> m_web_init_completed{false};
|
std::atomic<bool> m_web_init_completed{false};
|
||||||
bool m_reload_already = {false};
|
|
||||||
|
|
||||||
std::shared_ptr<std::atomic<bool>> m_reload_cancel_token{std::make_shared<std::atomic<bool>>(false)};
|
std::shared_ptr<std::atomic<bool>> m_reload_cancel_token{std::make_shared<std::atomic<bool>>(false)};
|
||||||
std::unique_ptr<boost::thread> m_reload_task;
|
std::unique_ptr<boost::thread> m_reload_task;
|
||||||
|
|||||||
@@ -10,8 +10,6 @@ namespace Slic3r { namespace GUI {
|
|||||||
class RecenterDialog : public DPIDialog
|
class RecenterDialog : public DPIDialog
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
wxStaticText* m_staticText_hint;
|
|
||||||
wxStaticBitmap* m_bitmap_home;
|
|
||||||
ScalableBitmap m_home_bmp;
|
ScalableBitmap m_home_bmp;
|
||||||
wxString hint1;
|
wxString hint1;
|
||||||
wxString hint2;
|
wxString hint2;
|
||||||
|
|||||||
@@ -681,7 +681,7 @@ SearchDialog::SearchDialog(OptionsSearcher *searcher, Preset::Type type, wxWindo
|
|||||||
|
|
||||||
SearchDialog::~SearchDialog() {}
|
SearchDialog::~SearchDialog() {}
|
||||||
|
|
||||||
void SearchDialog::Popup(wxPoint position /*= wxDefaultPosition*/)
|
void SearchDialog::Popup(wxWindow *focus /*= nullptr*/)
|
||||||
{
|
{
|
||||||
/* const std::string& line = searcher->search_string();
|
/* const std::string& line = searcher->search_string();
|
||||||
search_line->SetValue(line.empty() ? default_string : from_u8(line));
|
search_line->SetValue(line.empty() ? default_string : from_u8(line));
|
||||||
@@ -696,17 +696,19 @@ void SearchDialog::Popup(wxPoint position /*= wxDefaultPosition*/)
|
|||||||
search_line2->SetValue(wxString(""));
|
search_line2->SetValue(wxString(""));
|
||||||
//const std::string &line = searcher->search_string();
|
//const std::string &line = searcher->search_string();
|
||||||
//searcher->search(into_u8(line), true);
|
//searcher->search(into_u8(line), true);
|
||||||
PopupWindow::Popup();
|
PopupWindow::Popup(focus);
|
||||||
search_line2->SetFocus();
|
search_line2->SetFocus();
|
||||||
update_list();
|
update_list();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __WXMSW__
|
||||||
void SearchDialog::MSWDismissUnfocusedPopup()
|
void SearchDialog::MSWDismissUnfocusedPopup()
|
||||||
{
|
{
|
||||||
Dismiss();
|
Dismiss();
|
||||||
OnDismiss();
|
OnDismiss();
|
||||||
}
|
}
|
||||||
|
#endif // __WXMSW__
|
||||||
|
|
||||||
void SearchDialog::OnDismiss() { }
|
void SearchDialog::OnDismiss() { }
|
||||||
|
|
||||||
@@ -926,7 +928,7 @@ SearchObjectDialog::SearchObjectDialog(GUI::ObjectList* object_list, wxWindow* p
|
|||||||
|
|
||||||
SearchObjectDialog::~SearchObjectDialog() {}
|
SearchObjectDialog::~SearchObjectDialog() {}
|
||||||
|
|
||||||
void SearchObjectDialog::Popup(wxPoint position /*= wxDefaultPosition*/)
|
void SearchObjectDialog::Popup(wxWindow *focus /*= nullptr*/)
|
||||||
{
|
{
|
||||||
if (m_is_dismissing || this->IsShown()) {
|
if (m_is_dismissing || this->IsShown()) {
|
||||||
return;
|
return;
|
||||||
@@ -937,7 +939,7 @@ void SearchObjectDialog::Popup(wxPoint position /*= wxDefaultPosition*/)
|
|||||||
// dropdown list, otherwise the text input won't be usable
|
// dropdown list, otherwise the text input won't be usable
|
||||||
m_object_list->SetFocus();
|
m_object_list->SetFocus();
|
||||||
#endif
|
#endif
|
||||||
PopupWindow::Popup();
|
PopupWindow::Popup(focus);
|
||||||
search_line2->SetFocus();
|
search_line2->SetFocus();
|
||||||
|
|
||||||
m_object_list->assembly_plate_object_name();
|
m_object_list->assembly_plate_object_name();
|
||||||
@@ -945,11 +947,13 @@ void SearchObjectDialog::Popup(wxPoint position /*= wxDefaultPosition*/)
|
|||||||
update_list();
|
update_list();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef __WXMSW__
|
||||||
void SearchObjectDialog::MSWDismissUnfocusedPopup()
|
void SearchObjectDialog::MSWDismissUnfocusedPopup()
|
||||||
{
|
{
|
||||||
Dismiss();
|
Dismiss();
|
||||||
OnDismiss();
|
OnDismiss();
|
||||||
}
|
}
|
||||||
|
#endif // __WXMSW__
|
||||||
|
|
||||||
void SearchObjectDialog::OnDismiss() {}
|
void SearchObjectDialog::OnDismiss() {}
|
||||||
|
|
||||||
|
|||||||
@@ -216,10 +216,12 @@ public:
|
|||||||
SearchDialog(OptionsSearcher *searcher, Preset::Type type, wxWindow *parent, TextInput *input, wxWindow *search_btn);
|
SearchDialog(OptionsSearcher *searcher, Preset::Type type, wxWindow *parent, TextInput *input, wxWindow *search_btn);
|
||||||
~SearchDialog();
|
~SearchDialog();
|
||||||
|
|
||||||
void MSWDismissUnfocusedPopup();
|
#ifdef __WXMSW__
|
||||||
void Popup(wxPoint position = wxDefaultPosition);
|
void MSWDismissUnfocusedPopup() override;
|
||||||
void OnDismiss();
|
#endif // __WXMSW__
|
||||||
void Dismiss();
|
void Popup(wxWindow *focus = nullptr) override;
|
||||||
|
void OnDismiss() override;
|
||||||
|
void Dismiss() override;
|
||||||
void Die();
|
void Die();
|
||||||
void msw_rescale();
|
void msw_rescale();
|
||||||
|
|
||||||
@@ -260,10 +262,12 @@ public:
|
|||||||
SearchObjectDialog(GUI::ObjectList* object_list, wxWindow* parent, TextInput* input);
|
SearchObjectDialog(GUI::ObjectList* object_list, wxWindow* parent, TextInput* input);
|
||||||
~SearchObjectDialog();
|
~SearchObjectDialog();
|
||||||
|
|
||||||
void MSWDismissUnfocusedPopup();
|
#ifdef __WXMSW__
|
||||||
void Popup(wxPoint position = wxDefaultPosition);
|
void MSWDismissUnfocusedPopup() override;
|
||||||
void OnDismiss();
|
#endif // __WXMSW__
|
||||||
void Dismiss();
|
void Popup(wxWindow *focus = nullptr) override;
|
||||||
|
void OnDismiss() override;
|
||||||
|
void Dismiss() override;
|
||||||
void Die();
|
void Die();
|
||||||
|
|
||||||
void OnInputText(wxCommandEvent& event);
|
void OnInputText(wxCommandEvent& event);
|
||||||
|
|||||||
@@ -483,7 +483,7 @@ SelectMachineDialog::SelectMachineDialog(Plater *plater)
|
|||||||
|
|
||||||
m_link_edit_nozzle->Bind(wxEVT_LEFT_DOWN, [this](auto &e) {
|
m_link_edit_nozzle->Bind(wxEVT_LEFT_DOWN, [this](auto &e) {
|
||||||
|
|
||||||
if (this && this->m_is_in_sending_mode) {
|
if (m_is_in_sending_mode) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -181,8 +181,6 @@ private:
|
|||||||
PinCodePanel* m_panel_direct_connection{nullptr};
|
PinCodePanel* m_panel_direct_connection{nullptr};
|
||||||
wxWindow* m_placeholder_panel{nullptr};
|
wxWindow* m_placeholder_panel{nullptr};
|
||||||
HyperLink* m_hyperlink{nullptr}; // ORCA
|
HyperLink* m_hyperlink{nullptr}; // ORCA
|
||||||
Label* m_ping_code_text{nullptr};
|
|
||||||
wxStaticBitmap* m_img_ping_code{nullptr};
|
|
||||||
wxBoxSizer * m_sizer_body{nullptr};
|
wxBoxSizer * m_sizer_body{nullptr};
|
||||||
wxBoxSizer * m_sizer_my_devices{nullptr};
|
wxBoxSizer * m_sizer_my_devices{nullptr};
|
||||||
wxBoxSizer * m_sizer_other_devices{nullptr};
|
wxBoxSizer * m_sizer_other_devices{nullptr};
|
||||||
|
|||||||
@@ -149,7 +149,6 @@ private:
|
|||||||
ScalableBitmap* print_time{ nullptr };
|
ScalableBitmap* print_time{ nullptr };
|
||||||
wxStaticBitmap* weightimg{ nullptr };
|
wxStaticBitmap* weightimg{ nullptr };
|
||||||
ScalableBitmap* print_weight{ nullptr };
|
ScalableBitmap* print_weight{ nullptr };
|
||||||
wxBoxSizer* m_thumbnail_sizer{ nullptr };
|
|
||||||
ThumbnailPanel* m_thumbnail_panel{nullptr};
|
ThumbnailPanel* m_thumbnail_panel{nullptr};
|
||||||
wxPanel* m_panel_image{ nullptr };
|
wxPanel* m_panel_image{ nullptr };
|
||||||
wxBoxSizer* m_image_sizer{ nullptr };
|
wxBoxSizer* m_image_sizer{ nullptr };
|
||||||
|
|||||||
@@ -994,7 +994,6 @@ void SendToPrinterDialog::on_ok(wxCommandEvent &event)
|
|||||||
m_send_job->on_check_ip_address_fail([this, token = std::weak_ptr(m_token)](int result) {
|
m_send_job->on_check_ip_address_fail([this, token = std::weak_ptr(m_token)](int result) {
|
||||||
CallAfter([token, this] {
|
CallAfter([token, this] {
|
||||||
if (token.expired()) { return; }
|
if (token.expired()) { return; }
|
||||||
if (this) {
|
|
||||||
SendFailedConfirm sfcDlg;
|
SendFailedConfirm sfcDlg;
|
||||||
auto res = sfcDlg.ShowModal();
|
auto res = sfcDlg.ShowModal();
|
||||||
m_status_bar->cancel();
|
m_status_bar->cancel();
|
||||||
@@ -1006,7 +1005,6 @@ void SendToPrinterDialog::on_ok(wxCommandEvent &event)
|
|||||||
wxQueueEvent(this, evt);
|
wxQueueEvent(this, evt);
|
||||||
wxGetApp().show_ip_address_enter_dialog();
|
wxGetApp().show_ip_address_enter_dialog();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -62,7 +62,6 @@ private:
|
|||||||
bool m_is_in_sending_mode{ false };
|
bool m_is_in_sending_mode{ false };
|
||||||
bool m_is_rename_mode{ false };
|
bool m_is_rename_mode{ false };
|
||||||
bool enable_prepare_mode{ true };
|
bool enable_prepare_mode{ true };
|
||||||
bool m_need_adaptation_screen{ false };
|
|
||||||
bool m_export_3mf_cancel{ false };
|
bool m_export_3mf_cancel{ false };
|
||||||
bool m_is_canceled{ false };
|
bool m_is_canceled{ false };
|
||||||
bool m_tcp_try_connect{true};
|
bool m_tcp_try_connect{true};
|
||||||
@@ -81,7 +80,6 @@ private:
|
|||||||
wxStaticBitmap* m_staticbitmap{ nullptr };
|
wxStaticBitmap* m_staticbitmap{ nullptr };
|
||||||
ThumbnailPanel* m_thumbnailPanel{ nullptr };
|
ThumbnailPanel* m_thumbnailPanel{ nullptr };
|
||||||
ComboBox* m_comboBox_printer{ nullptr };
|
ComboBox* m_comboBox_printer{ nullptr };
|
||||||
ComboBox* m_comboBox_bed{ nullptr };
|
|
||||||
Button* m_rename_button{ nullptr };
|
Button* m_rename_button{ nullptr };
|
||||||
Button* m_button_refresh{ nullptr };
|
Button* m_button_refresh{ nullptr };
|
||||||
Button* m_button_ensure{ nullptr };
|
Button* m_button_ensure{ nullptr };
|
||||||
|
|||||||
@@ -87,7 +87,6 @@ private:
|
|||||||
std::unordered_map < uint32_t, std::vector<std::vector<FloatPoint>>> parts_triangles_;
|
std::unordered_map < uint32_t, std::vector<std::vector<FloatPoint>>> parts_triangles_;
|
||||||
std::unordered_map < uint32_t, std::vector<std::vector<cv::Point>>> pick_parts_;
|
std::unordered_map < uint32_t, std::vector<std::vector<cv::Point>>> pick_parts_;
|
||||||
std::unordered_map<uint32_t, PartState> parts_state_;
|
std::unordered_map<uint32_t, PartState> parts_state_;
|
||||||
bool gl_inited_{false};
|
|
||||||
int zoom_percent_{100};
|
int zoom_percent_{100};
|
||||||
wxPoint offset_{0,0};
|
wxPoint offset_{0,0};
|
||||||
wxPoint drag_start_offset_{0,0};
|
wxPoint drag_start_offset_{0,0};
|
||||||
|
|||||||
@@ -1531,7 +1531,7 @@ wxBoxSizer *StatusBasePanel::create_monitoring_page()
|
|||||||
// media_ctrl_panel = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxDefaultSize);
|
// media_ctrl_panel = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxDefaultSize);
|
||||||
// media_ctrl_panel->SetBackgroundColour(*wxBLACK);
|
// media_ctrl_panel->SetBackgroundColour(*wxBLACK);
|
||||||
// wxBoxSizer *bSizer_monitoring = new wxBoxSizer(wxVERTICAL);
|
// wxBoxSizer *bSizer_monitoring = new wxBoxSizer(wxVERTICAL);
|
||||||
m_media_ctrl = new wxMediaCtrl2(this);
|
m_media_ctrl = new wxMediaCtrl3(this);
|
||||||
m_media_ctrl->SetMinSize(wxSize(PAGE_MIN_WIDTH, FromDIP(288)));
|
m_media_ctrl->SetMinSize(wxSize(PAGE_MIN_WIDTH, FromDIP(288)));
|
||||||
|
|
||||||
m_custom_camera_view = WebView::CreateWebView(this, wxEmptyString);
|
m_custom_camera_view = WebView::CreateWebView(this, wxEmptyString);
|
||||||
|
|||||||
@@ -15,7 +15,6 @@
|
|||||||
#include <wx/gbsizer.h>
|
#include <wx/gbsizer.h>
|
||||||
#include <wx/webrequest.h>
|
#include <wx/webrequest.h>
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include "wxMediaCtrl2.h"
|
|
||||||
#include "MediaPlayCtrl.h"
|
#include "MediaPlayCtrl.h"
|
||||||
#include "AMSSetting.hpp"
|
#include "AMSSetting.hpp"
|
||||||
#include "Calibration.hpp"
|
#include "Calibration.hpp"
|
||||||
@@ -444,7 +443,7 @@ protected:
|
|||||||
wxStaticBitmap* m_camera_switch_button;
|
wxStaticBitmap* m_camera_switch_button;
|
||||||
|
|
||||||
|
|
||||||
wxMediaCtrl2 * m_media_ctrl;
|
wxMediaCtrl3 * m_media_ctrl;
|
||||||
MediaPlayCtrl * m_media_play_ctrl;
|
MediaPlayCtrl * m_media_play_ctrl;
|
||||||
|
|
||||||
Label * m_staticText_printing;
|
Label * m_staticText_printing;
|
||||||
|
|||||||
@@ -307,8 +307,6 @@ private:
|
|||||||
// wxBoxSizer * m_plate_combox_sizer = nullptr;
|
// wxBoxSizer * m_plate_combox_sizer = nullptr;
|
||||||
wxBoxSizer * m_mode_combox_sizer = nullptr;
|
wxBoxSizer * m_mode_combox_sizer = nullptr;
|
||||||
//wxStaticText * m_printer_title = nullptr;
|
//wxStaticText * m_printer_title = nullptr;
|
||||||
wxStaticText * m_printer_device_name = nullptr;
|
|
||||||
wxStaticText * m_printer_is_map_title = nullptr;
|
|
||||||
|
|
||||||
CapsuleButton * m_colormap_btn = nullptr;
|
CapsuleButton * m_colormap_btn = nullptr;
|
||||||
CapsuleButton * m_override_btn = nullptr;
|
CapsuleButton * m_override_btn = nullptr;
|
||||||
@@ -326,7 +324,6 @@ private:
|
|||||||
|
|
||||||
bool m_check_dirty_fialment = true;
|
bool m_check_dirty_fialment = true;
|
||||||
bool m_expand_more_settings = true;
|
bool m_expand_more_settings = true;
|
||||||
bool m_image_is_top = false;
|
|
||||||
|
|
||||||
const int LEFT_THUMBNAIL_SIZE_WIDTH = 100;
|
const int LEFT_THUMBNAIL_SIZE_WIDTH = 100;
|
||||||
const int RIGHT_THUMBNAIL_SIZE_WIDTH = 300;
|
const int RIGHT_THUMBNAIL_SIZE_WIDTH = 300;
|
||||||
|
|||||||
@@ -7530,7 +7530,7 @@ void Tab::delete_preset()
|
|||||||
for (auto &preset2 : *m_presets)
|
for (auto &preset2 : *m_presets)
|
||||||
if (preset2.inherits() == current_preset.name) {
|
if (preset2.inherits() == current_preset.name) {
|
||||||
++count;
|
++count;
|
||||||
presets += "\n - " + preset2.name;
|
presets += "\n - " + from_u8(preset2.name);
|
||||||
}
|
}
|
||||||
if (count > 0) {
|
if (count > 0) {
|
||||||
msg = _L("Presets inherited by other presets cannot be deleted!");
|
msg = _L("Presets inherited by other presets cannot be deleted!");
|
||||||
|
|||||||
@@ -626,8 +626,6 @@ private:
|
|||||||
bool m_rebuild_kinematics_page = false;
|
bool m_rebuild_kinematics_page = false;
|
||||||
void update_input_shaper_menu(GCodeFlavor flavor);
|
void update_input_shaper_menu(GCodeFlavor flavor);
|
||||||
|
|
||||||
ogStaticText* m_fff_print_host_upload_description_line {nullptr};
|
|
||||||
ogStaticText* m_sla_print_host_upload_description_line {nullptr};
|
|
||||||
|
|
||||||
std::vector<PageShp> m_pages_fff;
|
std::vector<PageShp> m_pages_fff;
|
||||||
std::vector<PageShp> m_pages_sla;
|
std::vector<PageShp> m_pages_sla;
|
||||||
|
|||||||
@@ -31,7 +31,6 @@ private:
|
|||||||
wxStaticText *m_remaining_time_label;
|
wxStaticText *m_remaining_time_label;
|
||||||
wxStaticText *m_explanation_label;
|
wxStaticText *m_explanation_label;
|
||||||
wxButton *m_ok_button;
|
wxButton *m_ok_button;
|
||||||
wxStaticBitmap *m_title_bitmap;
|
|
||||||
|
|
||||||
DECLARE_EVENT_TABLE()
|
DECLARE_EVENT_TABLE()
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -862,7 +862,6 @@ void MachineInfoPanel::update_ams_ext(MachineObject *obj)
|
|||||||
if (new_extra_ams_ver != obj->new_ver_list.end())
|
if (new_extra_ams_ver != obj->new_ver_list.end())
|
||||||
has_new_version = true;
|
has_new_version = true;
|
||||||
|
|
||||||
extra_ams_it->second.sw_new_ver;
|
|
||||||
if (has_new_version) {
|
if (has_new_version) {
|
||||||
m_extra_ams_panel->m_ams_new_version_img->Show();
|
m_extra_ams_panel->m_ams_new_version_img->Show();
|
||||||
ver_text = new_extra_ams_ver->second.sw_ver;
|
ver_text = new_extra_ams_ver->second.sw_ver;
|
||||||
|
|||||||
@@ -112,7 +112,6 @@ private:
|
|||||||
AppConfig m_appconfig_new;
|
AppConfig m_appconfig_new;
|
||||||
|
|
||||||
wxWebView *m_browser;
|
wxWebView *m_browser;
|
||||||
wxButton * m_TestBtn;
|
|
||||||
|
|
||||||
wxString m_SectionName;
|
wxString m_SectionName;
|
||||||
|
|
||||||
|
|||||||
@@ -125,10 +125,6 @@ private:
|
|||||||
wxMenuItem* m_edit_undo;
|
wxMenuItem* m_edit_undo;
|
||||||
wxMenuItem* m_edit_redo;
|
wxMenuItem* m_edit_redo;
|
||||||
wxMenuItem* m_edit_mode;
|
wxMenuItem* m_edit_mode;
|
||||||
wxMenuItem* m_scroll_line_up;
|
|
||||||
wxMenuItem* m_scroll_line_down;
|
|
||||||
wxMenuItem* m_scroll_page_up;
|
|
||||||
wxMenuItem* m_scroll_page_down;
|
|
||||||
wxMenuItem* m_script_string;
|
wxMenuItem* m_script_string;
|
||||||
wxMenuItem* m_script_integer;
|
wxMenuItem* m_script_integer;
|
||||||
wxMenuItem* m_script_double;
|
wxMenuItem* m_script_double;
|
||||||
|
|||||||
@@ -114,7 +114,6 @@ bool AMSinfo::parse_ams_info(MachineObject *obj, DevAms *ams, bool remain_flag,
|
|||||||
info.ctype = 0;
|
info.ctype = 0;
|
||||||
info.material_colour = AMS_TRAY_DEFAULT_COL;
|
info.material_colour = AMS_TRAY_DEFAULT_COL;
|
||||||
info.material_state = AMSCanType::AMS_CAN_TYPE_THIRDBRAND;
|
info.material_state = AMSCanType::AMS_CAN_TYPE_THIRDBRAND;
|
||||||
wxColour(255, 255, 255);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (it->second->is_tray_info_ready() && obj->cali_version >= 0) {
|
if (it->second->is_tray_info_ready() && obj->cali_version >= 0) {
|
||||||
@@ -171,7 +170,6 @@ void AMSinfo::parse_ext_info(MachineObject* obj, DevAmsTray tray) {
|
|||||||
info.filament_id = "";
|
info.filament_id = "";
|
||||||
info.ctype = 0;
|
info.ctype = 0;
|
||||||
info.material_colour = AMS_TRAY_DEFAULT_COL;
|
info.material_colour = AMS_TRAY_DEFAULT_COL;
|
||||||
wxColour(255, 255, 255);
|
|
||||||
}
|
}
|
||||||
info.material_state = AMSCanType::AMS_CAN_TYPE_VIRTUAL;
|
info.material_state = AMSCanType::AMS_CAN_TYPE_VIRTUAL;
|
||||||
if (tray.is_tray_info_ready() && obj->cali_version >= 0) {
|
if (tray.is_tray_info_ready() && obj->cali_version >= 0) {
|
||||||
|
|||||||
@@ -684,7 +684,6 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
int m_nozzle_num = {1};
|
int m_nozzle_num = {1};
|
||||||
AMSRoadShowMode m_single_ext_rode_mode = {AMSRoadShowMode::AMS_ROAD_MODE_FOUR};
|
|
||||||
AMSRoadShowMode m_left_rode_mode = {AMSRoadShowMode::AMS_ROAD_MODE_FOUR};
|
AMSRoadShowMode m_left_rode_mode = {AMSRoadShowMode::AMS_ROAD_MODE_FOUR};
|
||||||
AMSRoadShowMode m_right_rode_mode = {AMSRoadShowMode::AMS_ROAD_MODE_FOUR};
|
AMSRoadShowMode m_right_rode_mode = {AMSRoadShowMode::AMS_ROAD_MODE_FOUR};
|
||||||
bool m_selected = {false};
|
bool m_selected = {false};
|
||||||
@@ -693,7 +692,6 @@ private:
|
|||||||
int m_right_road_length = {-1};
|
int m_right_road_length = {-1};
|
||||||
int m_passroad_width = {6};
|
int m_passroad_width = {6};
|
||||||
double m_radius = {4};
|
double m_radius = {4};
|
||||||
AMSPassRoadType m_pass_road_type = {AMSPassRoadType::AMS_ROAD_TYPE_NONE};
|
|
||||||
AMSPassRoadSTEP m_pass_road_left_step = {AMSPassRoadSTEP::AMS_ROAD_STEP_NONE};
|
AMSPassRoadSTEP m_pass_road_left_step = {AMSPassRoadSTEP::AMS_ROAD_STEP_NONE};
|
||||||
AMSPassRoadSTEP m_pass_road_right_step = {AMSPassRoadSTEP::AMS_ROAD_STEP_NONE};
|
AMSPassRoadSTEP m_pass_road_right_step = {AMSPassRoadSTEP::AMS_ROAD_STEP_NONE};
|
||||||
|
|
||||||
@@ -866,11 +864,7 @@ private:
|
|||||||
AMSinfo m_info;
|
AMSinfo m_info;
|
||||||
wxBoxSizer * sizer_can = {nullptr};
|
wxBoxSizer * sizer_can = {nullptr};
|
||||||
wxGridSizer* sizer_can_extra = { nullptr };
|
wxGridSizer* sizer_can_extra = { nullptr };
|
||||||
wxBoxSizer * sizer_humidity = { nullptr };
|
|
||||||
wxBoxSizer * sizer_item = { nullptr };
|
wxBoxSizer * sizer_item = { nullptr };
|
||||||
wxBoxSizer * sizer_can_middle = {nullptr};
|
|
||||||
wxBoxSizer * sizer_can_left = {nullptr};
|
|
||||||
wxBoxSizer * sizer_can_right = {nullptr};
|
|
||||||
AMSExtImage* m_ext_image = { nullptr }; //the ext image upon the ext ams
|
AMSExtImage* m_ext_image = { nullptr }; //the ext image upon the ext ams
|
||||||
AMSExtText* m_ext_text = { nullptr }; //the ext text upon the ext ams
|
AMSExtText* m_ext_text = { nullptr }; //the ext text upon the ext ams
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -124,7 +124,7 @@ void AxisCtrlButton::SetInnerBackgroundColor(StateColor const& color)
|
|||||||
|
|
||||||
void AxisCtrlButton::SetBitmap(ScalableBitmap &bmp)
|
void AxisCtrlButton::SetBitmap(ScalableBitmap &bmp)
|
||||||
{
|
{
|
||||||
if (&bmp && (& bmp.bmp()) && (bmp.bmp().IsOk())) {
|
if (bmp.bmp().IsOk()) {
|
||||||
m_icon = bmp;
|
m_icon = bmp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user